Skip to content

Commit afb249f

Browse files
authored
Replaces bespoke call captures from mock gles with gmock (flutter/engine#56995)
test exempt: test only code ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide] and the [C++, Objective-C, Java style guides]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I added new tests to check the change I am making or feature I am adding, or the PR is [test-exempt]. See [testing the engine] for instructions on writing and running engine tests. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I signed the [CLA]. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style [testing the engine]: https://github.com/flutter/engine/blob/main/docs/testing/Testing-the-engine.md [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/master/docs/contributing/Chat.md
1 parent 30289be commit afb249f

File tree

8 files changed

+204
-146
lines changed

8 files changed

+204
-146
lines changed

engine/src/flutter/impeller/renderer/backend/gles/buffer_bindings_gles_unittests.cc

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,18 @@
1212
namespace impeller {
1313
namespace testing {
1414

15+
using ::testing::_;
16+
1517
TEST(BufferBindingsGLESTest, BindUniformData) {
1618
BufferBindingsGLES bindings;
1719
absl::flat_hash_map<std::string, GLint> uniform_bindings;
1820
uniform_bindings["SHADERMETADATA.FOOBAR"] = 1;
1921
bindings.SetUniformBindings(std::move(uniform_bindings));
20-
std::shared_ptr<MockGLES> mock_gl = MockGLES::Init();
22+
auto mock_gles_impl = std::make_unique<MockGLESImpl>();
23+
24+
EXPECT_CALL(*mock_gles_impl, Uniform1fv(_, _, _)).Times(1);
25+
26+
std::shared_ptr<MockGLES> mock_gl = MockGLES::Init(std::move(mock_gles_impl));
2127
std::vector<BufferResource> bound_buffers;
2228
std::vector<TextureAndSampler> bound_textures;
2329

@@ -39,9 +45,6 @@ TEST(BufferBindingsGLESTest, BindUniformData) {
3945
EXPECT_TRUE(bindings.BindUniformData(mock_gl->GetProcTable(), bound_textures,
4046
bound_buffers, Range{0, 0},
4147
Range{0, 1}));
42-
std::vector<std::string> captured_calls = mock_gl->GetCapturedCalls();
43-
EXPECT_TRUE(std::find(captured_calls.begin(), captured_calls.end(),
44-
"glUniform1fv") != captured_calls.end());
4548
}
4649

4750
} // namespace testing

engine/src/flutter/impeller/renderer/backend/gles/test/capabilities_unittests.cc

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,30 +33,29 @@ TEST(CapabilitiesGLES, CanInitializeWithDefaults) {
3333
}
3434

3535
TEST(CapabilitiesGLES, SupportsDecalSamplerAddressMode) {
36-
auto const extensions = std::vector<const unsigned char*>{
37-
reinterpret_cast<const unsigned char*>("GL_KHR_debug"), //
38-
reinterpret_cast<const unsigned char*>("GL_EXT_texture_border_clamp"), //
36+
auto const extensions = std::vector<const char*>{
37+
"GL_KHR_debug", //
38+
"GL_EXT_texture_border_clamp", //
3939
};
4040
auto mock_gles = MockGLES::Init(extensions);
4141
auto capabilities = mock_gles->GetProcTable().GetCapabilities();
4242
EXPECT_TRUE(capabilities->SupportsDecalSamplerAddressMode());
4343
}
4444

4545
TEST(CapabilitiesGLES, SupportsDecalSamplerAddressModeNotOES) {
46-
auto const extensions = std::vector<const unsigned char*>{
47-
reinterpret_cast<const unsigned char*>("GL_KHR_debug"), //
48-
reinterpret_cast<const unsigned char*>("GL_OES_texture_border_clamp"), //
46+
auto const extensions = std::vector<const char*>{
47+
"GL_KHR_debug", //
48+
"GL_OES_texture_border_clamp", //
4949
};
5050
auto mock_gles = MockGLES::Init(extensions);
5151
auto capabilities = mock_gles->GetProcTable().GetCapabilities();
5252
EXPECT_FALSE(capabilities->SupportsDecalSamplerAddressMode());
5353
}
5454

5555
TEST(CapabilitiesGLES, SupportsFramebufferFetch) {
56-
auto const extensions = std::vector<const unsigned char*>{
57-
reinterpret_cast<const unsigned char*>("GL_KHR_debug"), //
58-
reinterpret_cast<const unsigned char*>(
59-
"GL_EXT_shader_framebuffer_fetch"), //
56+
auto const extensions = std::vector<const char*>{
57+
"GL_KHR_debug", //
58+
"GL_EXT_shader_framebuffer_fetch", //
6059
};
6160
auto mock_gles = MockGLES::Init(extensions);
6261
auto capabilities = mock_gles->GetProcTable().GetCapabilities();

engine/src/flutter/impeller/renderer/backend/gles/test/gpu_tracer_gles_unittests.cc

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,38 +10,48 @@
1010
namespace impeller {
1111
namespace testing {
1212

13+
using ::testing::_;
14+
1315
#ifdef IMPELLER_DEBUG
1416
TEST(GPUTracerGLES, CanFormatFramebufferErrorMessage) {
15-
auto const extensions = std::vector<const unsigned char*>{
16-
reinterpret_cast<const unsigned char*>("GL_KHR_debug"), //
17-
reinterpret_cast<const unsigned char*>("GL_EXT_disjoint_timer_query"), //
17+
auto const extensions = std::vector<const char*>{
18+
"GL_KHR_debug", //
19+
"GL_EXT_disjoint_timer_query", //
1820
};
19-
auto mock_gles = MockGLES::Init(extensions);
21+
auto mock_gles_impl = std::make_unique<MockGLESImpl>();
22+
23+
{
24+
::testing::InSequence seq;
25+
auto gen_queries = [](GLsizei n, GLuint* ids) {
26+
for (int i = 0; i < n; ++i) {
27+
ids[i] = i + 1;
28+
}
29+
};
30+
EXPECT_CALL(*mock_gles_impl, GenQueriesEXT(_, _)).WillOnce(gen_queries);
31+
EXPECT_CALL(*mock_gles_impl, BeginQueryEXT(GL_TIME_ELAPSED_EXT, _));
32+
EXPECT_CALL(*mock_gles_impl, EndQueryEXT(GL_TIME_ELAPSED_EXT));
33+
EXPECT_CALL(*mock_gles_impl,
34+
GetQueryObjectuivEXT(_, GL_QUERY_RESULT_AVAILABLE_EXT, _))
35+
.WillOnce([](GLuint id, GLenum target, GLuint* result) {
36+
*result = GL_TRUE;
37+
});
38+
EXPECT_CALL(*mock_gles_impl,
39+
GetQueryObjectui64vEXT(_, GL_QUERY_RESULT_EXT, _))
40+
.WillOnce([](GLuint id, GLenum target, GLuint64* result) {
41+
*result = 1000u;
42+
});
43+
EXPECT_CALL(*mock_gles_impl, DeleteQueriesEXT(_, _));
44+
EXPECT_CALL(*mock_gles_impl, GenQueriesEXT(_, _)).WillOnce(gen_queries);
45+
EXPECT_CALL(*mock_gles_impl, BeginQueryEXT(GL_TIME_ELAPSED_EXT, _));
46+
}
47+
std::shared_ptr<MockGLES> mock_gles =
48+
MockGLES::Init(std::move(mock_gles_impl), extensions);
2049
auto tracer =
2150
std::make_shared<GPUTracerGLES>(mock_gles->GetProcTable(), true);
2251
tracer->RecordRasterThread();
2352
tracer->MarkFrameStart(mock_gles->GetProcTable());
2453
tracer->MarkFrameEnd(mock_gles->GetProcTable());
25-
26-
auto calls = mock_gles->GetCapturedCalls();
27-
28-
std::vector<std::string> expected = {"glGenQueriesEXT", "glBeginQueryEXT",
29-
"glEndQueryEXT"};
30-
for (auto i = 0; i < 3; i++) {
31-
EXPECT_EQ(calls[i], expected[i]);
32-
}
33-
34-
// Begin second frame, which prompts the tracer to query the result
35-
// from the previous frame.
3654
tracer->MarkFrameStart(mock_gles->GetProcTable());
37-
38-
calls = mock_gles->GetCapturedCalls();
39-
std::vector<std::string> expected_b = {"glGetQueryObjectuivEXT",
40-
"glGetQueryObjectui64vEXT",
41-
"glDeleteQueriesEXT"};
42-
for (auto i = 0; i < 3; i++) {
43-
EXPECT_EQ(calls[i], expected_b[i]);
44-
}
4555
}
4656

4757
#endif // IMPELLER_DEBUG

engine/src/flutter/impeller/renderer/backend/gles/test/mock_gles.cc

Lines changed: 53 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,9 @@ static std::mutex g_test_lock;
1919

2020
static std::weak_ptr<MockGLES> g_mock_gles;
2121

22-
static ProcTableGLES::Resolver g_resolver;
22+
static std::vector<const char*> g_extensions;
2323

24-
static std::vector<const unsigned char*> g_extensions;
25-
26-
static const unsigned char* g_version;
27-
28-
// Has friend visibility into MockGLES to record calls.
29-
void RecordGLCall(const char* name) {
30-
if (auto mock_gles = g_mock_gles.lock()) {
31-
mock_gles->RecordCall(name);
32-
}
33-
}
24+
static const char* g_version;
3425

3526
template <typename T, typename U>
3627
struct CheckSameSignature : std::false_type {};
@@ -41,22 +32,34 @@ struct CheckSameSignature<Ret(Args...), Ret(Args...)> : std::true_type {};
4132
// This is a stub function that does nothing/records nothing.
4233
void doNothing() {}
4334

44-
auto const kMockVendor = (unsigned char*)"MockGLES";
45-
const auto kMockShadingLanguageVersion = (unsigned char*)"GLSL ES 1.0";
46-
auto const kExtensions = std::vector<const unsigned char*>{
47-
(unsigned char*)"GL_KHR_debug" //
35+
auto const kMockVendor = "MockGLES";
36+
const auto kMockShadingLanguageVersion = "GLSL ES 1.0";
37+
auto const kExtensions = std::vector<const char*>{
38+
"GL_KHR_debug" //
4839
};
4940

41+
namespace {
42+
template <typename Func, typename... Args>
43+
void CallMockMethod(Func func, Args&&... args) {
44+
if (auto mock_gles = g_mock_gles.lock()) {
45+
if (mock_gles->GetImpl()) {
46+
(mock_gles->GetImpl()->*func)(std::forward<Args>(args)...);
47+
}
48+
}
49+
}
50+
} // namespace
51+
5052
const unsigned char* mockGetString(GLenum name) {
5153
switch (name) {
5254
case GL_VENDOR:
53-
return kMockVendor;
55+
return reinterpret_cast<const unsigned char*>(kMockVendor);
5456
case GL_VERSION:
55-
return g_version;
57+
return reinterpret_cast<const unsigned char*>(g_version);
5658
case GL_SHADING_LANGUAGE_VERSION:
57-
return kMockShadingLanguageVersion;
59+
return reinterpret_cast<const unsigned char*>(
60+
kMockShadingLanguageVersion);
5861
default:
59-
return (unsigned char*)"";
62+
return reinterpret_cast<const unsigned char*>("");
6063
}
6164
}
6265

@@ -66,9 +69,9 @@ static_assert(CheckSameSignature<decltype(mockGetString), //
6669
const unsigned char* mockGetStringi(GLenum name, GLuint index) {
6770
switch (name) {
6871
case GL_EXTENSIONS:
69-
return g_extensions[index];
72+
return reinterpret_cast<const unsigned char*>(g_extensions[index]);
7073
default:
71-
return (unsigned char*)"";
74+
return reinterpret_cast<const unsigned char*>("");
7275
}
7376
}
7477

@@ -102,89 +105,73 @@ GLenum mockGetError() {
102105
static_assert(CheckSameSignature<decltype(mockGetError), //
103106
decltype(glGetError)>::value);
104107

105-
void mockPopDebugGroupKHR() {
106-
RecordGLCall("PopDebugGroupKHR");
107-
}
108+
void mockPopDebugGroupKHR() {}
108109

109110
static_assert(CheckSameSignature<decltype(mockPopDebugGroupKHR), //
110111
decltype(glPopDebugGroupKHR)>::value);
111112

112113
void mockPushDebugGroupKHR(GLenum source,
113114
GLuint id,
114115
GLsizei length,
115-
const GLchar* message) {
116-
RecordGLCall("PushDebugGroupKHR");
117-
}
116+
const GLchar* message) {}
118117

119118
static_assert(CheckSameSignature<decltype(mockPushDebugGroupKHR), //
120119
decltype(glPushDebugGroupKHR)>::value);
121120

122121
void mockGenQueriesEXT(GLsizei n, GLuint* ids) {
123-
RecordGLCall("glGenQueriesEXT");
124-
for (auto i = 0; i < n; i++) {
125-
ids[i] = i + 1;
126-
}
122+
CallMockMethod(&IMockGLESImpl::GenQueriesEXT, n, ids);
127123
}
128124

129125
static_assert(CheckSameSignature<decltype(mockGenQueriesEXT), //
130126
decltype(glGenQueriesEXT)>::value);
131127

132128
void mockBeginQueryEXT(GLenum target, GLuint id) {
133-
RecordGLCall("glBeginQueryEXT");
129+
CallMockMethod(&IMockGLESImpl::BeginQueryEXT, target, id);
134130
}
135131

136132
static_assert(CheckSameSignature<decltype(mockBeginQueryEXT), //
137133
decltype(glBeginQueryEXT)>::value);
138134

139135
void mockEndQueryEXT(GLuint id) {
140-
RecordGLCall("glEndQueryEXT");
136+
CallMockMethod(&IMockGLESImpl::EndQueryEXT, id);
141137
}
142138

143139
static_assert(CheckSameSignature<decltype(mockEndQueryEXT), //
144140
decltype(glEndQueryEXT)>::value);
145141

146142
void mockGetQueryObjectuivEXT(GLuint id, GLenum target, GLuint* result) {
147-
RecordGLCall("glGetQueryObjectuivEXT");
148-
*result = GL_TRUE;
143+
CallMockMethod(&IMockGLESImpl::GetQueryObjectuivEXT, id, target, result);
149144
}
150145

151146
static_assert(CheckSameSignature<decltype(mockGetQueryObjectuivEXT), //
152147
decltype(glGetQueryObjectuivEXT)>::value);
153148

154149
void mockGetQueryObjectui64vEXT(GLuint id, GLenum target, GLuint64* result) {
155-
RecordGLCall("glGetQueryObjectui64vEXT");
156-
*result = 1000u;
150+
CallMockMethod(&IMockGLESImpl::GetQueryObjectui64vEXT, id, target, result);
157151
}
158152

159153
static_assert(CheckSameSignature<decltype(mockGetQueryObjectui64vEXT), //
160154
decltype(glGetQueryObjectui64vEXT)>::value);
161155

162156
void mockDeleteQueriesEXT(GLsizei size, const GLuint* queries) {
163-
RecordGLCall("glDeleteQueriesEXT");
157+
CallMockMethod(&IMockGLESImpl::DeleteQueriesEXT, size, queries);
164158
}
165159

166160
void mockDeleteTextures(GLsizei size, const GLuint* queries) {
167-
RecordGLCall("glDeleteTextures");
161+
CallMockMethod(&IMockGLESImpl::DeleteTextures, size, queries);
168162
}
169163

170164
static_assert(CheckSameSignature<decltype(mockDeleteQueriesEXT), //
171165
decltype(glDeleteQueriesEXT)>::value);
172166

173167
void mockUniform1fv(GLint location, GLsizei count, const GLfloat* value) {
174-
RecordGLCall("glUniform1fv");
168+
CallMockMethod(&IMockGLESImpl::Uniform1fv, location, count, value);
175169
}
176170
static_assert(CheckSameSignature<decltype(mockUniform1fv), //
177171
decltype(glUniform1fv)>::value);
178172

179173
void mockGenTextures(GLsizei n, GLuint* textures) {
180-
RecordGLCall("glGenTextures");
181-
if (auto mock_gles = g_mock_gles.lock()) {
182-
std::optional<uint64_t> next_texture;
183-
std::swap(mock_gles->next_texture_, next_texture);
184-
if (next_texture.has_value()) {
185-
textures[0] = next_texture.value();
186-
}
187-
}
174+
CallMockMethod(&IMockGLESImpl::GenTextures, n, textures);
188175
}
189176

190177
static_assert(CheckSameSignature<decltype(mockGenTextures), //
@@ -194,20 +181,35 @@ void mockObjectLabelKHR(GLenum identifier,
194181
GLuint name,
195182
GLsizei length,
196183
const GLchar* label) {
197-
RecordGLCall("glObjectLabelKHR");
184+
CallMockMethod(&IMockGLESImpl::ObjectLabelKHR, identifier, name, length,
185+
label);
198186
}
199187
static_assert(CheckSameSignature<decltype(mockObjectLabelKHR), //
200188
decltype(glObjectLabelKHR)>::value);
201189

190+
// static
191+
std::shared_ptr<MockGLES> MockGLES::Init(
192+
std::unique_ptr<MockGLESImpl> impl,
193+
const std::optional<std::vector<const char*>>& extensions) {
194+
FML_CHECK(g_test_lock.try_lock())
195+
<< "MockGLES is already being used by another test.";
196+
g_extensions = extensions.value_or(kExtensions);
197+
g_version = "OpenGL ES 3.0";
198+
auto mock_gles = std::shared_ptr<MockGLES>(new MockGLES());
199+
mock_gles->impl_ = std::move(impl);
200+
g_mock_gles = mock_gles;
201+
return mock_gles;
202+
}
203+
202204
std::shared_ptr<MockGLES> MockGLES::Init(
203-
const std::optional<std::vector<const unsigned char*>>& extensions,
205+
const std::optional<std::vector<const char*>>& extensions,
204206
const char* version_string,
205207
ProcTableGLES::Resolver resolver) {
206208
// If we cannot obtain a lock, MockGLES is already being used elsewhere.
207209
FML_CHECK(g_test_lock.try_lock())
208210
<< "MockGLES is already being used by another test.";
209-
g_version = (unsigned char*)version_string;
210211
g_extensions = extensions.value_or(kExtensions);
212+
g_version = version_string;
211213
auto mock_gles = std::shared_ptr<MockGLES>(new MockGLES(std::move(resolver)));
212214
g_mock_gles = mock_gles;
213215
return mock_gles;

0 commit comments

Comments
 (0)