Add debug utils loader testing
authorMark Young <marky@lunarg.com>
Sat, 5 Feb 2022 01:00:11 +0000 (18:00 -0700)
committerMark Young <marky@lunarg.com>
Wed, 9 Feb 2022 20:19:48 +0000 (13:19 -0700)
loader/trampoline.c
tests/loader_debug_ext_tests.cpp

index 931166a..be06f57 100644 (file)
@@ -732,14 +732,16 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance,
     }
 
     if (messenger_setup) {
-        loader_log(ptr_instance, VULKAN_LOADER_INFO_BIT, 0, "vkDestroyInstance: destroying all debug util messengers");
+        loader_log(ptr_instance, VULKAN_LOADER_INFO_BIT, 0,
+                   "vkDestroyInstance: destroying temporary instance debug util messenger");
 
         util_DestroyDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers, ptr_instance->tmp_messengers);
         util_FreeDebugUtilsMessengerCreateInfos(pAllocator, ptr_instance->tmp_messenger_create_infos, ptr_instance->tmp_messengers);
     }
 
     if (callback_setup) {
-        loader_log(ptr_instance, VULKAN_LOADER_INFO_BIT, 0, "vkDestroyInstance: destroying all debug report callbacks");
+        loader_log(ptr_instance, VULKAN_LOADER_INFO_BIT, 0,
+                   "vkDestroyInstance: destroying temporary instance debug report callback");
 
         util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
                                          ptr_instance->tmp_report_callbacks);
index d7a7e43..411b13b 100644 (file)
 #include "test_environment.h"
 
 //
-// VK_EXT_debug_report
+// VK_EXT_debug_report specific tests
+// =========================================
 //
 
-struct ExpectedDebugReportMessage {
-    bool any_message = false;
-    std::string message;
-    VkDebugReportObjectTypeEXT object_type;
-    VkDebugReportFlagBitsEXT flag;
-    bool found = false;
-};
-static ExpectedDebugReportMessage expected_debug_report{};
-
+// Prototype declaration for callback so we can use it in class utility methods
 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;
