def testReplicateInvalidRules(self): """Tests invalid FileReplicationRules cause errors.""" with self.assertRaisesRegex( ValueError, 'Rule for JSON source a.json must use REPLICATION_TYPE_FILTER' ): replication_lib.Replicate( ReplicationConfig(file_replication_rules=[ FileReplicationRule( source_path='a.json', destination_path='b.json', file_type=FILE_TYPE_JSON, replication_type=REPLICATION_TYPE_COPY, ), ])) with self.assertRaisesRegex( ValueError, 'Rule for source a.bin must use REPLICATION_TYPE_COPY'): replication_lib.Replicate( ReplicationConfig(file_replication_rules=[ FileReplicationRule( source_path='a.bin', destination_path='b.bin', file_type=FILE_TYPE_OTHER, replication_type=REPLICATION_TYPE_FILTER, ), ])) with self.assertRaisesRegex( ValueError, 'Rule with REPLICATION_TYPE_COPY cannot use destination_fields' ): replication_lib.Replicate( ReplicationConfig(file_replication_rules=[ FileReplicationRule( source_path='a.bin', destination_path='b.bin', file_type=FILE_TYPE_OTHER, replication_type=REPLICATION_TYPE_COPY, destination_fields=FieldMask(paths=['c', 'd']), ), ])) with self.assertRaisesRegex( ValueError, 'Rule with REPLICATION_TYPE_FILTER must use destination_fields' ): replication_lib.Replicate( ReplicationConfig(file_replication_rules=[ FileReplicationRule( source_path='a.json', destination_path='b.json', file_type=FILE_TYPE_JSON, replication_type=REPLICATION_TYPE_FILTER, ), ]))
def testReplicateFileMode(self): """Tests file mode data is replicated.""" # Check that the original mode is not 777 and then chmod. full_audio_path = os.path.join(self.tempdir, self.audio_path) self.assertNotEqual(stat.S_IMODE(os.stat(full_audio_path).st_mode), 0o777) os.chmod(full_audio_path, 0o777) audio_dst_path = os.path.join('dst', 'audio_file') replication_config = ReplicationConfig(file_replication_rules=[ FileReplicationRule( source_path=self.audio_path, destination_path=audio_dst_path, file_type=FILE_TYPE_OTHER, replication_type=REPLICATION_TYPE_COPY, ), ]) replication_lib.Replicate(replication_config) self.assertEqual( stat.S_IMODE( os.stat(os.path.join(self.tempdir, audio_dst_path)).st_mode), 0o777)
def testReplicateDestinationExists(self): """Test existing files are overwritten.""" file_layout = (D('dst', ['audio_file']), ) cros_test_lib.CreateOnDiskHierarchy(self.tempdir, file_layout) audio_dst_path = os.path.join('dst', 'audio_file') self.WriteTempFile(audio_dst_path, 'Original audio data') replication_config = ReplicationConfig(file_replication_rules=[ FileReplicationRule( source_path=self.audio_path, destination_path=audio_dst_path, file_type=FILE_TYPE_OTHER, replication_type=REPLICATION_TYPE_COPY, ), ]) replication_lib.Replicate(replication_config) expected_file_layout = ( D('src', ['build_config.json', 'audio_file', 'firmware.bin']), D('dst', ['audio_file']), ) cros_test_lib.VerifyOnDiskHierarchy(self.tempdir, expected_file_layout) self.assertTempFileContents(audio_dst_path, '[Speaker A Settings]')
def Run(options): """Runs the replication described by a PrelicationConfig proto.""" replication_config = json_format.Parse( osutils.ReadFile(options.replication_config), replication_config_pb2.ReplicationConfig(), ) replication_lib.Replicate(replication_config)
def testReplicate(self): """Test basic Replication functionality. - destination_fields used to filter JSON payload. - firmware.bin not copied. """ build_config_dst_path = os.path.join(self.tempdir, 'dst', 'build_config.json') audio_dst_path = os.path.join(self.tempdir, 'dst', 'audio_file') replication_config = ReplicationConfig(file_replication_rules=[ FileReplicationRule(source_path=self.build_config_path, destination_path=build_config_dst_path, file_type=FILE_TYPE_JSON, replication_type=REPLICATION_TYPE_FILTER, destination_fields=FieldMask( paths=['name', 'field2'])), FileReplicationRule( source_path=self.audio_path, destination_path=audio_dst_path, file_type=FILE_TYPE_OTHER, replication_type=REPLICATION_TYPE_COPY, ), ]) replication_lib.Replicate(replication_config) expected_file_layout = ( D('src', ['build_config.json', 'audio_file', 'firmware.bin']), D('dst', ['build_config.json', 'audio_file']), ) cros_test_lib.VerifyOnDiskHierarchy(self.tempdir, expected_file_layout) build_config_dst = json.loads(osutils.ReadFile(build_config_dst_path)) expected_build_config_dst = { 'chromeos': { 'configs': [ { 'name': 'A', 'field2': 2, }, { 'name': 'B', 'field2': 4, }, ] } } self.assertDictEqual(expected_build_config_dst, build_config_dst) self.assertFileContents(audio_dst_path, '[Speaker A Settings]')
def replicate_private_config(_build_targets, refs, chroot): """Replicate a private cros_config change to the corresponding public config. See uprev_versioned_package for args """ package = 'chromeos-base/chromeos-config-bsp' if len(refs) != 1: raise ValueError('Expected exactly one ref, actual %s' % refs) # Expect a replication_config.jsonpb in the package root. package_root = _get_private_overlay_package_root(refs[0], package) replication_config_path = os.path.join(package_root, 'replication_config.jsonpb') try: replication_config = json_format.Parse( osutils.ReadFile(replication_config_path), replication_config_pb2.ReplicationConfig()) except IOError: raise ValueError('Expected ReplicationConfig missing at %s' % replication_config_path) replication_lib.Replicate(replication_config) modified_files = [ rule.destination_path for rule in replication_config.file_replication_rules ] # The generated platform C files are not easily filtered by replication rules, # i.e. JSON / proto filtering can be described by a FieldMask, arbitrary C # files cannot. Therefore, replicate and filter the JSON payloads, and then # generate filtered C files from the JSON payload. modified_files.extend( _generate_platform_c_files(replication_config, chroot)) # Use the private repo's commit hash as the new version. new_private_version = refs[0].revision # modified_files should contain only relative paths at this point, but the # returned UprevVersionedPackageResult must contain only absolute paths. for i, modified_file in enumerate(modified_files): assert not os.path.isabs(modified_file) modified_files[i] = os.path.join(constants.SOURCE_ROOT, modified_file) return UprevVersionedPackageResult().add_result(new_private_version, modified_files)
def testReplicateJsonTrailingNewline(self): """Test JSON payloads have a trailing newline.""" build_config_dst_path = os.path.join('dst', 'build_config.json') replication_config = ReplicationConfig(file_replication_rules=[ FileReplicationRule(source_path=self.build_config_path, destination_path=build_config_dst_path, file_type=FILE_TYPE_JSON, replication_type=REPLICATION_TYPE_FILTER, destination_fields=FieldMask( paths=['name', 'field2'])), ]) replication_lib.Replicate(replication_config) self.assertEqual(self.ReadTempFile(build_config_dst_path)[-1], '\n')
def testReplicateNonChromeOSConfig(self): """Tests replicating a JSON file that is not a ChromeOS Config payload.""" src_path = os.path.join('src', 'other.json') dst_path = os.path.join('dst', 'other.json') self.WriteTempFile(src_path, json.dumps({'a': 1, 'b': 2})) replication_config = ReplicationConfig(file_replication_rules=[ FileReplicationRule(source_path=src_path, destination_path=dst_path, file_type=FILE_TYPE_JSON, replication_type=REPLICATION_TYPE_FILTER, destination_fields=FieldMask(paths=['a'])), ]) with self.assertRaisesRegex( NotImplementedError, 'Currently only ChromeOS Configs are supported'): replication_lib.Replicate(replication_config)
def testReplicateStringReplicationRules(self): audio_dst_path = os.path.join('dst', 'audio_file') replication_config = ReplicationConfig(file_replication_rules=[ FileReplicationRule( source_path=self.audio_path, destination_path=audio_dst_path, file_type=FILE_TYPE_OTHER, replication_type=REPLICATION_TYPE_COPY, string_replacement_rules=[ StringReplacementRule(before='A', after='B'), StringReplacementRule(before='Settings', after='Settings (Updated)'), ]), ]) replication_lib.Replicate(replication_config) self.assertTempFileContents(audio_dst_path, '[Speaker B Settings (Updated)]')
def replicate_private_config(_build_targets, refs, _chroot): """Replicate a private cros_config change to the corresponding public config. See uprev_versioned_package for args """ # TODO(crbug.com/1020262): Generalize this to other packages. package = 'chromeos-base/chromeos-config-bsp-coral-private' if len(refs) != 1: raise ValueError('Expected exactly one ref, actual %s' % refs) # Expect a replication_config.jsonpb in the package root. package_root = os.path.join(constants.SOURCE_ROOT, refs[0].path, package) replication_config_path = os.path.join(package_root, 'replication_config.jsonpb') try: replication_config = json_format.Parse( osutils.ReadFile(replication_config_path), replication_config_pb2.ReplicationConfig()) except IOError: raise ValueError('Expected ReplicationConfig missing at %s' % replication_config_path) replication_lib.Replicate(replication_config) modified_files = [ rule.destination_path for rule in replication_config.file_replication_rules ] # TODO(crbug.com/1021241): Use cros_config_schema to generate platform JSON # and C files. # Use the private repo's commit hash as the new version. new_private_version = refs[0].revision return UprevVersionedPackageResult().add_result(new_private_version, modified_files)