Reland: Replaces bespoke call captures from mock gles with gmock (flutter/engine#57019)
relands https://github.com/flutter/engine/pull/56995 It previously landed with stale presubmits, this should be up to date now. I have the fix in a separate commit. [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This commit is contained in:
parent
0e4fafd629
commit
592ceb7326
@ -12,12 +12,18 @@
|
|||||||
namespace impeller {
|
namespace impeller {
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
|
using ::testing::_;
|
||||||
|
|
||||||
TEST(BufferBindingsGLESTest, BindUniformData) {
|
TEST(BufferBindingsGLESTest, BindUniformData) {
|
||||||
BufferBindingsGLES bindings;
|
BufferBindingsGLES bindings;
|
||||||
absl::flat_hash_map<std::string, GLint> uniform_bindings;
|
absl::flat_hash_map<std::string, GLint> uniform_bindings;
|
||||||
uniform_bindings["SHADERMETADATA.FOOBAR"] = 1;
|
uniform_bindings["SHADERMETADATA.FOOBAR"] = 1;
|
||||||
bindings.SetUniformBindings(std::move(uniform_bindings));
|
bindings.SetUniformBindings(std::move(uniform_bindings));
|
||||||
std::shared_ptr<MockGLES> mock_gl = MockGLES::Init();
|
auto mock_gles_impl = std::make_unique<MockGLESImpl>();
|
||||||
|
|
||||||
|
EXPECT_CALL(*mock_gles_impl, Uniform1fv(_, _, _)).Times(1);
|
||||||
|
|
||||||
|
std::shared_ptr<MockGLES> mock_gl = MockGLES::Init(std::move(mock_gles_impl));
|
||||||
std::vector<BufferResource> bound_buffers;
|
std::vector<BufferResource> bound_buffers;
|
||||||
std::vector<TextureAndSampler> bound_textures;
|
std::vector<TextureAndSampler> bound_textures;
|
||||||
|
|
||||||
@ -39,9 +45,6 @@ TEST(BufferBindingsGLESTest, BindUniformData) {
|
|||||||
EXPECT_TRUE(bindings.BindUniformData(mock_gl->GetProcTable(), bound_textures,
|
EXPECT_TRUE(bindings.BindUniformData(mock_gl->GetProcTable(), bound_textures,
|
||||||
bound_buffers, Range{0, 0},
|
bound_buffers, Range{0, 0},
|
||||||
Range{0, 1}));
|
Range{0, 1}));
|
||||||
std::vector<std::string> captured_calls = mock_gl->GetCapturedCalls();
|
|
||||||
EXPECT_TRUE(std::find(captured_calls.begin(), captured_calls.end(),
|
|
||||||
"glUniform1fv") != captured_calls.end());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
@ -33,9 +33,9 @@ TEST(CapabilitiesGLES, CanInitializeWithDefaults) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(CapabilitiesGLES, SupportsDecalSamplerAddressMode) {
|
TEST(CapabilitiesGLES, SupportsDecalSamplerAddressMode) {
|
||||||
auto const extensions = std::vector<const unsigned char*>{
|
auto const extensions = std::vector<const char*>{
|
||||||
reinterpret_cast<const unsigned char*>("GL_KHR_debug"), //
|
"GL_KHR_debug", //
|
||||||
reinterpret_cast<const unsigned char*>("GL_EXT_texture_border_clamp"), //
|
"GL_EXT_texture_border_clamp", //
|
||||||
};
|
};
|
||||||
auto mock_gles = MockGLES::Init(extensions);
|
auto mock_gles = MockGLES::Init(extensions);
|
||||||
auto capabilities = mock_gles->GetProcTable().GetCapabilities();
|
auto capabilities = mock_gles->GetProcTable().GetCapabilities();
|
||||||
@ -43,9 +43,9 @@ TEST(CapabilitiesGLES, SupportsDecalSamplerAddressMode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(CapabilitiesGLES, SupportsDecalSamplerAddressModeNotOES) {
|
TEST(CapabilitiesGLES, SupportsDecalSamplerAddressModeNotOES) {
|
||||||
auto const extensions = std::vector<const unsigned char*>{
|
auto const extensions = std::vector<const char*>{
|
||||||
reinterpret_cast<const unsigned char*>("GL_KHR_debug"), //
|
"GL_KHR_debug", //
|
||||||
reinterpret_cast<const unsigned char*>("GL_OES_texture_border_clamp"), //
|
"GL_OES_texture_border_clamp", //
|
||||||
};
|
};
|
||||||
auto mock_gles = MockGLES::Init(extensions);
|
auto mock_gles = MockGLES::Init(extensions);
|
||||||
auto capabilities = mock_gles->GetProcTable().GetCapabilities();
|
auto capabilities = mock_gles->GetProcTable().GetCapabilities();
|
||||||
@ -53,10 +53,9 @@ TEST(CapabilitiesGLES, SupportsDecalSamplerAddressModeNotOES) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(CapabilitiesGLES, SupportsFramebufferFetch) {
|
TEST(CapabilitiesGLES, SupportsFramebufferFetch) {
|
||||||
auto const extensions = std::vector<const unsigned char*>{
|
auto const extensions = std::vector<const char*>{
|
||||||
reinterpret_cast<const unsigned char*>("GL_KHR_debug"), //
|
"GL_KHR_debug", //
|
||||||
reinterpret_cast<const unsigned char*>(
|
"GL_EXT_shader_framebuffer_fetch", //
|
||||||
"GL_EXT_shader_framebuffer_fetch"), //
|
|
||||||
};
|
};
|
||||||
auto mock_gles = MockGLES::Init(extensions);
|
auto mock_gles = MockGLES::Init(extensions);
|
||||||
auto capabilities = mock_gles->GetProcTable().GetCapabilities();
|
auto capabilities = mock_gles->GetProcTable().GetCapabilities();
|
||||||
@ -64,9 +63,8 @@ TEST(CapabilitiesGLES, SupportsFramebufferFetch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(CapabilitiesGLES, SupportsMSAA) {
|
TEST(CapabilitiesGLES, SupportsMSAA) {
|
||||||
auto const extensions = std::vector<const unsigned char*>{
|
auto const extensions = std::vector<const char*>{
|
||||||
reinterpret_cast<const unsigned char*>(
|
"GL_EXT_multisampled_render_to_texture",
|
||||||
"GL_EXT_multisampled_render_to_texture"),
|
|
||||||
};
|
};
|
||||||
auto mock_gles = MockGLES::Init(extensions);
|
auto mock_gles = MockGLES::Init(extensions);
|
||||||
auto capabilities = mock_gles->GetProcTable().GetCapabilities();
|
auto capabilities = mock_gles->GetProcTable().GetCapabilities();
|
||||||
|
@ -10,38 +10,48 @@
|
|||||||
namespace impeller {
|
namespace impeller {
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
|
using ::testing::_;
|
||||||
|
|
||||||
#ifdef IMPELLER_DEBUG
|
#ifdef IMPELLER_DEBUG
|
||||||
TEST(GPUTracerGLES, CanFormatFramebufferErrorMessage) {
|
TEST(GPUTracerGLES, CanFormatFramebufferErrorMessage) {
|
||||||
auto const extensions = std::vector<const unsigned char*>{
|
auto const extensions = std::vector<const char*>{
|
||||||
reinterpret_cast<const unsigned char*>("GL_KHR_debug"), //
|
"GL_KHR_debug", //
|
||||||
reinterpret_cast<const unsigned char*>("GL_EXT_disjoint_timer_query"), //
|
"GL_EXT_disjoint_timer_query", //
|
||||||
};
|
};
|
||||||
auto mock_gles = MockGLES::Init(extensions);
|
auto mock_gles_impl = std::make_unique<MockGLESImpl>();
|
||||||
|
|
||||||
|
{
|
||||||
|
::testing::InSequence seq;
|
||||||
|
auto gen_queries = [](GLsizei n, GLuint* ids) {
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
ids[i] = i + 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
EXPECT_CALL(*mock_gles_impl, GenQueriesEXT(_, _)).WillOnce(gen_queries);
|
||||||
|
EXPECT_CALL(*mock_gles_impl, BeginQueryEXT(GL_TIME_ELAPSED_EXT, _));
|
||||||
|
EXPECT_CALL(*mock_gles_impl, EndQueryEXT(GL_TIME_ELAPSED_EXT));
|
||||||
|
EXPECT_CALL(*mock_gles_impl,
|
||||||
|
GetQueryObjectuivEXT(_, GL_QUERY_RESULT_AVAILABLE_EXT, _))
|
||||||
|
.WillOnce([](GLuint id, GLenum target, GLuint* result) {
|
||||||
|
*result = GL_TRUE;
|
||||||
|
});
|
||||||
|
EXPECT_CALL(*mock_gles_impl,
|
||||||
|
GetQueryObjectui64vEXT(_, GL_QUERY_RESULT_EXT, _))
|
||||||
|
.WillOnce([](GLuint id, GLenum target, GLuint64* result) {
|
||||||
|
*result = 1000u;
|
||||||
|
});
|
||||||
|
EXPECT_CALL(*mock_gles_impl, DeleteQueriesEXT(_, _));
|
||||||
|
EXPECT_CALL(*mock_gles_impl, GenQueriesEXT(_, _)).WillOnce(gen_queries);
|
||||||
|
EXPECT_CALL(*mock_gles_impl, BeginQueryEXT(GL_TIME_ELAPSED_EXT, _));
|
||||||
|
}
|
||||||
|
std::shared_ptr<MockGLES> mock_gles =
|
||||||
|
MockGLES::Init(std::move(mock_gles_impl), extensions);
|
||||||
auto tracer =
|
auto tracer =
|
||||||
std::make_shared<GPUTracerGLES>(mock_gles->GetProcTable(), true);
|
std::make_shared<GPUTracerGLES>(mock_gles->GetProcTable(), true);
|
||||||
tracer->RecordRasterThread();
|
tracer->RecordRasterThread();
|
||||||
tracer->MarkFrameStart(mock_gles->GetProcTable());
|
tracer->MarkFrameStart(mock_gles->GetProcTable());
|
||||||
tracer->MarkFrameEnd(mock_gles->GetProcTable());
|
tracer->MarkFrameEnd(mock_gles->GetProcTable());
|
||||||
|
|
||||||
auto calls = mock_gles->GetCapturedCalls();
|
|
||||||
|
|
||||||
std::vector<std::string> expected = {"glGenQueriesEXT", "glBeginQueryEXT",
|
|
||||||
"glEndQueryEXT"};
|
|
||||||
for (auto i = 0; i < 3; i++) {
|
|
||||||
EXPECT_EQ(calls[i], expected[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Begin second frame, which prompts the tracer to query the result
|
|
||||||
// from the previous frame.
|
|
||||||
tracer->MarkFrameStart(mock_gles->GetProcTable());
|
tracer->MarkFrameStart(mock_gles->GetProcTable());
|
||||||
|
|
||||||
calls = mock_gles->GetCapturedCalls();
|
|
||||||
std::vector<std::string> expected_b = {"glGetQueryObjectuivEXT",
|
|
||||||
"glGetQueryObjectui64vEXT",
|
|
||||||
"glDeleteQueriesEXT"};
|
|
||||||
for (auto i = 0; i < 3; i++) {
|
|
||||||
EXPECT_EQ(calls[i], expected_b[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // IMPELLER_DEBUG
|
#endif // IMPELLER_DEBUG
|
||||||
|
@ -19,18 +19,9 @@ static std::mutex g_test_lock;
|
|||||||
|
|
||||||
static std::weak_ptr<MockGLES> g_mock_gles;
|
static std::weak_ptr<MockGLES> g_mock_gles;
|
||||||
|
|
||||||
static ProcTableGLES::Resolver g_resolver;
|
static std::vector<const char*> g_extensions;
|
||||||
|
|
||||||
static std::vector<const unsigned char*> g_extensions;
|
static const char* g_version;
|
||||||
|
|
||||||
static const unsigned char* g_version;
|
|
||||||
|
|
||||||
// Has friend visibility into MockGLES to record calls.
|
|
||||||
void RecordGLCall(const char* name) {
|
|
||||||
if (auto mock_gles = g_mock_gles.lock()) {
|
|
||||||
mock_gles->RecordCall(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
struct CheckSameSignature : std::false_type {};
|
struct CheckSameSignature : std::false_type {};
|
||||||
@ -41,22 +32,34 @@ struct CheckSameSignature<Ret(Args...), Ret(Args...)> : std::true_type {};
|
|||||||
// This is a stub function that does nothing/records nothing.
|
// This is a stub function that does nothing/records nothing.
|
||||||
void doNothing() {}
|
void doNothing() {}
|
||||||
|
|
||||||
auto const kMockVendor = (unsigned char*)"MockGLES";
|
auto const kMockVendor = "MockGLES";
|
||||||
const auto kMockShadingLanguageVersion = (unsigned char*)"GLSL ES 1.0";
|
const auto kMockShadingLanguageVersion = "GLSL ES 1.0";
|
||||||
auto const kExtensions = std::vector<const unsigned char*>{
|
auto const kExtensions = std::vector<const char*>{
|
||||||
(unsigned char*)"GL_KHR_debug" //
|
"GL_KHR_debug" //
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
template <typename Func, typename... Args>
|
||||||
|
void CallMockMethod(Func func, Args&&... args) {
|
||||||
|
if (auto mock_gles = g_mock_gles.lock()) {
|
||||||
|
if (mock_gles->GetImpl()) {
|
||||||
|
(mock_gles->GetImpl()->*func)(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
const unsigned char* mockGetString(GLenum name) {
|
const unsigned char* mockGetString(GLenum name) {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case GL_VENDOR:
|
case GL_VENDOR:
|
||||||
return kMockVendor;
|
return reinterpret_cast<const unsigned char*>(kMockVendor);
|
||||||
case GL_VERSION:
|
case GL_VERSION:
|
||||||
return g_version;
|
return reinterpret_cast<const unsigned char*>(g_version);
|
||||||
case GL_SHADING_LANGUAGE_VERSION:
|
case GL_SHADING_LANGUAGE_VERSION:
|
||||||
return kMockShadingLanguageVersion;
|
return reinterpret_cast<const unsigned char*>(
|
||||||
|
kMockShadingLanguageVersion);
|
||||||
default:
|
default:
|
||||||
return (unsigned char*)"";
|
return reinterpret_cast<const unsigned char*>("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,9 +69,9 @@ static_assert(CheckSameSignature<decltype(mockGetString), //
|
|||||||
const unsigned char* mockGetStringi(GLenum name, GLuint index) {
|
const unsigned char* mockGetStringi(GLenum name, GLuint index) {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case GL_EXTENSIONS:
|
case GL_EXTENSIONS:
|
||||||
return g_extensions[index];
|
return reinterpret_cast<const unsigned char*>(g_extensions[index]);
|
||||||
default:
|
default:
|
||||||
return (unsigned char*)"";
|
return reinterpret_cast<const unsigned char*>("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,9 +105,7 @@ GLenum mockGetError() {
|
|||||||
static_assert(CheckSameSignature<decltype(mockGetError), //
|
static_assert(CheckSameSignature<decltype(mockGetError), //
|
||||||
decltype(glGetError)>::value);
|
decltype(glGetError)>::value);
|
||||||
|
|
||||||
void mockPopDebugGroupKHR() {
|
void mockPopDebugGroupKHR() {}
|
||||||
RecordGLCall("PopDebugGroupKHR");
|
|
||||||
}
|
|
||||||
|
|
||||||
static_assert(CheckSameSignature<decltype(mockPopDebugGroupKHR), //
|
static_assert(CheckSameSignature<decltype(mockPopDebugGroupKHR), //
|
||||||
decltype(glPopDebugGroupKHR)>::value);
|
decltype(glPopDebugGroupKHR)>::value);
|
||||||
@ -112,79 +113,65 @@ static_assert(CheckSameSignature<decltype(mockPopDebugGroupKHR), //
|
|||||||
void mockPushDebugGroupKHR(GLenum source,
|
void mockPushDebugGroupKHR(GLenum source,
|
||||||
GLuint id,
|
GLuint id,
|
||||||
GLsizei length,
|
GLsizei length,
|
||||||
const GLchar* message) {
|
const GLchar* message) {}
|
||||||
RecordGLCall("PushDebugGroupKHR");
|
|
||||||
}
|
|
||||||
|
|
||||||
static_assert(CheckSameSignature<decltype(mockPushDebugGroupKHR), //
|
static_assert(CheckSameSignature<decltype(mockPushDebugGroupKHR), //
|
||||||
decltype(glPushDebugGroupKHR)>::value);
|
decltype(glPushDebugGroupKHR)>::value);
|
||||||
|
|
||||||
void mockGenQueriesEXT(GLsizei n, GLuint* ids) {
|
void mockGenQueriesEXT(GLsizei n, GLuint* ids) {
|
||||||
RecordGLCall("glGenQueriesEXT");
|
CallMockMethod(&IMockGLESImpl::GenQueriesEXT, n, ids);
|
||||||
for (auto i = 0; i < n; i++) {
|
|
||||||
ids[i] = i + 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert(CheckSameSignature<decltype(mockGenQueriesEXT), //
|
static_assert(CheckSameSignature<decltype(mockGenQueriesEXT), //
|
||||||
decltype(glGenQueriesEXT)>::value);
|
decltype(glGenQueriesEXT)>::value);
|
||||||
|
|
||||||
void mockBeginQueryEXT(GLenum target, GLuint id) {
|
void mockBeginQueryEXT(GLenum target, GLuint id) {
|
||||||
RecordGLCall("glBeginQueryEXT");
|
CallMockMethod(&IMockGLESImpl::BeginQueryEXT, target, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert(CheckSameSignature<decltype(mockBeginQueryEXT), //
|
static_assert(CheckSameSignature<decltype(mockBeginQueryEXT), //
|
||||||
decltype(glBeginQueryEXT)>::value);
|
decltype(glBeginQueryEXT)>::value);
|
||||||
|
|
||||||
void mockEndQueryEXT(GLuint id) {
|
void mockEndQueryEXT(GLuint id) {
|
||||||
RecordGLCall("glEndQueryEXT");
|
CallMockMethod(&IMockGLESImpl::EndQueryEXT, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert(CheckSameSignature<decltype(mockEndQueryEXT), //
|
static_assert(CheckSameSignature<decltype(mockEndQueryEXT), //
|
||||||
decltype(glEndQueryEXT)>::value);
|
decltype(glEndQueryEXT)>::value);
|
||||||
|
|
||||||
void mockGetQueryObjectuivEXT(GLuint id, GLenum target, GLuint* result) {
|
void mockGetQueryObjectuivEXT(GLuint id, GLenum target, GLuint* result) {
|
||||||
RecordGLCall("glGetQueryObjectuivEXT");
|
CallMockMethod(&IMockGLESImpl::GetQueryObjectuivEXT, id, target, result);
|
||||||
*result = GL_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert(CheckSameSignature<decltype(mockGetQueryObjectuivEXT), //
|
static_assert(CheckSameSignature<decltype(mockGetQueryObjectuivEXT), //
|
||||||
decltype(glGetQueryObjectuivEXT)>::value);
|
decltype(glGetQueryObjectuivEXT)>::value);
|
||||||
|
|
||||||
void mockGetQueryObjectui64vEXT(GLuint id, GLenum target, GLuint64* result) {
|
void mockGetQueryObjectui64vEXT(GLuint id, GLenum target, GLuint64* result) {
|
||||||
RecordGLCall("glGetQueryObjectui64vEXT");
|
CallMockMethod(&IMockGLESImpl::GetQueryObjectui64vEXT, id, target, result);
|
||||||
*result = 1000u;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert(CheckSameSignature<decltype(mockGetQueryObjectui64vEXT), //
|
static_assert(CheckSameSignature<decltype(mockGetQueryObjectui64vEXT), //
|
||||||
decltype(glGetQueryObjectui64vEXT)>::value);
|
decltype(glGetQueryObjectui64vEXT)>::value);
|
||||||
|
|
||||||
void mockDeleteQueriesEXT(GLsizei size, const GLuint* queries) {
|
void mockDeleteQueriesEXT(GLsizei size, const GLuint* queries) {
|
||||||
RecordGLCall("glDeleteQueriesEXT");
|
CallMockMethod(&IMockGLESImpl::DeleteQueriesEXT, size, queries);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mockDeleteTextures(GLsizei size, const GLuint* queries) {
|
void mockDeleteTextures(GLsizei size, const GLuint* queries) {
|
||||||
RecordGLCall("glDeleteTextures");
|
CallMockMethod(&IMockGLESImpl::DeleteTextures, size, queries);
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert(CheckSameSignature<decltype(mockDeleteQueriesEXT), //
|
static_assert(CheckSameSignature<decltype(mockDeleteQueriesEXT), //
|
||||||
decltype(glDeleteQueriesEXT)>::value);
|
decltype(glDeleteQueriesEXT)>::value);
|
||||||
|
|
||||||
void mockUniform1fv(GLint location, GLsizei count, const GLfloat* value) {
|
void mockUniform1fv(GLint location, GLsizei count, const GLfloat* value) {
|
||||||
RecordGLCall("glUniform1fv");
|
CallMockMethod(&IMockGLESImpl::Uniform1fv, location, count, value);
|
||||||
}
|
}
|
||||||
static_assert(CheckSameSignature<decltype(mockUniform1fv), //
|
static_assert(CheckSameSignature<decltype(mockUniform1fv), //
|
||||||
decltype(glUniform1fv)>::value);
|
decltype(glUniform1fv)>::value);
|
||||||
|
|
||||||
void mockGenTextures(GLsizei n, GLuint* textures) {
|
void mockGenTextures(GLsizei n, GLuint* textures) {
|
||||||
RecordGLCall("glGenTextures");
|
CallMockMethod(&IMockGLESImpl::GenTextures, n, textures);
|
||||||
if (auto mock_gles = g_mock_gles.lock()) {
|
|
||||||
std::optional<uint64_t> next_texture;
|
|
||||||
std::swap(mock_gles->next_texture_, next_texture);
|
|
||||||
if (next_texture.has_value()) {
|
|
||||||
textures[0] = next_texture.value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert(CheckSameSignature<decltype(mockGenTextures), //
|
static_assert(CheckSameSignature<decltype(mockGenTextures), //
|
||||||
@ -194,20 +181,35 @@ void mockObjectLabelKHR(GLenum identifier,
|
|||||||
GLuint name,
|
GLuint name,
|
||||||
GLsizei length,
|
GLsizei length,
|
||||||
const GLchar* label) {
|
const GLchar* label) {
|
||||||
RecordGLCall("glObjectLabelKHR");
|
CallMockMethod(&IMockGLESImpl::ObjectLabelKHR, identifier, name, length,
|
||||||
|
label);
|
||||||
}
|
}
|
||||||
static_assert(CheckSameSignature<decltype(mockObjectLabelKHR), //
|
static_assert(CheckSameSignature<decltype(mockObjectLabelKHR), //
|
||||||
decltype(glObjectLabelKHR)>::value);
|
decltype(glObjectLabelKHR)>::value);
|
||||||
|
|
||||||
|
// static
|
||||||
std::shared_ptr<MockGLES> MockGLES::Init(
|
std::shared_ptr<MockGLES> MockGLES::Init(
|
||||||
const std::optional<std::vector<const unsigned char*>>& extensions,
|
std::unique_ptr<MockGLESImpl> impl,
|
||||||
|
const std::optional<std::vector<const char*>>& extensions) {
|
||||||
|
FML_CHECK(g_test_lock.try_lock())
|
||||||
|
<< "MockGLES is already being used by another test.";
|
||||||
|
g_extensions = extensions.value_or(kExtensions);
|
||||||
|
g_version = "OpenGL ES 3.0";
|
||||||
|
auto mock_gles = std::shared_ptr<MockGLES>(new MockGLES());
|
||||||
|
mock_gles->impl_ = std::move(impl);
|
||||||
|
g_mock_gles = mock_gles;
|
||||||
|
return mock_gles;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<MockGLES> MockGLES::Init(
|
||||||
|
const std::optional<std::vector<const char*>>& extensions,
|
||||||
const char* version_string,
|
const char* version_string,
|
||||||
ProcTableGLES::Resolver resolver) {
|
ProcTableGLES::Resolver resolver) {
|
||||||
// If we cannot obtain a lock, MockGLES is already being used elsewhere.
|
// If we cannot obtain a lock, MockGLES is already being used elsewhere.
|
||||||
FML_CHECK(g_test_lock.try_lock())
|
FML_CHECK(g_test_lock.try_lock())
|
||||||
<< "MockGLES is already being used by another test.";
|
<< "MockGLES is already being used by another test.";
|
||||||
g_version = (unsigned char*)version_string;
|
|
||||||
g_extensions = extensions.value_or(kExtensions);
|
g_extensions = extensions.value_or(kExtensions);
|
||||||
|
g_version = version_string;
|
||||||
auto mock_gles = std::shared_ptr<MockGLES>(new MockGLES(std::move(resolver)));
|
auto mock_gles = std::shared_ptr<MockGLES>(new MockGLES(std::move(resolver)));
|
||||||
g_mock_gles = mock_gles;
|
g_mock_gles = mock_gles;
|
||||||
return mock_gles;
|
return mock_gles;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
#include "impeller/renderer/backend/gles/proc_table_gles.h"
|
#include "impeller/renderer/backend/gles/proc_table_gles.h"
|
||||||
|
|
||||||
namespace impeller {
|
namespace impeller {
|
||||||
@ -15,6 +16,60 @@ namespace testing {
|
|||||||
|
|
||||||
extern const ProcTableGLES::Resolver kMockResolverGLES;
|
extern const ProcTableGLES::Resolver kMockResolverGLES;
|
||||||
|
|
||||||
|
class IMockGLESImpl {
|
||||||
|
public:
|
||||||
|
virtual ~IMockGLESImpl() = default;
|
||||||
|
virtual void DeleteTextures(GLsizei size, const GLuint* queries) {}
|
||||||
|
virtual void GenTextures(GLsizei n, GLuint* textures) {}
|
||||||
|
virtual void ObjectLabelKHR(GLenum identifier,
|
||||||
|
GLuint name,
|
||||||
|
GLsizei length,
|
||||||
|
const GLchar* label) {}
|
||||||
|
virtual void Uniform1fv(GLint location, GLsizei count, const GLfloat* value) {
|
||||||
|
}
|
||||||
|
virtual void GenQueriesEXT(GLsizei n, GLuint* ids) {}
|
||||||
|
virtual void BeginQueryEXT(GLenum target, GLuint id) {}
|
||||||
|
virtual void EndQueryEXT(GLuint id) {}
|
||||||
|
virtual void GetQueryObjectuivEXT(GLuint id, GLenum target, GLuint* result) {}
|
||||||
|
virtual void GetQueryObjectui64vEXT(GLuint id,
|
||||||
|
GLenum target,
|
||||||
|
GLuint64* result) {}
|
||||||
|
virtual void DeleteQueriesEXT(GLsizei size, const GLuint* queries) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class MockGLESImpl : public IMockGLESImpl {
|
||||||
|
public:
|
||||||
|
MOCK_METHOD(void,
|
||||||
|
DeleteTextures,
|
||||||
|
(GLsizei size, const GLuint* queries),
|
||||||
|
(override));
|
||||||
|
MOCK_METHOD(void, GenTextures, (GLsizei n, GLuint* textures), (override));
|
||||||
|
MOCK_METHOD(
|
||||||
|
void,
|
||||||
|
ObjectLabelKHR,
|
||||||
|
(GLenum identifier, GLuint name, GLsizei length, const GLchar* label),
|
||||||
|
(override));
|
||||||
|
MOCK_METHOD(void,
|
||||||
|
Uniform1fv,
|
||||||
|
(GLint location, GLsizei count, const GLfloat* value),
|
||||||
|
(override));
|
||||||
|
MOCK_METHOD(void, GenQueriesEXT, (GLsizei n, GLuint* ids), (override));
|
||||||
|
MOCK_METHOD(void, BeginQueryEXT, (GLenum target, GLuint id), (override));
|
||||||
|
MOCK_METHOD(void, EndQueryEXT, (GLuint id), (override));
|
||||||
|
MOCK_METHOD(void,
|
||||||
|
GetQueryObjectuivEXT,
|
||||||
|
(GLuint id, GLenum target, GLuint* result),
|
||||||
|
(override));
|
||||||
|
MOCK_METHOD(void,
|
||||||
|
GetQueryObjectui64vEXT,
|
||||||
|
(GLuint id, GLenum target, GLuint64* result),
|
||||||
|
(override));
|
||||||
|
MOCK_METHOD(void,
|
||||||
|
DeleteQueriesEXT,
|
||||||
|
(GLsizei size, const GLuint* queries),
|
||||||
|
(override));
|
||||||
|
};
|
||||||
|
|
||||||
/// @brief Provides a mocked version of the |ProcTableGLES| class.
|
/// @brief Provides a mocked version of the |ProcTableGLES| class.
|
||||||
///
|
///
|
||||||
/// Typically, Open GLES at runtime will be provided the host's GLES bindings
|
/// Typically, Open GLES at runtime will be provided the host's GLES bindings
|
||||||
@ -25,32 +80,26 @@ extern const ProcTableGLES::Resolver kMockResolverGLES;
|
|||||||
/// See `README.md` for more information.
|
/// See `README.md` for more information.
|
||||||
class MockGLES final {
|
class MockGLES final {
|
||||||
public:
|
public:
|
||||||
|
static std::shared_ptr<MockGLES> Init(
|
||||||
|
std::unique_ptr<MockGLESImpl> impl,
|
||||||
|
const std::optional<std::vector<const char*>>& extensions = std::nullopt);
|
||||||
|
|
||||||
/// @brief Returns an initialized |MockGLES| instance.
|
/// @brief Returns an initialized |MockGLES| instance.
|
||||||
///
|
///
|
||||||
/// This method overwrites mocked global GLES function pointers to record
|
/// This method overwrites mocked global GLES function pointers to record
|
||||||
/// invocations on this instance of |MockGLES|. As such, it should only be
|
/// invocations on this instance of |MockGLES|. As such, it should only be
|
||||||
/// called once per test.
|
/// called once per test.
|
||||||
static std::shared_ptr<MockGLES> Init(
|
static std::shared_ptr<MockGLES> Init(
|
||||||
const std::optional<std::vector<const unsigned char*>>& extensions =
|
const std::optional<std::vector<const char*>>& extensions = std::nullopt,
|
||||||
std::nullopt,
|
|
||||||
const char* version_string = "OpenGL ES 3.0",
|
const char* version_string = "OpenGL ES 3.0",
|
||||||
ProcTableGLES::Resolver resolver = kMockResolverGLES);
|
ProcTableGLES::Resolver resolver = kMockResolverGLES);
|
||||||
|
|
||||||
/// @brief Returns a configured |ProcTableGLES| instance.
|
/// @brief Returns a configured |ProcTableGLES| instance.
|
||||||
const ProcTableGLES& GetProcTable() const { return proc_table_; }
|
const ProcTableGLES& GetProcTable() const { return proc_table_; }
|
||||||
|
|
||||||
/// @brief Returns a vector of the names of all recorded calls.
|
|
||||||
///
|
|
||||||
/// Calls are cleared after this method is called.
|
|
||||||
std::vector<std::string> GetCapturedCalls() {
|
|
||||||
std::vector<std::string> calls = captured_calls_;
|
|
||||||
captured_calls_.clear();
|
|
||||||
return calls;
|
|
||||||
}
|
|
||||||
|
|
||||||
~MockGLES();
|
~MockGLES();
|
||||||
|
|
||||||
void SetNextTexture(uint64_t next_texture) { next_texture_ = next_texture; }
|
IMockGLESImpl* GetImpl() { return impl_.get(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend void RecordGLCall(const char* name);
|
friend void RecordGLCall(const char* name);
|
||||||
@ -58,11 +107,8 @@ class MockGLES final {
|
|||||||
|
|
||||||
explicit MockGLES(ProcTableGLES::Resolver resolver = kMockResolverGLES);
|
explicit MockGLES(ProcTableGLES::Resolver resolver = kMockResolverGLES);
|
||||||
|
|
||||||
void RecordCall(const char* name) { captured_calls_.emplace_back(name); }
|
|
||||||
|
|
||||||
ProcTableGLES proc_table_;
|
ProcTableGLES proc_table_;
|
||||||
std::vector<std::string> captured_calls_;
|
std::unique_ptr<IMockGLESImpl> impl_;
|
||||||
std::optional<uint64_t> next_texture_;
|
|
||||||
|
|
||||||
MockGLES(const MockGLES&) = delete;
|
MockGLES(const MockGLES&) = delete;
|
||||||
|
|
||||||
|
@ -21,19 +21,6 @@ TEST(MockGLES, CanInitialize) {
|
|||||||
EXPECT_EQ(vendor, "MockGLES");
|
EXPECT_EQ(vendor, "MockGLES");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests we can call two functions and capture the calls.
|
|
||||||
TEST(MockGLES, CapturesPushAndPopDebugGroup) {
|
|
||||||
auto mock_gles = MockGLES::Init();
|
|
||||||
|
|
||||||
auto& gl = mock_gles->GetProcTable();
|
|
||||||
gl.PushDebugGroupKHR(GL_DEBUG_SOURCE_APPLICATION_KHR, 0, -1, "test");
|
|
||||||
gl.PopDebugGroupKHR();
|
|
||||||
|
|
||||||
auto calls = mock_gles->GetCapturedCalls();
|
|
||||||
EXPECT_EQ(calls, std::vector<std::string>(
|
|
||||||
{"PushDebugGroupKHR", "PopDebugGroupKHR"}));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests that if we call a function we have not mocked, it's OK.
|
// Tests that if we call a function we have not mocked, it's OK.
|
||||||
TEST(MockGLES, CanCallUnmockedFunction) {
|
TEST(MockGLES, CanCallUnmockedFunction) {
|
||||||
auto mock_gles = MockGLES::Init();
|
auto mock_gles = MockGLES::Init();
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include "flutter/fml/synchronization/waitable_event.h"
|
#include "flutter/fml/synchronization/waitable_event.h"
|
||||||
#include "flutter/testing/testing.h" // IWYU pragma: keep
|
#include "flutter/testing/testing.h" // IWYU pragma: keep
|
||||||
|
#include "gmock/gmock.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "impeller/renderer/backend/gles/handle_gles.h"
|
#include "impeller/renderer/backend/gles/handle_gles.h"
|
||||||
#include "impeller/renderer/backend/gles/proc_table_gles.h"
|
#include "impeller/renderer/backend/gles/proc_table_gles.h"
|
||||||
@ -15,6 +16,8 @@
|
|||||||
namespace impeller {
|
namespace impeller {
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
|
using ::testing::_;
|
||||||
|
|
||||||
class TestWorker : public ReactorGLES::Worker {
|
class TestWorker : public ReactorGLES::Worker {
|
||||||
public:
|
public:
|
||||||
bool CanReactorReactOnCurrentThreadNow(
|
bool CanReactorReactOnCurrentThreadNow(
|
||||||
@ -46,31 +49,40 @@ TEST(ReactorGLES, CanAttachCleanupCallbacksToHandles) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(ReactorGLES, DeletesHandlesDuringShutdown) {
|
TEST(ReactorGLES, DeletesHandlesDuringShutdown) {
|
||||||
auto mock_gles = MockGLES::Init();
|
auto mock_gles_impl = std::make_unique<MockGLESImpl>();
|
||||||
|
|
||||||
|
EXPECT_CALL(*mock_gles_impl, GenTextures(1, _))
|
||||||
|
.WillOnce([](GLsizei size, GLuint* queries) { queries[0] = 1234; });
|
||||||
|
EXPECT_CALL(*mock_gles_impl, DeleteTextures(1, ::testing::Pointee(1234)))
|
||||||
|
.Times(1);
|
||||||
|
|
||||||
|
std::shared_ptr<MockGLES> mock_gles =
|
||||||
|
MockGLES::Init(std::move(mock_gles_impl));
|
||||||
ProcTableGLES::Resolver resolver = kMockResolverGLES;
|
ProcTableGLES::Resolver resolver = kMockResolverGLES;
|
||||||
auto proc_table = std::make_unique<ProcTableGLES>(resolver);
|
auto proc_table = std::make_unique<ProcTableGLES>(resolver);
|
||||||
auto worker = std::make_shared<TestWorker>();
|
auto worker = std::make_shared<TestWorker>();
|
||||||
auto reactor = std::make_shared<ReactorGLES>(std::move(proc_table));
|
auto reactor = std::make_shared<ReactorGLES>(std::move(proc_table));
|
||||||
reactor->AddWorker(worker);
|
reactor->AddWorker(worker);
|
||||||
|
reactor->CreateHandle(HandleType::kTexture);
|
||||||
reactor->CreateHandle(HandleType::kTexture, 123);
|
|
||||||
|
|
||||||
reactor.reset();
|
reactor.reset();
|
||||||
|
|
||||||
auto calls = mock_gles->GetCapturedCalls();
|
|
||||||
EXPECT_TRUE(std::find(calls.begin(), calls.end(), "glDeleteTextures") !=
|
|
||||||
calls.end());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ReactorGLES, UntrackedHandle) {
|
TEST(ReactorGLES, UntrackedHandle) {
|
||||||
std::shared_ptr<MockGLES> mock_gles = MockGLES::Init();
|
auto mock_gles_impl = std::make_unique<MockGLESImpl>();
|
||||||
|
|
||||||
|
EXPECT_CALL(*mock_gles_impl, GenTextures(1, _))
|
||||||
|
.WillOnce([](GLsizei size, GLuint* queries) { queries[0] = 1234; });
|
||||||
|
EXPECT_CALL(*mock_gles_impl, DeleteTextures(1, ::testing::Pointee(1234)))
|
||||||
|
.Times(1);
|
||||||
|
|
||||||
|
std::shared_ptr<MockGLES> mock_gles =
|
||||||
|
MockGLES::Init(std::move(mock_gles_impl));
|
||||||
ProcTableGLES::Resolver resolver = kMockResolverGLES;
|
ProcTableGLES::Resolver resolver = kMockResolverGLES;
|
||||||
auto proc_table = std::make_unique<ProcTableGLES>(resolver);
|
auto proc_table = std::make_unique<ProcTableGLES>(resolver);
|
||||||
auto worker = std::make_shared<TestWorker>();
|
auto worker = std::make_shared<TestWorker>();
|
||||||
auto reactor = std::make_shared<ReactorGLES>(std::move(proc_table));
|
auto reactor = std::make_shared<ReactorGLES>(std::move(proc_table));
|
||||||
reactor->AddWorker(worker);
|
reactor->AddWorker(worker);
|
||||||
|
|
||||||
mock_gles->SetNextTexture(1234u);
|
|
||||||
HandleGLES handle = reactor->CreateUntrackedHandle(HandleType::kTexture);
|
HandleGLES handle = reactor->CreateUntrackedHandle(HandleType::kTexture);
|
||||||
EXPECT_FALSE(handle.IsDead());
|
EXPECT_FALSE(handle.IsDead());
|
||||||
std::optional<GLuint> glint = reactor->GetGLHandle(handle);
|
std::optional<GLuint> glint = reactor->GetGLHandle(handle);
|
||||||
@ -78,34 +90,30 @@ TEST(ReactorGLES, UntrackedHandle) {
|
|||||||
if (glint.has_value()) {
|
if (glint.has_value()) {
|
||||||
EXPECT_EQ(1234u, *glint);
|
EXPECT_EQ(1234u, *glint);
|
||||||
}
|
}
|
||||||
mock_gles->GetCapturedCalls();
|
|
||||||
reactor->CollectHandle(handle);
|
reactor->CollectHandle(handle);
|
||||||
std::vector<std::string> calls = mock_gles->GetCapturedCalls();
|
|
||||||
EXPECT_TRUE(std::find(calls.begin(), calls.end(), "glDeleteTextures") ==
|
|
||||||
calls.end());
|
|
||||||
// Without an operation nothing is cleaned up.
|
|
||||||
EXPECT_TRUE(reactor->AddOperation([&](const ReactorGLES&) {}));
|
EXPECT_TRUE(reactor->AddOperation([&](const ReactorGLES&) {}));
|
||||||
EXPECT_TRUE(reactor->React());
|
EXPECT_TRUE(reactor->React());
|
||||||
calls = mock_gles->GetCapturedCalls();
|
|
||||||
EXPECT_FALSE(std::find(calls.begin(), calls.end(), "glDeleteTextures") ==
|
|
||||||
calls.end());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ReactorGLES, NameUntrackedHandle) {
|
TEST(ReactorGLES, NameUntrackedHandle) {
|
||||||
std::shared_ptr<MockGLES> mock_gles = MockGLES::Init();
|
auto mock_gles_impl = std::make_unique<MockGLESImpl>();
|
||||||
|
|
||||||
|
EXPECT_CALL(*mock_gles_impl, GenTextures(1, _))
|
||||||
|
.WillOnce([](GLsizei size, GLuint* queries) { queries[0] = 1234; });
|
||||||
|
EXPECT_CALL(*mock_gles_impl,
|
||||||
|
ObjectLabelKHR(_, 1234, _, ::testing::StrEq("hello, joe!")))
|
||||||
|
.Times(1);
|
||||||
|
|
||||||
|
std::shared_ptr<MockGLES> mock_gles =
|
||||||
|
MockGLES::Init(std::move(mock_gles_impl));
|
||||||
ProcTableGLES::Resolver resolver = kMockResolverGLES;
|
ProcTableGLES::Resolver resolver = kMockResolverGLES;
|
||||||
auto proc_table = std::make_unique<ProcTableGLES>(resolver);
|
auto proc_table = std::make_unique<ProcTableGLES>(resolver);
|
||||||
auto worker = std::make_shared<TestWorker>();
|
auto worker = std::make_shared<TestWorker>();
|
||||||
auto reactor = std::make_shared<ReactorGLES>(std::move(proc_table));
|
auto reactor = std::make_shared<ReactorGLES>(std::move(proc_table));
|
||||||
reactor->AddWorker(worker);
|
reactor->AddWorker(worker);
|
||||||
|
|
||||||
mock_gles->SetNextTexture(1234u);
|
|
||||||
HandleGLES handle = reactor->CreateUntrackedHandle(HandleType::kTexture);
|
HandleGLES handle = reactor->CreateUntrackedHandle(HandleType::kTexture);
|
||||||
mock_gles->GetCapturedCalls();
|
|
||||||
reactor->SetDebugLabel(handle, "hello, joe!");
|
reactor->SetDebugLabel(handle, "hello, joe!");
|
||||||
std::vector<std::string> calls = mock_gles->GetCapturedCalls();
|
|
||||||
EXPECT_TRUE(std::find(calls.begin(), calls.end(), "glObjectLabelKHR") !=
|
|
||||||
calls.end());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ReactorGLES, PerThreadOperationQueues) {
|
TEST(ReactorGLES, PerThreadOperationQueues) {
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
namespace impeller {
|
namespace impeller {
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
|
using ::testing::_;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class TestWorker : public ReactorGLES::Worker {
|
class TestWorker : public ReactorGLES::Worker {
|
||||||
public:
|
public:
|
||||||
@ -22,20 +24,21 @@ class TestWorker : public ReactorGLES::Worker {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST(UniqueHandleGLES, MakeUntracked) {
|
TEST(UniqueHandleGLES, MakeUntracked) {
|
||||||
auto mock_gles = MockGLES::Init();
|
auto mock_gles_impl = std::make_unique<MockGLESImpl>();
|
||||||
|
|
||||||
|
EXPECT_CALL(*mock_gles_impl, GenTextures(1, _)).Times(1);
|
||||||
|
|
||||||
|
std::shared_ptr<MockGLES> mock_gled =
|
||||||
|
MockGLES::Init(std::move(mock_gles_impl));
|
||||||
ProcTableGLES::Resolver resolver = kMockResolverGLES;
|
ProcTableGLES::Resolver resolver = kMockResolverGLES;
|
||||||
auto proc_table = std::make_unique<ProcTableGLES>(resolver);
|
auto proc_table = std::make_unique<ProcTableGLES>(resolver);
|
||||||
auto worker = std::make_shared<TestWorker>();
|
auto worker = std::make_shared<TestWorker>();
|
||||||
auto reactor = std::make_shared<ReactorGLES>(std::move(proc_table));
|
auto reactor = std::make_shared<ReactorGLES>(std::move(proc_table));
|
||||||
reactor->AddWorker(worker);
|
reactor->AddWorker(worker);
|
||||||
|
|
||||||
mock_gles->GetCapturedCalls();
|
|
||||||
UniqueHandleGLES handle =
|
UniqueHandleGLES handle =
|
||||||
UniqueHandleGLES::MakeUntracked(reactor, HandleType::kTexture);
|
UniqueHandleGLES::MakeUntracked(reactor, HandleType::kTexture);
|
||||||
EXPECT_FALSE(handle.Get().IsDead());
|
EXPECT_FALSE(handle.Get().IsDead());
|
||||||
std::vector<std::string> calls = mock_gles->GetCapturedCalls();
|
|
||||||
EXPECT_TRUE(std::find(calls.begin(), calls.end(), "glGenTextures") !=
|
|
||||||
calls.end());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
Loading…
x
Reference in New Issue
Block a user