+                                                    const char* pMessage, void* pUserData);
+
+class DebugReportTest : public ::testing::Test {
+   public:
+    void VerifyExpected(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT object_type, const std::string& message) {
+        if (object_type == expected_object_type && 0 < (flags | expected_flag)) {
+            if (allow_any_message || (std::string::npos != message.find(expected_message))) {
+                message_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({});
+   protected:
+    virtual void SetUp() {
+        env = std::unique_ptr<FrameworkEnvironment>(new FrameworkEnvironment());
+        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
+        allow_any_message = false;
+        expected_message = "";
+        expected_object_type = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;
+        message_found = false;
+    }
+
+    VkResult CreateReportInstance(VkDebugReportFlagsEXT debug_report_flags, VkInstance* inst,
+                                  VkApplicationInfo* app_info = nullptr) {
+        std::vector<const char*> enabled_extensions;
+        enabled_extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
+
+        // Setup the debug report struct
+        VkDebugReportCallbackCreateInfoEXT debug_report_info{VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT};
+        debug_report_info.pNext = nullptr;
+        debug_report_info.flags = debug_report_flags;
+        debug_report_info.pfnCallback = reinterpret_cast<PFN_vkDebugReportCallbackEXT>(test_DebugReportCallback);
+        debug_report_info.pUserData = reinterpret_cast<void*>(this);
+
+        // Pass it into instance create struct
+        VkInstanceCreateInfo create_info{};
+        create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+        create_info.pNext = &debug_report_info;
+        create_info.pApplicationInfo = app_info;
+        create_info.enabledExtensionCount = static_cast<uint32_t>(enabled_extensions.size());
+        create_info.ppEnabledExtensionNames = enabled_extensions.data();
+
+        return env->vulkan_functions.vkCreateInstance(&create_info, nullptr, inst);
     }
 
-    // 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();
+    VkResult CreateReportCallback(VkInstance inst, VkDebugReportFlagsEXT debug_report_flags, VkDebugReportCallbackEXT* callback) {
+        PFN_vkCreateDebugReportCallbackEXT create_debug_report = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
+            env->vulkan_functions.vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT"));
+        if (nullptr == create_debug_report) {
+            return VK_ERROR_INITIALIZATION_FAILED;
+        }
+        VkDebugReportCallbackCreateInfoEXT debug_report_info{VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT};
+        debug_report_info.pNext = nullptr;
+        debug_report_info.flags = debug_report_flags;
+        debug_report_info.pfnCallback = reinterpret_cast<PFN_vkDebugReportCallbackEXT>(test_DebugReportCallback);
+        debug_report_info.pUserData = reinterpret_cast<void*>(this);
+        return create_debug_report(inst, &debug_report_info, nullptr, callback);
+    }
+
+    VkResult DestroyReportCallback(VkInstance inst, VkDebugReportCallbackEXT callback) {
+        PFN_vkDestroyDebugReportCallbackEXT destroy_debug_report = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
+            env->vulkan_functions.vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT"));
+        if (nullptr == destroy_debug_report) {
+            return VK_ERROR_INITIALIZATION_FAILED;
+        }
+        destroy_debug_report(inst, callback, nullptr);
+        return VK_SUCCESS;
+    }
+
+    virtual void TearDown() { env.reset(); }
+
+    std::unique_ptr<FrameworkEnvironment> env;
+    bool allow_any_message;
+    std::string expected_message;
+    VkDebugReportObjectTypeEXT expected_object_type;
+    VkDebugReportFlagBitsEXT expected_flag;
+    bool message_found;
+};
+
+// This is the actual callback prototyped above.
+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) {
+    DebugReportTest* debug_report_test = reinterpret_cast<DebugReportTest*>(pUserData);
+    debug_report_test->VerifyExpected(flags, objectType, pMessage);
+    return VK_FALSE;
 }
 
-// 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);
+class CreateDestroyInstanceReport : public DebugReportTest {};
+class SeparateReport : public DebugReportTest {};
+class ManualReport : public DebugReportTest {};
 
+// Test creating and destroying instance looking for errors, but none should occur.
+TEST_F(CreateDestroyInstanceReport, NoCallback) {
     // 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;
+    allow_any_message = true;
+    expected_object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_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(VK_SUCCESS, CreateReportInstance(VK_DEBUG_REPORT_ERROR_BIT_EXT, &inst));
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
 
-    ASSERT_EQ(false, expected_debug_report.found);
+    ASSERT_EQ(false, message_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);
+// Test report (error) created in vkCreateInstance with warning in vkCreateInstance
+TEST_F(CreateDestroyInstanceReport, WarnInCreateIgnored) {
+    expected_message = "The API Variant specified";
+    expected_object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_flag = VK_DEBUG_REPORT_WARNING_BIT_EXT;
 
     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);
+    ASSERT_EQ(VK_SUCCESS, CreateReportInstance(VK_DEBUG_REPORT_ERROR_BIT_EXT, &inst, &app_info));
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
 
-    // Should be found because we're reporting errors and warnings
-    ASSERT_EQ(true, expected_debug_report.found);
+    // Message should NOT be found (because we only have errors reported in create)
+    ASSERT_EQ(false, message_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);
+// Test creating and destroying instance looking for errors, but none should occur.
+TEST_F(CreateDestroyInstanceReport, WarnInCreate) {
+    expected_message = "The API Variant specified";
+    expected_object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_flag = VK_DEBUG_REPORT_WARNING_BIT_EXT;
 
     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);
+    ASSERT_EQ(VK_SUCCESS, CreateReportInstance(VK_DEBUG_REPORT_WARNING_BIT_EXT, &inst, &app_info));
+    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);
+    // Message should be found (because we only have errors reported in create)
+    ASSERT_EQ(true, message_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;
+TEST_F(CreateDestroyInstanceReport, InfoInDestroyIgnored) {
+    expected_message = "destroying temporary instance debug report callback";
+    expected_object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_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);
+    ASSERT_EQ(VK_SUCCESS, CreateReportInstance(VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT, &inst));
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
 
     // Should be not be found
-    ASSERT_EQ(false, expected_debug_report.found);
+    ASSERT_EQ(false, message_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;
+TEST_F(CreateDestroyInstanceReport, InfoInDestroy) {
+    expected_message = "destroying temporary instance debug report callback";
+    expected_object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_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);
+    ASSERT_EQ(VK_SUCCESS, CreateReportInstance(VK_DEBUG_REPORT_INFORMATION_BIT_EXT, &inst));
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
 
     // Message should be found
-    ASSERT_EQ(true, expected_debug_report.found);
+    ASSERT_EQ(true, message_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);
-
+TEST_F(SeparateReport, ErrorInEnumDevsNoCallback) {
     // 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;
+    expected_message = "VUID-vkEnumeratePhysicalDevices-pPhysicalDeviceCount-parameter";
+    expected_object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_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(VK_SUCCESS, CreateReportInstance(VK_DEBUG_REPORT_ERROR_BIT_EXT, &inst));
 
-    ASSERT_EQ(env.vulkan_functions.vkEnumeratePhysicalDevices(inst, nullptr, nullptr), VK_ERROR_INITIALIZATION_FAILED);
+    ASSERT_EQ(env->vulkan_functions.vkEnumeratePhysicalDevices(inst, nullptr, nullptr), VK_ERROR_INITIALIZATION_FAILED);
 
-    env.vulkan_functions.vkDestroyInstance(inst, nullptr);
+    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);
+    ASSERT_EQ(false, message_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);
-
+TEST_F(SeparateReport, ErrorInEnumDevs) {
     // 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;
+    expected_message = "VUID-vkEnumeratePhysicalDevices-pPhysicalDeviceCount-parameter";
+    expected_object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_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);
+    ASSERT_EQ(VK_SUCCESS, CreateReportInstance(VK_DEBUG_REPORT_ERROR_BIT_EXT, &inst));
+
+    VkDebugReportCallbackEXT callback;
+    ASSERT_EQ(VK_SUCCESS, CreateReportCallback(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, &callback));
+
+    ASSERT_EQ(env->vulkan_functions.vkEnumeratePhysicalDevices(inst, nullptr, nullptr), VK_ERROR_INITIALIZATION_FAILED);
+
+    ASSERT_EQ(VK_SUCCESS, DestroyReportCallback(inst, callback));
+
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
 
     // Message should be found
-    ASSERT_EQ(true, expected_debug_report.found);
+    ASSERT_EQ(true, message_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;
+TEST_F(SeparateReport, InfoInEnumDevsIgnored) {
+    expected_message = "Trimming device count down by application request";
+    expected_object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_flag = VK_DEBUG_REPORT_INFORMATION_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(VK_SUCCESS, CreateReportInstance(VK_DEBUG_REPORT_ERROR_BIT_EXT, &inst));
+
+    VkDebugReportCallbackEXT callback;
+    ASSERT_EQ(VK_SUCCESS, CreateReportCallback(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, &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);
+    ASSERT_EQ(env->vulkan_functions.vkEnumeratePhysicalDevices(inst, &max_count, devices.data()), VK_INCOMPLETE);
+
+    ASSERT_EQ(VK_SUCCESS, DestroyReportCallback(inst, callback));
 
-    env.vulkan_functions.vkDestroyInstance(inst, nullptr);
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
 
     // Message should not be found (because it's info)
-    ASSERT_EQ(false, expected_debug_report.found);
+    ASSERT_EQ(false, message_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;
+TEST_F(SeparateReport, InfoInEnumDevs) {
+    expected_message = "Trimming device count down by application request";
+    expected_object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_flag = VK_DEBUG_REPORT_INFORMATION_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));
+    ASSERT_EQ(VK_SUCCESS, CreateReportInstance(VK_DEBUG_REPORT_ERROR_BIT_EXT, &inst));
+
+    VkDebugReportCallbackEXT callback;
+    ASSERT_EQ(VK_SUCCESS, CreateReportCallback(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, &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);
+    ASSERT_EQ(env->vulkan_functions.vkEnumeratePhysicalDevices(inst, &max_count, devices.data()), VK_INCOMPLETE);
+
+    ASSERT_EQ(VK_SUCCESS, DestroyReportCallback(inst, callback));
 
-    env.vulkan_functions.vkDestroyInstance(inst, nullptr);
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
 
     // Message should be found
-    ASSERT_EQ(true, expected_debug_report.found);
+    ASSERT_EQ(true, message_found);
 }
 
 // Test report created outside of vkCreateInstance with a manual info message of the wrong message flag type to be logged.
-TEST(DebugExtensionTests, ManualInfoMessageWrongMessageFlag) {
+TEST_F(ManualReport, InfoIgnoredWrongType) {
     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;
+    expected_message = my_message;
+    expected_object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_flag = VK_DEBUG_REPORT_INFORMATION_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;
+    ASSERT_EQ(VK_SUCCESS, CreateReportInstance(VK_DEBUG_REPORT_ERROR_BIT_EXT, &inst));
 
-    VkDebugReportCallbackEXT callback = VK_NULL_HANDLE;
-    ASSERT_EQ(VK_SUCCESS, create_debug_report(inst, &debug_report_info, nullptr, &callback));
+    VkDebugReportCallbackEXT callback;
+    ASSERT_EQ(VK_SUCCESS, CreateReportCallback(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, &callback));
 
+    PFN_vkDebugReportMessageEXT log_debug_report =
+        reinterpret_cast<PFN_vkDebugReportMessageEXT>(env->vulkan_functions.vkGetInstanceProcAddr(inst, "vkDebugReportMessageEXT"));
+    ASSERT_NE(nullptr, log_debug_report);
     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);
+    ASSERT_EQ(VK_SUCCESS, DestroyReportCallback(inst, callback));
 
-    env.vulkan_functions.vkDestroyInstance(inst, nullptr);
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
 
     // Message should not be found
-    ASSERT_EQ(false, expected_debug_report.found);
+    ASSERT_EQ(false, message_found);
 }
 
 // Test report created outside of vkCreateInstance with a manual info message of the wrong object type to be logged.
-TEST(DebugExtensionTests, ManualInfoMessageWrongObjectType) {
+TEST_F(ManualReport, InfoIgnoredWrongObject) {
     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;
+    expected_message = my_message;
+    expected_object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_flag = VK_DEBUG_REPORT_INFORMATION_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);
+    ASSERT_EQ(VK_SUCCESS, CreateReportInstance(VK_DEBUG_REPORT_ERROR_BIT_EXT, &inst));
 
-    // 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));
+    VkDebugReportCallbackEXT callback;
+    ASSERT_EQ(VK_SUCCESS, CreateReportCallback(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, &callback));
 
+    PFN_vkDebugReportMessageEXT log_debug_report =
+        reinterpret_cast<PFN_vkDebugReportMessageEXT>(env->vulkan_functions.vkGetInstanceProcAddr(inst, "vkDebugReportMessageEXT"));
+    ASSERT_NE(nullptr, log_debug_report);
     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);
+    ASSERT_EQ(VK_SUCCESS, DestroyReportCallback(inst, callback));
 
-    env.vulkan_functions.vkDestroyInstance(inst, nullptr);
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
 
     // Message should not be found
-    ASSERT_EQ(false, expected_debug_report.found);
+    ASSERT_EQ(false, message_found);
 }
 
 // Test report created outside of vkCreateInstance with a manual info message to be logged.
-TEST(DebugExtensionTests, ManualInfoMessageLogged) {
+TEST_F(ManualReport, InfoMessage) {
     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;
+    expected_message = my_message;
+    expected_object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
+    expected_flag = VK_DEBUG_REPORT_INFORMATION_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;
+    ASSERT_EQ(VK_SUCCESS, CreateReportInstance(VK_DEBUG_REPORT_ERROR_BIT_EXT, &inst));
 
-    VkDebugReportCallbackEXT callback = VK_NULL_HANDLE;
-    ASSERT_EQ(VK_SUCCESS, create_debug_report(inst, &debug_report_info, nullptr, &callback));
+    VkDebugReportCallbackEXT callback;
+    ASSERT_EQ(VK_SUCCESS, CreateReportCallback(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, &callback));
 
+    PFN_vkDebugReportMessageEXT log_debug_report =
+        reinterpret_cast<PFN_vkDebugReportMessageEXT>(env->vulkan_functions.vkGetInstanceProcAddr(inst, "vkDebugReportMessageEXT"));
+    ASSERT_NE(nullptr, log_debug_report);
     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);
+    ASSERT_EQ(VK_SUCCESS, DestroyReportCallback(inst, callback));
 
-    env.vulkan_functions.vkDestroyInstance(inst, nullptr);
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
 
     // Message should be found
-    ASSERT_EQ(true, expected_debug_report.found);
+    ASSERT_EQ(true, message_found);
 }
 
 //
-// VK_EXT_debug_utils
+// VK_EXT_debug_util specific tests
+// =========================================
 //
 
-// Test creating and destroying report (no logging)
+// Prototype declaration for callback so we can use it in class utility methods
+static VkBool32 VKAPI_CALL test_DebugUtilsCallback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
+                                                   VkDebugUtilsMessageTypeFlagsEXT message_types,
+                                                   const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data);
+
+class DebugUtilTest : public ::testing::Test {
+   public:
+    void VerifyExpected(VkDebugUtilsMessageTypeFlagsEXT message_flags, VkDebugUtilsMessageSeverityFlagsEXT severity_flags,
+                        const std::string& message, const VkDebugUtilsMessengerCallbackDataEXT* callback_data) {
+        if ((0 < (severity_flags | expected_severity_flags)) && (0 < (message_flags | expected_message_flags))) {
+            if (allow_any_message || (std::string::npos != message.find(expected_message))) {
+                for (uint32_t obj = 0; obj < callback_data->objectCount; ++obj) {
+                    if (callback_data->pObjects[obj].objectType == expected_object_type &&
+                        (!check_object_handle || callback_data->pObjects[obj].objectHandle == expected_object_handle)) {
+                        message_found = true;
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+   protected:
+    virtual void SetUp() {
+        env = std::unique_ptr<FrameworkEnvironment>(new FrameworkEnvironment());
+        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
+        allow_any_message = false;
+        expected_message = "";
+        expected_object_type = VK_OBJECT_TYPE_UNKNOWN;
+        check_object_handle = false;
+        expected_object_handle = 0;
+        message_found = false;
+    }
+
+    VkResult CreateUtilsInstance(VkDebugUtilsMessageTypeFlagsEXT types, VkDebugUtilsMessageSeverityFlagsEXT severities,
+                                 VkInstance* inst, VkApplicationInfo* app_info = nullptr) {
+        std::vector<const char*> enabled_extensions;
+        enabled_extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+
+        // Setup the debug utils struct
+        VkDebugUtilsMessengerCreateInfoEXT debug_utils_info{VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT};
+        debug_utils_info.pNext = nullptr;
+        debug_utils_info.messageSeverity = severities;
+        debug_utils_info.messageType = types;
+        debug_utils_info.pfnUserCallback = reinterpret_cast<PFN_vkDebugUtilsMessengerCallbackEXT>(test_DebugUtilsCallback);
+        debug_utils_info.pUserData = reinterpret_cast<void*>(this);
+
+        VkInstanceCreateInfo create_info{};
+        create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+        create_info.pNext = &debug_utils_info;
+        create_info.pApplicationInfo = app_info;
+        create_info.enabledExtensionCount = static_cast<uint32_t>(enabled_extensions.size());
+        create_info.ppEnabledExtensionNames = enabled_extensions.data();
+        return env->vulkan_functions.vkCreateInstance(&create_info, nullptr, inst);
+    }
+
+    VkResult CreateUtilsMessenger(VkInstance inst, VkDebugUtilsMessageTypeFlagsEXT types,
+                                  VkDebugUtilsMessageSeverityFlagsEXT severities, VkDebugUtilsMessengerEXT* messenger) {
+        PFN_vkCreateDebugUtilsMessengerEXT create_messenger = reinterpret_cast<PFN_vkCreateDebugUtilsMessengerEXT>(
+            env->vulkan_functions.vkGetInstanceProcAddr(inst, "vkCreateDebugUtilsMessengerEXT"));
+        if (nullptr == create_messenger) {
+            return VK_ERROR_INITIALIZATION_FAILED;
+        }
+        VkDebugUtilsMessengerCreateInfoEXT debug_utils_info{VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT};
+        debug_utils_info.pNext = nullptr;
+        debug_utils_info.messageSeverity = severities;
+        debug_utils_info.messageType = types;
+        debug_utils_info.pfnUserCallback = reinterpret_cast<PFN_vkDebugUtilsMessengerCallbackEXT>(test_DebugUtilsCallback);
+        debug_utils_info.pUserData = reinterpret_cast<void*>(this);
+        return create_messenger(inst, &debug_utils_info, nullptr, messenger);
+    }
+
+    VkResult DestroyUtilsMessenger(VkInstance inst, VkDebugUtilsMessengerEXT messenger) {
+        PFN_vkDestroyDebugUtilsMessengerEXT destroy_messenger = reinterpret_cast<PFN_vkDestroyDebugUtilsMessengerEXT>(
+            env->vulkan_functions.vkGetInstanceProcAddr(inst, "vkDestroyDebugUtilsMessengerEXT"));
+        if (nullptr == destroy_messenger) {
+            return VK_ERROR_INITIALIZATION_FAILED;
+        }
+        destroy_messenger(inst, messenger, nullptr);
+        return VK_SUCCESS;
+    }
 
-// Test report (error/warning) created in vkCreateInstance with error in create instance (logging)
+    virtual void TearDown() { env.reset(); }
+
+    std::unique_ptr<FrameworkEnvironment> env;
+    bool allow_any_message;
+    std::string expected_message;
+    VkObjectType expected_object_type;
+    bool check_object_handle;
+    uint64_t expected_object_handle;
+    VkDebugUtilsMessageTypeFlagsEXT expected_message_flags;
+    VkDebugUtilsMessageSeverityFlagsEXT expected_severity_flags;
+    bool message_found;
+};
 
-// Test report (warning) created in vkCreateInstance with error in create instance (no logging)
+// This is the actual callback prototyped above.
+
+static VkBool32 VKAPI_CALL test_DebugUtilsCallback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
+                                                   VkDebugUtilsMessageTypeFlagsEXT message_types,
+                                                   const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data) {
+    DebugUtilTest* debug_util_test = reinterpret_cast<DebugUtilTest*>(user_data);
+    debug_util_test->VerifyExpected(message_types, message_severity, callback_data->pMessage, callback_data);
+    return VK_FALSE;
+}
 
-// Test report (error/warning) created in vkCreateInstance with error in destroy instance (logging)
+class CreateDestroyInstanceMessenger : public DebugUtilTest {};
+class SeparateMessenger : public DebugUtilTest {};
+class ManualMessage : public DebugUtilTest {};
 
-// Test report (warning) created in vkCreateInstance with error in destroy instance (no logging)
+// Test creating and destroying instance looking for errors, but none should occur.
+TEST_F(CreateDestroyInstanceMessenger, NoCallback) {
+    // Make sure we don't find any errors
+    allow_any_message = true;
+    expected_object_type = VK_OBJECT_TYPE_INSTANCE;
+    expected_message_flags = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+    expected_severity_flags = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
 
-// Test report (error/warning) created in vkCreateInstance with error in vkEnumeratePhysicalDevices (logging)
-// (NULL == pPhysicalDeviceCount)
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS,
+              CreateUtilsInstance(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
+                                  VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, &inst));
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
 
-// Test report (error/warning) created in vkCreateInstance with info in vkEnumeratePhysicalDevices (no logging)
-// (*pPhysicalDeviceCount < number)
+    ASSERT_EQ(false, message_found);
+}
 
-// Test report (error/warning/info) created in vkCreateInstance with info in vkEnumeratePhysicalDevices (logging)
-// (*pPhysicalDeviceCount < number)
+// Test debug utils (error) created in vkCreateInstance with warning in vkCreateInstance
+TEST_F(CreateDestroyInstanceMessenger, WarnInCreateIgnored) {
+    expected_message = "The API Variant specified";
+    expected_object_type = VK_OBJECT_TYPE_INSTANCE;
+    expected_message_flags = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+    expected_severity_flags = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
 
-//
-// VK_EXT_debug_utils
-//
+    VkApplicationInfo app_info;
+    app_info.apiVersion = VK_MAKE_API_VERSION(1, 1, 0, 0);
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS, CreateUtilsInstance(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
+                                              VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, &inst, &app_info));
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    ASSERT_EQ(false, message_found);
+}
+
+// Test debug utils (error/warning) created in vkCreateInstance with warning in vkCreateInstance
+TEST_F(CreateDestroyInstanceMessenger, WarnInCreate) {
+    expected_message = "The API Variant specified";
+    expected_object_type = VK_OBJECT_TYPE_INSTANCE;
+    expected_message_flags = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+    expected_severity_flags = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
+
+    VkApplicationInfo app_info;
+    app_info.apiVersion = VK_MAKE_API_VERSION(1, 1, 0, 0);
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS, CreateUtilsInstance(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
+                                              VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT, &inst, &app_info));
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    ASSERT_EQ(true, message_found);
+}
+
+// Test debug utils error/warn created in vkCreateInstance with info in vkDestroyInstance
+TEST_F(CreateDestroyInstanceMessenger, DestroyInfoIgnoredSeverity) {
+    expected_message = "destroying temporary instance debug util messenger";
+    expected_object_type = VK_OBJECT_TYPE_INSTANCE;
+    expected_message_flags = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+    expected_severity_flags = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+
+    VkApplicationInfo app_info;
+    app_info.apiVersion = VK_MAKE_API_VERSION(1, 1, 0, 0);
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS,
+              CreateUtilsInstance(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
+                                  VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT,
+                                  &inst, &app_info));
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    ASSERT_EQ(false, message_found);
+}
+
+// Test debug utils info/performance created in vkCreateInstance with info/general in vkDestroyInstance
+TEST_F(CreateDestroyInstanceMessenger, DestroyInfoIgnoredType) {
+    expected_message = "destroying temporary instance debug util messenger";
+    expected_object_type = VK_OBJECT_TYPE_INSTANCE;
+    expected_message_flags = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+    expected_severity_flags = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+
+    VkApplicationInfo app_info;
+    app_info.apiVersion = VK_MAKE_API_VERSION(1, 1, 0, 0);
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS, CreateUtilsInstance(VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
+                                              VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, &inst, &app_info));
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    ASSERT_EQ(false, message_found);
+}
+
+// Test debug utils info/general created in vkCreateInstance with info/general in vkDestroyInstance
+TEST_F(CreateDestroyInstanceMessenger, DestroyInfo) {
+    expected_message = "destroying temporary instance debug util messenger";
+    expected_object_type = VK_OBJECT_TYPE_INSTANCE;
+    expected_message_flags = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+    expected_severity_flags = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+
+    VkApplicationInfo app_info;
+    app_info.apiVersion = VK_MAKE_API_VERSION(1, 1, 0, 0);
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS, CreateUtilsInstance(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
+                                              VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, &inst, &app_info));
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    ASSERT_EQ(true, message_found);
+}
+
+// Test debug utils error created in vkCreateInstance with error in vkEnumeratePhysicalDevices.
+// This should not be logged because we have only defined the debug utils logging for vkCreateInstance
+// and vkDestroyInstance.
+TEST_F(SeparateMessenger, ErrorInEnumDevsNoMessenger) {
+    expected_message = "VUID-vkEnumeratePhysicalDevices-pPhysicalDeviceCount-parameter";
+    expected_object_type = VK_OBJECT_TYPE_INSTANCE;
+    expected_message_flags = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
+    expected_severity_flags = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS,
+              CreateUtilsInstance(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
+                                  VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, &inst));
+
+    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, message_found);
+}
+
+// Test debug utils created outside of vkCreateInstance with error in vkEnumeratePhysicalDevices, but, with the wrong
+// message type so it still won't be logged.
+TEST_F(SeparateMessenger, ErrorInEnumDevsWrongType) {
+    expected_message = "VUID-vkEnumeratePhysicalDevices-pPhysicalDeviceCount-parameter";
+    expected_object_type = VK_OBJECT_TYPE_INSTANCE;
+    expected_message_flags = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
+    expected_severity_flags = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS,
+              CreateUtilsInstance(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
+                                  VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, &inst));
+
+    // Create the debug utils messenger to collect performance warnings and errors
+    VkDebugUtilsMessengerEXT messenger = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS,
+              CreateUtilsMessenger(inst, VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
+                                   VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT,
+                                   &messenger));
+
+    ASSERT_EQ(env->vulkan_functions.vkEnumeratePhysicalDevices(inst, nullptr, nullptr), VK_ERROR_INITIALIZATION_FAILED);
+
+    // Now that we should have gotten our message, destroy the messenger
+    ASSERT_EQ(VK_SUCCESS, DestroyUtilsMessenger(inst, messenger));
+
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    ASSERT_EQ(false, message_found);
+}
+
+// Test debug utils created outside of vkCreateInstance with error in vkEnumeratePhysicalDevices, but, with the wrong
+// message severity so it still won't be logged.
+TEST_F(SeparateMessenger, ErrorInEnumDevsWrongSeverity) {
+    expected_message = "VUID-vkEnumeratePhysicalDevices-pPhysicalDeviceCount-parameter";
+    expected_object_type = VK_OBJECT_TYPE_INSTANCE;
+    expected_message_flags = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
+    expected_severity_flags = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS,
+              CreateUtilsInstance(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
+                                  VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, &inst));
+
+    // Create the debug utils messenger to collect only validation warnings
+    VkDebugUtilsMessengerEXT messenger = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS, CreateUtilsMessenger(inst, VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
+                                               VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT, &messenger));
+
+    ASSERT_EQ(env->vulkan_functions.vkEnumeratePhysicalDevices(inst, nullptr, nullptr), VK_ERROR_INITIALIZATION_FAILED);
+
+    // Now that we should have gotten our message, destroy the messenger
+    ASSERT_EQ(VK_SUCCESS, DestroyUtilsMessenger(inst, messenger));
+
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    ASSERT_EQ(false, message_found);
+}
+
+// Test debug utils created outside of vkCreateInstance with error in vkEnumeratePhysicalDevices with the correct type.
+TEST_F(SeparateMessenger, ErrorInEnumDevs) {
+    expected_message = "VUID-vkEnumeratePhysicalDevices-pPhysicalDeviceCount-parameter";
+    expected_object_type = VK_OBJECT_TYPE_INSTANCE;
+    expected_message_flags = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
+    expected_severity_flags = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS,
+              CreateUtilsInstance(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
+                                  VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, &inst));
+
+    // Create the debug utils messenger to collect validation errors
+    VkDebugUtilsMessengerEXT messenger = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS, CreateUtilsMessenger(inst, VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
+                                               VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, &messenger));
+
+    ASSERT_EQ(env->vulkan_functions.vkEnumeratePhysicalDevices(inst, nullptr, nullptr), VK_ERROR_INITIALIZATION_FAILED);
+
+    // Now that we should have gotten our message, destroy the messenger
+    ASSERT_EQ(VK_SUCCESS, DestroyUtilsMessenger(inst, messenger));
+
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    ASSERT_EQ(true, message_found);
+}
+
+// Test debug utils created outside of vkCreateInstance with info in vkEnumeratePhysicalDevices.
+// This should not be logged because type is wrong.
+TEST_F(SeparateMessenger, InfoInEnumDevsIgnoredType) {
+    expected_message = "Trimming device count down by application request";
+    expected_object_type = VK_OBJECT_TYPE_INSTANCE;
+    expected_message_flags = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+    expected_severity_flags = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS,
+              CreateUtilsInstance(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
+                                  VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, &inst));
+
+    // Create the debug utils messenger to collect validation info
+    VkDebugUtilsMessengerEXT messenger = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS, CreateUtilsMessenger(inst, VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
+                                               VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, &messenger));
+
+    uint32_t max_count = 5;
+    std::array<VkPhysicalDevice, 5> devices;
+    ASSERT_EQ(env->vulkan_functions.vkEnumeratePhysicalDevices(inst, &max_count, devices.data()), VK_INCOMPLETE);
+
+    // Now that we should have gotten our message, destroy the messenger
+    ASSERT_EQ(VK_SUCCESS, DestroyUtilsMessenger(inst, messenger));
+
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    // Message should not be found (because it's info)
+    ASSERT_EQ(false, message_found);
+}
+
+// Test debug utils created outside of vkCreateInstance with info in vkEnumeratePhysicalDevices.
+// This should not be logged because severity is wrong.
+TEST_F(SeparateMessenger, InfoInEnumDevsIgnoredSeverity) {
+    expected_message = "Trimming device count down by application request";
+    expected_object_type = VK_OBJECT_TYPE_INSTANCE;
+    expected_message_flags = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+    expected_severity_flags = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS,
+              CreateUtilsInstance(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
+                                  VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, &inst));
+
+    // Create the debug utils messenger to collect general errors/warnings
+    VkDebugUtilsMessengerEXT messenger = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS,
+              CreateUtilsMessenger(inst, VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
+                                   VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT,
+                                   &messenger));
+
+    uint32_t max_count = 5;
+    std::array<VkPhysicalDevice, 5> devices;
+    ASSERT_EQ(env->vulkan_functions.vkEnumeratePhysicalDevices(inst, &max_count, devices.data()), VK_INCOMPLETE);
+
+    // Now that we should have gotten our message, destroy the messenger
+    ASSERT_EQ(VK_SUCCESS, DestroyUtilsMessenger(inst, messenger));
+
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    // Message should not be found (because it's info)
+    ASSERT_EQ(false, message_found);
+}
+
+// Test debug utils created outside of vkCreateInstance with info in vkEnumeratePhysicalDevices.
+TEST_F(SeparateMessenger, DebugUtilsInfoInEnumDevs) {
+    expected_message = "Trimming device count down by application request";
+    expected_object_type = VK_OBJECT_TYPE_INSTANCE;
+    expected_message_flags = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+    expected_severity_flags = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS,
+              CreateUtilsInstance(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
+                                  VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, &inst));
+    ASSERT_EQ(false, message_found);
+
+    // Create the debug utils messenger to collect general errors/warnings
+    VkDebugUtilsMessengerEXT messenger = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS, CreateUtilsMessenger(inst, VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
+                                               VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, &messenger));
+
+    uint32_t max_count = 5;
+    std::array<VkPhysicalDevice, 5> devices;
+    ASSERT_EQ(env->vulkan_functions.vkEnumeratePhysicalDevices(inst, &max_count, devices.data()), VK_INCOMPLETE);
+
+    // Now that we should have gotten our message, destroy the messenger
+    ASSERT_EQ(VK_SUCCESS, DestroyUtilsMessenger(inst, messenger));
+
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    // Message should be found
+    ASSERT_EQ(true, message_found);
+}
+
+// Test messenger created outside of vkCreateInstance with a manual info message of the wrong message severity to be logged.
+TEST_F(ManualMessage, InfoMessageIgnoredSeverity) {
+    const char my_message[] = "This is my special message!";
+    expected_message = my_message;
+    expected_object_type = VK_OBJECT_TYPE_INSTANCE;
+    expected_message_flags = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+    expected_severity_flags = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS, CreateUtilsInstance(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
+                                              VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, &inst));
+
+    // Create the debug utils messenger to collect general errors/warnings
+    VkDebugUtilsMessengerEXT messenger = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS,
+              CreateUtilsMessenger(inst, VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
+                                   VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT,
+                                   &messenger));
+
+    // Trigger the message
+    PFN_vkSubmitDebugUtilsMessageEXT submit_message = reinterpret_cast<PFN_vkSubmitDebugUtilsMessageEXT>(
+        env->vulkan_functions.vkGetInstanceProcAddr(inst, "vkSubmitDebugUtilsMessageEXT"));
+    ASSERT_NE(nullptr, submit_message);
+
+    VkDebugUtilsObjectNameInfoEXT object{VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT};
+    object.objectType = VK_OBJECT_TYPE_INSTANCE;
+    object.objectHandle = (uint64_t)inst;
+    VkDebugUtilsMessengerCallbackDataEXT message_data{VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT};
+    message_data.pMessage = my_message;
+    message_data.objectCount = 1;
+    message_data.pObjects = &object;
+    submit_message(inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, &message_data);
+
+    // Now that we should have gotten our message, destroy the messenger
+    ASSERT_EQ(VK_SUCCESS, DestroyUtilsMessenger(inst, messenger));
+
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    // Message should not be found
+    ASSERT_EQ(false, message_found);
+}
+
+// Test messenger created outside of vkCreateInstance with a manual info message of the wrong object type to be logged.
+TEST_F(ManualMessage, InfoMessageIgnoredObject) {
+    const char my_message[] = "This is my special message!";
+    expected_message = my_message;
+    expected_object_type = VK_OBJECT_TYPE_INSTANCE;
+    expected_message_flags = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+    expected_severity_flags = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS, CreateUtilsInstance(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
+                                              VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, &inst));
+
+    // Create the debug utils messenger to collect general errors/warnings
+    VkDebugUtilsMessengerEXT messenger = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS, CreateUtilsMessenger(inst, VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
+                                               VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, &messenger));
+
+    // Trigger the message
+    PFN_vkSubmitDebugUtilsMessageEXT submit_message = reinterpret_cast<PFN_vkSubmitDebugUtilsMessageEXT>(
+        env->vulkan_functions.vkGetInstanceProcAddr(inst, "vkSubmitDebugUtilsMessageEXT"));
+    ASSERT_NE(nullptr, submit_message);
+
+    VkDebugUtilsObjectNameInfoEXT object{VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT};
+    object.objectType = VK_OBJECT_TYPE_COMMAND_POOL;
+    object.objectHandle = (uint64_t)inst;
+    VkDebugUtilsMessengerCallbackDataEXT message_data{VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT};
+    message_data.pMessage = my_message;
+    message_data.objectCount = 1;
+    message_data.pObjects = &object;
+    submit_message(inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, &message_data);
+
+    // Now that we should have gotten our message, destroy the messenger
+    ASSERT_EQ(VK_SUCCESS, DestroyUtilsMessenger(inst, messenger));
+
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    // Message should not be found
+    ASSERT_EQ(false, message_found);
+}
+
+// Test messenger created outside of vkCreateInstance with a manual info message.
+TEST_F(ManualMessage, InfoMessage) {
+    const char my_message[] = "This is my special message!";
+    expected_message = my_message;
+    expected_object_type = VK_OBJECT_TYPE_INSTANCE;
+    expected_message_flags = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+    expected_severity_flags = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+
+    VkInstance inst = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS, CreateUtilsInstance(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
+                                              VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, &inst));
+
+    // Create the debug utils messenger to collect general errors/warnings
+    VkDebugUtilsMessengerEXT messenger = VK_NULL_HANDLE;
+    ASSERT_EQ(VK_SUCCESS, CreateUtilsMessenger(inst, VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
+                                               VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, &messenger));
+
+    // Trigger the message
+    PFN_vkSubmitDebugUtilsMessageEXT submit_message = reinterpret_cast<PFN_vkSubmitDebugUtilsMessageEXT>(
+        env->vulkan_functions.vkGetInstanceProcAddr(inst, "vkSubmitDebugUtilsMessageEXT"));
+    ASSERT_NE(nullptr, submit_message);
+
+    VkDebugUtilsObjectNameInfoEXT object{VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT};
+    object.objectType = VK_OBJECT_TYPE_INSTANCE;
+    object.objectHandle = (uint64_t)inst;
+    VkDebugUtilsMessengerCallbackDataEXT message_data{VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT};
+    message_data.pMessage = my_message;
+    message_data.objectCount = 1;
+    message_data.pObjects = &object;
+    submit_message(inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, &message_data);
+
+    // Now that we should have gotten our message, destroy the messenger
+    ASSERT_EQ(VK_SUCCESS, DestroyUtilsMessenger(inst, messenger));
+
+    env->vulkan_functions.vkDestroyInstance(inst, nullptr);
+
+    // Message should be found
+    ASSERT_EQ(true, message_found);
+}