1 // Copyright 2021 The libgav1 Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "src/utils/blocking_counter.h"
16
17 #include <array>
18 #include <memory>
19
20 #include "absl/time/clock.h"
21 #include "absl/time/time.h"
22 #include "gtest/gtest.h"
23 #include "src/utils/threadpool.h"
24
25 namespace libgav1 {
26 namespace {
27
28 constexpr int kNumWorkers = 10;
29 constexpr int kNumJobs = 20;
30
TEST(BlockingCounterTest,BasicFunctionality)31 TEST(BlockingCounterTest, BasicFunctionality) {
32 std::unique_ptr<ThreadPool> pool = ThreadPool::Create(kNumWorkers);
33 BlockingCounter counter(kNumJobs);
34 std::array<bool, kNumJobs> done = {};
35
36 // Schedule the jobs.
37 for (int i = 0; i < kNumJobs; ++i) {
38 pool->Schedule([&counter, &done, i]() {
39 absl::SleepFor(absl::Seconds(1));
40 done[i] = true;
41 counter.Decrement();
42 });
43 }
44
45 // Wait for the jobs to complete. This should always return true.
46 ASSERT_TRUE(counter.Wait());
47
48 // Make sure the jobs were actually complete.
49 for (const auto& job_done : done) {
50 EXPECT_TRUE(job_done);
51 }
52 }
53
TEST(BlockingCounterTest,IncrementBy)54 TEST(BlockingCounterTest, IncrementBy) {
55 std::unique_ptr<ThreadPool> pool = ThreadPool::Create(kNumWorkers);
56 BlockingCounter counter(0);
57 std::array<bool, kNumJobs> done = {};
58
59 // Schedule the jobs.
60 for (int i = 0; i < kNumJobs; ++i) {
61 counter.IncrementBy(1);
62 pool->Schedule([&counter, &done, i]() {
63 absl::SleepFor(absl::Seconds(1));
64 done[i] = true;
65 counter.Decrement();
66 });
67 }
68
69 // Wait for the jobs to complete. This should always return true.
70 ASSERT_TRUE(counter.Wait());
71
72 // Make sure the jobs were actually complete.
73 for (const auto& job_done : done) {
74 EXPECT_TRUE(job_done);
75 }
76 }
77
TEST(BlockingCounterWithStatusTest,BasicFunctionality)78 TEST(BlockingCounterWithStatusTest, BasicFunctionality) {
79 std::unique_ptr<ThreadPool> pool = ThreadPool::Create(kNumWorkers);
80 BlockingCounterWithStatus counter(kNumJobs);
81 std::array<bool, kNumJobs> done = {};
82
83 // Schedule the jobs.
84 for (int i = 0; i < kNumJobs; ++i) {
85 pool->Schedule([&counter, &done, i]() {
86 absl::SleepFor(absl::Seconds(1));
87 done[i] = true;
88 counter.Decrement(true);
89 });
90 }
91
92 // Wait for the jobs to complete. This should return true since all the jobs
93 // reported |job_succeeded| as true.
94 ASSERT_TRUE(counter.Wait());
95
96 // Make sure the jobs were actually complete.
97 for (const auto& job_done : done) {
98 EXPECT_TRUE(job_done);
99 }
100 }
101
TEST(BlockingCounterWithStatusTest,BasicFunctionalityWithStatus)102 TEST(BlockingCounterWithStatusTest, BasicFunctionalityWithStatus) {
103 std::unique_ptr<ThreadPool> pool = ThreadPool::Create(kNumWorkers);
104 BlockingCounterWithStatus counter(kNumJobs);
105 std::array<bool, kNumJobs> done = {};
106
107 // Schedule the jobs.
108 for (int i = 0; i < kNumJobs; ++i) {
109 pool->Schedule([&counter, &done, i]() {
110 absl::SleepFor(absl::Seconds(1));
111 done[i] = true;
112 counter.Decrement(i != 10);
113 });
114 }
115
116 // Wait for the jobs to complete. This should return false since one of the
117 // jobs reported |job_succeeded| as false.
118 ASSERT_FALSE(counter.Wait());
119
120 // Make sure the jobs were actually complete.
121 for (const auto& job_done : done) {
122 EXPECT_TRUE(job_done);
123 }
124 }
125
126 } // namespace
127 } // namespace libgav1
128