Flutter Engine
 
Loading...
Searching...
No Matches
reactor_unittests.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <algorithm>
6#include <memory>
8#include "flutter/testing/testing.h" // IWYU pragma: keep
9#include "gmock/gmock.h"
10#include "gtest/gtest.h"
15
16namespace impeller {
17namespace testing {
18
19using ::testing::_;
20using ::testing::NiceMock;
21
22class TestWorker : public ReactorGLES::Worker {
23 public:
25 const ReactorGLES& reactor) const override {
26 return true;
27 }
28};
29
30TEST(ReactorGLES, CanAttachCleanupCallbacksToHandles) {
31 auto mock_gles = MockGLES::Init();
33 auto proc_table = std::make_unique<ProcTableGLES>(resolver);
34 auto worker = std::make_shared<TestWorker>();
35 auto reactor = std::make_shared<ReactorGLES>(std::move(proc_table));
36 reactor->AddWorker(worker);
37
38 int value = 0;
39 auto handle = reactor->CreateHandle(HandleType::kTexture, 1123);
40 auto added =
41 reactor->RegisterCleanupCallback(handle, [&value]() { value++; });
42
43 EXPECT_TRUE(added);
44 EXPECT_TRUE(reactor->React());
45
46 reactor->CollectHandle(handle);
47 EXPECT_TRUE(reactor->AddOperation([](const ReactorGLES& reactor) {}));
48 EXPECT_TRUE(reactor->React());
49 EXPECT_EQ(value, 1);
50}
51
52TEST(ReactorGLES, DeletesHandlesDuringShutdown) {
53 auto mock_gles_impl = std::make_unique<MockGLESImpl>();
54
55 EXPECT_CALL(*mock_gles_impl, GenTextures(1, _))
56 .WillOnce([](GLsizei size, GLuint* queries) { queries[0] = 1234; });
57 EXPECT_CALL(*mock_gles_impl, DeleteTextures(1, ::testing::Pointee(1234)))
58 .Times(1);
59
60 std::shared_ptr<MockGLES> mock_gles =
61 MockGLES::Init(std::move(mock_gles_impl));
63 auto proc_table = std::make_unique<ProcTableGLES>(resolver);
64 auto worker = std::make_shared<TestWorker>();
65 auto reactor = std::make_shared<ReactorGLES>(std::move(proc_table));
66 reactor->AddWorker(worker);
67 reactor->CreateHandle(HandleType::kTexture);
68 reactor.reset();
69}
70
71TEST(ReactorGLES, UntrackedHandle) {
72 auto mock_gles_impl = std::make_unique<MockGLESImpl>();
73
74 EXPECT_CALL(*mock_gles_impl, GenTextures(1, _))
75 .WillOnce([](GLsizei size, GLuint* queries) { queries[0] = 1234; });
76 EXPECT_CALL(*mock_gles_impl, DeleteTextures(1, ::testing::Pointee(1234)))
77 .Times(1);
78
79 std::shared_ptr<MockGLES> mock_gles =
80 MockGLES::Init(std::move(mock_gles_impl));
82 auto proc_table = std::make_unique<ProcTableGLES>(resolver);
83 auto worker = std::make_shared<TestWorker>();
84 auto reactor = std::make_shared<ReactorGLES>(std::move(proc_table));
85 reactor->AddWorker(worker);
86
87 HandleGLES handle = reactor->CreateUntrackedHandle(HandleType::kTexture);
88 EXPECT_FALSE(handle.IsDead());
89 std::optional<GLuint> glint = reactor->GetGLHandle(handle);
90 EXPECT_TRUE(glint.has_value());
91 if (glint.has_value()) {
92 EXPECT_EQ(1234u, *glint);
93 }
94 reactor->CollectHandle(handle);
95 EXPECT_TRUE(reactor->AddOperation([&](const ReactorGLES&) {}));
96 EXPECT_TRUE(reactor->React());
97}
98
99TEST(ReactorGLES, NameUntrackedHandle) {
100 auto mock_gles_impl = std::make_unique<NiceMock<MockGLESImpl>>();
101 NiceMock<MockGLESImpl>* raw_mock_gles = mock_gles_impl.get();
102
103 std::shared_ptr<MockGLES> mock_gles =
104 MockGLES::Init(std::move(mock_gles_impl));
106 auto proc_table = std::make_unique<ProcTableGLES>(resolver);
107
108 if (!proc_table->SupportsDebugLabels()) {
109 GTEST_SKIP() << "This device doesn't support labelling.";
110 }
111
112 EXPECT_CALL(*raw_mock_gles, GenTextures(1, _))
113 .WillOnce([](GLsizei size, GLuint* queries) { queries[0] = 1234; });
114 EXPECT_CALL(*raw_mock_gles,
115 ObjectLabelKHR(_, 1234, _, ::testing::StrEq("hello, joe!")))
116 .Times(1);
117 ON_CALL(*raw_mock_gles, IsTexture).WillByDefault(::testing::Return(GL_TRUE));
118
119 auto worker = std::make_shared<TestWorker>();
120 auto reactor = std::make_shared<ReactorGLES>(std::move(proc_table));
121 reactor->AddWorker(worker);
122
123 HandleGLES handle = reactor->CreateUntrackedHandle(HandleType::kTexture);
124 reactor->SetDebugLabel(handle, "hello, joe!");
125}
126
127TEST(ReactorGLES, PerThreadOperationQueues) {
128 auto mock_gles = MockGLES::Init();
130 auto proc_table = std::make_unique<ProcTableGLES>(resolver);
131 auto worker = std::make_shared<TestWorker>();
132 auto reactor = std::make_shared<ReactorGLES>(std::move(proc_table));
133 reactor->AddWorker(worker);
134
135 bool op1_called = false;
136 EXPECT_TRUE(
137 reactor->AddOperation([&](const ReactorGLES&) { op1_called = true; }));
138
140 bool op2_called = false;
141 std::thread thread([&] {
142 EXPECT_TRUE(reactor->AddOperation(
143 [&](const ReactorGLES&) { op2_called = true; }, true));
144 event.Wait();
145 EXPECT_TRUE(reactor->React());
146 });
147
148 // Reacting on the main thread should only run the main thread's operation.
149 EXPECT_TRUE(reactor->React());
150 EXPECT_TRUE(op1_called);
151 EXPECT_FALSE(op2_called);
152
153 // Reacting on the second thread will run the second thread's operation.
154 event.Signal();
155 thread.join();
156 EXPECT_TRUE(op2_called);
157}
158
159TEST(ReactorGLES, CanDeferOperations) {
160 auto mock_gles = MockGLES::Init();
162 auto proc_table = std::make_unique<ProcTableGLES>(resolver);
163 auto worker = std::make_shared<TestWorker>();
164 auto reactor = std::make_shared<ReactorGLES>(std::move(proc_table));
165 reactor->AddWorker(worker);
166
167 // Add operation executes tasks as long as the reactor can run tasks on
168 // the current thread.
169 bool did_run = false;
170 EXPECT_TRUE(
171 reactor->AddOperation([&](const ReactorGLES&) { did_run = true; }));
172 EXPECT_TRUE(did_run);
173
174 //...unless defer=true is specified, which only enqueues in the reactor.
175 did_run = false;
176 EXPECT_TRUE(reactor->AddOperation([&](const ReactorGLES&) { did_run = true; },
177 /*defer=*/true));
178 EXPECT_FALSE(did_run);
179 EXPECT_TRUE(reactor->React());
180 EXPECT_TRUE(did_run);
181}
182
183} // namespace testing
184} // namespace impeller
Represents a handle to an underlying OpenGL object. Unlike OpenGL object handles, these handles can b...
Definition handle_gles.h:37
constexpr bool IsDead() const
Determines if the handle is dead.
Definition handle_gles.h:53
std::function< void *(const char *function_name)> Resolver
A delegate implemented by a thread on which an OpenGL context is current. There may be multiple worke...
The reactor attempts to make thread-safe usage of OpenGL ES easier to reason about.
bool React()
Perform a reaction on the current thread if able.
static std::shared_ptr< MockGLES > Init(std::unique_ptr< MockGLESImpl > impl, const std::optional< std::vector< const char * > > &extensions=std::nullopt)
Definition mock_gles.cc:260
bool CanReactorReactOnCurrentThreadNow(const ReactorGLES &reactor) const override
Determines the ability of the worker to service a reaction on the current thread. The OpenGL context ...
int32_t value
TEST(FrameTimingsRecorderTest, RecordVsync)
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
const ProcTableGLES::Resolver kMockResolverGLES
Definition mock_gles.cc:287