def test_json(self): json_value = { "operation": "remove", "sdk_version": { "from": "15.0.0", "to": "16.0.0" }, "sources": ['s1', 's2'], "includes": { "public": ["inc1"] } } patch = LibraryPatch.from_json(json_value) self.assertEqual(patch.operation, LibraryOperation.REMOVE) self.assertEqual( patch.sdk_version, LibraryVersion(from_version=Version(15, 0, 0), to_version=Version(16, 0, 0)) ) self.assertEqual( patch.library.sources, {'s1', 's2'} ) self.assertEqual( patch.library.get_prop(LibraryProperty.INCLUDES) .get_items(Access.PUBLIC), {'inc1'} ) self.assertEqual(json_value, patch.to_json())
def test_json(self): json_value = {"from": "15.3.0", "to": "16.0.0"} version = LibraryVersion.from_json(json_value) self.assertEqual(version.from_version, Version(15, 3, 0)) self.assertEqual(version.to_version, Version(16, 0, 0)) self.assertEqual(json_value, version.to_json())
def from_json(json_value: dict) -> LibraryVersion: validate_json(instance=json_value, schema=LibraryVersion.json_schema) from_version = None to_version = None if "from" in json_value: from_version = Version.from_string(json_value["from"]) if "to" in json_value: to_version = Version.from_string(json_value["to"]) return LibraryVersion(from_version=from_version, to_version=to_version)
def test_dependencies(self): sdk_14 = Version.from_string("14.0.0") sdk_15 = Version.from_string("15.0.0") sdk_16 = Version.from_string("16.0.0") library_a = LibraryDescription( variant=LibraryVariant.OBJECT, library=Library(dependencies=Property(public={"b"})), sdk_version=LibraryVersion(sdk_15), patches=[ LibraryPatch( operation=LibraryOperation.ADD, sdk_version=LibraryVersion(sdk_15), library=Library(dependencies=Property(public={"c"}))), LibraryPatch( operation=LibraryOperation.REMOVE, sdk_version=LibraryVersion(sdk_16), library=Library(dependencies=Property(public={"c"}))), LibraryPatch( operation=LibraryOperation.ADD, sdk_version=LibraryVersion(sdk_16), library=Library(dependencies=Property(public={"d"}))), ]) library_b = LibraryDescription(variant=LibraryVariant.OBJECT, ) library_c = LibraryDescription(variant=LibraryVariant.OBJECT) library_d = LibraryDescription( variant=LibraryVariant.OBJECT, library=Library(dependencies=Property(public={"e"}))) library_e = LibraryDescription(variant=LibraryVariant.OBJECT) library_f = LibraryDescription(variant=LibraryVariant.OBJECT) all_libraries = { "a": library_a, "b": library_b, "c": library_c, "d": library_d, "e": library_e, "f": library_f } supported_sdks = [sdk_14, sdk_15, sdk_16] result = libraries_dependencies_per_sdk({"a": library_a}, all_libraries, supported_sdks) self.assertEqual(result[sdk_14], set()) self.assertEqual(result[sdk_15], {"a", "b", "c"}) self.assertEqual(result[sdk_16], {"a", "b", "d", "e"})
def test_applies_to(self): version_range = LibraryVersion(Version(15, 3, 0), Version(16, 0, 0)) self.assertTrue(version_range.applies_to(Version(15, 3, 0))) self.assertTrue(version_range.applies_to(Version(15, 4, 0))) self.assertTrue(version_range.applies_to(Version(15, 4, 9))) self.assertTrue(version_range.applies_to(Version(16, 0, 0))) self.assertFalse(version_range.applies_to(Version(15, 2, 0))) self.assertFalse(version_range.applies_to(Version(14, 3, 0))) self.assertFalse(version_range.applies_to(Version(16, 1, 0))) self.assertFalse(version_range.applies_to(Version(16, 0, 1)))
def test_json(self): json_value = { "variant": "object", "documentation": "This is a simple object library", "sources": ["s1", "s2"], "sdk_version": { "from": "15.3.0" }, "dependencies": { "private": ["prv_dep1"], "public": ["pub_dep1"] }, "includes": { "interface": ["inc1", "inc2"] }, "patches": [{ "operation": "add", "sdk_version": { "to": "16.0.0" }, "sources": ["s3", "s4"] }] } library = LibraryDescription.from_json(json_value) self.assertEqual(library.variant, LibraryVariant.OBJECT) self.assertEqual(library.documentation, "This is a simple object library") self.assertEqual(library.sdk_version, LibraryVersion(from_version=Version(15, 3, 0))) self.assertEqual(json_value, library.to_json())
def generate_library_test(library_name: str, library: LibraryDescription, libraries: Dict[str, LibraryDescription], supported_sdks: List[str]): # Collect all dependencies custom_patch: bool = False # Collect a list of dependencies for each SDK version. selected_libraries: Dict[str, LibraryDescription] = { library_name: library } custom_patches = { "nrf5_ble_lesc": {"nrf5_crypto_cc310_backend"}, "nrf5_fds": {"nrf5_fstorage_sd"}, "nrf5_ext_fatfs": {"nrf5_ext_fatfs_port_diskio_blkdev"}, "nrf5_ble_peer_data_storage": {"nrf5_ble_peer_manager"}, "nrf5_ble_peer_manager": {"nrf5_fstorage_sd"}, "nrf5_ble_srv_ots": {"nrf5_fstorage_sd"}, "nrf5_ble_srv_eddystone": {"nrf5_fstorage_sd"}, "nrf5_log_default_backends": { "nrf5_log_backend_uart", "nrf5_log_backend_serial" } } if library_name in custom_patches: custom_patch = True for library_patch_name in custom_patches[library_name]: selected_libraries[library_patch_name] = all_libraries[library_patch_name] sdk_dependencies: Dict[Version, Set[str]] = libraries_dependencies_per_sdk( selected_libraries, libraries, [Version.from_string(x) for x in supported_sdks] ) # Generate base dependencies. base_dependencies = set.intersection( *(x[1] for x in sdk_dependencies.items()) ) # Add SDK version sdk_version = None if library.sdk_version: sdk_version = library.sdk_version.to_json() # Return data used to create a library test. return { "name": library_name, "custom_patch": custom_patch, "sdk_version": sdk_version, "base": sorted(base_dependencies), "patches": { str(x[0]): sorted(set.difference(x[1], base_dependencies)) for x in sdk_dependencies.items() } }
def from_json(json_value: dict) -> Example: validate_json(instance=json_value, schema=Example.json_schema) example = Example( json_value["path"], json_value["local_path"], Version.from_string(json_value["sdk_version"]), ) for prop in ExampleProperty: if prop.value in json_value: example._props[prop] = set(json_value[prop.value]) else: example._props[prop] = set() return example
def test_json(self): json_value = { "path": "path", "local_path": "local_path", "sdk_version": "15.3.0", "sources": ["s1", "s2"], "ldflags": ["ld1", "ld2"] } example = Example.from_json(json_value) self.assertEqual(example.path, "path") self.assertEqual(example.local_path, "local_path") self.assertEqual(example.sdk_version, Version(15, 3, 0)) self.assertEqual(example.get_prop(ExampleProperty.SOURCES), {"s1", "s2"}) self.assertEqual(example.get_prop(ExampleProperty.LDFLAGS), {"ld1", "ld2"}) self.assertEqual(json_value, example.to_json())
# Parse arguments parser = argparse.ArgumentParser() parser.add_argument("--input", required=True) parser.add_argument("--supported_sdks", required=True, nargs="+") parser.add_argument("--output", required=True) parser.add_argument("--template", required=True) args = parser.parse_args() input_filepath: str = args.input output_filepath: str = args.output template_filepath: str = args.template supported_sdks: str = args.supported_sdks # Get list of supported SKDs for generation sdk_list = [Version.from_string(sdk) for sdk in supported_sdks] # Load libraries and process them. Result is a JSON file containing libraries. libraries = libraries_load_from_file(input_filepath) cmake_libraries = [ process_library_description(lib[0], lib[1], sdk_list) for lib in libraries.items() if is_library_description_ok(lib[1], sdk_list) ] # Check if there is a need to generate file. if len(cmake_libraries) == 0: print("Skipping " + input_filepath + "... No definitions.") exit(0) # Render with provided template with open(template_filepath, 'r') as template_file, open(output_filepath, 'w') as output_file:
def test_library_patches(self): lib_desc = LibraryDescription( variant=LibraryVariant.OBJECT, documentation="", sdk_version=LibraryVersion(Version(15, 0, 0), Version(16, 0, 0)), library=Library(sources={"s1", "s2"}), patches=[ LibraryPatch(LibraryOperation.ADD, LibraryVersion(Version(15, 1, 0)), Library({"s3"})), LibraryPatch( LibraryOperation.ADD, LibraryVersion(Version(15, 2, 0), Version(15, 3, 0)), Library({"s4"})), LibraryPatch( LibraryOperation.REMOVE, LibraryVersion(Version(15, 2, 1), Version(15, 4, 0)), Library({"s1"})) ]) self.assertEqual(lib_desc.library_for_sdk_version(Version(14, 0, 0)), None) self.assertEqual(lib_desc.library_for_sdk_version(Version(16, 1, 0)), None) self.assertSetEqual( lib_desc.library_for_sdk_version(Version(15, 0, 2)).sources, {'s1', 's2'}) self.assertSetEqual( lib_desc.library_for_sdk_version(Version(15, 1, 2)).sources, {'s1', 's2', 's3'}) self.assertSetEqual( lib_desc.library_for_sdk_version(Version(15, 2, 0)).sources, {'s1', 's2', 's3', 's4'}) self.assertSetEqual( lib_desc.library_for_sdk_version(Version(15, 2, 2)).sources, {'s2', 's3', 's4'}) self.assertSetEqual( lib_desc.library_for_sdk_version(Version(15, 4, 0)).sources, {'s2', 's3'}) self.assertSetEqual( lib_desc.library_for_sdk_version(Version(15, 4, 1)).sources, {'s1', 's2', 's3'})
def generate_library_test(library_name: str, library: LibraryDescription, libraries: Dict[str, LibraryDescription], supported_sdks: List[str]): # Collect all dependencies custom_patch: bool = False # Collect a list of dependencies for each SDK version. sdk_dependencies: Dict[str, Set[str]] = {} for sdk_version in supported_sdks: # Get list of all dependencies version = Version.from_string(sdk_version) library_for_sdk = library.library_for_sdk_version(version) if library_for_sdk == None: sdk_dependencies[sdk_version] = set() continue # Get all dependencies (merge interface & private) dependencies = library_for_sdk.get_prop( LibraryProperty.DEPENDENCIES).get_all_items() dependencies.add(library_name) # Custom patches to make tests buildable with optional deps. custom_patches = { "nrf5_ble_lesc": {"nrf5_crypto_cc310_backend"}, "nrf5_fds": {"nrf5_fstorage_sd"}, "nrf5_ble_peer_data_storage": {"nrf5_ble_peer_manager"}, "nrf5_ble_peer_manager": {"nrf5_fstorage_sd"}, "nrf5_log_default_backends": {"nrf5_log_backend_uart", "nrf5_log_backend_serial"} } if library_name in custom_patches: custom_patch = True dependencies.update(custom_patches[library_name]) # Iterate over all existing dependencies and collect new ones. # If expanded list of dependencies is bigger than original ones # continue. while True: new_dependencies = dependencies.copy() for dependency in dependencies: # Check if dependecy exists... if not dependency in all_libraries: print(f"WARNING: dependency {dependency} doesn't exist") continue library_dep_desc = all_libraries[dependency] # Check if dependency exists for this SDK version. library_dep = library_dep_desc.library_for_sdk_version(version) if library_dep == None: print( f"WARNING: dependency {dependency} should exist for SDK {version} inside {library_name}" ) continue # Get all dependencies and apply them. library_dep_dep_list = library_dep.get_prop( LibraryProperty.DEPENDENCIES).get_all_items() new_dependencies.update(library_dep_dep_list) # Check if two sets are the same if new_dependencies == dependencies: break # Use new extended list of dependencies. dependencies = new_dependencies # Add generated dependencies to version sdk_dependencies[sdk_version] = dependencies # Generate base dependencies. base_dependencies = set.intersection(*(x[1] for x in sdk_dependencies.items())) # Add SDK version sdk_version = None if library.sdk_version: sdk_version = library.sdk_version.to_json() # Return data used to create a library test. return { "name": library_name, "custom_patch": custom_patch, "sdk_version": sdk_version, "base": sorted(base_dependencies), "patches": { x[0]: sorted(set.difference(x[1], base_dependencies)) for x in sdk_dependencies.items() } }
def process_example(file_path: str, examples: List[Example]): with open(file_path, 'r') as file: content = file.read() # File data file_local_path = \ re.sub(r"\S+\/[0-9]+\.[0-9]\.[0-9]\/", "", file_path) file_sdk_version = \ re.findall(r"\/([0-9]+\.[0-9]\.[0-9])\/", file_path)[0] file_sources = set() file_includes = set() file_cflags = set() file_asmflags = set() file_ldflags = set() # Remove comments content = re.sub(r"#.*\n", "", content) # Find all sources (first regexp find SRC_FILES += .. \ .. \.. block, second extracts path) for sources in re.findall( r"SRC_FILES[ \t]*\+=(?:(?:[ \t]*\\[ \t]*\n)|(?:[ \t]*\S+[ \t]*(?:\\[ \t]*\n)?))+", content): sources = re.findall(r"\$\(SDK_ROOT\)\/(\S+)", sources) file_sources.update(sources) # Find all includes (first regexp find SRC_FILES += .. \ .. \.. block, second extracts path) for includes in re.findall( r"INC_FOLDERS[ \t]*\+=(?:(?:[ \t]*\\[ \t]*\n)|(?:[ \t]*\S+[ \t]*(?:\\[ \t]*\n)?))+", content): includes = re.findall(r"\$\(SDK_ROOT\)\/(\S+)", includes) file_includes.update(includes) # Find all c flags for cflags in re.findall( r"CFLAGS[ \t]*\+=(?:(?:[ \t]*\\[ \t]*\n)|(?:[ \t]*\S+[ \t]*(?:\\[ \t]*\n)?))+", content): cflags = re.findall(r"-\S+", cflags) for cflag in cflags: file_cflags.update(cflag.split(",")) # Find all asm flags for asmflags in re.findall( r"ASMFLAGS[ \t]*\+=(?:(?:[ \t]*\\[ \t]*\n)|(?:[ \t]*\S+[ \t]*(?:\\[ \t]*\n)?))+", content): asmflags = re.findall(r"-\S+", asmflags) for cflag in asmflags: file_asmflags.update(cflag.split(",")) # Find all ld flags for ldflags in re.findall( r"LDFLAGS[ \t]*\+=(?:(?:[ \t]*\\[ \t]*\n)|(?:[ \t]*\S+[ \t]*(?:\\[ \t]*\n)?))+", content): ldflags = re.findall(r"-\S+", ldflags) for cflag in ldflags: file_ldflags.update(cflag.split(",")) examples.append( Example(path=file_path, local_path=file_local_path, sdk_version=Version.from_string(file_sdk_version), sources=file_sources, includes=file_includes, cflags=file_cflags, asmflags=file_asmflags, ldflags=file_ldflags))