Add DebugReport
authorMark Young <marky@lunarg.com>
Fri, 4 Feb 2022 16:00:55 +0000 (09:00 -0700)
committerMark Young <marky@lunarg.com>
Wed, 9 Feb 2022 20:19:48 +0000 (13:19 -0700)
tests/CMakeLists.txt
tests/loader_debug_ext_tests.cpp [new file with mode: 0644]

index f54825432631a3249302868b0b84b26eaf766342..403951ec0c9b4592ef700fc5ca775f0a025eb630 100644 (file)
@@ -29,6 +29,7 @@ add_executable(
         loader_testing_main.cpp
         loader_alloc_callback_tests.cpp
         loader_get_proc_addr_tests.cpp
+        loader_debug_ext_tests.cpp
         loader_handle_validation_tests.cpp
         loader_layer_tests.cpp
         loader_regression_tests.cpp
diff --git a/tests/loader_debug_ext_tests.cpp b/tests/loader_debug_ext_tests.cpp
new file mode 100644 (file)
index 0000000..d7a7e43
--- /dev/null
@@ -0,0 +1,489 @@
+/*
+ * Copyright (c) 2022 The Khronos Group Inc.
+ * Copyright (c) 2022 Valve Corporation
+ * Copyright (c) 2022 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and/or associated documentation files (the "Materials"), to
+ * deal in the Materials without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Materials, and to permit persons to whom the Materials are
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included in
+ * all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
+ * USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ * Author: Charles Giessen <charles@lunarg.com>
+ * Author: Mark Young <marky@lunarg.com>
+ */
+
+#include "test_environment.h"
+
+//
+// VK_EXT_debug_report
+//
+
+struct ExpectedDebugReportMessage {
+    bool any_message = false;
+    std::string message;
+    VkDebugReportObjectTypeEXT object_type;
+    VkDebugReportFlagBitsEXT flag;
+    bool found = false;
+};
+static ExpectedDebugReportMessage expected_debug_report{};
+
+static VkBool32 VKAPI_CALL test_DebugReportCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType,
+                                                    uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix,
+                                                    const char* pMessage, void* pUserData) {
+    if (objectType == expected_debug_report.object_type && 0 < (flags | expected_debug_report.flag)) {
+        std::string message_str = pMessage;
+        if (expected_debug_report.any_message || (std::string::npos != message_str.find(expected_debug_report.message))) {
+            expected_debug_report.found = true;
+        }
+    }
+    return VK_FALSE;
+}
+
+static void CreateDebugReportEnvironment(FrameworkEnvironment& env, VkDebugReportFlagsEXT flags,
+                                         VkInstanceCreateInfo& create_info) {
+    for (uint32_t icd = 0; icd < 3; ++icd) {
+        env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6, VK_API_VERSION_1_0));
+        env.get_test_icd(icd).physical_devices.push_back({});
+        env.get_test_icd(icd).physical_devices.push_back({});
+    }
+
+    // Initialize the expected output
+    expected_debug_report.any_message = false;
+    expected_debug_report.message = "";
+    expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;
+    expected_debug_report.found = false;
+
+    // Setup the debug report struct
+    static VkDebugReportCallbackCreateInfoEXT debug_report_info{VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT};
+    debug_report_info.pNext = nullptr;
+    debug_report_info.flags = flags;
+    debug_report_info.pfnCallback = reinterpret_cast<PFN_vkDebugReportCallbackEXT>(test_DebugReportCallback);
+    debug_report_info.pUserData = nullptr;
+
+    static std::vector<const char*> enabled_extensions;
+    enabled_extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
+    create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+    create_info.pNext = &debug_report_info;
+    create_info.enabledExtensionCount = static_cast<uint32_t>(enabled_extensions.size());
+    create_info.ppEnabledExtensionNames = enabled_extensions.data();
+}
+
+// Test creating and destroying report with errors, but none should occur.
+TEST(DebugExtensionTests, NormalCreateDestroy) {
+    FrameworkEnvironment env{};
+    VkInstanceCreateInfo create_info{};
+    CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT, create_info);
+
+    // Make sure we don't find any errors
+    expected_debug_report.any_message = true;
+    expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_debug_report.flag = VK_DEBUG_REPORT_ERROR_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS);
+    env.vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    ASSERT_EQ(false, expected_debug_report.found);
+}
+
+// Test report (error/warning) created in vkCreateInstance with warning in vkCreateInstance
+TEST(DebugExtensionTests, WarningInCreateInstance) {
+    FrameworkEnvironment env{};
+    VkInstanceCreateInfo create_info{};
+    CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT, create_info);
+
+    VkApplicationInfo app_info;
+    app_info.apiVersion = VK_MAKE_API_VERSION(1, 1, 0, 0);
+    create_info.pApplicationInfo = &app_info;
+
+    // Make sure we find the invalid variant message
+    expected_debug_report.message = "The API Variant specified";
+    expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_debug_report.flag = VK_DEBUG_REPORT_WARNING_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS);
+    env.vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    // Should be found because we're reporting errors and warnings
+    ASSERT_EQ(true, expected_debug_report.found);
+}
+
+// Test report (error) created in vkCreateInstance with warning in vkCreateInstance
+TEST(DebugExtensionTests, WarningInCreateInstanceNotLogged) {
+    FrameworkEnvironment env{};
+    VkInstanceCreateInfo create_info{};
+    CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT, create_info);
+
+    VkApplicationInfo app_info;
+    app_info.apiVersion = VK_MAKE_API_VERSION(1, 1, 0, 0);
+    create_info.pApplicationInfo = &app_info;
+
+    // Make sure we find the invalid variant message
+    expected_debug_report.message = "The API Variant specified";
+    expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_debug_report.flag = VK_DEBUG_REPORT_WARNING_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS);
+    env.vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    // Message should NOT be found (because we only have errors reported in create)
+    ASSERT_EQ(false, expected_debug_report.found);
+}
+
+// Test report (error/warning) created in vkCreateInstance with info in vkDestroyInstance
+TEST(DebugExtensionTests, InfoInDestroyInstanceNotLogged) {
+    FrameworkEnvironment env{};
+    VkInstanceCreateInfo create_info{};
+    CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT, create_info);
+
+    expected_debug_report.message = "destroying all debug report callbacks";
+    expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_debug_report.flag = VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS);
+    env.vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    // Should be not be found
+    ASSERT_EQ(false, expected_debug_report.found);
+}
+
+// Test report (info) created in vkCreateInstance with info in vkDestroyInstance
+TEST(DebugExtensionTests, InfoInDestroyInstanceLogged) {
+    FrameworkEnvironment env{};
+    VkInstanceCreateInfo create_info{};
+    CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, create_info);
+
+    expected_debug_report.message = "destroying all debug report callbacks";
+    expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_debug_report.flag = VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS);
+    env.vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    // Message should be found
+    ASSERT_EQ(true, expected_debug_report.found);
+}
+
+// Test report (error/warning) created in vkCreateInstance with error in vkEnumeratePhysicalDevices.
+// This should not be logged because we have only defined the debug report logging for vkCreateInstance
+// and vkDestroyInstance.
+TEST(DebugExtensionTests, ErrorInEnumDevsNotLogged) {
+    FrameworkEnvironment env{};
+    VkInstanceCreateInfo create_info{};
+    CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT, create_info);
+
+    // Look for the invaid count param message
+    expected_debug_report.message = "VUID-vkEnumeratePhysicalDevices-pPhysicalDeviceCount-parameter";
+    expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_debug_report.flag = VK_DEBUG_REPORT_ERROR_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS);
+
+    ASSERT_EQ(env.vulkan_functions.vkEnumeratePhysicalDevices(inst, nullptr, nullptr), VK_ERROR_INITIALIZATION_FAILED);
+
+    env.vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    // Message should NOT be found (because we don't have a report callback setup outside of the create/destroy instance chain)
+    ASSERT_EQ(false, expected_debug_report.found);
+}
+
+// Test report created outside of vkCreateInstance with error in vkEnumeratePhysicalDevices.
+// This should be logged now.
+TEST(DebugExtensionTests, ErrorInEnumDevsLogged) {
+    FrameworkEnvironment env{};
+    VkInstanceCreateInfo create_info{};
+    CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT, create_info);
+
+    // Look for the invaid count param message
+    expected_debug_report.message = "VUID-vkEnumeratePhysicalDevices-pPhysicalDeviceCount-parameter";
+    expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_debug_report.flag = VK_DEBUG_REPORT_ERROR_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS);
+    PFN_vkCreateDebugReportCallbackEXT create_debug_report = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
+        env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT"));
+    PFN_vkDestroyDebugReportCallbackEXT destroy_debug_report = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
+        env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT"));
+    ASSERT_NE(nullptr, create_debug_report);
+    ASSERT_NE(nullptr, destroy_debug_report);
+
+    // Setup the debug report struct
+    static VkDebugReportCallbackCreateInfoEXT debug_report_info{VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT};
+    debug_report_info.pNext = nullptr;
+    debug_report_info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
+    debug_report_info.pfnCallback = reinterpret_cast<PFN_vkDebugReportCallbackEXT>(test_DebugReportCallback);
+    debug_report_info.pUserData = nullptr;
+
+    VkDebugReportCallbackEXT callback = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS, create_debug_report(inst, &debug_report_info, nullptr, &callback));
+    ASSERT_EQ(env.vulkan_functions.vkEnumeratePhysicalDevices(inst, nullptr, nullptr), VK_ERROR_INITIALIZATION_FAILED);
+    destroy_debug_report(inst, callback, nullptr);
+
+    env.vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    // Message should be found
+    ASSERT_EQ(true, expected_debug_report.found);
+}
+
+// Test report created outside of vkCreateInstance with info in vkEnumeratePhysicalDevices.
+// This should not be logged because type is wrong.
+TEST(DebugExtensionTests, InfoInEnumDevsNotLogged) {
+    FrameworkEnvironment env{};
+    VkInstanceCreateInfo create_info{};
+    CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT, create_info);
+
+    expected_debug_report.message = "Trimming device count down by application request";
+    expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_debug_report.flag = VK_DEBUG_REPORT_ERROR_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS);
+    PFN_vkCreateDebugReportCallbackEXT create_debug_report = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
+        env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT"));
+    PFN_vkDestroyDebugReportCallbackEXT destroy_debug_report = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
+        env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT"));
+    ASSERT_NE(nullptr, create_debug_report);
+    ASSERT_NE(nullptr, destroy_debug_report);
+
+    // Setup the debug report struct
+    static VkDebugReportCallbackCreateInfoEXT debug_report_info{VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT};
+    debug_report_info.pNext = nullptr;
+    debug_report_info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
+    debug_report_info.pfnCallback = reinterpret_cast<PFN_vkDebugReportCallbackEXT>(test_DebugReportCallback);
+    debug_report_info.pUserData = nullptr;
+
+    VkDebugReportCallbackEXT callback = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS, create_debug_report(inst, &debug_report_info, nullptr, &callback));
+
+    uint32_t max_count = 5;
+    std::array<VkPhysicalDevice, 5> devices;
+    ASSERT_EQ(env.vulkan_functions.vkEnumeratePhysicalDevices(inst, &max_count, devices.data()), VK_INCOMPLETE);
+    destroy_debug_report(inst, callback, nullptr);
+
+    env.vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    // Message should not be found (because it's info)
+    ASSERT_EQ(false, expected_debug_report.found);
+}
+
+// Test report created outside of vkCreateInstance with info in vkEnumeratePhysicalDevices.
+// This should be logged because type is correct.
+TEST(DebugExtensionTests, InfoInEnumDevLogged) {
+    FrameworkEnvironment env{};
+    VkInstanceCreateInfo create_info{};
+    CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT, create_info);
+
+    expected_debug_report.message = "Trimming device count down by application request";
+    expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_debug_report.flag = VK_DEBUG_REPORT_ERROR_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS);
+    PFN_vkCreateDebugReportCallbackEXT create_debug_report = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
+        env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT"));
+    PFN_vkDestroyDebugReportCallbackEXT destroy_debug_report = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
+        env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT"));
+    ASSERT_NE(nullptr, create_debug_report);
+    ASSERT_NE(nullptr, destroy_debug_report);
+
+    // Setup the debug report struct
+    static VkDebugReportCallbackCreateInfoEXT debug_report_info{VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT};
+    debug_report_info.pNext = nullptr;
+    debug_report_info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
+    debug_report_info.pfnCallback = reinterpret_cast<PFN_vkDebugReportCallbackEXT>(test_DebugReportCallback);
+    debug_report_info.pUserData = nullptr;
+
+    VkDebugReportCallbackEXT callback = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS, create_debug_report(inst, &debug_report_info, nullptr, &callback));
+
+    uint32_t max_count = 5;
+    std::array<VkPhysicalDevice, 5> devices;
+    ASSERT_EQ(env.vulkan_functions.vkEnumeratePhysicalDevices(inst, &max_count, devices.data()), VK_INCOMPLETE);
+    destroy_debug_report(inst, callback, nullptr);
+
+    env.vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    // Message should be found
+    ASSERT_EQ(true, expected_debug_report.found);
+}
+
+// Test report created outside of vkCreateInstance with a manual info message of the wrong message flag type to be logged.
+TEST(DebugExtensionTests, ManualInfoMessageWrongMessageFlag) {
+    const char my_message[] = "This is my special message!";
+    FrameworkEnvironment env{};
+    VkInstanceCreateInfo create_info{};
+    CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT, create_info);
+
+    expected_debug_report.message = my_message;
+    expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_debug_report.flag = VK_DEBUG_REPORT_ERROR_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS);
+    PFN_vkCreateDebugReportCallbackEXT create_debug_report = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
+        env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT"));
+    PFN_vkDestroyDebugReportCallbackEXT destroy_debug_report = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
+        env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT"));
+    PFN_vkDebugReportMessageEXT log_debug_report =
+        reinterpret_cast<PFN_vkDebugReportMessageEXT>(env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkDebugReportMessageEXT"));
+    ASSERT_NE(nullptr, create_debug_report);
+    ASSERT_NE(nullptr, destroy_debug_report);
+    ASSERT_NE(nullptr, log_debug_report);
+
+    // Setup the debug report struct
+    static VkDebugReportCallbackCreateInfoEXT debug_report_info{VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT};
+    debug_report_info.pNext = nullptr;
+    debug_report_info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
+    debug_report_info.pfnCallback = reinterpret_cast<PFN_vkDebugReportCallbackEXT>(test_DebugReportCallback);
+    debug_report_info.pUserData = nullptr;
+
+    VkDebugReportCallbackEXT callback = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS, create_debug_report(inst, &debug_report_info, nullptr, &callback));
+
+    log_debug_report(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, (uint64_t)(inst), 0, 0,
+                     nullptr, my_message);
+
+    destroy_debug_report(inst, callback, nullptr);
+
+    env.vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    // Message should not be found
+    ASSERT_EQ(false, expected_debug_report.found);
+}
+
+// Test report created outside of vkCreateInstance with a manual info message of the wrong object type to be logged.
+TEST(DebugExtensionTests, ManualInfoMessageWrongObjectType) {
+    const char my_message[] = "This is my special message!";
+    FrameworkEnvironment env{};
+    VkInstanceCreateInfo create_info{};
+    CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT, create_info);
+
+    // Look for any message
+    expected_debug_report.any_message = true;
+    expected_debug_report.message = my_message;
+    expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_debug_report.flag = VK_DEBUG_REPORT_ERROR_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS);
+    PFN_vkCreateDebugReportCallbackEXT create_debug_report = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
+        env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT"));
+    PFN_vkDestroyDebugReportCallbackEXT destroy_debug_report = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
+        env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT"));
+    PFN_vkDebugReportMessageEXT log_debug_report =
+        reinterpret_cast<PFN_vkDebugReportMessageEXT>(env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkDebugReportMessageEXT"));
+    ASSERT_NE(nullptr, create_debug_report);
+    ASSERT_NE(nullptr, destroy_debug_report);
+    ASSERT_NE(nullptr, log_debug_report);
+
+    // Setup the debug report struct
+    static VkDebugReportCallbackCreateInfoEXT debug_report_info{VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT};
+    debug_report_info.pNext = nullptr;
+    debug_report_info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
+    debug_report_info.pfnCallback = reinterpret_cast<PFN_vkDebugReportCallbackEXT>(test_DebugReportCallback);
+    debug_report_info.pUserData = nullptr;
+
+    VkDebugReportCallbackEXT callback = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS, create_debug_report(inst, &debug_report_info, nullptr, &callback));
+
+    log_debug_report(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)(inst), 0, 0,
+                     nullptr, my_message);
+
+    destroy_debug_report(inst, callback, nullptr);
+
+    env.vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    // Message should not be found
+    ASSERT_EQ(false, expected_debug_report.found);
+}
+
+// Test report created outside of vkCreateInstance with a manual info message to be logged.
+TEST(DebugExtensionTests, ManualInfoMessageLogged) {
+    const char my_message[] = "This is my special message!";
+    FrameworkEnvironment env{};
+    VkInstanceCreateInfo create_info{};
+    CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT, create_info);
+
+    expected_debug_report.message = my_message;
+    expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_debug_report.flag = VK_DEBUG_REPORT_ERROR_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS);
+    PFN_vkCreateDebugReportCallbackEXT create_debug_report = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
+        env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT"));
+    PFN_vkDestroyDebugReportCallbackEXT destroy_debug_report = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
+        env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT"));
+    PFN_vkDebugReportMessageEXT log_debug_report =
+        reinterpret_cast<PFN_vkDebugReportMessageEXT>(env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkDebugReportMessageEXT"));
+    ASSERT_NE(nullptr, create_debug_report);
+    ASSERT_NE(nullptr, destroy_debug_report);
+    ASSERT_NE(nullptr, log_debug_report);
+
+    // Setup the debug report struct
+    static VkDebugReportCallbackCreateInfoEXT debug_report_info{VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT};
+    debug_report_info.pNext = nullptr;
+    debug_report_info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
+    debug_report_info.pfnCallback = reinterpret_cast<PFN_vkDebugReportCallbackEXT>(test_DebugReportCallback);
+    debug_report_info.pUserData = nullptr;
+
+    VkDebugReportCallbackEXT callback = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS, create_debug_report(inst, &debug_report_info, nullptr, &callback));
+
+    log_debug_report(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, (uint64_t)(inst), 0, 0,
+                     nullptr, my_message);
+
+    destroy_debug_report(inst, callback, nullptr);
+
+    env.vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    // Message should be found
+    ASSERT_EQ(true, expected_debug_report.found);
+}
+
+//
+// VK_EXT_debug_utils
+//
+
+// Test creating and destroying report (no logging)
+
+// Test report (error/warning) created in vkCreateInstance with error in create instance (logging)
+
+// Test report (warning) created in vkCreateInstance with error in create instance (no logging)
+
+// Test report (error/warning) created in vkCreateInstance with error in destroy instance (logging)
+
+// Test report (warning) created in vkCreateInstance with error in destroy instance (no logging)
+
+// Test report (error/warning) created in vkCreateInstance with error in vkEnumeratePhysicalDevices (logging)
+// (NULL == pPhysicalDeviceCount)
+
+// Test report (error/warning) created in vkCreateInstance with info in vkEnumeratePhysicalDevices (no logging)
+// (*pPhysicalDeviceCount < number)
+
+// Test report (error/warning/info) created in vkCreateInstance with info in vkEnumeratePhysicalDevices (logging)
+// (*pPhysicalDeviceCount < number)
+
+//
+// VK_EXT_debug_utils
+//