Make tests get files in a consistent order
authorCharles Giessen <charles@lunarg.com>
Tue, 28 Jun 2022 23:46:39 +0000 (17:46 -0600)
committerCharles Giessen <46324611+charles-lunarg@users.noreply.github.com>
Fri, 1 Jul 2022 19:36:27 +0000 (13:36 -0600)
Use the order defined the FolderManager's to define the order readdir
uses, rather than leaving it undetermined. This makes tests more consistent
by forcing layers and drivers to always be found in the same order on all
systems.

Note: MacOS doesn't currently have consistent ordering due to a crash with
ASAN. But even if ASAN isn't running, the dirent structure is being filled
out incorrectly, causing further test failures. While not ideal to disable
consistent ordering on MacOS, it is needed for linux and thus the issue
isn't high enough priority to resolve.

tests/framework/shim/shim.h
tests/framework/shim/shim_common.cpp
tests/framework/shim/unix_shim.cpp
tests/framework/shim/windows_shim.cpp
tests/framework/test_environment.cpp
tests/framework/test_environment.h
tests/framework/test_util.cpp
tests/framework/test_util.h
tests/loader_envvar_tests.cpp
tests/loader_layer_tests.cpp

index 80e6470898deb1a620ee8a80b2a060c78c04155a..bb0ad9a30b8e70f3c00f665e754c6ef4dbade6ac 100644 (file)
@@ -109,10 +109,28 @@ struct D3DKMT_Adapter {
     D3DKMT_Adapter& add_path(fs::path src, std::vector<std::wstring>& dest);
 };
 
+#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
+
+struct DirEntry {
+    DIR* directory;
+    std::string folder_path;
+    std::vector<struct dirent*> contents;
+    size_t current_index;
+};
+
 #endif
