| Flutter Impeller |

resource_manager_vk_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 <sys/types.h>
6 #include <functional>
7 #include <memory>
8 #include <utility>
9 #include "fml/synchronization/waitable_event.h"
10 #include "gtest/gtest.h"
11 #include "impeller/renderer/backend/vulkan/resource_manager_vk.h"
12
13 namespace impeller {
14 namespace testing {
15
16 // While expected to be a singleton per context, the class does not enforce it.
17 TEST(ResourceManagerVKTest, CreatesANewInstance) {
18 auto const a = ResourceManagerVK::Create();
19 auto const b = ResourceManagerVK::Create();
20 EXPECT_NE(a, b);
21 }
22
23 namespace {
24
25 // Invokes the provided callback when the destructor is called.
26 //
27 // Can be moved, but not copied.
28 class DeathRattle final {
29 public:
30 explicit DeathRattle(std::function<void()> callback)
31 : callback_(std::move(callback)) {}
32
33 DeathRattle(DeathRattle&&) = default;
34 DeathRattle& operator=(DeathRattle&&) = default;
35
36 ~DeathRattle() { callback_(); }
37
38 private:
39 std::function<void()> callback_;
40 };
41
42 } // namespace
43
44 TEST(ResourceManagerVKTest, ReclaimMovesAResourceAndDestroysIt) {
45 auto const manager = ResourceManagerVK::Create();
46
47 auto waiter = fml::AutoResetWaitableEvent();
48 auto dead = false;
49 auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
50
51 // Not killed immediately.
52 EXPECT_FALSE(waiter.IsSignaledForTest());
53
54 {
55 auto resource = UniqueResourceVKT<DeathRattle>(manager, std::move(rattle));
56 }
57
58 waiter.Wait();
59 }
60
61 // Regression test for https://github.com/flutter/flutter/issues/134482.
62 TEST(ResourceManagerVKTest, TerminatesWhenOutOfScope) {
63 // Originally, this shared_ptr was never destroyed, and the thread never
64 // terminated. This test ensures that the thread terminates when the
65 // ResourceManagerVK is out of scope.
66 std::weak_ptr<ResourceManagerVK> manager;
67
68 {
69 auto shared = ResourceManagerVK::Create();
70 manager = shared;
71 }
72
73 // The thread should have terminated.
74 EXPECT_EQ(manager.lock(), nullptr);
75 }
76
77 TEST(ResourceManagerVKTest, IsThreadSafe) {
78 // In a typical app, there is a single ResourceManagerVK per app, shared b/w
79 // threads.
80 //
81 // This test ensures that the ResourceManagerVK is thread-safe.
82 std::weak_ptr<ResourceManagerVK> manager;
83
84 {
85 auto const manager = ResourceManagerVK::Create();
86
87 // Spawn two threads, and have them both put resources into the manager.
88 struct MockResource {};
89
90 std::thread thread1([&manager]() {
91 UniqueResourceVKT<MockResource>(manager, MockResource{});
92 });
93
94 std::thread thread2([&manager]() {
95 UniqueResourceVKT<MockResource>(manager, MockResource{});
96 });
97
98 thread1.join();
99 thread2.join();
100 }
101
102 // The thread should have terminated.
103 EXPECT_EQ(manager.lock(), nullptr);
104 }
105
106 } // namespace testing
107 } // namespace impeller
impeller::ResourceManagerVK::Create
static std::shared_ptr< ResourceManagerVK > Create()
Creates a shared resource manager (a dedicated thread).
Definition: resource_manager_vk.cc:14
impeller::UniqueResourceVKT
A unique handle to a resource which will be reclaimed by the specified resource manager.
Definition: resource_manager_vk.h:145
impeller::testing::TEST
TEST(CanvasRecorder, Save)
Definition: canvas_recorder_unittests.cc:61
resource_manager_vk.h
std
Definition: comparable.h:95
impeller
Definition: aiks_context.cc:10