From 669c41d69f037dac427a70cb5dae9fe503fc4538 Mon Sep 17 00:00:00 2001 From: Charles Giessen Date: Wed, 25 Aug 2021 16:41:59 -0600 Subject: [PATCH] test: Add DebugUtilsWrapper This wrapper allows easy reading of the log output through the debug utils messenger infrastructure. Since getting the stdout/stderr is not well supported by googletest, this allows tests to be written which check for specific log messages to be emitted, allowing another way to verify the loader is behaving as expected. --- tests/framework/framework_config.h.in | 4 +- tests/framework/test_util.cpp | 18 +++++- tests/framework/test_util.h | 79 ++++++++++++++++++++++++++- 3 files changed, 96 insertions(+), 5 deletions(-) diff --git a/tests/framework/framework_config.h.in b/tests/framework/framework_config.h.in index 87e695aa..06d2260f 100644 --- a/tests/framework/framework_config.h.in +++ b/tests/framework/framework_config.h.in @@ -56,8 +56,8 @@ // Dummy Binaries #if _WIN32 || _WIN64 -#define DUMMY_BINARY_WINDOWS_64 "${CMAKE_CURRENT_SOURCE_DIR}/data/binaries/dummy_library_pe_64.so" -#define DUMMY_BINARY_WINDOWS_32 "${CMAKE_CURRENT_SOURCE_DIR}/data/binaries/dummy_library_pe_32.so" +#define DUMMY_BINARY_WINDOWS_64 "${CMAKE_CURRENT_SOURCE_DIR}/data/binaries/dummy_library_pe_64.dll" +#define DUMMY_BINARY_WINDOWS_32 "${CMAKE_CURRENT_SOURCE_DIR}/data/binaries/dummy_library_pe_32.dll" #endif #if defined(__linux__) || defined(__APPLE__) #define DUMMY_BINARY_LINUX_64 "${CMAKE_CURRENT_SOURCE_DIR}/data/binaries/libdummy_library_elf_64.so" diff --git a/tests/framework/test_util.cpp b/tests/framework/test_util.cpp index faed08bd..37ca8124 100644 --- a/tests/framework/test_util.cpp +++ b/tests/framework/test_util.cpp @@ -88,7 +88,7 @@ bool set_env_var(std::string const& name, std::string const& value) { return set bool remove_env_var(std::string const& name) { return unsetenv(name.c_str()); } std::string get_env_var(std::string const& name) { char* ret = getenv(name.c_str()); - if (ret == nullptr){ + if (ret == nullptr) { std::cerr << "Failed to get environment variable:" << name << "\n"; return std::string(); } @@ -647,4 +647,18 @@ VkResult CreatePhysDev(InstWrapper& inst, VkPhysicalDevice& physical_device) { VkResult CreateDevice(VkPhysicalDevice phys_dev, DeviceWrapper& dev, DeviceCreateInfo& dev_info) { return dev.functions->vkCreateDevice(phys_dev, dev_info.get(), dev.callbacks, &dev.dev); -} \ No newline at end of file +} + +VkResult CreateDebugUtilsMessenger(DebugUtilsWrapper& debug_utils) { + return debug_utils.vkCreateDebugUtilsMessengerEXT(debug_utils.inst, debug_utils.get(), debug_utils.callbacks, + &debug_utils.messenger); +} + +void FillDebugUtilsCreateDetails(InstanceCreateInfo& create_info, DebugUtilsLogger& logger) { + create_info.add_extension("VK_EXT_debug_utils"); + create_info.inst_info.pNext = logger.get(); +} +void FillDebugUtilsCreateDetails(InstanceCreateInfo& create_info, DebugUtilsWrapper& wrapper) { + create_info.add_extension("VK_EXT_debug_utils"); + create_info.inst_info.pNext = wrapper.get(); +} diff --git a/tests/framework/test_util.h b/tests/framework/test_util.h index fce5eff4..900f7e82 100644 --- a/tests/framework/test_util.h +++ b/tests/framework/test_util.h @@ -625,7 +625,8 @@ struct DeviceCreateInfo { }; struct InstWrapper { - InstWrapper(VulkanFunctions& functions, VkAllocationCallbacks* callbacks = nullptr) noexcept : functions(&functions), callbacks(callbacks) {} + InstWrapper(VulkanFunctions& functions, VkAllocationCallbacks* callbacks = nullptr) noexcept + : functions(&functions), callbacks(callbacks) {} InstWrapper(VulkanFunctions& functions, VkInstance inst, VkAllocationCallbacks* callbacks = nullptr) noexcept : functions(&functions), inst(inst), callbacks(callbacks) {} ~InstWrapper() { @@ -675,6 +676,82 @@ struct DeviceWrapper { }; VkResult CreateDevice(VkPhysicalDevice phys_dev, DeviceWrapper& dev, DeviceCreateInfo& dev_info); +struct DebugUtilsLogger { + static VkBool32 VKAPI_PTR DebugUtilsMessengerLoggerCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, + void* pUserData) { + DebugUtilsLogger* debug = reinterpret_cast(pUserData); + debug->returned_output += pCallbackData->pMessage; + debug->returned_output += '\n'; + return VK_FALSE; + } + DebugUtilsLogger(VkDebugUtilsMessageSeverityFlagsEXT severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { + returned_output.reserve(4096); // output can be very noisy, reserving should help prevent many small allocations + create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + create_info.pNext = nullptr; + create_info.messageSeverity = severity; + create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + create_info.pfnUserCallback = DebugUtilsMessengerLoggerCallback; + create_info.pUserData = this; + } + + // Immoveable object + DebugUtilsLogger(DebugUtilsLogger const&) = delete; + DebugUtilsLogger& operator=(DebugUtilsLogger const&) = delete; + DebugUtilsLogger(DebugUtilsLogger&&) = delete; + DebugUtilsLogger& operator=(DebugUtilsLogger&&) = delete; + + bool find(std::string const& search_text) { return returned_output.find(search_text) != std::string::npos; } + + VkDebugUtilsMessengerCreateInfoEXT* get() noexcept { return &create_info; } + VkDebugUtilsMessengerCreateInfoEXT create_info{}; + std::string returned_output; +}; + +struct DebugUtilsWrapper { + DebugUtilsWrapper() noexcept {} + DebugUtilsWrapper(InstWrapper& inst_wrapper, + VkDebugUtilsMessageSeverityFlagsEXT severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, + VkAllocationCallbacks* callbacks = nullptr) + : logger(severity), inst(inst_wrapper.inst), callbacks(callbacks) { + vkCreateDebugUtilsMessengerEXT = reinterpret_cast( + inst_wrapper.functions->vkGetInstanceProcAddr(inst_wrapper.inst, "vkCreateDebugUtilsMessengerEXT")); + vkDestroyDebugUtilsMessengerEXT = reinterpret_cast( + inst_wrapper.functions->vkGetInstanceProcAddr(inst_wrapper.inst, "vkDestroyDebugUtilsMessengerEXT")); + }; + ~DebugUtilsWrapper() noexcept { + if (messenger) { + vkDestroyDebugUtilsMessengerEXT(inst, messenger, callbacks); + } + } + // Immoveable object + DebugUtilsWrapper(DebugUtilsWrapper const&) = delete; + DebugUtilsWrapper& operator=(DebugUtilsWrapper const&) = delete; + DebugUtilsWrapper(DebugUtilsWrapper&&) = delete; + DebugUtilsWrapper& operator=(DebugUtilsWrapper&&) = delete; + + bool find(std::string const& search_text) { return logger.find(search_text); } + VkDebugUtilsMessengerCreateInfoEXT* get() noexcept { return logger.get(); } + + DebugUtilsLogger logger; + VkInstance inst; + VkAllocationCallbacks* callbacks = nullptr; + PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = nullptr; + PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT = nullptr; + VkDebugUtilsMessengerEXT messenger = VK_NULL_HANDLE; +}; + +VkResult CreateDebugUtilsMessenger(DebugUtilsWrapper& debug_utils); + +// Helper that adds the debug utils extension name and sets the pNext chain up +// NOTE: Ignores existing pNext chains +void FillDebugUtilsCreateDetails(InstanceCreateInfo& create_info, DebugUtilsLogger& logger); +void FillDebugUtilsCreateDetails(InstanceCreateInfo& create_info, DebugUtilsWrapper& wrapper); + inline bool operator==(const VkExtent3D& a, const VkExtent3D& b) { return a.width == b.width && a.height == b.height && a.depth == b.depth; } -- 2.34.1