From afb249fd2b263b9d16ed49647224e4f544a6b4c8 Mon Sep 17 00:00:00 2001 From: gaaclarke <30870216+gaaclarke@users.noreply.github.com> Date: Fri, 6 Dec 2024 09:17:57 -0800 Subject: [PATCH] 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]. [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 --- .../gles/buffer_bindings_gles_unittests.cc | 11 +- .../gles/test/capabilities_unittests.cc | 19 ++-- .../gles/test/gpu_tracer_gles_unittests.cc | 56 ++++++---- .../renderer/backend/gles/test/mock_gles.cc | 104 +++++++++--------- .../renderer/backend/gles/test/mock_gles.h | 78 ++++++++++--- .../backend/gles/test/mock_gles_unittests.cc | 13 --- .../backend/gles/test/reactor_unittests.cc | 56 ++++++---- .../gles/unique_handle_gles_unittests.cc | 13 ++- 8 files changed, 204 insertions(+), 146 deletions(-) diff --git a/engine/src/flutter/impeller/renderer/backend/gles/buffer_bindings_gles_unittests.cc b/engine/src/flutter/impeller/renderer/backend/gles/buffer_bindings_gles_unittests.cc index 9078447433..45a342bfcb 100644 --- a/engine/src/flutter/impeller/renderer/backend/gles/buffer_bindings_gles_unittests.cc +++ b/engine/src/flutter/impeller/renderer/backend/gles/buffer_bindings_gles_unittests.cc @@ -12,12 +12,18 @@ namespace impeller { namespace testing { +using ::testing::_; + TEST(BufferBindingsGLESTest, BindUniformData) { BufferBindingsGLES bindings; absl::flat_hash_map uniform_bindings; uniform_bindings["SHADERMETADATA.FOOBAR"] = 1; bindings.SetUniformBindings(std::move(uniform_bindings)); - std::shared_ptr mock_gl = MockGLES::Init(); + auto mock_gles_impl = std::make_unique(); + + EXPECT_CALL(*mock_gles_impl, Uniform1fv(_, _, _)).Times(1); + + std::shared_ptr mock_gl = MockGLES::Init(std::move(mock_gles_impl)); std::vector bound_buffers; std::vector bound_textures; @@ -39,9 +45,6 @@ TEST(BufferBindingsGLESTest, BindUniformData) { EXPECT_TRUE(bindings.BindUniformData(mock_gl->GetProcTable(), bound_textures, bound_buffers, Range{0, 0}, Range{0, 1})); - std::vector captured_calls = mock_gl->GetCapturedCalls(); - EXPECT_TRUE(std::find(captured_calls.begin(), captured_calls.end(), - "glUniform1fv") != captured_calls.end()); } } // namespace testing diff --git a/engine/src/flutter/impeller/renderer/backend/gles/test/capabilities_unittests.cc b/engine/src/flutter/impeller/renderer/backend/gles/test/capabilities_unittests.cc index 4fd30fff77..f78d63afb3 100644 --- a/engine/src/flutter/impeller/renderer/backend/gles/test/capabilities_unittests.cc +++ b/engine/src/flutter/impeller/renderer/backend/gles/test/capabilities_unittests.cc @@ -33,9 +33,9 @@ TEST(CapabilitiesGLES, CanInitializeWithDefaults) { } TEST(CapabilitiesGLES, SupportsDecalSamplerAddressMode) { - auto const extensions = std::vector{ - reinterpret_cast("GL_KHR_debug"), // - reinterpret_cast("GL_EXT_texture_border_clamp"), // + auto const extensions = std::vector{ + "GL_KHR_debug", // + "GL_EXT_texture_border_clamp", // }; auto mock_gles = MockGLES::Init(extensions); auto capabilities = mock_gles->GetProcTable().GetCapabilities(); @@ -43,9 +43,9 @@ TEST(CapabilitiesGLES, SupportsDecalSamplerAddressMode) { } TEST(CapabilitiesGLES, SupportsDecalSamplerAddressModeNotOES) { - auto const extensions = std::vector{ - reinterpret_cast("GL_KHR_debug"), // - reinterpret_cast("GL_OES_texture_border_clamp"), // + auto const extensions = std::vector{ + "GL_KHR_debug", // + "GL_OES_texture_border_clamp", // }; auto mock_gles = MockGLES::Init(extensions); auto capabilities = mock_gles->GetProcTable().GetCapabilities(); @@ -53,10 +53,9 @@ TEST(CapabilitiesGLES, SupportsDecalSamplerAddressModeNotOES) { } TEST(CapabilitiesGLES, SupportsFramebufferFetch) { - auto const extensions = std::vector{ - reinterpret_cast("GL_KHR_debug"), // - reinterpret_cast( - "GL_EXT_shader_framebuffer_fetch"), // + auto const extensions = std::vector{ + "GL_KHR_debug", // + "GL_EXT_shader_framebuffer_fetch", // }; auto mock_gles = MockGLES::Init(extensions); auto capabilities = mock_gles->GetProcTable().GetCapabilities(); diff --git a/engine/src/flutter/impeller/renderer/backend/gles/test/gpu_tracer_gles_unittests.cc b/engine/src/flutter/impeller/renderer/backend/gles/test/gpu_tracer_gles_unittests.cc index d0579a2091..2ee1da6c1b 100644 --- a/engine/src/flutter/impeller/renderer/backend/gles/test/gpu_tracer_gles_unittests.cc +++ b/engine/src/flutter/impeller/renderer/backend/gles/test/gpu_tracer_gles_unittests.cc @@ -10,38 +10,48 @@ namespace impeller { namespace testing { +using ::testing::_; + #ifdef IMPELLER_DEBUG TEST(GPUTracerGLES, CanFormatFramebufferErrorMessage) { - auto const extensions = std::vector{ - reinterpret_cast("GL_KHR_debug"), // - reinterpret_cast("GL_EXT_disjoint_timer_query"), // + auto const extensions = std::vector{ + "GL_KHR_debug", // + "GL_EXT_disjoint_timer_query", // }; - auto mock_gles = MockGLES::Init(extensions); + auto mock_gles_impl = std::make_unique(); + + { + ::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 mock_gles = + MockGLES::Init(std::move(mock_gles_impl), extensions); auto tracer = std::make_shared(mock_gles->GetProcTable(), true); tracer->RecordRasterThread(); tracer->MarkFrameStart(mock_gles->GetProcTable()); tracer->MarkFrameEnd(mock_gles->GetProcTable()); - - auto calls = mock_gles->GetCapturedCalls(); - - std::vector 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()); - - calls = mock_gles->GetCapturedCalls(); - std::vector expected_b = {"glGetQueryObjectuivEXT", - "glGetQueryObjectui64vEXT", - "glDeleteQueriesEXT"}; - for (auto i = 0; i < 3; i++) { - EXPECT_EQ(calls[i], expected_b[i]); - } } #endif // IMPELLER_DEBUG diff --git a/engine/src/flutter/impeller/renderer/backend/gles/test/mock_gles.cc b/engine/src/flutter/impeller/renderer/backend/gles/test/mock_gles.cc index 9b1965ab2b..5b890d989f 100644 --- a/engine/src/flutter/impeller/renderer/backend/gles/test/mock_gles.cc +++ b/engine/src/flutter/impeller/renderer/backend/gles/test/mock_gles.cc @@ -19,18 +19,9 @@ static std::mutex g_test_lock; static std::weak_ptr g_mock_gles; -static ProcTableGLES::Resolver g_resolver; +static std::vector g_extensions; -static std::vector g_extensions; - -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); - } -} +static const char* g_version; template struct CheckSameSignature : std::false_type {}; @@ -41,22 +32,34 @@ struct CheckSameSignature : std::true_type {}; // This is a stub function that does nothing/records nothing. void doNothing() {} -auto const kMockVendor = (unsigned char*)"MockGLES"; -const auto kMockShadingLanguageVersion = (unsigned char*)"GLSL ES 1.0"; -auto const kExtensions = std::vector{ - (unsigned char*)"GL_KHR_debug" // +auto const kMockVendor = "MockGLES"; +const auto kMockShadingLanguageVersion = "GLSL ES 1.0"; +auto const kExtensions = std::vector{ + "GL_KHR_debug" // }; +namespace { +template +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)...); + } + } +} +} // namespace + const unsigned char* mockGetString(GLenum name) { switch (name) { case GL_VENDOR: - return kMockVendor; + return reinterpret_cast(kMockVendor); case GL_VERSION: - return g_version; + return reinterpret_cast(g_version); case GL_SHADING_LANGUAGE_VERSION: - return kMockShadingLanguageVersion; + return reinterpret_cast( + kMockShadingLanguageVersion); default: - return (unsigned char*)""; + return reinterpret_cast(""); } } @@ -66,9 +69,9 @@ static_assert(CheckSameSignature(g_extensions[index]); default: - return (unsigned char*)""; + return reinterpret_cast(""); } } @@ -102,9 +105,7 @@ GLenum mockGetError() { static_assert(CheckSameSignature::value); -void mockPopDebugGroupKHR() { - RecordGLCall("PopDebugGroupKHR"); -} +void mockPopDebugGroupKHR() {} static_assert(CheckSameSignature::value); @@ -112,79 +113,65 @@ static_assert(CheckSameSignature::value); void mockGenQueriesEXT(GLsizei n, GLuint* ids) { - RecordGLCall("glGenQueriesEXT"); - for (auto i = 0; i < n; i++) { - ids[i] = i + 1; - } + CallMockMethod(&IMockGLESImpl::GenQueriesEXT, n, ids); } static_assert(CheckSameSignature::value); void mockBeginQueryEXT(GLenum target, GLuint id) { - RecordGLCall("glBeginQueryEXT"); + CallMockMethod(&IMockGLESImpl::BeginQueryEXT, target, id); } static_assert(CheckSameSignature::value); void mockEndQueryEXT(GLuint id) { - RecordGLCall("glEndQueryEXT"); + CallMockMethod(&IMockGLESImpl::EndQueryEXT, id); } static_assert(CheckSameSignature::value); void mockGetQueryObjectuivEXT(GLuint id, GLenum target, GLuint* result) { - RecordGLCall("glGetQueryObjectuivEXT"); - *result = GL_TRUE; + CallMockMethod(&IMockGLESImpl::GetQueryObjectuivEXT, id, target, result); } static_assert(CheckSameSignature::value); void mockGetQueryObjectui64vEXT(GLuint id, GLenum target, GLuint64* result) { - RecordGLCall("glGetQueryObjectui64vEXT"); - *result = 1000u; + CallMockMethod(&IMockGLESImpl::GetQueryObjectui64vEXT, id, target, result); } static_assert(CheckSameSignature::value); void mockDeleteQueriesEXT(GLsizei size, const GLuint* queries) { - RecordGLCall("glDeleteQueriesEXT"); + CallMockMethod(&IMockGLESImpl::DeleteQueriesEXT, size, queries); } void mockDeleteTextures(GLsizei size, const GLuint* queries) { - RecordGLCall("glDeleteTextures"); + CallMockMethod(&IMockGLESImpl::DeleteTextures, size, queries); } static_assert(CheckSameSignature::value); void mockUniform1fv(GLint location, GLsizei count, const GLfloat* value) { - RecordGLCall("glUniform1fv"); + CallMockMethod(&IMockGLESImpl::Uniform1fv, location, count, value); } static_assert(CheckSameSignature::value); void mockGenTextures(GLsizei n, GLuint* textures) { - RecordGLCall("glGenTextures"); - if (auto mock_gles = g_mock_gles.lock()) { - std::optional next_texture; - std::swap(mock_gles->next_texture_, next_texture); - if (next_texture.has_value()) { - textures[0] = next_texture.value(); - } - } + CallMockMethod(&IMockGLESImpl::GenTextures, n, textures); } static_assert(CheckSameSignature::value); +// static std::shared_ptr MockGLES::Init( - const std::optional>& extensions, + std::unique_ptr impl, + const std::optional>& 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(new MockGLES()); + mock_gles->impl_ = std::move(impl); + g_mock_gles = mock_gles; + return mock_gles; +} + +std::shared_ptr MockGLES::Init( + const std::optional>& extensions, const char* version_string, ProcTableGLES::Resolver resolver) { // If we cannot obtain a lock, MockGLES is already being used elsewhere. FML_CHECK(g_test_lock.try_lock()) << "MockGLES is already being used by another test."; - g_version = (unsigned char*)version_string; g_extensions = extensions.value_or(kExtensions); + g_version = version_string; auto mock_gles = std::shared_ptr(new MockGLES(std::move(resolver))); g_mock_gles = mock_gles; return mock_gles; diff --git a/engine/src/flutter/impeller/renderer/backend/gles/test/mock_gles.h b/engine/src/flutter/impeller/renderer/backend/gles/test/mock_gles.h index aa5a66c296..35b041b13d 100644 --- a/engine/src/flutter/impeller/renderer/backend/gles/test/mock_gles.h +++ b/engine/src/flutter/impeller/renderer/backend/gles/test/mock_gles.h @@ -8,6 +8,7 @@ #include #include +#include "gmock/gmock.h" #include "impeller/renderer/backend/gles/proc_table_gles.h" namespace impeller { @@ -15,6 +16,60 @@ namespace testing { 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. /// /// 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. class MockGLES final { public: + static std::shared_ptr Init( + std::unique_ptr impl, + const std::optional>& extensions = std::nullopt); + /// @brief Returns an initialized |MockGLES| instance. /// /// This method overwrites mocked global GLES function pointers to record /// invocations on this instance of |MockGLES|. As such, it should only be /// called once per test. static std::shared_ptr Init( - const std::optional>& extensions = - std::nullopt, + const std::optional>& extensions = std::nullopt, const char* version_string = "OpenGL ES 3.0", ProcTableGLES::Resolver resolver = kMockResolverGLES); /// @brief Returns a configured |ProcTableGLES| instance. 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 GetCapturedCalls() { - std::vector calls = captured_calls_; - captured_calls_.clear(); - return calls; - } - ~MockGLES(); - void SetNextTexture(uint64_t next_texture) { next_texture_ = next_texture; } + IMockGLESImpl* GetImpl() { return impl_.get(); } private: friend void RecordGLCall(const char* name); @@ -58,11 +107,8 @@ class MockGLES final { explicit MockGLES(ProcTableGLES::Resolver resolver = kMockResolverGLES); - void RecordCall(const char* name) { captured_calls_.emplace_back(name); } - ProcTableGLES proc_table_; - std::vector captured_calls_; - std::optional next_texture_; + std::unique_ptr impl_; MockGLES(const MockGLES&) = delete; diff --git a/engine/src/flutter/impeller/renderer/backend/gles/test/mock_gles_unittests.cc b/engine/src/flutter/impeller/renderer/backend/gles/test/mock_gles_unittests.cc index 5345cdbd00..96dea6bffc 100644 --- a/engine/src/flutter/impeller/renderer/backend/gles/test/mock_gles_unittests.cc +++ b/engine/src/flutter/impeller/renderer/backend/gles/test/mock_gles_unittests.cc @@ -21,19 +21,6 @@ TEST(MockGLES, CanInitialize) { 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( - {"PushDebugGroupKHR", "PopDebugGroupKHR"})); -} - // Tests that if we call a function we have not mocked, it's OK. TEST(MockGLES, CanCallUnmockedFunction) { auto mock_gles = MockGLES::Init(); diff --git a/engine/src/flutter/impeller/renderer/backend/gles/test/reactor_unittests.cc b/engine/src/flutter/impeller/renderer/backend/gles/test/reactor_unittests.cc index e2c49fb27c..48ee45dd3a 100644 --- a/engine/src/flutter/impeller/renderer/backend/gles/test/reactor_unittests.cc +++ b/engine/src/flutter/impeller/renderer/backend/gles/test/reactor_unittests.cc @@ -6,6 +6,7 @@ #include #include "flutter/fml/synchronization/waitable_event.h" #include "flutter/testing/testing.h" // IWYU pragma: keep +#include "gmock/gmock.h" #include "gtest/gtest.h" #include "impeller/renderer/backend/gles/handle_gles.h" #include "impeller/renderer/backend/gles/proc_table_gles.h" @@ -15,6 +16,8 @@ namespace impeller { namespace testing { +using ::testing::_; + class TestWorker : public ReactorGLES::Worker { public: bool CanReactorReactOnCurrentThreadNow( @@ -46,31 +49,40 @@ TEST(ReactorGLES, CanAttachCleanupCallbacksToHandles) { } TEST(ReactorGLES, DeletesHandlesDuringShutdown) { - auto mock_gles = MockGLES::Init(); + auto mock_gles_impl = std::make_unique(); + + 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 mock_gles = + MockGLES::Init(std::move(mock_gles_impl)); ProcTableGLES::Resolver resolver = kMockResolverGLES; auto proc_table = std::make_unique(resolver); auto worker = std::make_shared(); auto reactor = std::make_shared(std::move(proc_table)); reactor->AddWorker(worker); - - reactor->CreateHandle(HandleType::kTexture, 123); - + reactor->CreateHandle(HandleType::kTexture); reactor.reset(); - - auto calls = mock_gles->GetCapturedCalls(); - EXPECT_TRUE(std::find(calls.begin(), calls.end(), "glDeleteTextures") != - calls.end()); } TEST(ReactorGLES, UntrackedHandle) { - std::shared_ptr mock_gles = MockGLES::Init(); + auto mock_gles_impl = std::make_unique(); + + 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 mock_gles = + MockGLES::Init(std::move(mock_gles_impl)); ProcTableGLES::Resolver resolver = kMockResolverGLES; auto proc_table = std::make_unique(resolver); auto worker = std::make_shared(); auto reactor = std::make_shared(std::move(proc_table)); reactor->AddWorker(worker); - mock_gles->SetNextTexture(1234u); HandleGLES handle = reactor->CreateUntrackedHandle(HandleType::kTexture); EXPECT_FALSE(handle.IsDead()); std::optional glint = reactor->GetGLHandle(handle); @@ -78,34 +90,30 @@ TEST(ReactorGLES, UntrackedHandle) { if (glint.has_value()) { EXPECT_EQ(1234u, *glint); } - mock_gles->GetCapturedCalls(); reactor->CollectHandle(handle); - std::vector 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->React()); - calls = mock_gles->GetCapturedCalls(); - EXPECT_FALSE(std::find(calls.begin(), calls.end(), "glDeleteTextures") == - calls.end()); } TEST(ReactorGLES, NameUntrackedHandle) { - std::shared_ptr mock_gles = MockGLES::Init(); + auto mock_gles_impl = std::make_unique(); + + 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 mock_gles = + MockGLES::Init(std::move(mock_gles_impl)); ProcTableGLES::Resolver resolver = kMockResolverGLES; auto proc_table = std::make_unique(resolver); auto worker = std::make_shared(); auto reactor = std::make_shared(std::move(proc_table)); reactor->AddWorker(worker); - mock_gles->SetNextTexture(1234u); HandleGLES handle = reactor->CreateUntrackedHandle(HandleType::kTexture); - mock_gles->GetCapturedCalls(); reactor->SetDebugLabel(handle, "hello, joe!"); - std::vector calls = mock_gles->GetCapturedCalls(); - EXPECT_TRUE(std::find(calls.begin(), calls.end(), "glObjectLabelKHR") != - calls.end()); } TEST(ReactorGLES, PerThreadOperationQueues) { diff --git a/engine/src/flutter/impeller/renderer/backend/gles/unique_handle_gles_unittests.cc b/engine/src/flutter/impeller/renderer/backend/gles/unique_handle_gles_unittests.cc index 6a01fefbc4..01ddf037f1 100644 --- a/engine/src/flutter/impeller/renderer/backend/gles/unique_handle_gles_unittests.cc +++ b/engine/src/flutter/impeller/renderer/backend/gles/unique_handle_gles_unittests.cc @@ -11,6 +11,8 @@ namespace impeller { namespace testing { +using ::testing::_; + namespace { class TestWorker : public ReactorGLES::Worker { public: @@ -22,20 +24,21 @@ class TestWorker : public ReactorGLES::Worker { } // namespace TEST(UniqueHandleGLES, MakeUntracked) { - auto mock_gles = MockGLES::Init(); + auto mock_gles_impl = std::make_unique(); + + EXPECT_CALL(*mock_gles_impl, GenTextures(1, _)).Times(1); + + std::shared_ptr mock_gled = + MockGLES::Init(std::move(mock_gles_impl)); ProcTableGLES::Resolver resolver = kMockResolverGLES; auto proc_table = std::make_unique(resolver); auto worker = std::make_shared(); auto reactor = std::make_shared(std::move(proc_table)); reactor->AddWorker(worker); - mock_gles->GetCapturedCalls(); UniqueHandleGLES handle = UniqueHandleGLES::MakeUntracked(reactor, HandleType::kTexture); EXPECT_FALSE(handle.Get().IsDead()); - std::vector calls = mock_gles->GetCapturedCalls(); - EXPECT_TRUE(std::find(calls.begin(), calls.end(), "glGenTextures") != - calls.end()); } } // namespace testing