Making bagmigration not pass through in the event that constants have changed in the message.

This commit is contained in:
Jeremy Leibs 2009-10-03 01:11:14 +00:00
parent 1b5fa1e910
commit ff3e472a5b
8 changed files with 115 additions and 3 deletions

View File

@ -0,0 +1,3 @@
int32 CONSTANT=2
int32 CONSTANT_TWO=42
int32 value

View File

@ -0,0 +1,2 @@
int32 CONSTANT=1
int32 value

View File

@ -0,0 +1,2 @@
int32 CONSTANT=2
int32 value

View File

@ -90,6 +90,11 @@ def generate_data():
m = Converged([1.2, 3.4, 5.6, 7.8], [SimpleMigrated(11), SimpleMigrated(22), SimpleMigrated(33), SimpleMigrated(44)])
bag.add("converged", m, roslib.rostime.Time())
bag.close()
bag = rosrecord.Rebagger("test/constants_gen1.bag")
m = Constants(Constants.CONSTANT)
bag.add("constants", m, roslib.rostime.Time())
bag.close()
if __name__ == '__main__':
generate_data()

View File

@ -75,6 +75,11 @@ def generate_data():
m = Converged([1.2, 3.4, 5.6, 7.8], [SimpleMigrated(11), SimpleMigrated(22), SimpleMigrated(33), SimpleMigrated(44)])
bag.add("converged", m, roslib.rostime.Time())
bag.close()
bag = rosrecord.Rebagger("test/constants_gen2.bag")
m = Constants(Constants.CONSTANT)
bag.add("constants", m, roslib.rostime.Time())
bag.close()
if __name__ == '__main__':
generate_data()

View File

@ -0,0 +1,23 @@
class update_test_rosbagmigration_Constants_06a34bda7d4ea2950ab952e89ca35d7a(MessageUpdateRule):
old_type = "test_rosbagmigration/Constants"
old_full_text = """
int32 CONSTANT=1
int32 value
"""
new_type = "test_rosbagmigration/Constants"
new_full_text = """
int32 CONSTANT=2
int32 CONSTANT_TWO=42
int32 value
"""
order = 0
migrated_types = []
valid = True
def update(self, old_msg, new_msg):
#Constant 'CONSTANT' has changed
if (old_msg.value == old_msg.CONSTANT):
new_msg.value = new_msg.CONSTANT

View File

@ -348,5 +348,54 @@ class MigrationTest(unittest.TestCase):
def do_test_constants_no_rules(self, N):
tmp_rule_files = []
rule_files = ["%s/test/%s"%(self.pkg_dir,r) for r in tmp_rule_files]
inbag = "%s/test/constants_gen%d.bag"%(self.pkg_dir,N)
outbag = "%s/test/constants_gen%d.fixed.bag"%(self.pkg_dir,N)
mm = rosbagmigration.MessageMigrator(rule_files, False)
res = rosbagmigration.checkbag(mm, inbag)
self.assertTrue(len(res[0][1]) == 1)
self.assertTrue(not res[0][1][0].valid)
self.assertEqual(res[0][1][0].old_class._md5sum, '06a34bda7d4ea2950ab952e89ca35d7a')
self.assertEqual(res[0][1][0].new_class._md5sum, 'b45401c4d442c4da7b0a2a105075fa4a')
def do_test_constants_rules(self, N):
tmp_rule_files = ['constants.bmr']
rule_files = ["%s/test/%s"%(self.pkg_dir,r) for r in tmp_rule_files]
inbag = "%s/test/constants_gen%d.bag"%(self.pkg_dir,N)
outbag = "%s/test/constants_gen%d.fixed.bag"%(self.pkg_dir,N)
mm = rosbagmigration.MessageMigrator(rule_files, False)
res = rosbagmigration.checkbag(mm, inbag)
self.assertTrue(not False in [m[1] == [] for m in res], 'Bag not ready to be migrated')
res = rosbagmigration.fixbag(mm, inbag, outbag)
self.assertTrue(res, 'Bag not converted successfully')
msgs = [msg for msg in rosrecord.logplayer(outbag)]
self.assertTrue(len(msgs) > 0)
self.assertEqual(msgs[0][1]._type, 'test_rosbagmigration/Constants', 'Type name is wrong')
self.assertEqual(msgs[0][1].value, msgs[0][1].CONSTANT)
def test_constants_no_rules_gen1(self):
self.do_test_constants_no_rules(1)
def test_constants_gen1(self):
self.do_test_constants_rules(1)
def test_constants_gen2(self):
self.do_test_constants_rules(2)
if __name__ == '__main__':
rostest.unitrun('test_rosbagmigration', 'migration_test', MigrationTest, sys.argv)

View File

@ -121,9 +121,6 @@ def fixbag(migrator, inbag, outbag):
# This checks/builds up rules for the given migrator
res = checkbag(migrator, inbag)
if res == []:
return True
# Deserializing all messages is inefficient, but we can speed this up later
if not False in [m[1] == [] for m in res]:
rebag = rosrecord.Rebagger(outbag)
@ -1070,6 +1067,14 @@ class MessageMigrator(object):
migratedefs = "\tmigrated_types = ["
updatedef = "\tdef update(self, old_msg, new_msg):\n"
old_consts = constants_from_def(old_class._type, old_class._full_text)
new_consts = constants_from_def(new_class._type, new_class._full_text)
if (not new_consts >= old_consts):
validdef = "\tvalid = False\n"
for c in (old_consts - new_consts):
updatedef += "\t\t#Constant '%s' has changed\n"%(c[0],)
old_slots = []
old_slots.extend(old_class.__slots__)
@ -1229,3 +1234,21 @@ def migration_default_value(field_type):
return '[' + ','.join(itertools.repeat(def_val, array_len)) + ']'
else:
return "self.get_new_class('%s')()"%field_type
def constants_from_def(core_type, msg_def):
core_pkg, core_base_type = roslib.names.package_resource_name(core_type)
splits = msg_def.split('\n'+'='*80+'\n')
core_msg = splits[0]
deps_msgs = splits[1:]
# create MsgSpec representations of .msg text
specs = { core_type: roslib.msgs.load_from_string(core_msg, core_pkg) }
# - dependencies
# for dep_msg in deps_msgs:
# # dependencies require more handling to determine type name
# dep_type, dep_spec = _generate_dynamic_specs(specs, dep_msg)
# specs[dep_type] = dep_spec
return Set([(x.name, x.val, x.type) for x in specs[core_type].constants])