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"
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:65
resource_manager_vk.h
std
Definition: comparable.h:95
impeller::saturated::b
SI b
Definition: saturated_math.h:87
impeller
Definition: aiks_blur_unittests.cc:20