1 // Copyright 2022 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <gmock/gmock.h>
16 #include <gtest/gtest.h>
17
18 #include "vk_util.h"
19
20 #include <vulkan/vulkan_core.h>
21
22 #include <tuple>
23
24 namespace vk_util {
25 namespace vk_fn_info {
26
27 // Register a fake Vulkan function for testing.
28 using PFN_vkGfxstreamTestFunc = PFN_vkCreateDevice;
29 REGISTER_VK_FN_INFO(GfxstreamTestFunc, ("vkGfxstreamTestFunc", "vkGfxstreamTestFuncGOOGLE",
30 "vkGfxstreamTestFuncGFXSTREAM"))
31 constexpr auto vkGfxstreamTestFuncNames = vk_fn_info::GetVkFnInfo<GfxstreamTestFunc>::names;
32
33 namespace {
34 using ::testing::_;
35 using ::testing::MockFunction;
36 using ::testing::Return;
37 using ::testing::StrEq;
38 using ::testing::StrNe;
39
TEST(getVkInstanceProcAddrWithFallbackTest,ShouldReturnNullOnFailure)40 TEST(getVkInstanceProcAddrWithFallbackTest, ShouldReturnNullOnFailure) {
41 VkInstance instance = reinterpret_cast<VkInstance>(0x1234'0000);
42 MockFunction<std::remove_pointer_t<PFN_vkGetInstanceProcAddr>> vkGetInstanceProcAddrAlwaysNULL;
43
44 EXPECT_CALL(vkGetInstanceProcAddrAlwaysNULL, Call(instance, _)).WillRepeatedly(Return(nullptr));
45
46 EXPECT_EQ(getVkInstanceProcAddrWithFallback<GfxstreamTestFunc>({}, instance), nullptr);
47 EXPECT_EQ(getVkInstanceProcAddrWithFallback<GfxstreamTestFunc>({nullptr, nullptr}, instance),
48 nullptr);
49 EXPECT_EQ(getVkInstanceProcAddrWithFallback<GfxstreamTestFunc>(
50 {vkGetInstanceProcAddrAlwaysNULL.AsStdFunction(),
51 vkGetInstanceProcAddrAlwaysNULL.AsStdFunction()},
52 instance),
53 nullptr);
54 }
55
TEST(getVkInstanceProcAddrWithFallbackTest,ShouldSkipNullVkGetInstanceProcAddr)56 TEST(getVkInstanceProcAddrWithFallbackTest, ShouldSkipNullVkGetInstanceProcAddr) {
57 VkInstance instance = reinterpret_cast<VkInstance>(0x1234'0000);
58 PFN_vkGfxstreamTestFunc validFp = reinterpret_cast<PFN_vkGfxstreamTestFunc>(0x4321'0000);
59 MockFunction<std::remove_pointer_t<PFN_vkGetInstanceProcAddr>> vkGetInstanceProcAddrMock;
60
61 EXPECT_CALL(vkGetInstanceProcAddrMock, Call(instance, _))
62 .WillRepeatedly(Return(reinterpret_cast<PFN_vkVoidFunction>(validFp)));
63
64 EXPECT_EQ(getVkInstanceProcAddrWithFallback<GfxstreamTestFunc>(
65 {nullptr, vkGetInstanceProcAddrMock.AsStdFunction()}, instance),
66 validFp);
67 EXPECT_EQ(getVkInstanceProcAddrWithFallback<GfxstreamTestFunc>(
68 {vkGetInstanceProcAddrMock.AsStdFunction(), nullptr}, instance),
69 validFp);
70 }
71
TEST(getVkInstanceProcAddrWithFallbackTest,ShouldSkipNullFpReturned)72 TEST(getVkInstanceProcAddrWithFallbackTest, ShouldSkipNullFpReturned) {
73 VkInstance instance = reinterpret_cast<VkInstance>(0x1234'0000);
74 PFN_vkGfxstreamTestFunc validFp = reinterpret_cast<PFN_vkGfxstreamTestFunc>(0x4321'0000);
75 MockFunction<std::remove_pointer_t<PFN_vkGetInstanceProcAddr>> vkGetInstanceProcAddrMock;
76 MockFunction<std::remove_pointer_t<PFN_vkGetInstanceProcAddr>> vkGetInstanceProcAddrAlwaysNULL;
77
78 // We know that vkGfxstreamTest has different names.
79 EXPECT_CALL(vkGetInstanceProcAddrMock,
80 Call(instance, StrNe(std::get<1>(vkGfxstreamTestFuncNames))))
81 .WillRepeatedly(Return(nullptr));
82 EXPECT_CALL(vkGetInstanceProcAddrMock,
83 Call(instance, StrEq(std::get<1>(vkGfxstreamTestFuncNames))))
84 .WillRepeatedly(Return(reinterpret_cast<PFN_vkVoidFunction>(validFp)));
85 EXPECT_CALL(vkGetInstanceProcAddrAlwaysNULL, Call(instance, _)).WillRepeatedly(Return(nullptr));
86
87 EXPECT_EQ(getVkInstanceProcAddrWithFallback<GfxstreamTestFunc>(
88 {vkGetInstanceProcAddrMock.AsStdFunction(),
89 vkGetInstanceProcAddrAlwaysNULL.AsStdFunction()},
90 instance),
91 validFp);
92 EXPECT_EQ(getVkInstanceProcAddrWithFallback<GfxstreamTestFunc>(
93 {vkGetInstanceProcAddrAlwaysNULL.AsStdFunction(),
94 vkGetInstanceProcAddrMock.AsStdFunction()},
95 instance),
96 validFp);
97 }
98
TEST(getVkInstanceProcAddrWithFallbackTest,firstVkInstanceProcAddrShouldTakeThePriority)99 TEST(getVkInstanceProcAddrWithFallbackTest, firstVkInstanceProcAddrShouldTakeThePriority) {
100 VkInstance instance = reinterpret_cast<VkInstance>(0x1234'0000);
101 PFN_vkGfxstreamTestFunc validFp1 = reinterpret_cast<PFN_vkGfxstreamTestFunc>(0x4321'0000);
102 PFN_vkGfxstreamTestFunc validFp2 = reinterpret_cast<PFN_vkGfxstreamTestFunc>(0x3421'0070);
103 MockFunction<std::remove_pointer_t<PFN_vkGetInstanceProcAddr>> vkGetInstanceProcAddrMock1;
104 MockFunction<std::remove_pointer_t<PFN_vkGetInstanceProcAddr>> vkGetInstanceProcAddrMock2;
105
106 EXPECT_CALL(vkGetInstanceProcAddrMock1, Call(instance, _))
107 .WillRepeatedly(Return(reinterpret_cast<PFN_vkVoidFunction>(validFp1)));
108 EXPECT_CALL(vkGetInstanceProcAddrMock2, Call(instance, _))
109 .WillRepeatedly(Return(reinterpret_cast<PFN_vkVoidFunction>(validFp2)));
110
111 EXPECT_EQ(getVkInstanceProcAddrWithFallback<GfxstreamTestFunc>(
112 {vkGetInstanceProcAddrMock1.AsStdFunction(),
113 vkGetInstanceProcAddrMock2.AsStdFunction()},
114 instance),
115 validFp1);
116 }
117
TEST(getVkInstanceProcAddrWithFallbackTest,firstNameShouldTakeThePriority)118 TEST(getVkInstanceProcAddrWithFallbackTest, firstNameShouldTakeThePriority) {
119 VkInstance instance = reinterpret_cast<VkInstance>(0x1234'0000);
120 PFN_vkGfxstreamTestFunc validFps[] = {reinterpret_cast<PFN_vkGfxstreamTestFunc>(0x4321'0000),
121 reinterpret_cast<PFN_vkGfxstreamTestFunc>(0x3421'0070),
122 reinterpret_cast<PFN_vkGfxstreamTestFunc>(0x2222'4321)};
123 MockFunction<std::remove_pointer_t<PFN_vkGetInstanceProcAddr>> vkGetInstanceProcAddrMock;
124
125 EXPECT_CALL(vkGetInstanceProcAddrMock,
126 Call(instance, StrEq(std::get<0>(vkGfxstreamTestFuncNames))))
127 .WillRepeatedly(Return(reinterpret_cast<PFN_vkVoidFunction>(validFps[0])));
128 ON_CALL(vkGetInstanceProcAddrMock, Call(instance, StrEq(std::get<1>(vkGfxstreamTestFuncNames))))
129 .WillByDefault(Return(reinterpret_cast<PFN_vkVoidFunction>(validFps[1])));
130 ON_CALL(vkGetInstanceProcAddrMock, Call(instance, StrEq(std::get<2>(vkGfxstreamTestFuncNames))))
131 .WillByDefault(Return(reinterpret_cast<PFN_vkVoidFunction>(validFps[2])));
132
133 EXPECT_EQ(getVkInstanceProcAddrWithFallback<GfxstreamTestFunc>(
134 {vkGetInstanceProcAddrMock.AsStdFunction()}, instance),
135 validFps[0]);
136 }
137
TEST(VkCheckCallbacksDeathTest,deviceLostCallbackShouldBeCalled)138 TEST(VkCheckCallbacksDeathTest, deviceLostCallbackShouldBeCalled) {
139 setVkCheckCallbacks(std::make_unique<VkCheckCallbacks>(VkCheckCallbacks{
140 .onVkErrorDeviceLost = [] { exit(43); },
141 }));
142
143 EXPECT_EXIT(VK_CHECK(VK_ERROR_DEVICE_LOST), testing::ExitedWithCode(43), "");
144 }
145
TEST(VkCheckCallbacksDeathTest,deviceLostCallbackShouldNotBeCalled)146 TEST(VkCheckCallbacksDeathTest, deviceLostCallbackShouldNotBeCalled) {
147 // Default death function uses exit code 42
148 emugl::setDieFunction([] { exit(42); });
149
150 // Device lost death function uses exit code 43
151 setVkCheckCallbacks(std::make_unique<VkCheckCallbacks>(VkCheckCallbacks{
152 .onVkErrorDeviceLost = [] { exit(43); },
153 }));
154
155 EXPECT_EXIT(VK_CHECK(VK_ERROR_OUT_OF_DEVICE_MEMORY), testing::ExitedWithCode(42), "");
156 }
157
TEST(VkCheckCallbacksDeathTest,nullCallbacksShouldntCrash)158 TEST(VkCheckCallbacksDeathTest, nullCallbacksShouldntCrash) {
159 emugl::setDieFunction([] { exit(42); });
160 setVkCheckCallbacks(nullptr);
161 EXPECT_EXIT(VK_CHECK(VK_ERROR_DEVICE_LOST), testing::ExitedWithCode(42), "");
162 }
163
TEST(VkCheckCallbacksDeathTest,nullVkDeviceLostErrorCallbackShouldntCrash)164 TEST(VkCheckCallbacksDeathTest, nullVkDeviceLostErrorCallbackShouldntCrash) {
165 emugl::setDieFunction([] { exit(42); });
166 setVkCheckCallbacks(
167 std::make_unique<VkCheckCallbacks>(VkCheckCallbacks{.onVkErrorDeviceLost = nullptr}));
168 EXPECT_EXIT(VK_CHECK(VK_ERROR_DEVICE_LOST), testing::ExitedWithCode(42), "");
169 }
170
171 } // namespace
172 } // namespace vk_fn_info
173 } // namespace vk_util
174