blob: aa0e6d24aa7f70367adea1679d8b4e85a63fc82a [file] [log] [blame]
Ben Fredricksond69f38b2015-01-28 20:06:15 -08001#include <unistd.h>
2
3#include <memory>
Brian Silvermana2ae62d2015-03-15 15:55:22 -07004#include <thread>
Austin Schuhf2a50ba2016-12-24 16:16:26 -08005#include <chrono>
Ben Fredricksond69f38b2015-01-28 20:06:15 -08006
7#include "gtest/gtest.h"
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -05008
John Park33858a32018-09-28 23:05:48 -07009#include "aos/actions/actions.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070010#include "aos/actions/actions_generated.h"
Austin Schuh1bf8a212019-05-26 22:13:14 -070011#include "aos/actions/actor.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070012#include "aos/actions/test_action_generated.h"
13#include "aos/events/simulated_event_loop.h"
Austin Schuh1bf8a212019-05-26 22:13:14 -070014#include "aos/testing/test_logging.h"
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -050015#include "aos/testing/test_shm.h"
Ben Fredricksond69f38b2015-01-28 20:06:15 -080016
Ben Fredricksond69f38b2015-01-28 20:06:15 -080017namespace aos {
18namespace common {
19namespace actions {
20namespace testing {
21
Austin Schuhf2a50ba2016-12-24 16:16:26 -080022namespace chrono = ::std::chrono;
23
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -080024class TestActorIndex
Alex Perrycb7da4b2019-08-28 19:35:56 -070025 : public aos::common::actions::ActorBase<actions::TestActionGoal> {
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -080026 public:
Alex Perrycb7da4b2019-08-28 19:35:56 -070027 typedef TypedActionFactory<actions::TestActionGoal> Factory;
Austin Schuh1bf8a212019-05-26 22:13:14 -070028
29 explicit TestActorIndex(::aos::EventLoop *event_loop)
Alex Perrycb7da4b2019-08-28 19:35:56 -070030 : aos::common::actions::ActorBase<actions::TestActionGoal>(
31 event_loop, "/test_action") {}
Austin Schuh1bf8a212019-05-26 22:13:14 -070032
33 static Factory MakeFactory(::aos::EventLoop *event_loop) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070034 return Factory(event_loop, "/test_action");
Austin Schuh1bf8a212019-05-26 22:13:14 -070035 }
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -080036
Alex Perrycb7da4b2019-08-28 19:35:56 -070037 bool RunAction(const UInt *new_index) override {
38 VLOG(1) << "New index " << FlatbufferToJson(new_index);
39 index = new_index->val();
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -080040 return true;
41 }
42
43 uint32_t index = 0;
44};
45
Ben Fredricksond69f38b2015-01-28 20:06:15 -080046class TestActorNOP
Alex Perrycb7da4b2019-08-28 19:35:56 -070047 : public aos::common::actions::ActorBase<actions::TestActionGoal> {
Ben Fredricksond69f38b2015-01-28 20:06:15 -080048 public:
Alex Perrycb7da4b2019-08-28 19:35:56 -070049 typedef TypedActionFactory<actions::TestActionGoal> Factory;
Austin Schuh1bf8a212019-05-26 22:13:14 -070050
51 explicit TestActorNOP(::aos::EventLoop *event_loop)
Alex Perrycb7da4b2019-08-28 19:35:56 -070052 : actions::ActorBase<actions::TestActionGoal>(
53 event_loop, "/test_action") {}
Austin Schuh1bf8a212019-05-26 22:13:14 -070054
55 static Factory MakeFactory(::aos::EventLoop *event_loop) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070056 return Factory(event_loop, "/test_action");
Austin Schuh1bf8a212019-05-26 22:13:14 -070057 }
Ben Fredricksond69f38b2015-01-28 20:06:15 -080058
Alex Perrycb7da4b2019-08-28 19:35:56 -070059 bool RunAction(const UInt *) override { return true; }
Ben Fredricksond69f38b2015-01-28 20:06:15 -080060};
61
Ben Fredricksond69f38b2015-01-28 20:06:15 -080062class TestActorShouldCancel
Alex Perrycb7da4b2019-08-28 19:35:56 -070063 : public aos::common::actions::ActorBase<actions::TestActionGoal> {
Ben Fredricksond69f38b2015-01-28 20:06:15 -080064 public:
Alex Perrycb7da4b2019-08-28 19:35:56 -070065 typedef TypedActionFactory<actions::TestActionGoal> Factory;
Austin Schuh1bf8a212019-05-26 22:13:14 -070066
67 explicit TestActorShouldCancel(::aos::EventLoop *event_loop)
Alex Perrycb7da4b2019-08-28 19:35:56 -070068 : aos::common::actions::ActorBase<actions::TestActionGoal>(
69 event_loop, "/test_action") {}
Austin Schuh1bf8a212019-05-26 22:13:14 -070070
71 static Factory MakeFactory(::aos::EventLoop *event_loop) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070072 return Factory(event_loop, "/test_action");
Austin Schuh1bf8a212019-05-26 22:13:14 -070073 }
Ben Fredricksond69f38b2015-01-28 20:06:15 -080074
Alex Perrycb7da4b2019-08-28 19:35:56 -070075 bool RunAction(const UInt *) override {
Ben Fredricksond69f38b2015-01-28 20:06:15 -080076 while (!ShouldCancel()) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070077 AOS_LOG(FATAL, "NOT CANCELED!!\n");
Ben Fredricksond69f38b2015-01-28 20:06:15 -080078 }
Daniel Petti3b1e48f2015-02-15 15:57:53 -080079 return true;
Ben Fredricksond69f38b2015-01-28 20:06:15 -080080 }
81};
82
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -080083class TestActor2Nop
Alex Perrycb7da4b2019-08-28 19:35:56 -070084 : public aos::common::actions::ActorBase<actions::TestAction2Goal> {
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -080085 public:
Alex Perrycb7da4b2019-08-28 19:35:56 -070086 typedef TypedActionFactory<actions::TestAction2Goal> Factory;
Austin Schuh1bf8a212019-05-26 22:13:14 -070087
88 explicit TestActor2Nop(::aos::EventLoop *event_loop)
Alex Perrycb7da4b2019-08-28 19:35:56 -070089 : actions::ActorBase<actions::TestAction2Goal>(
90 event_loop, "/test_action2") {}
Austin Schuh1bf8a212019-05-26 22:13:14 -070091
92 static Factory MakeFactory(::aos::EventLoop *event_loop) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070093 return Factory(event_loop, "/test_action2");
Austin Schuh1bf8a212019-05-26 22:13:14 -070094 }
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -080095
Alex Perrycb7da4b2019-08-28 19:35:56 -070096 bool RunAction(const actions::MyParams *) { return true; }
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -080097};
98
Ben Fredricksond69f38b2015-01-28 20:06:15 -080099class ActionTest : public ::testing::Test {
100 protected:
Austin Schuh1bf8a212019-05-26 22:13:14 -0700101 ActionTest()
Alex Perrycb7da4b2019-08-28 19:35:56 -0700102 : configuration_(
103 configuration::ReadConfig("aos/actions/action_test_config.json")),
104 event_loop_factory_(&configuration_.message()),
105 actor1_event_loop_(event_loop_factory_.MakeEventLoop()),
Austin Schuh1bf8a212019-05-26 22:13:14 -0700106 actor2_event_loop_(event_loop_factory_.MakeEventLoop()),
107 test_event_loop_(event_loop_factory_.MakeEventLoop()) {
108 ::aos::testing::EnableTestLogging();
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800109 }
110
Alex Perrycb7da4b2019-08-28 19:35:56 -0700111 FlatbufferDetachedBuffer<Configuration> configuration_;
112
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800113 // Bring up and down Core.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700114 ::aos::SimulatedEventLoopFactory event_loop_factory_;
115
116 ::std::unique_ptr<::aos::EventLoop> actor1_event_loop_;
117 ::std::unique_ptr<::aos::EventLoop> actor2_event_loop_;
118 ::std::unique_ptr<::aos::EventLoop> test_event_loop_;
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800119};
120
121// Tests that the the actions exist in a safe state at startup.
122TEST_F(ActionTest, DoesNothing) {
Austin Schuh1bf8a212019-05-26 22:13:14 -0700123 ActionQueue action_queue;
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800124 // Tick an empty queue and make sure it was not running.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700125 EXPECT_FALSE(action_queue.Running());
126 action_queue.Tick();
127 EXPECT_FALSE(action_queue.Running());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800128}
129
Brian Silvermana2ae62d2015-03-15 15:55:22 -0700130// Tests that starting with an old run message in the goal queue actually works.
131// This used to result in the client hanging, waiting for a response to its
132// cancel message.
133TEST_F(ActionTest, StartWithOldGoal) {
Austin Schuh1bf8a212019-05-26 22:13:14 -0700134 ::std::unique_ptr<::aos::EventLoop> test2_event_loop =
135 event_loop_factory_.MakeEventLoop();
Alex Perrycb7da4b2019-08-28 19:35:56 -0700136 ::aos::Sender<TestActionGoal> goal_sender =
137 test2_event_loop->MakeSender<TestActionGoal>("/test_action");
138 ::aos::Fetcher<Status> status_fetcher =
139 test2_event_loop->MakeFetcher<Status>("/test_action");
Brian Silvermana2ae62d2015-03-15 15:55:22 -0700140
Austin Schuh1bf8a212019-05-26 22:13:14 -0700141 TestActorIndex::Factory nop_actor_factory =
142 TestActorNOP::MakeFactory(test_event_loop_.get());
Brian Silvermana2ae62d2015-03-15 15:55:22 -0700143
Austin Schuh1bf8a212019-05-26 22:13:14 -0700144 ActionQueue action_queue;
Brian Silvermana2ae62d2015-03-15 15:55:22 -0700145
Austin Schuh1bf8a212019-05-26 22:13:14 -0700146 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700147 ::aos::Sender<TestActionGoal>::Builder builder =
148 goal_sender.MakeBuilder();
149
150 TestActionGoal::Builder goal_builder =
151 builder.MakeBuilder<TestActionGoal>();
152
153 goal_builder.add_run(971);
154 ASSERT_TRUE(builder.Send(goal_builder.Finish()));
Austin Schuh1bf8a212019-05-26 22:13:14 -0700155 }
156
157 TestActorNOP nop_act(actor1_event_loop_.get());
158
159 ASSERT_FALSE(status_fetcher.Fetch());
160
161 event_loop_factory_.RunFor(chrono::seconds(1));
162
163 ASSERT_TRUE(status_fetcher.Fetch());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700164 EXPECT_EQ(0u, status_fetcher->running());
165 EXPECT_EQ(0u, status_fetcher->last_running());
Austin Schuh1bf8a212019-05-26 22:13:14 -0700166
Alex Perrycb7da4b2019-08-28 19:35:56 -0700167 {
168 UIntT uint;
169 uint.val = 0;
170 action_queue.EnqueueAction(nop_actor_factory.Make(uint));
171 }
Brian Silvermana2ae62d2015-03-15 15:55:22 -0700172
173 // We started an action and it should be running.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700174 EXPECT_TRUE(action_queue.Running());
Brian Silvermana2ae62d2015-03-15 15:55:22 -0700175
Austin Schuh1bf8a212019-05-26 22:13:14 -0700176 action_queue.CancelAllActions();
177 action_queue.Tick();
Brian Silvermana2ae62d2015-03-15 15:55:22 -0700178
Austin Schuh1bf8a212019-05-26 22:13:14 -0700179 EXPECT_TRUE(action_queue.Running());
Brian Silvermana2ae62d2015-03-15 15:55:22 -0700180
181 // Run the action so it can signal completion.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700182 event_loop_factory_.RunFor(chrono::seconds(1));
183 action_queue.Tick();
Brian Silvermana2ae62d2015-03-15 15:55:22 -0700184
185 // Make sure it stopped.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700186 EXPECT_FALSE(action_queue.Running());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800187}
188
189// Tests that an action starts and stops.
190TEST_F(ActionTest, ActionQueueWasRunning) {
Austin Schuh1bf8a212019-05-26 22:13:14 -0700191 TestActorNOP nop_act(actor1_event_loop_.get());
192
193 TestActorIndex::Factory nop_actor_factory =
194 TestActorNOP::MakeFactory(test_event_loop_.get());
195
196 ActionQueue action_queue;
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800197
198 // Tick an empty queue and make sure it was not running.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700199 event_loop_factory_.RunFor(chrono::seconds(1));
200 action_queue.Tick();
201 EXPECT_FALSE(action_queue.Running());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800202
Alex Perrycb7da4b2019-08-28 19:35:56 -0700203 {
204 UIntT uint;
205 uint.val = 0;
206 action_queue.EnqueueAction(nop_actor_factory.Make(uint));
207 }
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800208
209 // We started an action and it should be running.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700210 EXPECT_TRUE(action_queue.Running());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800211
212 // Tick it and make sure it is still running.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700213 action_queue.Tick();
214 EXPECT_TRUE(action_queue.Running());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800215
216 // Run the action so it can signal completion.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700217 event_loop_factory_.RunFor(chrono::seconds(1));
218 action_queue.Tick();
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800219
220 // Make sure it stopped.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700221 EXPECT_FALSE(action_queue.Running());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800222}
223
224// Tests that we can cancel two actions and have them both stop.
225TEST_F(ActionTest, ActionQueueCancelAll) {
Austin Schuh1bf8a212019-05-26 22:13:14 -0700226 TestActorNOP nop_act(actor1_event_loop_.get());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800227
Austin Schuh1bf8a212019-05-26 22:13:14 -0700228 TestActorIndex::Factory nop_actor_factory =
229 TestActorNOP::MakeFactory(test_event_loop_.get());
230
231 ActionQueue action_queue;
232
233 // Let the actor and action queue start up and confirm nothing is running.
234 event_loop_factory_.RunFor(chrono::seconds(1));
235 action_queue.Tick();
236
237 EXPECT_FALSE(action_queue.Running());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800238
239 // Enqueue two actions to test both cancel. We can have an action and a next
240 // action so we want to test that.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700241 {
242 UIntT uint;
243 uint.val = 0;
244 action_queue.EnqueueAction(nop_actor_factory.Make(uint));
245 action_queue.EnqueueAction(nop_actor_factory.Make(uint));
246 }
Austin Schuh1bf8a212019-05-26 22:13:14 -0700247
248 action_queue.Tick();
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800249
250 // Check that current and next exist.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700251 EXPECT_TRUE(action_queue.GetCurrentActionState(nullptr, nullptr, nullptr,
252 nullptr, nullptr, nullptr));
253 EXPECT_TRUE(action_queue.GetNextActionState(nullptr, nullptr, nullptr,
254 nullptr, nullptr, nullptr));
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800255
Austin Schuh1bf8a212019-05-26 22:13:14 -0700256 action_queue.CancelAllActions();
257 action_queue.Tick();
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800258
259 // It should still be running as the actor could not have signaled.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700260 EXPECT_TRUE(action_queue.Running());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800261
262 bool sent_started, sent_cancel, interrupted;
Austin Schuh1bf8a212019-05-26 22:13:14 -0700263 EXPECT_TRUE(action_queue.GetCurrentActionState(
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800264 nullptr, &sent_started, &sent_cancel, &interrupted, nullptr, nullptr));
265 EXPECT_TRUE(sent_started);
266 EXPECT_TRUE(sent_cancel);
267 EXPECT_FALSE(interrupted);
268
Austin Schuh1bf8a212019-05-26 22:13:14 -0700269 EXPECT_FALSE(action_queue.GetNextActionState(nullptr, nullptr, nullptr,
270 nullptr, nullptr, nullptr));
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800271
272 // Run the action so it can signal completion.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700273 event_loop_factory_.RunFor(chrono::seconds(1));
274
275 action_queue.Tick();
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800276
277 // Make sure it stopped.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700278 EXPECT_FALSE(action_queue.Running());
279 EXPECT_EQ(1, nop_act.running_count());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800280}
281
282// Tests that an action that would block forever stops when canceled.
283TEST_F(ActionTest, ActionQueueCancelOne) {
Austin Schuh1bf8a212019-05-26 22:13:14 -0700284 TestActorShouldCancel cancel_act(actor1_event_loop_.get());
285
286 TestActorShouldCancel::Factory cancel_action_factory =
287 TestActorShouldCancel::MakeFactory(test_event_loop_.get());
288
289 ActionQueue action_queue;
290
291 // Let the actor and action queue start up.
292 event_loop_factory_.RunFor(chrono::seconds(1));
293 action_queue.Tick();
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800294
295 // Enqueue blocking action.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700296 {
297 UIntT uint;
298 uint.val = 0;
299 action_queue.EnqueueAction(cancel_action_factory.Make(uint));
300 }
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800301
Austin Schuh1bf8a212019-05-26 22:13:14 -0700302 action_queue.Tick();
303 EXPECT_TRUE(action_queue.Running());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800304
305 // Tell action to cancel.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700306 action_queue.CancelCurrentAction();
307 action_queue.Tick();
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800308
309 // This will block forever on failure.
310 // TODO(ben): prolly a bad way to fail
Austin Schuh1bf8a212019-05-26 22:13:14 -0700311 event_loop_factory_.RunFor(chrono::seconds(1));
312 action_queue.Tick();
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800313
314 // It should still be running as the actor could not have signalled.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700315 EXPECT_FALSE(action_queue.Running());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800316}
317
Austin Schuh1bf8a212019-05-26 22:13:14 -0700318// Tests that 2 actions in a row causes the second one to cancel the first one.
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800319TEST_F(ActionTest, ActionQueueTwoActions) {
Austin Schuh1bf8a212019-05-26 22:13:14 -0700320 TestActorNOP nop_actor(actor1_event_loop_.get());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800321
Austin Schuh1bf8a212019-05-26 22:13:14 -0700322 TestActorIndex::Factory nop_actor_factory =
323 TestActorNOP::MakeFactory(test_event_loop_.get());
324
325 ActionQueue action_queue;
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800326 // Tick an empty queue and make sure it was not running.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700327 event_loop_factory_.RunFor(chrono::seconds(1));
328 action_queue.Tick();
329 EXPECT_FALSE(action_queue.Running());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800330
331 // Enqueue action to be canceled.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700332 {
333 UIntT uint;
334 uint.val = 0;
335 action_queue.EnqueueAction(nop_actor_factory.Make(uint));
336 }
Austin Schuh1bf8a212019-05-26 22:13:14 -0700337 action_queue.Tick();
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800338
339 // Should still be running as the actor could not have signalled.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700340 EXPECT_TRUE(action_queue.Running());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800341
342 // id for the first time run.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700343 uint32_t nop_actor_id = 0;
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800344 // Check the internal state and write down id for later use.
345 bool sent_started, sent_cancel, interrupted;
Austin Schuh1bf8a212019-05-26 22:13:14 -0700346 EXPECT_TRUE(action_queue.GetCurrentActionState(nullptr, &sent_started,
347 &sent_cancel, &interrupted,
348 &nop_actor_id, nullptr));
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800349 EXPECT_TRUE(sent_started);
350 EXPECT_FALSE(sent_cancel);
351 EXPECT_FALSE(interrupted);
Austin Schuh1bf8a212019-05-26 22:13:14 -0700352 ASSERT_NE(0u, nop_actor_id);
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800353
354 // Add the next action which should ensure the first stopped.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700355 {
356 UIntT uint;
357 uint.val = 0;
358 action_queue.EnqueueAction(nop_actor_factory.Make(uint));
359 }
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800360
361 // id for the second run.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700362 uint32_t nop_actor2_id = 0;
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800363 // Check the internal state and write down id for later use.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700364 EXPECT_TRUE(action_queue.GetNextActionState(nullptr, &sent_started,
365 &sent_cancel, &interrupted,
366 &nop_actor2_id, nullptr));
367 EXPECT_NE(nop_actor_id, nop_actor2_id);
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800368 EXPECT_FALSE(sent_started);
369 EXPECT_FALSE(sent_cancel);
370 EXPECT_FALSE(interrupted);
Austin Schuh1bf8a212019-05-26 22:13:14 -0700371 ASSERT_NE(0u, nop_actor2_id);
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800372
Austin Schuh1bf8a212019-05-26 22:13:14 -0700373 action_queue.Tick();
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800374
375 // Run the action so it can signal completion.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700376 event_loop_factory_.RunFor(chrono::seconds(1));
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800377
Austin Schuh1bf8a212019-05-26 22:13:14 -0700378 action_queue.Tick();
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800379
380 // Check the new action is the right one.
381 uint32_t test_id = 0;
Austin Schuh1bf8a212019-05-26 22:13:14 -0700382 EXPECT_TRUE(action_queue.GetCurrentActionState(
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800383 nullptr, &sent_started, &sent_cancel, &interrupted, &test_id, nullptr));
384 EXPECT_TRUE(sent_started);
385 EXPECT_FALSE(sent_cancel);
386 EXPECT_FALSE(interrupted);
Austin Schuh1bf8a212019-05-26 22:13:14 -0700387 EXPECT_EQ(nop_actor2_id, test_id);
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800388
389 // Make sure it is still going.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700390 EXPECT_TRUE(action_queue.Running());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800391
Austin Schuh1bf8a212019-05-26 22:13:14 -0700392 // Now let everything finish.
393 event_loop_factory_.RunFor(chrono::seconds(1));
394 action_queue.Tick();
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800395
396 // Make sure it stopped.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700397 EXPECT_FALSE(action_queue.Running());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800398}
399
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800400// Tests that we do get an index with our goal
401TEST_F(ActionTest, ActionIndex) {
Austin Schuh1bf8a212019-05-26 22:13:14 -0700402 TestActorIndex idx_actor(actor1_event_loop_.get());
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800403
Austin Schuh1bf8a212019-05-26 22:13:14 -0700404 TestActorIndex::Factory test_actor_index_factory =
405 TestActorIndex::MakeFactory(test_event_loop_.get());
406
407 ActionQueue action_queue;
408 // Tick an empty queue and make sure it was not running. Also tick the
409 // factory to allow it to send out the initial cancel message.
410 event_loop_factory_.RunFor(chrono::seconds(1));
411 action_queue.Tick();
412
413 EXPECT_FALSE(action_queue.Running());
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800414
415 // Enqueue action to post index.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700416 {
417 UIntT uint;
418 uint.val = 5;
419 action_queue.EnqueueAction(test_actor_index_factory.Make(uint));
420 }
421 ::aos::Fetcher<actions::TestActionGoal> goal_fetcher_ =
422 test_event_loop_->MakeFetcher<actions::TestActionGoal>(
423 "/test_action");
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800424
Austin Schuh1bf8a212019-05-26 22:13:14 -0700425 ASSERT_TRUE(goal_fetcher_.Fetch());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700426 EXPECT_EQ(5u, goal_fetcher_->params()->val());
Austin Schuh1bf8a212019-05-26 22:13:14 -0700427 EXPECT_EQ(0u, idx_actor.index);
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800428
Austin Schuh1bf8a212019-05-26 22:13:14 -0700429 action_queue.Tick();
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800430
431 // Run the next action so it can accomplish signal completion.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700432 event_loop_factory_.RunFor(chrono::seconds(1));
433
434 action_queue.Tick();
435 EXPECT_EQ(5u, idx_actor.index);
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800436
437 // Enqueue action to post index.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700438 {
439 UIntT uint;
440 uint.val = 3;
441 action_queue.EnqueueAction(test_actor_index_factory.Make(uint));
442 }
Austin Schuh1bf8a212019-05-26 22:13:14 -0700443 ASSERT_TRUE(goal_fetcher_.Fetch());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700444 EXPECT_EQ(3u, goal_fetcher_->params()->val());
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800445
446 // Run the next action so it can accomplish signal completion.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700447 event_loop_factory_.RunFor(chrono::seconds(1));
448
449 action_queue.Tick();
450 EXPECT_EQ(3u, idx_actor.index);
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800451}
452
453// Tests that an action with a structure params works.
454TEST_F(ActionTest, StructParamType) {
Austin Schuh1bf8a212019-05-26 22:13:14 -0700455 TestActor2Nop nop_actor(actor2_event_loop_.get());
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800456
Austin Schuh1bf8a212019-05-26 22:13:14 -0700457 TestActor2Nop::Factory test_action_2_nop_factory =
458 TestActor2Nop::MakeFactory(test_event_loop_.get());
459
460 ActionQueue action_queue;
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800461 // Tick an empty queue and make sure it was not running.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700462 action_queue.Tick();
463 EXPECT_FALSE(action_queue.Running());
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800464
Alex Perrycb7da4b2019-08-28 19:35:56 -0700465 actions::MyParamsT p;
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800466 p.param1 = 5.0;
467 p.param2 = 7;
468
Austin Schuh1bf8a212019-05-26 22:13:14 -0700469 action_queue.EnqueueAction(test_action_2_nop_factory.Make(p));
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800470
471 // We started an action and it should be running.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700472 EXPECT_TRUE(action_queue.Running());
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800473
474 // Tick it and make sure it is still running.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700475 action_queue.Tick();
476 EXPECT_TRUE(action_queue.Running());
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800477
478 // Run the action so it can signal completion.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700479 // The actor takes no time, but running for a second is the best way to get it
480 // to go.
481 event_loop_factory_.RunFor(chrono::seconds(1));
482
483 action_queue.Tick();
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800484
485 // Make sure it stopped.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700486 EXPECT_FALSE(action_queue.Running());
Brian Silverman237a5542015-03-29 17:59:29 -0400487}
488
489} // namespace testing
490} // namespace actions
491} // namespace common
492} // namespace aos