Add relative path support to test harness
authorCharles Giessen <charles@lunarg.com>
Thu, 25 Aug 2022 17:38:49 +0000 (11:38 -0600)
committerCharles Giessen <46324611+charles-lunarg@users.noreply.github.com>
Sat, 29 Jul 2023 04:44:07 +0000 (22:44 -0600)
Makes sure the loader test framework can create relative paths in
the library_path fields. Adds a test to insure those paths still
work.

Since the contents of "library_path" is mututally exclusive with
the existing use_dynamic_library_default_search_paths, a new enum
was added to allow tests to choose which of the three content
types a given ICD or Layer manifest should use.

tests/framework/test_environment.cpp
tests/framework/test_environment.h
tests/framework/test_util.cpp
tests/framework/test_util.h
tests/loader_regression_tests.cpp

index ee1451165344cf2a5740760ef0dd8d36b6764a0a..4c4287bc1e90fb3744d8f1423ea4fac84b746060 100644 (file)
@@ -467,20 +467,28 @@ TestICD& FrameworkEnvironment::add_icd(TestICDDetails icd_details) noexcept {
         auto new_driver_location = folder->copy_file(icd_details.icd_manifest.lib_path, new_driver_name.str());
 
 #if COMMON_UNIX_PLATFORMS
-        if (icd_details.use_dynamic_library_default_search_paths) {
+        if (icd_details.library_path_type == LibraryPathType::default_search_paths) {
             platform_shim->redirect_dlopen_name(new_driver_name, new_driver_location);
+        } else if (icd_details.library_path_type == LibraryPathType::relative) {
+            platform_shim->redirect_dlopen_name(fs::path(SYSCONFDIR) / "vulkan" / "icd.d" / "." / new_driver_name,
+                                                new_driver_location);
         }
 #endif
 #if defined(WIN32)
-        if (icd_details.use_dynamic_library_default_search_paths) {
+        if (icd_details.library_path_type == LibraryPathType::default_search_paths) {
             SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_USER_DIRS);
             AddDllDirectory(conver_str_to_wstr(new_driver_location.parent_path().str()).c_str());
         }
 #endif
         icds.push_back(TestICDHandle(new_driver_location));
         icds.back().reset_icd();
-        icd_details.icd_manifest.lib_path =
-            icd_details.use_dynamic_library_default_search_paths ? new_driver_name.str() : new_driver_location.str();
+        if (icd_details.library_path_type == LibraryPathType::relative) {
+            icd_details.icd_manifest.lib_path = fs::path(".") / new_driver_name;
+        } else if (icd_details.library_path_type == LibraryPathType::default_search_paths) {
+            icd_details.icd_manifest.lib_path = new_driver_name.str();
+        } else {
+            icd_details.icd_manifest.lib_path = new_driver_location.str();
+        }
     }
     if (icd_details.discovery_type != ManifestDiscoveryType::none) {
         std::string full_json_name = icd_details.json_name;
@@ -593,12 +601,16 @@ void FrameworkEnvironment::add_layer_impl(TestLayerDetails layer_details, Manife
             auto new_layer_location = folder.copy_file(layer.lib_path, layer_binary_name.str());
 
 #if COMMON_UNIX_PLATFORMS
-            if (layer_details.use_dynamic_library_default_search_paths) {
+            if (layer_details.library_path_type == LibraryPathType::default_search_paths) {
                 platform_shim->redirect_dlopen_name(layer_binary_name, new_layer_location);
             }
+            if (layer_details.library_path_type == LibraryPathType::relative) {
+                platform_shim->redirect_dlopen_name(
+                    fs::path(SYSCONFDIR) / "vulkan" / category_path_name(category) / "." / layer_binary_name, new_layer_location);
+            }
 #endif
 #if defined(WIN32)
-            if (layer_details.use_dynamic_library_default_search_paths) {
+            if (layer_details.library_path_type == LibraryPathType::default_search_paths) {
                 SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_USER_DIRS);
                 AddDllDirectory(conver_str_to_wstr(new_layer_location.parent_path().str()).c_str());
             }
@@ -611,7 +623,13 @@ void FrameworkEnvironment::add_layer_impl(TestLayerDetails layer_details, Manife
                 layers.push_back(TestLayerHandle(new_layer_location));
                 layers.back().reset_layer();
             }
-            layer.lib_path = layer_details.use_dynamic_library_default_search_paths ? layer_binary_name : new_layer_location;
+            if (layer_details.library_path_type == LibraryPathType::relative) {
+                layer.lib_path = fs::path(".") / layer_binary_name;
+            } else if (layer_details.library_path_type == LibraryPathType::default_search_paths) {
+                layer.lib_path = layer_binary_name;
+            } else {
+                layer.lib_path = new_layer_location;
+            }
         }
     }
     if (layer_details.discovery_type != ManifestDiscoveryType::none) {
index 42f19f987478d69351c58accf2684a6d9182683a..47c2697512c40d9b22ad7a560450c0c98b787d5c 100644 (file)
@@ -519,6 +519,12 @@ enum class ManifestDiscoveryType {
     macos_bundle,         // place it in a location only accessible to macos bundles
 };
 
+enum class LibraryPathType {
+    absolute,              // default for testing - the exact path of the binary
+    relative,              // Relative to the manifest file
+    default_search_paths,  // Dont add any path information to the library_path - force the use of the default search paths
+};
+
 struct TestICDDetails {
     TestICDDetails(ManifestICD icd_manifest) noexcept : icd_manifest(icd_manifest) {}
     TestICDDetails(fs::path icd_binary_path, uint32_t api_version = VK_API_VERSION_1_0) noexcept {
@@ -531,7 +537,7 @@ struct TestICDDetails {
     BUILDER_VALUE(TestICDDetails, ManifestDiscoveryType, discovery_type, ManifestDiscoveryType::generic);
     BUILDER_VALUE(TestICDDetails, bool, is_fake, false);
     // Dont add any path information to the library_path - force the use of the default search paths
-    BUILDER_VALUE(TestICDDetails, bool, use_dynamic_library_default_search_paths, false);
+    BUILDER_VALUE(TestICDDetails, LibraryPathType, library_path_type, LibraryPathType::absolute);
 };
 
 struct TestLayerDetails {
@@ -543,8 +549,7 @@ struct TestLayerDetails {
     BUILDER_VALUE(TestLayerDetails, bool, is_fake, false);
     // If discovery type is env-var, is_dir controls whether the env-var has the full name to the manifest or just the folder
     BUILDER_VALUE(TestLayerDetails, bool, is_dir, true);
-    // Dont add any path information to the library_path - force the use of the default search paths
-    BUILDER_VALUE(TestLayerDetails, bool, use_dynamic_library_default_search_paths, false);
+    BUILDER_VALUE(TestLayerDetails, LibraryPathType, library_path_type, LibraryPathType::absolute);
 };
 
 // Locations manifests can go in the test framework
index 381b9acf657598b62e39d0d8450106e25da139fe..6952a480d2f97bb950694f9f69d0728947acaf8b 100644 (file)
@@ -126,7 +126,7 @@ std::string ManifestICD::get_manifest_str() const {
     writer.StartObject();
     writer.AddKeyedString("file_format_version", file_format_version.get_version_str());
     writer.StartKeyedObject("ICD");
-    writer.AddKeyedString("library_path", fs::fixup_backslashes_in_path(lib_path));
+    writer.AddKeyedString("library_path", fs::fixup_backslashes_in_path(lib_path).str());
     writer.AddKeyedString("api_version", version_to_string(api_version));
     writer.AddKeyedBool("is_portability_driver", is_portability_driver);
     if (!library_arch.empty()) writer.AddKeyedString("library_arch", library_arch);
index 2cebfc68092bbe1d858c14c0cafccac06a21b24d..3c5ea2742664e8974df5d8b063a0d8d77b81123c 100644 (file)
@@ -216,11 +216,11 @@ struct path {
     path operator/(const char* in) const;
 
     // accessors
-    path parent_path() const;
-    bool has_parent_path() const;
-    path filename() const;
-    path extension() const;
-    path stem() const;
+    path parent_path() const;      // Everything before the last path separator, if there is one.
+    bool has_parent_path() const;  // True if the path contains more than just a filename.
+    path filename() const;         // Everything after the last path separator.
+    path extension() const;        // The file extension, if it has one.
+    path stem() const;             // The filename minus the extension.
 
     // modifiers
     path& replace_filename(path const& replacement);
@@ -595,7 +595,7 @@ struct ManifestVersion {
 struct ManifestICD {
     BUILDER_VALUE(ManifestICD, ManifestVersion, file_format_version, {})
     BUILDER_VALUE(ManifestICD, uint32_t, api_version, 0)
-    BUILDER_VALUE(ManifestICD, std::string, lib_path, {})
+    BUILDER_VALUE(ManifestICD, fs::path, lib_path, {})
     BUILDER_VALUE(ManifestICD, bool, is_portability_driver, false)
     BUILDER_VALUE(ManifestICD, std::string, library_arch, "")
     std::string get_manifest_str() const;
index 21d6c25c8fea4cb2215d66d52befd45b33e4d925..23e20135fec0d952de348a1a99e3fc498d1575d0 100644 (file)
@@ -93,7 +93,7 @@ TEST(CreateInstance, LayerNotPresent) {
 
 TEST(CreateInstance, LayerPresent) {
     FrameworkEnvironment env{};
-    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
+    env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2}).add_physical_device({});
 
     const char* layer_name = "TestLayer";
     env.add_explicit_layer(
@@ -106,6 +106,25 @@ TEST(CreateInstance, LayerPresent) {
     inst.CheckCreate();
 }
 
+TEST(CreateInstance, RelativePaths) {
+    FrameworkEnvironment env{};
+    env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2}.set_library_path_type(LibraryPathType::relative)).add_physical_device({});
+
+    const char* layer_name = "VK_LAYER_TestLayer";
+    env.add_explicit_layer(
+        TestLayerDetails{ManifestLayer{}.add_layer(
+                             ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
+                         "test_layer.json"}
+            .set_library_path_type(LibraryPathType::relative));
+
+    InstWrapper inst{env.vulkan_functions};
+    inst.create_info.add_layer(layer_name);
+    inst.CheckCreate();
+
+    auto layers = inst.GetActiveLayers(inst.GetPhysDev(), 1);
+    ASSERT_TRUE(string_eq(layers.at(0).layerName, layer_name));
+}
+
 TEST(CreateInstance, ConsecutiveCreate) {
     FrameworkEnvironment env{};
     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
@@ -3827,7 +3846,7 @@ TEST(LibraryLoading, SystemLocations) {
     EnvVarWrapper ld_library_path("LD_LIBRARY_PATH", env.get_folder(ManifestLocation::driver).location().str());
     ld_library_path.add_to_list(env.get_folder(ManifestLocation::explicit_layer).location().str());
 
-    auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2).set_use_dynamic_library_default_search_paths(true))
+    auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2).set_library_path_type(LibraryPathType::default_search_paths))
                        .add_physical_device({});
     const char* fake_ext_name = "VK_FAKE_extension";
     driver.physical_devices.back().add_extension(fake_ext_name);
@@ -3837,7 +3856,7 @@ TEST(LibraryLoading, SystemLocations) {
         TestLayerDetails{ManifestLayer{}.add_layer(
                              ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
                          "test_layer.json"}
-            .set_use_dynamic_library_default_search_paths(true));
+            .set_library_path_type(LibraryPathType::default_search_paths));
 
     auto props = env.GetLayerProperties(1);
     ASSERT_TRUE(string_eq(props.at(0).layerName, layer_name));