task_test.cc
Go to the documentation of this file.
1 /*
2  * Copyright 2018 The Cartographer Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
18 
19 #include <memory>
20 #include <queue>
21 
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 
26 namespace cartographer {
27 namespace common {
28 namespace {
29 
30 class MockCallback {
31  public:
32  MOCK_METHOD0(Run, void());
33 };
34 
35 class FakeThreadPool : public ThreadPoolInterface {
36  public:
37  void NotifyDependenciesCompleted(Task* task) override {
38  auto it = tasks_not_ready_.find(task);
39  ASSERT_NE(it, tasks_not_ready_.end());
40  task_queue_.push_back(it->second);
41  tasks_not_ready_.erase(it);
42  }
43 
44  std::weak_ptr<Task> Schedule(std::unique_ptr<Task> task) override {
45  std::shared_ptr<Task> shared_task;
46  auto it =
47  tasks_not_ready_.insert(std::make_pair(task.get(), std::move(task)));
48  EXPECT_TRUE(it.second);
49  shared_task = it.first->second;
50  SetThreadPool(shared_task.get());
51  return shared_task;
52  }
53 
54  void RunNext() {
55  ASSERT_GE(task_queue_.size(), 1);
56  Execute(task_queue_.front().get());
57  task_queue_.pop_front();
58  }
59 
60  bool IsEmpty() { return task_queue_.empty(); }
61 
62  private:
63  std::deque<std::shared_ptr<Task>> task_queue_;
64  std::map<Task*, std::shared_ptr<Task>> tasks_not_ready_;
65 };
66 
67 class TaskTest : public ::testing::Test {
68  protected:
69  FakeThreadPool* thread_pool() { return &thread_pool_; }
70  FakeThreadPool thread_pool_;
71 };
72 
73 TEST_F(TaskTest, RunTask) {
74  auto a = make_unique<Task>();
75  MockCallback callback;
76  a->SetWorkItem([&callback]() { callback.Run(); });
77  EXPECT_EQ(a->GetState(), Task::NEW);
78  auto shared_a = thread_pool()->Schedule(std::move(a)).lock();
79  EXPECT_NE(shared_a, nullptr);
80  EXPECT_EQ(shared_a->GetState(), Task::DEPENDENCIES_COMPLETED);
81  EXPECT_CALL(callback, Run()).Times(1);
82  thread_pool()->RunNext();
83  EXPECT_EQ(shared_a->GetState(), Task::COMPLETED);
84  EXPECT_TRUE(thread_pool()->IsEmpty());
85 }
86 
87 TEST_F(TaskTest, RunTaskWithDependency) {
88  auto a = make_unique<Task>();
89  auto b = make_unique<Task>();
90  MockCallback callback_a;
91  a->SetWorkItem([&callback_a]() { callback_a.Run(); });
92  MockCallback callback_b;
93  b->SetWorkItem([&callback_b]() { callback_b.Run(); });
94  EXPECT_EQ(a->GetState(), Task::NEW);
95  EXPECT_EQ(b->GetState(), Task::NEW);
96  {
97  ::testing::InSequence dummy;
98  EXPECT_CALL(callback_a, Run()).Times(1);
99  EXPECT_CALL(callback_b, Run()).Times(1);
100  }
101  auto shared_a = thread_pool()->Schedule(std::move(a)).lock();
102  EXPECT_NE(shared_a, nullptr);
103  b->AddDependency(shared_a);
104  auto shared_b = thread_pool()->Schedule(std::move(b)).lock();
105  EXPECT_NE(shared_b, nullptr);
106  EXPECT_EQ(shared_b->GetState(), Task::DISPATCHED);
107  EXPECT_EQ(shared_a->GetState(), Task::DEPENDENCIES_COMPLETED);
108  thread_pool()->RunNext();
109  EXPECT_EQ(shared_b->GetState(), Task::DEPENDENCIES_COMPLETED);
110  thread_pool()->RunNext();
111  EXPECT_EQ(shared_a->GetState(), Task::COMPLETED);
112  EXPECT_EQ(shared_b->GetState(), Task::COMPLETED);
113 }
114 
115 TEST_F(TaskTest, RunTaskWithTwoDependency) {
116  /* c \
117  * a --> b --> d
118  */
119  auto a = make_unique<Task>();
120  auto b = make_unique<Task>();
121  auto c = make_unique<Task>();
122  auto d = make_unique<Task>();
123  MockCallback callback_a;
124  a->SetWorkItem([&callback_a]() { callback_a.Run(); });
125  MockCallback callback_b;
126  b->SetWorkItem([&callback_b]() { callback_b.Run(); });
127  MockCallback callback_c;
128  c->SetWorkItem([&callback_c]() { callback_c.Run(); });
129  MockCallback callback_d;
130  d->SetWorkItem([&callback_d]() { callback_d.Run(); });
131  EXPECT_CALL(callback_a, Run()).Times(1);
132  EXPECT_CALL(callback_b, Run()).Times(1);
133  EXPECT_CALL(callback_c, Run()).Times(1);
134  EXPECT_CALL(callback_d, Run()).Times(1);
135  auto shared_a = thread_pool()->Schedule(std::move(a)).lock();
136  EXPECT_NE(shared_a, nullptr);
137  b->AddDependency(shared_a);
138  auto shared_b = thread_pool()->Schedule(std::move(b)).lock();
139  EXPECT_NE(shared_b, nullptr);
140  auto shared_c = thread_pool()->Schedule(std::move(c)).lock();
141  EXPECT_NE(shared_c, nullptr);
142  d->AddDependency(shared_b);
143  d->AddDependency(shared_c);
144  auto shared_d = thread_pool()->Schedule(std::move(d)).lock();
145  EXPECT_NE(shared_d, nullptr);
146  EXPECT_EQ(shared_b->GetState(), Task::DISPATCHED);
147  EXPECT_EQ(shared_d->GetState(), Task::DISPATCHED);
148  thread_pool()->RunNext();
149  EXPECT_EQ(shared_a->GetState(), Task::COMPLETED);
150  EXPECT_EQ(shared_b->GetState(), Task::DEPENDENCIES_COMPLETED);
151  EXPECT_EQ(shared_c->GetState(), Task::DEPENDENCIES_COMPLETED);
152  thread_pool()->RunNext();
153  thread_pool()->RunNext();
154  EXPECT_EQ(shared_b->GetState(), Task::COMPLETED);
155  EXPECT_EQ(shared_c->GetState(), Task::COMPLETED);
156  EXPECT_EQ(shared_d->GetState(), Task::DEPENDENCIES_COMPLETED);
157  thread_pool()->RunNext();
158  EXPECT_EQ(shared_d->GetState(), Task::COMPLETED);
159 }
160 
161 TEST_F(TaskTest, RunWithCompletedDependency) {
162  auto a = make_unique<Task>();
163  MockCallback callback_a;
164  a->SetWorkItem([&callback_a]() { callback_a.Run(); });
165  auto shared_a = thread_pool()->Schedule(std::move(a)).lock();
166  EXPECT_NE(shared_a, nullptr);
167  EXPECT_EQ(shared_a->GetState(), Task::DEPENDENCIES_COMPLETED);
168  EXPECT_CALL(callback_a, Run()).Times(1);
169  thread_pool()->RunNext();
170  EXPECT_EQ(shared_a->GetState(), Task::COMPLETED);
171  auto b = make_unique<Task>();
172  MockCallback callback_b;
173  b->SetWorkItem([&callback_b]() { callback_b.Run(); });
174  b->AddDependency(shared_a);
175  EXPECT_EQ(b->GetState(), Task::NEW);
176  auto shared_b = thread_pool()->Schedule(std::move(b)).lock();
177  EXPECT_NE(shared_b, nullptr);
178  EXPECT_EQ(shared_b->GetState(), Task::DEPENDENCIES_COMPLETED);
179  EXPECT_CALL(callback_b, Run()).Times(1);
180  thread_pool()->RunNext();
181  EXPECT_EQ(shared_b->GetState(), Task::COMPLETED);
182 }
183 
184 } // namespace
185 } // namespace common
186 } // namespace cartographer
std::map< Task *, std::shared_ptr< Task > > tasks_not_ready_
Definition: task_test.cc:64
FakeThreadPool thread_pool_
Definition: task_test.cc:70
std::deque< std::shared_ptr< Task > > task_queue_
Definition: task_test.cc:63
void Run(const std::string &configuration_directory, const std::string &configuration_basename)


cartographer
Author(s): The Cartographer Authors
autogenerated on Mon Feb 28 2022 22:00:58