+
+struct FrameworkEnvironment;  // forward declaration
+
 // Necessary to have inline definitions as shim is a dll and thus functions
 // defined in the .cpp wont be found by the rest of the application
 struct PlatformShim {
+    PlatformShim() = default;
+    PlatformShim(std::vector<fs::FolderManager>* folders) : folders(folders) {}
+
+    // Used to get info about which drivers & layers have been added to folders
+    std::vector<fs::FolderManager>* folders;
+
     // Test Framework interface
     void reset();
 
@@ -170,20 +188,24 @@ struct PlatformShim {
 
     void set_elevated_privilege(bool elev) { use_fake_elevation = elev; }
     bool use_fake_elevation = false;
+
+    std::vector<DirEntry> dir_entries;
 #endif
 };
 
 std::vector<std::string> parse_env_var_list(std::string const& var);
 std::string category_path_name(ManifestCategory category);
 
+std::vector<std::string> get_folder_contents(std::vector<fs::FolderManager>* folders, std::string folder_name) noexcept;
+
 extern "C" {
 // dynamically link on windows and macos
 #if defined(WIN32) || defined(__APPLE__)
-using PFN_get_platform_shim = PlatformShim* (*)();
+using PFN_get_platform_shim = PlatformShim* (*)(std::vector<fs::FolderManager>* folders);
 #define GET_PLATFORM_SHIM_STR "get_platform_shim"
 
 #elif defined(__linux__) || defined(__FreeBSD__)
 // statically link on linux
-PlatformShim* get_platform_shim();
+PlatformShim* get_platform_shim(std::vector<fs::FolderManager>* folders);
 #endif
 }
index 1cf2ec76647c92f51804b2c7affe096f0140c197..721aabef5a3e420555848b4785554c5a46ca2c7f 100644 (file)
@@ -60,6 +60,15 @@ std::vector<std::string> parse_env_var_list(std::string const& var) {
     return items;
 }
 
+std::vector<std::string> get_folder_contents(std::vector<fs::FolderManager>* folders, std::string folder_name) noexcept {
+    for (auto& folder : *folders) {
+        if (folder.location() == folder_name) {
+            return folder.get_files();
+        }
+    }
+    return {};
+}
+
 #if defined(WIN32)
 
 D3DKMT_Adapter& D3DKMT_Adapter::add_driver_manifest_path(fs::path const& src) { return add_path(src, driver_paths); }
@@ -200,4 +209,4 @@ void PlatformShim::set_path(ManifestCategory category, fs::path const& path) {
     redirect_path(fs::path(SYSCONFDIR) / "vulkan" / category_path_name(category), path);
 }
 
-#endif
\ No newline at end of file
+#endif
index cf8453edb7721288f7b1508bafe5cd04644e3098..1fdadbcfbe9c37c3560c69f2c2e44b8fd0f0f186 100644 (file)
 static PlatformShim platform_shim;
 extern "C" {
 #if defined(__linux__) || defined(__FreeBSD__)
-PlatformShim* get_platform_shim() {
-    platform_shim = PlatformShim();
+PlatformShim* get_platform_shim(std::vector<fs::FolderManager>* folders) {
+    platform_shim = PlatformShim(folders);
     return &platform_shim;
 }
 #elif defined(__APPLE__)
-FRAMEWORK_EXPORT PlatformShim* get_platform_shim() {
-    platform_shim = PlatformShim();
+FRAMEWORK_EXPORT PlatformShim* get_platform_shim(std::vector<fs::FolderManager>* folders) {
+    platform_shim = PlatformShim(folders);
     return &platform_shim;
 }
 #endif
 
-// Necessary for MacOS function himming
+// Necessary for MacOS function shimming
 #if defined(__linux__) || defined(__FreeBSD__)
 #define OPENDIR_FUNC_NAME opendir
+#define READDIR_FUNC_NAME readdir
+#define CLOSEDIR_FUNC_NAME closedir
 #define ACCESS_FUNC_NAME access
 #define FOPEN_FUNC_NAME fopen
 #define GETEUID_FUNC_NAME geteuid
@@ -56,6 +58,8 @@ FRAMEWORK_EXPORT PlatformShim* get_platform_shim() {
 #endif
 #elif defined(__APPLE__)
 #define OPENDIR_FUNC_NAME my_opendir
+#define READDIR_FUNC_NAME my_readdir
+#define CLOSEDIR_FUNC_NAME my_closedir
 #define ACCESS_FUNC_NAME my_access
 #define FOPEN_FUNC_NAME my_fopen
 #define GETEUID_FUNC_NAME my_geteuid
@@ -69,6 +73,8 @@ FRAMEWORK_EXPORT PlatformShim* get_platform_shim() {
 #endif
 
 using PFN_OPENDIR = DIR* (*)(const char* path_name);
+using PFN_READDIR = struct dirent* (*)(DIR* dir_stream);
+using PFN_CLOSEDIR = int (*)(DIR* dir_stream);
 using PFN_ACCESS = int (*)(const char* pathname, int mode);
 using PFN_FOPEN = FILE* (*)(const char* filename, const char* mode);
 using PFN_GETEUID = uid_t (*)(void);
@@ -78,6 +84,8 @@ using PFN_SEC_GETENV = char* (*)(const char* name);
 #endif
 
 static PFN_OPENDIR real_opendir = nullptr;
+static PFN_READDIR real_readdir = nullptr;
+static PFN_CLOSEDIR real_closedir = nullptr;
 static PFN_ACCESS real_access = nullptr;
 static PFN_FOPEN real_fopen = nullptr;
 static PFN_GETEUID real_geteuid = nullptr;
@@ -96,6 +104,7 @@ FRAMEWORK_EXPORT DIR* OPENDIR_FUNC_NAME(const char* path_name) {
     if (platform_shim.is_fake_path(path_name)) {
         auto fake_path_name = platform_shim.get_fake_path(fs::path(path_name));
         dir = real_opendir(fake_path_name.c_str());
+        platform_shim.dir_entries.push_back(DirEntry{dir, std::string(path_name), {}, false});
     } else {
         dir = real_opendir(path_name);
     }
@@ -103,6 +112,57 @@ FRAMEWORK_EXPORT DIR* OPENDIR_FUNC_NAME(const char* path_name) {
     return dir;
 }
 
+FRAMEWORK_EXPORT struct dirent* READDIR_FUNC_NAME(DIR* dir_stream) {
+    if (!real_readdir) real_readdir = (PFN_READDIR)dlsym(RTLD_NEXT, "readdir");
+    auto it = std::find_if(platform_shim.dir_entries.begin(), platform_shim.dir_entries.end(),
+                           [dir_stream](DirEntry const& entry) { return entry.directory == dir_stream; });
+
+    if (it == platform_shim.dir_entries.end()) {
+        return real_readdir(dir_stream);
+    }
+    // Folder was found but this is the first file to be read from it
+    if (it->current_index == 0) {
+        std::vector<struct dirent*> folder_contents;
+        std::vector<std::string> dirent_filenames;
+        while (true) {
+            struct dirent* dir_entry = real_readdir(dir_stream);
+            if (NULL == dir_entry) {
+                break;
+            }
+            folder_contents.push_back(dir_entry);
+            dirent_filenames.push_back(&dir_entry->d_name[0]);
+        }
+        auto real_path = platform_shim.redirection_map.at(it->folder_path);
+        auto filenames = get_folder_contents(platform_shim.folders, real_path.str());
+
+        // Add the dirent structures in the order they appear in the FolderManager
+        // Ignore anything which wasn't in the FolderManager
+        for (auto const& file : filenames) {
+            for (size_t i = 0; i < dirent_filenames.size(); i++) {
+                if (file == dirent_filenames.at(i)) {
+                    it->contents.push_back(folder_contents.at(i));
+                    break;
+                }
+            }
+        }
+    }
+    if (it->current_index >= it->contents.size()) return nullptr;
+    return it->contents.at(it->current_index++);
+}
+
+FRAMEWORK_EXPORT int CLOSEDIR_FUNC_NAME(DIR* dir_stream) {
+    if (!real_closedir) real_closedir = (PFN_CLOSEDIR)dlsym(RTLD_NEXT, "closedir");
+
+    auto it = std::find_if(platform_shim.dir_entries.begin(), platform_shim.dir_entries.end(),
+                           [dir_stream](DirEntry const& entry) { return entry.directory == dir_stream; });
+
+    if (it != platform_shim.dir_entries.end()) {
+        platform_shim.dir_entries.erase(it);
+    }
+
+    return real_closedir(dir_stream);
+}
+
 FRAMEWORK_EXPORT int ACCESS_FUNC_NAME(const char* in_pathname, int mode) {
     if (!real_access) real_access = (PFN_ACCESS)dlsym(RTLD_NEXT, "access");
 
@@ -197,6 +257,9 @@ struct Interposer {
 };
 
 __attribute__((used)) static Interposer _interpose_opendir MACOS_ATTRIB = {VOIDP_CAST(my_opendir), VOIDP_CAST(opendir)};
+// don't intercept readdir as it crashes when using ASAN with macOS
+// __attribute__((used)) static Interposer _interpose_readdir MACOS_ATTRIB = {VOIDP_CAST(my_readdir), VOIDP_CAST(readdir)};
+__attribute__((used)) static Interposer _interpose_closedir MACOS_ATTRIB = {VOIDP_CAST(my_closedir), VOIDP_CAST(closedir)};
 __attribute__((used)) static Interposer _interpose_access MACOS_ATTRIB = {VOIDP_CAST(my_access), VOIDP_CAST(access)};
 __attribute__((used)) static Interposer _interpose_fopen MACOS_ATTRIB = {VOIDP_CAST(my_fopen), VOIDP_CAST(fopen)};
 __attribute__((used)) static Interposer _interpose_euid MACOS_ATTRIB = {VOIDP_CAST(my_geteuid), VOIDP_CAST(geteuid)};
index 87edf0de49eba1133ff7f401a20f5a7d3ab809cc..15117606e77e0ad8fa5e80234b17b658d22eecbb 100644 (file)
@@ -224,7 +224,7 @@ HRESULT __stdcall ShimEnumAdapters1_1(IDXGIFactory1 *This,
         return DXGI_ERROR_INVALID_CALL;
     }
     if (ppAdapter != nullptr) {
-        autopAdapter = create_IDXGIAdapter1();
+        auto *pAdapter = create_IDXGIAdapter1();
         *ppAdapter = pAdapter;
         platform_shim.dxgi_adapter_map[pAdapter] = Adapter;
     }
@@ -239,7 +239,7 @@ HRESULT __stdcall ShimEnumAdapters1_6(IDXGIFactory6 *This,
         return DXGI_ERROR_INVALID_CALL;
     }
     if (ppAdapter != nullptr) {
-        autopAdapter = create_IDXGIAdapter1();
+        auto *pAdapter = create_IDXGIAdapter1();
         *ppAdapter = pAdapter;
         platform_shim.dxgi_adapter_map[pAdapter] = Adapter;
     }
@@ -256,7 +256,7 @@ HRESULT __stdcall ShimEnumAdapterByGpuPreference(IDXGIFactory6 *This, _In_ UINT
     assert(GpuPreference == DXGI_GPU_PREFERENCE::DXGI_GPU_PREFERENCE_UNSPECIFIED &&
            "Test shim assumes the GpuPreference is unspecified.");
     if (ppvAdapter != nullptr) {
-        autopAdapter = create_IDXGIAdapter1();
+        auto *pAdapter = create_IDXGIAdapter1();
         *ppvAdapter = pAdapter;
         platform_shim.dxgi_adapter_map[pAdapter] = Adapter;
     }
@@ -351,10 +351,12 @@ LSTATUS __stdcall ShimRegEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpValueName,
                                     LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) {
     const std::string *path = get_path_of_created_key(hKey);
     if (path == nullptr) return ERROR_NO_MORE_ITEMS;
+
     const auto *location_ptr = get_registry_vector(*path);
     if (location_ptr == nullptr) return ERROR_NO_MORE_ITEMS;
     const auto &location = *location_ptr;
     if (dwIndex >= location.size()) return ERROR_NO_MORE_ITEMS;
+
     if (*lpcchValueName < location[dwIndex].name.size()) return ERROR_NO_MORE_ITEMS;
     for (size_t i = 0; i < location[dwIndex].name.size(); i++) {
         lpValueName[i] = location[dwIndex].name[i];
@@ -466,8 +468,8 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) {
     }
     return TRUE;
 }
-FRAMEWORK_EXPORT PlatformShim *get_platform_shim() {
-    platform_shim = PlatformShim();
+FRAMEWORK_EXPORT PlatformShim *get_platform_shim(std::vector<fs::FolderManager> *folders) {
+    platform_shim = PlatformShim(folders);
     return &platform_shim;
 }
-}
\ No newline at end of file
+}
index 9bb65e6fef4d912956860a8c0865581b8f67ebe2..92c88bb8fb98463bc28fcb9a47dd15799f26fcd8 100644 (file)
@@ -136,14 +136,14 @@ void FillDebugUtilsCreateDetails(InstanceCreateInfo& create_info, DebugUtilsWrap
     create_info.instance_info.pNext = wrapper.get();
 }
 
-PlatformShimWrapper::PlatformShimWrapper() noexcept {
+PlatformShimWrapper::PlatformShimWrapper(std::vector<fs::FolderManager>* folders) noexcept {
 #if defined(WIN32) || defined(__APPLE__)
     shim_library = LibraryWrapper(SHIM_LIBRARY_NAME);
     PFN_get_platform_shim get_platform_shim_func = shim_library.get_symbol(GET_PLATFORM_SHIM_STR);
     assert(get_platform_shim_func != NULL && "Must be able to get \"platform_shim\"");
-    platform_shim = get_platform_shim_func();
+    platform_shim = get_platform_shim_func(folders);
 #elif defined(__linux__) || defined(__FreeBSD__)
-    platform_shim = get_platform_shim();
+    platform_shim = get_platform_shim(folders);
 #endif
     platform_shim->reset();
 
@@ -184,29 +184,29 @@ TestLayer& TestLayerHandle::reset_layer() noexcept {
 fs::path TestLayerHandle::get_layer_full_path() noexcept { return layer_library.lib_path; }
 fs::path TestLayerHandle::get_layer_manifest_path() noexcept { return manifest_path; }
 
-FrameworkEnvironment::FrameworkEnvironment() noexcept
-    : platform_shim(),
-      null_folder(FRAMEWORK_BUILD_DIRECTORY, "null_dir"),
-      icd_folder(FRAMEWORK_BUILD_DIRECTORY, "icd_manifests"),
-      icd_env_vars_folder(FRAMEWORK_BUILD_DIRECTORY, "icd_env_vars_manifests"),
-      explicit_layer_folder(FRAMEWORK_BUILD_DIRECTORY, "explicit_layer_manifests"),
-      explicit_env_var_layer_folder(FRAMEWORK_BUILD_DIRECTORY, "explicit_env_var_layer_folder"),
-      explicit_add_env_var_layer_folder(FRAMEWORK_BUILD_DIRECTORY, "explicit_add_env_var_layer_folder"),
-      implicit_layer_folder(FRAMEWORK_BUILD_DIRECTORY, "implicit_layer_manifests"),
-      override_layer_folder(FRAMEWORK_BUILD_DIRECTORY, "override_layer_manifests"),
-      vulkan_functions() {
-    platform_shim->redirect_all_paths(null_folder.location());
-    platform_shim->set_path(ManifestCategory::icd, icd_folder.location());
-    platform_shim->set_path(ManifestCategory::explicit_layer, explicit_layer_folder.location());
-    platform_shim->set_path(ManifestCategory::implicit_layer, implicit_layer_folder.location());
+FrameworkEnvironment::FrameworkEnvironment() noexcept : platform_shim(&folders), vulkan_functions() {
+    // This order is important, it matches the enum ManifestLocation, used to index the folders vector
+    folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("null_dir"));
+    folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("icd_manifests"));
+    folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("icd_env_vars_manifests"));
+    folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("explicit_layer_manifests"));
+    folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("explicit_env_var_layer_folder"));
+    folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("explicit_add_env_var_layer_folder"));
+    folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("implicit_layer_manifests"));
+    folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("override_layer_manifests"));
+
+    platform_shim->redirect_all_paths(get_folder(ManifestLocation::null).location());
+    platform_shim->set_path(ManifestCategory::icd, get_folder(ManifestLocation::driver).location());
+    platform_shim->set_path(ManifestCategory::explicit_layer, get_folder(ManifestLocation::explicit_layer).location());
+    platform_shim->set_path(ManifestCategory::implicit_layer, get_folder(ManifestLocation::implicit_layer).location());
 }
 
 void FrameworkEnvironment::add_icd(TestICDDetails icd_details) noexcept {
     size_t cur_icd_index = icds.size();
-    fs::FolderManager* folder = &icd_folder;
+    fs::FolderManager* folder = &get_folder(ManifestLocation::driver);
     if (icd_details.discovery_type == ManifestDiscoveryType::env_var ||
         icd_details.discovery_type == ManifestDiscoveryType::add_env_var) {
-        folder = &icd_env_vars_folder;
+        folder = &get_folder(ManifestLocation::driver_env_var);
     }
     if (!icd_details.is_fake) {
         fs::path new_driver_name = fs::path(icd_details.icd_manifest.lib_path).stem() + "_" + std::to_string(cur_icd_index) +
@@ -265,30 +265,30 @@ void FrameworkEnvironment::add_explicit_layer(TestLayerDetails layer_details) no
 }
 
 void FrameworkEnvironment::add_layer_impl(TestLayerDetails layer_details, ManifestCategory category) {
-    fs::FolderManager* fs_ptr = &explicit_layer_folder;
+    fs::FolderManager* fs_ptr = &get_folder(ManifestLocation::explicit_layer);
     switch (layer_details.discovery_type) {
         default:
         case (ManifestDiscoveryType::generic):
-            if (category == ManifestCategory::implicit_layer) fs_ptr = &implicit_layer_folder;
+            if (category == ManifestCategory::implicit_layer) fs_ptr = &get_folder(ManifestLocation::implicit_layer);
             break;
         case (ManifestDiscoveryType::env_var):
-            fs_ptr = &explicit_env_var_layer_folder;
+            fs_ptr = &get_folder(ManifestLocation::explicit_layer_env_var);
             if (!env_var_vk_layer_paths.empty()) {
                 env_var_vk_layer_paths += OS_ENV_VAR_LIST_SEPARATOR;
             }
-            env_var_vk_layer_paths += explicit_env_var_layer_folder.location().str();
+            env_var_vk_layer_paths += fs_ptr->location().str();
             set_env_var("VK_LAYER_PATH", env_var_vk_layer_paths);
             break;
         case (ManifestDiscoveryType::add_env_var):
-            fs_ptr = &explicit_add_env_var_layer_folder;
+            fs_ptr = &get_folder(ManifestLocation::explicit_layer_add_env_var);
             if (!add_env_var_vk_layer_paths.empty()) {
                 add_env_var_vk_layer_paths += OS_ENV_VAR_LIST_SEPARATOR;
             }
-            add_env_var_vk_layer_paths += explicit_add_env_var_layer_folder.location().str();
+            add_env_var_vk_layer_paths += fs_ptr->location().str();
             set_env_var("VK_ADD_LAYER_PATH", add_env_var_vk_layer_paths);
             break;
         case (ManifestDiscoveryType::override_folder):
-            fs_ptr = &override_layer_folder;
+            fs_ptr = &get_folder(ManifestLocation::override_layer);
             break;
         case (ManifestDiscoveryType::none):
             break;
@@ -331,6 +331,10 @@ TestLayer& FrameworkEnvironment::reset_layer(size_t index) noexcept { return lay
 fs::path FrameworkEnvironment::get_test_layer_path(size_t index) noexcept { return layers[index].get_layer_full_path(); }
 fs::path FrameworkEnvironment::get_layer_manifest_path(size_t index) noexcept { return layers[index].get_layer_manifest_path(); }
 
+fs::FolderManager& FrameworkEnvironment::get_folder(ManifestLocation location) noexcept {
+    // index it directly using the enum location since they will always be in that order
+    return folders.at(static_cast<size_t>(location));
+}
 void setup_WSI_in_ICD(TestICD& icd) {
     icd.enable_icd_wsi = true;
 #ifdef VK_USE_PLATFORM_ANDROID_KHR
@@ -494,4 +498,4 @@ VkSurfaceKHR create_surface(InstWrapper& inst, const char* api_selection) {
 #endif
 
     return surface;
-}
\ No newline at end of file
+}
index fe2bba3ecbfcc95e69c56ccd7440bcf534dc7390..4d33c28df7524f77f515179b7bcbd8c749d54180 100644 (file)
@@ -258,8 +258,10 @@ VkResult CreateDebugUtilsMessenger(DebugUtilsWrapper& debug_utils);
 void FillDebugUtilsCreateDetails(InstanceCreateInfo& create_info, DebugUtilsLogger& logger);
 void FillDebugUtilsCreateDetails(InstanceCreateInfo& create_info, DebugUtilsWrapper& wrapper);
 
+struct FrameworkEnvironment;  // forward declaration
+
 struct PlatformShimWrapper {
-    PlatformShimWrapper() noexcept;
+    PlatformShimWrapper(std::vector<fs::FolderManager>* folders) noexcept;
     ~PlatformShimWrapper() noexcept;
     PlatformShimWrapper(PlatformShimWrapper const&) = delete;
     PlatformShimWrapper& operator=(PlatformShimWrapper const&) = delete;
@@ -328,6 +330,17 @@ struct TestLayerDetails {
     BUILDER_VALUE(TestLayerDetails, bool, is_fake, false);
 };
 
+enum class ManifestLocation {
+    null = 0,
+    driver = 1,
+    driver_env_var = 2,
+    explicit_layer = 3,
+    explicit_layer_env_var = 4,
+    explicit_layer_add_env_var = 5,
+    implicit_layer = 6,
+    override_layer = 7
+};
+
 struct FrameworkEnvironment {
     FrameworkEnvironment() noexcept;
 
@@ -349,15 +362,10 @@ struct FrameworkEnvironment {
     fs::path get_test_layer_path(size_t index = 0) noexcept;
     fs::path get_layer_manifest_path(size_t index = 0) noexcept;
 
+    fs::FolderManager& get_folder(ManifestLocation location) noexcept;
+
     PlatformShimWrapper platform_shim;
-    fs::FolderManager null_folder;
-    fs::FolderManager icd_folder;
-    fs::FolderManager icd_env_vars_folder;
-    fs::FolderManager explicit_layer_folder;
-    fs::FolderManager explicit_env_var_layer_folder;
-    fs::FolderManager explicit_add_env_var_layer_folder;
-    fs::FolderManager implicit_layer_folder;
-    fs::FolderManager override_layer_folder;
+    std::vector<fs::FolderManager> folders;
 
     DebugUtilsLogger debug_log;
     VulkanFunctions vulkan_functions;
@@ -381,4 +389,4 @@ void setup_WSI_in_ICD(TestICD& icd);
 void setup_WSI_in_create_instance(InstWrapper& inst);
 // api_selection: optionally provide a VK_USE_PLATFORM_XXX string to select which API to create a surface with
 // Note: MUST provide api_selection on platforms with multiple viable API's, such as linux and MacOS
-VkSurfaceKHR create_surface(InstWrapper& inst, const char* api_selection = nullptr);
\ No newline at end of file
+VkSurfaceKHR create_surface(InstWrapper& inst, const char* api_selection = nullptr);
index 1c27c08698dd4b094ad8f5003d01268be72fd58f..e77b2c375ffc2eb1855fb3fddce8fecaad14b6a7 100644 (file)
@@ -429,11 +429,12 @@ std::wstring native_path(const std::string& utf8) { return widen(utf8); }
 const std::string& native_path(const std::string& utf8) { return utf8; }
 #endif
 
-FolderManager::FolderManager(path root_path, std::string name) : folder(root_path / name) {
+FolderManager::FolderManager(path root_path, std::string name) noexcept : folder(root_path / name) {
     delete_folder_contents(folder);
     create_folder(folder);
 }
-FolderManager::~FolderManager() {
+FolderManager::~FolderManager() noexcept {
+    if (folder.str().empty()) return;
     auto list_of_files_to_delete = files;
     // remove(file) modifies the files variable, copy the list before deleting it
     // Note: the allocation tests currently leak the loaded driver handles because in an OOM scenario the loader doesn't bother
@@ -444,6 +445,16 @@ FolderManager::~FolderManager() {
     }
     delete_folder(folder);
 }
+FolderManager::FolderManager(FolderManager&& other) noexcept : folder(other.folder), files(other.files) {
+    other.folder.str().clear();
+}
+FolderManager& FolderManager::operator=(FolderManager&& other) noexcept {
+    folder = other.folder;
+    files = other.files;
+    other.folder.str().clear();
+    return *this;
+}
+
 path FolderManager::write_manifest(std::string const& name, std::string const& contents) {
     path out_path = folder / name;
     auto found = std::find(files.begin(), files.end(), name);
index d6fe16367c7922b54c44ed879a108a1ed7e6accc..f3ee26b23e924ef02be5c1a99b8643c535777634 100644 (file)
@@ -203,10 +203,12 @@ int delete_folder(path const& folder);
 
 class FolderManager {
    public:
-    explicit FolderManager(path root_path, std::string name);
-    ~FolderManager();
+    explicit FolderManager(path root_path, std::string name) noexcept;
+    ~FolderManager() noexcept;
     FolderManager(FolderManager const&) = delete;
     FolderManager& operator=(FolderManager const&) = delete;
+    FolderManager(FolderManager&& other) noexcept;
+    FolderManager& operator=(FolderManager&& other) noexcept;
 
     path write_manifest(std::string const& name, std::string const& contents);
 
@@ -219,6 +221,8 @@ class FolderManager {
     // location of the managed folder
     path location() const { return folder; }
 
+    std::vector<std::string> get_files() const { return files; }
+
    private:
     path folder;
     std::vector<std::string> files;
index fb36aa32b30286140dbdd3232389194e7086d072..b7d7534f3a57cc7fa110947c11f918de7829a8d1 100644 (file)
@@ -261,7 +261,7 @@ TEST(EnvVarICDOverrideSetup, TestOnlyLayerEnvVar) {
     FrameworkEnvironment env{};
     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
     env.get_test_icd().physical_devices.push_back({});
-    env.platform_shim->redirect_path("/tmp/carol", env.explicit_env_var_layer_folder.location());
+    env.platform_shim->redirect_path("/tmp/carol", env.get_folder(ManifestLocation::explicit_layer_env_var).location());
 
     const char* layer_name = "TestLayer";
     env.add_explicit_layer(
@@ -310,7 +310,7 @@ TEST(EnvVarICDOverrideSetup, TestOnlyAddLayerEnvVar) {
     FrameworkEnvironment env{};
     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
     env.get_test_icd().physical_devices.push_back({});
-    env.platform_shim->redirect_path("/tmp/carol", env.explicit_add_env_var_layer_folder.location());
+    env.platform_shim->redirect_path("/tmp/carol", env.get_folder(ManifestLocation::explicit_layer_add_env_var).location());
 
     const char* layer_name = "TestLayer";
     env.add_explicit_layer(
index be5e18b6d33d48727228fd861cb169f60c11adae..de2a7f5f5d86b9a1f7a5144907191be310aa79c9 100644 (file)
@@ -1046,15 +1046,16 @@ TEST(OverrideMetaLayer, OverridePathsInteractionWithVK_LAYER_PATH) {
                                             "regular_test_layer.json"}
                                .set_discovery_type(ManifestDiscoveryType::override_folder));
 
-    env.add_implicit_layer(ManifestLayer{}
-                               .set_file_format_version(ManifestVersion(1, 2, 0))
-                               .add_layer(ManifestLayer::LayerDescription{}
-                                              .set_name(lunarg_meta_layer_name)
-                                              .set_api_version(VK_MAKE_API_VERSION(0, 1, 1, 0))
-                                              .add_component_layer(regular_layer_name)
-                                              .set_disable_environment("DisableMeIfYouCan")
-                                              .add_override_path(env.override_layer_folder.location().str())),
-                           "meta_test_layer.json");
+    env.add_implicit_layer(
+        ManifestLayer{}
+            .set_file_format_version(ManifestVersion(1, 2, 0))
+            .add_layer(ManifestLayer::LayerDescription{}
+                           .set_name(lunarg_meta_layer_name)
+                           .set_api_version(VK_MAKE_API_VERSION(0, 1, 1, 0))
+                           .add_component_layer(regular_layer_name)
+                           .set_disable_environment("DisableMeIfYouCan")
+                           .add_override_path(env.get_folder(ManifestLocation::override_layer).location().str())),
+        "meta_test_layer.json");
 
     InstWrapper inst{env.vulkan_functions};
     inst.create_info.set_api_version(1, 1, 0);