1 #include <gmock/gmock.h>
2 #include <gtest/gtest.h>
3
4 #include "utils/RenderDoc.h"
5
6 #include <type_traits>
7
8 #include "aemu/base/SharedLibrary.h"
9
10 namespace emugl {
11 namespace {
12
13 using ::testing::_;
14 using ::testing::DoAll;
15 using ::testing::InSequence;
16 using ::testing::MockFunction;
17 using ::testing::Return;
18 using ::testing::SetArgPointee;
19
20 using FunctionPtr = android::base::SharedLibrary::FunctionPtr;
21 using RenderDocApi = RenderDoc::RenderDocApi;
22
23 class MockSharedLibrary : public android::base::SharedLibrary {
24 public:
MockSharedLibrary()25 MockSharedLibrary() : SharedLibrary(NULL) {}
26 MOCK_METHOD(FunctionPtr, findSymbol, (const char*), (const, override));
27 };
28
TEST(RenderDocTest,InitializeWithNullSharedLibrary)29 TEST(RenderDocTest, InitializeWithNullSharedLibrary) {
30 EXPECT_EQ(RenderDoc::create(nullptr), nullptr);
31 }
32
TEST(RenderDocTest,CantFindRENDERDOC_GetAPI)33 TEST(RenderDocTest, CantFindRENDERDOC_GetAPI) {
34 MockSharedLibrary sharedLibrary;
35 EXPECT_CALL(sharedLibrary, findSymbol(_)).WillRepeatedly(Return(nullptr));
36 EXPECT_EQ(RenderDoc::create(&sharedLibrary), nullptr);
37 }
38
TEST(RenderDocTest,RENDERDOC_GetAPIFails)39 TEST(RenderDocTest, RENDERDOC_GetAPIFails) {
40 MockSharedLibrary sharedLibrary;
41 static MockFunction<std::remove_pointer_t<pRENDERDOC_GetAPI>> mockRENDERDOC_GetAPI;
42 static pRENDERDOC_GetAPI fpMockRENDERDOC_GetAPI = [](RENDERDOC_Version version,
43 void** outAPIPointers) {
44 return mockRENDERDOC_GetAPI.Call(version, outAPIPointers);
45 };
46 RenderDocApi rdocApi;
47
48 EXPECT_CALL(sharedLibrary, findSymbol(_)).WillRepeatedly(Return(nullptr));
49 EXPECT_CALL(sharedLibrary, findSymbol("RENDERDOC_GetAPI"))
50 .WillRepeatedly(Return(reinterpret_cast<FunctionPtr>(fpMockRENDERDOC_GetAPI)));
51
52 EXPECT_CALL(mockRENDERDOC_GetAPI, Call(_, _))
53 .WillRepeatedly(DoAll(SetArgPointee<1>(&rdocApi), Return(0)));
54 EXPECT_EQ(RenderDoc::create(&sharedLibrary), nullptr);
55
56 EXPECT_CALL(mockRENDERDOC_GetAPI, Call(_, _))
57 .WillRepeatedly(DoAll(SetArgPointee<1>(nullptr), Return(1)));
58 EXPECT_EQ(RenderDoc::create(&sharedLibrary), nullptr);
59 }
60
TEST(RenderDocTest,CreateSuccessfully)61 TEST(RenderDocTest, CreateSuccessfully) {
62 MockSharedLibrary sharedLibrary;
63 static MockFunction<std::remove_pointer_t<pRENDERDOC_GetAPI>> mockRENDERDOC_GetAPI;
64 static pRENDERDOC_GetAPI fpMockRENDERDOC_GetAPI = [](RENDERDOC_Version version,
65 void** outAPIPointers) {
66 return mockRENDERDOC_GetAPI.Call(version, outAPIPointers);
67 };
68 RenderDocApi rdocApiMock;
69 static MockFunction<std::remove_pointer_t<pRENDERDOC_GetCaptureOptionU32>>
70 getCaptureOptionU32Mock;
71 rdocApiMock.GetCaptureOptionU32 = [](RENDERDOC_CaptureOption option) {
72 return getCaptureOptionU32Mock.Call(option);
73 };
74
75 EXPECT_CALL(sharedLibrary, findSymbol(_)).WillRepeatedly(Return(nullptr));
76 EXPECT_CALL(sharedLibrary, findSymbol("RENDERDOC_GetAPI"))
77 .WillRepeatedly(Return(reinterpret_cast<FunctionPtr>(fpMockRENDERDOC_GetAPI)));
78 EXPECT_CALL(mockRENDERDOC_GetAPI, Call(_, _))
79 .WillRepeatedly(DoAll(SetArgPointee<1>(&rdocApiMock), Return(1)));
80 std::unique_ptr<RenderDoc> renderDoc = RenderDoc::create(&sharedLibrary);
81 EXPECT_NE(renderDoc, nullptr);
82
83 EXPECT_CALL(getCaptureOptionU32Mock, Call(eRENDERDOC_Option_DebugOutputMute))
84 .WillRepeatedly(Return(1));
85 EXPECT_EQ(renderDoc->call(RenderDoc::kGetCaptureOptionU32, eRENDERDOC_Option_DebugOutputMute),
86 1);
87 }
88
89 class RenderDocMock {
90 public:
91 // For StartFrameCapture
92 MOCK_METHOD(void, call,
93 (void (*RenderDocApi::*function)(RENDERDOC_DevicePointer, RENDERDOC_WindowHandle),
94 RENDERDOC_DevicePointer, RENDERDOC_WindowHandle),
95 (const));
96 // For EndFrameCapture
97 MOCK_METHOD(uint32_t, call,
98 (uint32_t(*RenderDocApi::*function)(RENDERDOC_DevicePointer,
99 RENDERDOC_WindowHandle),
100 RENDERDOC_DevicePointer, RENDERDOC_WindowHandle),
101 (const));
102 // For IsFrameCapturing
103 MOCK_METHOD(uint32_t, call, (uint32_t(*RenderDocApi::*function)()), (const));
104 };
105
106 using RenderDocWithMultipleVkInstances = RenderDocWithMultipleVkInstancesBase<RenderDocMock>;
107
TEST(RenderDocWithMultipleVkInstancesTest,ShouldNotStartFrameCaptureOnFrameDelimiterWhenNotCapturing)108 TEST(RenderDocWithMultipleVkInstancesTest,
109 ShouldNotStartFrameCaptureOnFrameDelimiterWhenNotCapturing) {
110 RenderDocMock renderDocMock;
111 intptr_t vkInstanceInternal = 0x1234;
112 VkInstance vkInstance = reinterpret_cast<VkInstance>(&vkInstanceInternal);
113 RenderDocWithMultipleVkInstances renderDocWithMultipleVkInstances(renderDocMock);
114
115 EXPECT_CALL(renderDocMock, call(RenderDoc::kIsFrameCapturing)).WillRepeatedly(Return(0));
116 EXPECT_CALL(renderDocMock, call(RenderDoc::kStartFrameCapture, _, _)).Times(0);
117 EXPECT_CALL(renderDocMock, call(RenderDoc::kEndFrameCapture, _, _)).Times(0);
118
119 renderDocWithMultipleVkInstances.onFrameDelimiter(vkInstance);
120 }
121
TEST(RenderDocWithMultipleVkInstancesTest,ShouldStartAndEndFrameCaptureOnFrameDelimiter)122 TEST(RenderDocWithMultipleVkInstancesTest, ShouldStartAndEndFrameCaptureOnFrameDelimiter) {
123 RenderDocMock renderDocMock;
124 intptr_t vkInstanceInternal = 0x4321;
125 VkInstance vkInstance = reinterpret_cast<VkInstance>(&vkInstanceInternal);
126 RenderDocWithMultipleVkInstances renderDocWithMultipleVkInstances(renderDocMock);
127
128 EXPECT_CALL(renderDocMock, call(RenderDoc::kIsFrameCapturing)).WillRepeatedly(Return(1));
129 {
130 InSequence s;
131
132 EXPECT_CALL(renderDocMock, call(RenderDoc::kStartFrameCapture,
133 RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(vkInstance), NULL))
134 .Times(1);
135 EXPECT_CALL(renderDocMock, call(RenderDoc::kEndFrameCapture,
136 RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(vkInstance), NULL))
137 .Times(1)
138 .WillRepeatedly(Return(1));
139 EXPECT_CALL(renderDocMock, call(RenderDoc::kStartFrameCapture,
140 RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(vkInstance), NULL))
141 .Times(1);
142 EXPECT_CALL(renderDocMock, call(RenderDoc::kEndFrameCapture,
143 RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(vkInstance), NULL))
144 .Times(1)
145 .WillRepeatedly(Return(1));
146 }
147
148 renderDocWithMultipleVkInstances.onFrameDelimiter(vkInstance);
149 renderDocWithMultipleVkInstances.onFrameDelimiter(vkInstance);
150 }
151
TEST(RenderDocWithMultipleVkInstancesTest,ShouldEndFrameCaptureOnVkInstanceRemoved)152 TEST(RenderDocWithMultipleVkInstancesTest, ShouldEndFrameCaptureOnVkInstanceRemoved) {
153 RenderDocMock renderDocMock;
154 intptr_t vkInstanceInternal = 0x4321;
155 VkInstance vkInstance = reinterpret_cast<VkInstance>(&vkInstanceInternal);
156 RenderDocWithMultipleVkInstances renderDocWithMultipleVkInstances(renderDocMock);
157
158 EXPECT_CALL(renderDocMock, call(RenderDoc::kIsFrameCapturing)).WillRepeatedly(Return(1));
159 {
160 InSequence s;
161
162 EXPECT_CALL(renderDocMock, call(RenderDoc::kStartFrameCapture,
163 RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(vkInstance), NULL))
164 .Times(1);
165 EXPECT_CALL(renderDocMock, call(RenderDoc::kEndFrameCapture,
166 RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(vkInstance), NULL))
167 .Times(1)
168 .WillRepeatedly(Return(1));
169 }
170
171 renderDocWithMultipleVkInstances.onFrameDelimiter(vkInstance);
172 renderDocWithMultipleVkInstances.removeVkInstance(vkInstance);
173 EXPECT_CALL(renderDocMock, call(RenderDoc::kEndFrameCapture,
174 RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(vkInstance), NULL))
175 .Times(0);
176 }
177 } // namespace
178 } // namespace emugl
179