From 731c4e0e639723a96b965e0e8e715e6f8ba80524 Mon Sep 17 00:00:00 2001 From: Joey Vagedes Date: Tue, 22 Aug 2023 09:17:40 -0700 Subject: [PATCH] instanced_inf_table: include library class with library instances The LIBRARIES_USED column in the instanced_inf table only contained the the edk2 relative path to the library instance. This made it impossible to determine (with 100% accuracy) which library class the particular library instance was representing. This commit changes the "LIBRARIES_USED" column to contain a list of (lib_class, lib_instance) tuples rather than a list of lib_instances. --- Pipfile | 11 +++++++++ .../queries/unused_component_query.py | 2 +- .../database/tables/instanced_inf_table.py | 23 ++++++++++++++----- tests.unit/database/test_component_query.py | 2 +- .../database/test_instanced_inf_table.py | 10 ++++---- 5 files changed, 35 insertions(+), 13 deletions(-) create mode 100644 Pipfile diff --git a/Pipfile b/Pipfile new file mode 100644 index 000000000..0757494bb --- /dev/null +++ b/Pipfile @@ -0,0 +1,11 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] + +[dev-packages] + +[requires] +python_version = "3.11" diff --git a/edk2toollib/database/queries/unused_component_query.py b/edk2toollib/database/queries/unused_component_query.py index de9b1065c..d39494cb1 100644 --- a/edk2toollib/database/queries/unused_component_query.py +++ b/edk2toollib/database/queries/unused_component_query.py @@ -91,4 +91,4 @@ def _recurse_inf(self, inf, table, library_list): library_list.append(inf) for inf in result["LIBRARIES_USED"]: - self._recurse_inf(inf, table, library_list) + self._recurse_inf(inf[1], table, library_list) diff --git a/edk2toollib/database/tables/instanced_inf_table.py b/edk2toollib/database/tables/instanced_inf_table.py index 1e759969c..55a6ea227 100644 --- a/edk2toollib/database/tables/instanced_inf_table.py +++ b/edk2toollib/database/tables/instanced_inf_table.py @@ -124,7 +124,9 @@ def _parse_inf_recursively( logging.debug(f" Parsing Library: [{inf}]") visited.append(inf) - library_instances = [] + library_instance_list = [] + library_class_list = [] + # # 0. Use the existing parser to parse the INF file. This parser parses an INF as an independent file @@ -138,19 +140,28 @@ def _parse_inf_recursively( # for lib in infp.get_libraries(self.arch): lib = lib.split(" ")[0].lower() - library_instances.append(self._lib_to_instance(lib, scope, library_dict, override_dict)) + library_instance_list.append(self._lib_to_instance(lib, scope, library_dict, override_dict)) + library_class_list.append(lib) # Append all NULL library instances for null_lib in override_dict["NULL"]: - library_instances.append(null_lib) + library_instance_list.append(null_lib) + library_class_list.append("NULL") - library_instances = list(filter(lambda lib: lib is not None, library_instances)) + to_parse = list(filter(lambda lib: lib is not None, library_instance_list)) # Time to visit in libraries that we have not visited yet. to_return = [] - for library in filter(lambda lib: lib not in visited, library_instances): + for library in filter(lambda lib: lib not in visited, to_parse): to_return += self._parse_inf_recursively(library, component, library_dict, override_dict, scope, visited) + # Transform path to edk2 relative form (POSIX) + def to_posix(path): + if path is None: + return None + return Path(path).as_posix() + library_instance_list = list(map(to_posix, library_instance_list)) + # Return Paths as posix paths, which is Edk2 standard. to_return.append({ "DSC": Path(self.dsc).name, @@ -160,7 +171,7 @@ def _parse_inf_recursively( "MODULE_TYPE": infp.Dict["MODULE_TYPE"], "ARCH": scope.split(".")[0].upper(), "SOURCES_USED": list(map(lambda p: Path(p).as_posix(), infp.Sources)), - "LIBRARIES_USED": list(map(lambda p: Path(p).as_posix(), library_instances)), + "LIBRARIES_USED": list(zip(library_class_list, library_instance_list)), "PROTOCOLS_USED": [], # TODO "GUIDS_USED": [], # TODO "PPIS_USED": [], # TODO diff --git a/tests.unit/database/test_component_query.py b/tests.unit/database/test_component_query.py index 44bcfa45d..401b5cb31 100644 --- a/tests.unit/database/test_component_query.py +++ b/tests.unit/database/test_component_query.py @@ -71,7 +71,7 @@ def test_simple_component(empty_tree: Tree): result = db.search(ComponentQuery(component = "TestDriver1")) assert len(result) == 1 - assert sorted(result[0]['LIBRARIES_USED']) == sorted(['TestPkg/Library/TestLib2.inf', 'TestPkg/Library/TestLib3.inf']) + assert sorted(result[0]['LIBRARIES_USED']) == sorted([('testcls','TestPkg/Library/TestLib2.inf'), ('NULL','TestPkg/Library/TestLib3.inf')]) result = db.search(ComponentQuery(component = "NonExistantDriver")) assert len(result) == 0 diff --git a/tests.unit/database/test_instanced_inf_table.py b/tests.unit/database/test_instanced_inf_table.py index 4f486bc9a..f29c98db1 100644 --- a/tests.unit/database/test_instanced_inf_table.py +++ b/tests.unit/database/test_instanced_inf_table.py @@ -128,8 +128,8 @@ def test_library_override(empty_tree: Tree): # Ensure the Test Driver is using TestLib2 from the override and the NULL library was added for row in db.table("instanced_inf").all(): if (row["NAME"] == Path(comp1).stem - and Path(lib2).as_posix() in row["LIBRARIES_USED"] - and Path(lib3).as_posix() in row["LIBRARIES_USED"]): + and ("testcls", Path(lib2).as_posix()) in row["LIBRARIES_USED"] + and ("NULL", Path(lib3).as_posix()) in row["LIBRARIES_USED"]): break else: assert False @@ -172,7 +172,7 @@ def test_scoped_libraries1(empty_tree: Tree): # For each driver, verify that the the driver number (1, 2, 3) uses the corresponding lib number (1, 2, 3) for row in db.table("instanced_inf").all(): if "COMPONENT" not in row: # Only care about looking at drivers, which do not have a component - assert row["NAME"].replace("Driver", "Lib") in row["LIBRARIES_USED"][0] + assert row["NAME"].replace("Driver", "Lib") in row["LIBRARIES_USED"][0][1] def test_scoped_libraries2(empty_tree: Tree): """Ensure that the correct libraries in regards to scoping. @@ -207,7 +207,7 @@ def test_scoped_libraries2(empty_tree: Tree): for row in db.table("instanced_inf").all(): if "COMPONENT" not in row: - assert row["NAME"].replace("Driver", "Lib") in row["LIBRARIES_USED"][0] + assert row["NAME"].replace("Driver", "Lib") in row["LIBRARIES_USED"][0][1] def test_missing_library(empty_tree: Tree, caplog): """Test when a library is missing.""" @@ -294,4 +294,4 @@ def test_skip_library_with_unsupported_module_type(empty_tree: Tree): component_list = db.table("instanced_inf").search(~Query().COMPONENT.exists()) assert len(component_list) == 2 for component in component_list: - assert component["LIBRARIES_USED"][0] == Path(testlib2).as_posix() + assert component["LIBRARIES_USED"][0] == ("testcls", Path(testlib2).as_posix())