blob: fca60a3899cbb2296895f87c35e4365105ac3b94 [file] [log] [blame]
Stephan Pleinesbad70072024-05-22 16:48:01 -07001#include <stdint.h>
Ben Fredricksond69f38b2015-01-28 20:06:15 -08002
milind1f1dca32021-07-03 13:50:07 -07003#include <chrono>
Stephan Pleinesbad70072024-05-22 16:48:01 -07004#include <functional>
Ben Fredricksond69f38b2015-01-28 20:06:15 -08005#include <memory>
Stephan Pleinesbad70072024-05-22 16:48:01 -07006#include <ostream>
7#include <string>
Ben Fredricksond69f38b2015-01-28 20:06:15 -08008
Stephan Pleinesbad70072024-05-22 16:48:01 -07009#include "flatbuffers/buffer.h"
10#include "glog/logging.h"
Philipp Schrader790cb542023-07-05 21:06:52 -070011#include "gtest/gtest.h"
12
John Park33858a32018-09-28 23:05:48 -070013#include "aos/actions/actions.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070014#include "aos/actions/actions_generated.h"
Austin Schuh1bf8a212019-05-26 22:13:14 -070015#include "aos/actions/actor.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070016#include "aos/actions/test_action_generated.h"
Stephan Pleinesbad70072024-05-22 16:48:01 -070017#include "aos/configuration.h"
18#include "aos/events/event_loop.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070019#include "aos/events/simulated_event_loop.h"
Stephan Pleinesbad70072024-05-22 16:48:01 -070020#include "aos/flatbuffers.h"
21#include "aos/json_to_flatbuffer.h"
22#include "aos/logging/implementations.h"
Austin Schuh373f1762021-06-02 21:07:09 -070023#include "aos/testing/path.h"
Stephan Pleinesbad70072024-05-22 16:48:01 -070024#include "aos/time/time.h"
Ben Fredricksond69f38b2015-01-28 20:06:15 -080025
Stephan Pleinesf63bde82024-01-13 15:59:33 -080026namespace aos::common::actions::testing {
Ben Fredricksond69f38b2015-01-28 20:06:15 -080027
Austin Schuhf2a50ba2016-12-24 16:16:26 -080028namespace chrono = ::std::chrono;
29
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -080030class TestActorIndex
Alex Perrycb7da4b2019-08-28 19:35:56 -070031 : public aos::common::actions::ActorBase<actions::TestActionGoal> {
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -080032 public:
Alex Perrycb7da4b2019-08-28 19:35:56 -070033 typedef TypedActionFactory<actions::TestActionGoal> Factory;
Austin Schuh1bf8a212019-05-26 22:13:14 -070034
35 explicit TestActorIndex(::aos::EventLoop *event_loop)
Alex Perrycb7da4b2019-08-28 19:35:56 -070036 : aos::common::actions::ActorBase<actions::TestActionGoal>(
37 event_loop, "/test_action") {}
Austin Schuh1bf8a212019-05-26 22:13:14 -070038
39 static Factory MakeFactory(::aos::EventLoop *event_loop) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070040 return Factory(event_loop, "/test_action");
Austin Schuh1bf8a212019-05-26 22:13:14 -070041 }
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -080042
Alex Perrycb7da4b2019-08-28 19:35:56 -070043 bool RunAction(const UInt *new_index) override {
44 VLOG(1) << "New index " << FlatbufferToJson(new_index);
45 index = new_index->val();
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -080046 return true;
47 }
48
49 uint32_t index = 0;
50};
51
Ben Fredricksond69f38b2015-01-28 20:06:15 -080052class TestActorNOP
Alex Perrycb7da4b2019-08-28 19:35:56 -070053 : public aos::common::actions::ActorBase<actions::TestActionGoal> {
Ben Fredricksond69f38b2015-01-28 20:06:15 -080054 public:
Alex Perrycb7da4b2019-08-28 19:35:56 -070055 typedef TypedActionFactory<actions::TestActionGoal> Factory;
Austin Schuh1bf8a212019-05-26 22:13:14 -070056
57 explicit TestActorNOP(::aos::EventLoop *event_loop)
milind1f1dca32021-07-03 13:50:07 -070058 : actions::ActorBase<actions::TestActionGoal>(event_loop,
59 "/test_action") {}
Austin Schuh1bf8a212019-05-26 22:13:14 -070060
61 static Factory MakeFactory(::aos::EventLoop *event_loop) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070062 return Factory(event_loop, "/test_action");
Austin Schuh1bf8a212019-05-26 22:13:14 -070063 }
Ben Fredricksond69f38b2015-01-28 20:06:15 -080064
Alex Perrycb7da4b2019-08-28 19:35:56 -070065 bool RunAction(const UInt *) override { return true; }
Ben Fredricksond69f38b2015-01-28 20:06:15 -080066};
67
Ben Fredricksond69f38b2015-01-28 20:06:15 -080068class TestActorShouldCancel
Alex Perrycb7da4b2019-08-28 19:35:56 -070069 : public aos::common::actions::ActorBase<actions::TestActionGoal> {
Ben Fredricksond69f38b2015-01-28 20:06:15 -080070 public:
Alex Perrycb7da4b2019-08-28 19:35:56 -070071 typedef TypedActionFactory<actions::TestActionGoal> Factory;
Austin Schuh1bf8a212019-05-26 22:13:14 -070072
73 explicit TestActorShouldCancel(::aos::EventLoop *event_loop)
Alex Perrycb7da4b2019-08-28 19:35:56 -070074 : aos::common::actions::ActorBase<actions::TestActionGoal>(
75 event_loop, "/test_action") {}
Austin Schuh1bf8a212019-05-26 22:13:14 -070076
77 static Factory MakeFactory(::aos::EventLoop *event_loop) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070078 return Factory(event_loop, "/test_action");
Austin Schuh1bf8a212019-05-26 22:13:14 -070079 }
Ben Fredricksond69f38b2015-01-28 20:06:15 -080080
Alex Perrycb7da4b2019-08-28 19:35:56 -070081 bool RunAction(const UInt *) override {
Ben Fredricksond69f38b2015-01-28 20:06:15 -080082 while (!ShouldCancel()) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070083 AOS_LOG(FATAL, "NOT CANCELED!!\n");
Ben Fredricksond69f38b2015-01-28 20:06:15 -080084 }
Daniel Petti3b1e48f2015-02-15 15:57:53 -080085 return true;
Ben Fredricksond69f38b2015-01-28 20:06:15 -080086 }
87};
88
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -080089class TestActor2Nop
Alex Perrycb7da4b2019-08-28 19:35:56 -070090 : public aos::common::actions::ActorBase<actions::TestAction2Goal> {
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -080091 public:
Alex Perrycb7da4b2019-08-28 19:35:56 -070092 typedef TypedActionFactory<actions::TestAction2Goal> Factory;
Austin Schuh1bf8a212019-05-26 22:13:14 -070093
94 explicit TestActor2Nop(::aos::EventLoop *event_loop)
milind1f1dca32021-07-03 13:50:07 -070095 : actions::ActorBase<actions::TestAction2Goal>(event_loop,
96 "/test_action2") {}
Austin Schuh1bf8a212019-05-26 22:13:14 -070097
98 static Factory MakeFactory(::aos::EventLoop *event_loop) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070099 return Factory(event_loop, "/test_action2");
Austin Schuh1bf8a212019-05-26 22:13:14 -0700100 }
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800101
Alex Perrycb7da4b2019-08-28 19:35:56 -0700102 bool RunAction(const actions::MyParams *) { return true; }
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800103};
104
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800105class ActionTest : public ::testing::Test {
106 protected:
Austin Schuh1bf8a212019-05-26 22:13:14 -0700107 ActionTest()
Austin Schuh373f1762021-06-02 21:07:09 -0700108 : configuration_(configuration::ReadConfig(
109 aos::testing::ArtifactPath("aos/actions/action_test_config.json"))),
Alex Perrycb7da4b2019-08-28 19:35:56 -0700110 event_loop_factory_(&configuration_.message()),
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800111 actor1_event_loop_(event_loop_factory_.MakeEventLoop("actor1")),
112 actor2_event_loop_(event_loop_factory_.MakeEventLoop("actor2")),
Brian Silverman13065ed2020-12-16 15:15:27 -0800113 test_event_loop_(event_loop_factory_.MakeEventLoop("test")) {}
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800114
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800115 void RunAt(monotonic_clock::time_point exec_time, std::function<void()> fn) {
116 TimerHandler *timer = test_event_loop_->AddTimer(fn);
Philipp Schradera6712522023-07-05 20:25:11 -0700117 test_event_loop_->OnRun(
118 [timer, exec_time]() { timer->Schedule(exec_time); });
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800119 }
120
Alex Perrycb7da4b2019-08-28 19:35:56 -0700121 FlatbufferDetachedBuffer<Configuration> configuration_;
122
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800123 // Bring up and down Core.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700124 ::aos::SimulatedEventLoopFactory event_loop_factory_;
125
126 ::std::unique_ptr<::aos::EventLoop> actor1_event_loop_;
127 ::std::unique_ptr<::aos::EventLoop> actor2_event_loop_;
128 ::std::unique_ptr<::aos::EventLoop> test_event_loop_;
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800129};
130
131// Tests that the the actions exist in a safe state at startup.
132TEST_F(ActionTest, DoesNothing) {
Austin Schuh1bf8a212019-05-26 22:13:14 -0700133 ActionQueue action_queue;
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800134 // Tick an empty queue and make sure it was not running.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700135 EXPECT_FALSE(action_queue.Running());
136 action_queue.Tick();
137 EXPECT_FALSE(action_queue.Running());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800138}
139
Brian Silvermana2ae62d2015-03-15 15:55:22 -0700140// Tests that starting with an old run message in the goal queue actually works.
141// This used to result in the client hanging, waiting for a response to its
142// cancel message.
143TEST_F(ActionTest, StartWithOldGoal) {
Austin Schuh1bf8a212019-05-26 22:13:14 -0700144 ::std::unique_ptr<::aos::EventLoop> test2_event_loop =
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800145 event_loop_factory_.MakeEventLoop("test2");
Alex Perrycb7da4b2019-08-28 19:35:56 -0700146 ::aos::Sender<TestActionGoal> goal_sender =
147 test2_event_loop->MakeSender<TestActionGoal>("/test_action");
148 ::aos::Fetcher<Status> status_fetcher =
149 test2_event_loop->MakeFetcher<Status>("/test_action");
Brian Silvermana2ae62d2015-03-15 15:55:22 -0700150
Austin Schuh1bf8a212019-05-26 22:13:14 -0700151 TestActorIndex::Factory nop_actor_factory =
152 TestActorNOP::MakeFactory(test_event_loop_.get());
Brian Silvermana2ae62d2015-03-15 15:55:22 -0700153
Austin Schuh1bf8a212019-05-26 22:13:14 -0700154 ActionQueue action_queue;
Brian Silvermana2ae62d2015-03-15 15:55:22 -0700155
Austin Schuh1bf8a212019-05-26 22:13:14 -0700156 {
milind1f1dca32021-07-03 13:50:07 -0700157 ::aos::Sender<TestActionGoal>::Builder builder = goal_sender.MakeBuilder();
Alex Perrycb7da4b2019-08-28 19:35:56 -0700158
159 TestActionGoal::Builder goal_builder =
160 builder.MakeBuilder<TestActionGoal>();
161
162 goal_builder.add_run(971);
milind1f1dca32021-07-03 13:50:07 -0700163 builder.CheckOk(builder.Send(goal_builder.Finish()));
Austin Schuh1bf8a212019-05-26 22:13:14 -0700164 }
165
166 TestActorNOP nop_act(actor1_event_loop_.get());
167
168 ASSERT_FALSE(status_fetcher.Fetch());
169
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800170 RunAt(monotonic_clock::time_point(chrono::seconds(1)), [&]() {
171 ASSERT_TRUE(status_fetcher.Fetch());
172 EXPECT_EQ(0u, status_fetcher->running());
173 EXPECT_EQ(0u, status_fetcher->last_running());
Austin Schuh1bf8a212019-05-26 22:13:14 -0700174
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800175 {
176 UIntT uint;
177 uint.val = 0;
178 action_queue.EnqueueAction(nop_actor_factory.Make(uint));
179 }
Austin Schuh1bf8a212019-05-26 22:13:14 -0700180
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800181 // We started an action and it should be running.
182 EXPECT_TRUE(action_queue.Running());
Brian Silvermana2ae62d2015-03-15 15:55:22 -0700183
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800184 action_queue.CancelAllActions();
185 action_queue.Tick();
Brian Silvermana2ae62d2015-03-15 15:55:22 -0700186
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800187 EXPECT_TRUE(action_queue.Running());
188 });
Brian Silvermana2ae62d2015-03-15 15:55:22 -0700189
190 // Run the action so it can signal completion.
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800191 RunAt(monotonic_clock::time_point(chrono::seconds(2)), [&]() {
192 action_queue.Tick();
Brian Silvermana2ae62d2015-03-15 15:55:22 -0700193
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800194 // Make sure it stopped.
195 EXPECT_FALSE(action_queue.Running());
196 });
197
198 event_loop_factory_.RunFor(chrono::seconds(3));
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800199}
200
201// Tests that an action starts and stops.
202TEST_F(ActionTest, ActionQueueWasRunning) {
Austin Schuh1bf8a212019-05-26 22:13:14 -0700203 TestActorNOP nop_act(actor1_event_loop_.get());
204
205 TestActorIndex::Factory nop_actor_factory =
206 TestActorNOP::MakeFactory(test_event_loop_.get());
207
208 ActionQueue action_queue;
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800209
210 // Tick an empty queue and make sure it was not running.
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800211 RunAt(monotonic_clock::time_point(chrono::seconds(1)), [&]() {
212 action_queue.Tick();
213 EXPECT_FALSE(action_queue.Running());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800214
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800215 {
216 UIntT uint;
217 uint.val = 0;
218 action_queue.EnqueueAction(nop_actor_factory.Make(uint));
219 }
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800220
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800221 // We started an action and it should be running.
222 EXPECT_TRUE(action_queue.Running());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800223
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800224 // Tick it and make sure it is still running.
225 action_queue.Tick();
226 EXPECT_TRUE(action_queue.Running());
227 });
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800228
229 // Run the action so it can signal completion.
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800230 RunAt(monotonic_clock::time_point(chrono::seconds(2)), [&]() {
231 action_queue.Tick();
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800232
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800233 // Make sure it stopped.
234 EXPECT_FALSE(action_queue.Running());
235 });
236
237 event_loop_factory_.RunFor(chrono::seconds(3));
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800238}
239
240// Tests that we can cancel two actions and have them both stop.
241TEST_F(ActionTest, ActionQueueCancelAll) {
Austin Schuh1bf8a212019-05-26 22:13:14 -0700242 TestActorNOP nop_act(actor1_event_loop_.get());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800243
Austin Schuh1bf8a212019-05-26 22:13:14 -0700244 TestActorIndex::Factory nop_actor_factory =
245 TestActorNOP::MakeFactory(test_event_loop_.get());
246
247 ActionQueue action_queue;
248
249 // Let the actor and action queue start up and confirm nothing is running.
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800250 RunAt(monotonic_clock::time_point(chrono::seconds(1)), [&]() {
251 action_queue.Tick();
Austin Schuh1bf8a212019-05-26 22:13:14 -0700252
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800253 EXPECT_FALSE(action_queue.Running());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800254
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800255 // Enqueue two actions to test both cancel. We can have an action and a next
256 // action so we want to test that.
257 {
258 UIntT uint;
259 uint.val = 0;
260 action_queue.EnqueueAction(nop_actor_factory.Make(uint));
261 action_queue.EnqueueAction(nop_actor_factory.Make(uint));
262 }
Austin Schuh1bf8a212019-05-26 22:13:14 -0700263
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800264 action_queue.Tick();
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800265
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800266 // Check that current and next exist.
267 EXPECT_TRUE(action_queue.GetCurrentActionState(nullptr, nullptr, nullptr,
268 nullptr, nullptr, nullptr));
269 EXPECT_TRUE(action_queue.GetNextActionState(nullptr, nullptr, nullptr,
270 nullptr, nullptr, nullptr));
271
272 action_queue.CancelAllActions();
273 action_queue.Tick();
274
275 // It should still be running as the actor could not have signaled.
276 EXPECT_TRUE(action_queue.Running());
277
278 bool sent_started, sent_cancel, interrupted;
279 EXPECT_TRUE(action_queue.GetCurrentActionState(
280 nullptr, &sent_started, &sent_cancel, &interrupted, nullptr, nullptr));
281 EXPECT_TRUE(sent_started);
282 EXPECT_TRUE(sent_cancel);
283 EXPECT_FALSE(interrupted);
284
285 EXPECT_FALSE(action_queue.GetNextActionState(nullptr, nullptr, nullptr,
Austin Schuh1bf8a212019-05-26 22:13:14 -0700286 nullptr, nullptr, nullptr));
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800287 });
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800288
289 // Run the action so it can signal completion.
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800290 RunAt(monotonic_clock::time_point(chrono::seconds(2)), [&]() {
291 action_queue.Tick();
Austin Schuh1bf8a212019-05-26 22:13:14 -0700292
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800293 // Make sure it stopped.
294 EXPECT_FALSE(action_queue.Running());
295 EXPECT_EQ(1, nop_act.running_count());
296 });
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800297
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800298 event_loop_factory_.RunFor(chrono::seconds(3));
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800299}
300
301// Tests that an action that would block forever stops when canceled.
302TEST_F(ActionTest, ActionQueueCancelOne) {
Austin Schuh1bf8a212019-05-26 22:13:14 -0700303 TestActorShouldCancel cancel_act(actor1_event_loop_.get());
304
305 TestActorShouldCancel::Factory cancel_action_factory =
306 TestActorShouldCancel::MakeFactory(test_event_loop_.get());
307
308 ActionQueue action_queue;
309
310 // Let the actor and action queue start up.
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800311 RunAt(monotonic_clock::time_point(chrono::seconds(1)), [&]() {
312 action_queue.Tick();
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800313
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800314 // Enqueue blocking action.
315 {
316 UIntT uint;
317 uint.val = 0;
318 action_queue.EnqueueAction(cancel_action_factory.Make(uint));
319 }
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800320
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800321 action_queue.Tick();
322 EXPECT_TRUE(action_queue.Running());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800323
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800324 // Tell action to cancel.
325 action_queue.CancelCurrentAction();
326 action_queue.Tick();
327 });
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800328
329 // This will block forever on failure.
330 // TODO(ben): prolly a bad way to fail
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800331 RunAt(monotonic_clock::time_point(chrono::seconds(2)), [&]() {
332 action_queue.Tick();
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800333
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800334 // It should still be running as the actor could not have signalled.
335 EXPECT_FALSE(action_queue.Running());
336 });
337
338 event_loop_factory_.RunFor(chrono::seconds(3));
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800339}
340
Austin Schuh1bf8a212019-05-26 22:13:14 -0700341// Tests that 2 actions in a row causes the second one to cancel the first one.
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800342TEST_F(ActionTest, ActionQueueTwoActions) {
Austin Schuh1bf8a212019-05-26 22:13:14 -0700343 TestActorNOP nop_actor(actor1_event_loop_.get());
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800344
Austin Schuh1bf8a212019-05-26 22:13:14 -0700345 TestActorIndex::Factory nop_actor_factory =
346 TestActorNOP::MakeFactory(test_event_loop_.get());
347
348 ActionQueue action_queue;
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800349
350 // id for the first time run.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700351 uint32_t nop_actor_id = 0;
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800352 // Check the internal state and write down id for later use.
353 bool sent_started, sent_cancel, interrupted;
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800354 // id for the second run.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700355 uint32_t nop_actor2_id = 0;
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800356
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800357 // Tick an empty queue and make sure it was not running.
358 RunAt(monotonic_clock::time_point(chrono::seconds(1)), [&]() {
359 action_queue.Tick();
360 EXPECT_FALSE(action_queue.Running());
361
362 // Enqueue action to be canceled.
363 {
364 UIntT uint;
365 uint.val = 0;
366 action_queue.EnqueueAction(nop_actor_factory.Make(uint));
367 }
368 action_queue.Tick();
369
370 // Should still be running as the actor could not have signalled.
371 EXPECT_TRUE(action_queue.Running());
372
373 EXPECT_TRUE(action_queue.GetCurrentActionState(nullptr, &sent_started,
374 &sent_cancel, &interrupted,
375 &nop_actor_id, nullptr));
376 EXPECT_TRUE(sent_started);
377 EXPECT_FALSE(sent_cancel);
378 EXPECT_FALSE(interrupted);
379 ASSERT_NE(0u, nop_actor_id);
380
381 // Add the next action which should ensure the first stopped.
382 {
383 UIntT uint;
384 uint.val = 0;
385 action_queue.EnqueueAction(nop_actor_factory.Make(uint));
386 }
387
388 // Check the internal state and write down id for later use.
389 EXPECT_TRUE(action_queue.GetNextActionState(nullptr, &sent_started,
390 &sent_cancel, &interrupted,
391 &nop_actor2_id, nullptr));
392 EXPECT_NE(nop_actor_id, nop_actor2_id);
393 EXPECT_FALSE(sent_started);
394 EXPECT_FALSE(sent_cancel);
395 EXPECT_FALSE(interrupted);
396 ASSERT_NE(0u, nop_actor2_id);
397
398 action_queue.Tick();
399 });
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800400
401 // Run the action so it can signal completion.
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800402 RunAt(monotonic_clock::time_point(chrono::seconds(2)), [&]() {
403 action_queue.Tick();
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800404
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800405 // Check the new action is the right one.
406 uint32_t test_id = 0;
407 EXPECT_TRUE(action_queue.GetCurrentActionState(
408 nullptr, &sent_started, &sent_cancel, &interrupted, &test_id, nullptr));
409 EXPECT_TRUE(sent_started);
410 EXPECT_FALSE(sent_cancel);
411 EXPECT_FALSE(interrupted);
412 EXPECT_EQ(nop_actor2_id, test_id);
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800413
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800414 // Make sure it is still going.
415 EXPECT_TRUE(action_queue.Running());
416 });
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800417
Austin Schuh1bf8a212019-05-26 22:13:14 -0700418 // Now let everything finish.
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800419 RunAt(monotonic_clock::time_point(chrono::seconds(3)), [&]() {
420 action_queue.Tick();
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800421
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800422 // Make sure it stopped.
423 EXPECT_FALSE(action_queue.Running());
424 });
425
426 event_loop_factory_.RunFor(chrono::seconds(4));
Ben Fredricksond69f38b2015-01-28 20:06:15 -0800427}
428
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800429// Tests that we do get an index with our goal
430TEST_F(ActionTest, ActionIndex) {
Austin Schuh1bf8a212019-05-26 22:13:14 -0700431 TestActorIndex idx_actor(actor1_event_loop_.get());
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800432
Austin Schuh1bf8a212019-05-26 22:13:14 -0700433 TestActorIndex::Factory test_actor_index_factory =
434 TestActorIndex::MakeFactory(test_event_loop_.get());
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800435 ::aos::Fetcher<actions::TestActionGoal> goal_fetcher_ =
436 test_event_loop_->MakeFetcher<actions::TestActionGoal>("/test_action");
Austin Schuh1bf8a212019-05-26 22:13:14 -0700437
438 ActionQueue action_queue;
439 // Tick an empty queue and make sure it was not running. Also tick the
440 // factory to allow it to send out the initial cancel message.
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800441 RunAt(monotonic_clock::time_point(chrono::seconds(1)), [&]() {
442 action_queue.Tick();
Austin Schuh1bf8a212019-05-26 22:13:14 -0700443
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800444 EXPECT_FALSE(action_queue.Running());
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800445
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800446 // Enqueue action to post index.
447 {
448 UIntT uint;
449 uint.val = 5;
450 action_queue.EnqueueAction(test_actor_index_factory.Make(uint));
451 }
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800452
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800453 ASSERT_TRUE(goal_fetcher_.Fetch());
454 EXPECT_EQ(5u, goal_fetcher_->params()->val());
455 EXPECT_EQ(0u, idx_actor.index);
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800456
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800457 action_queue.Tick();
458 });
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800459
460 // Run the next action so it can accomplish signal completion.
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800461 RunAt(monotonic_clock::time_point(chrono::seconds(2)), [&]() {
462 action_queue.Tick();
463 EXPECT_EQ(5u, idx_actor.index);
Austin Schuh1bf8a212019-05-26 22:13:14 -0700464
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800465 // Enqueue action to post index.
466 {
467 UIntT uint;
468 uint.val = 3;
469 action_queue.EnqueueAction(test_actor_index_factory.Make(uint));
470 }
471 ASSERT_TRUE(goal_fetcher_.Fetch());
472 EXPECT_EQ(3u, goal_fetcher_->params()->val());
473 });
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800474
475 // Run the next action so it can accomplish signal completion.
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800476 RunAt(monotonic_clock::time_point(chrono::seconds(3)), [&]() {
477 action_queue.Tick();
478 EXPECT_EQ(3u, idx_actor.index);
479 });
Austin Schuh1bf8a212019-05-26 22:13:14 -0700480
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800481 event_loop_factory_.RunFor(chrono::seconds(3));
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800482}
483
484// Tests that an action with a structure params works.
485TEST_F(ActionTest, StructParamType) {
Austin Schuh1bf8a212019-05-26 22:13:14 -0700486 TestActor2Nop nop_actor(actor2_event_loop_.get());
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800487
Austin Schuh1bf8a212019-05-26 22:13:14 -0700488 TestActor2Nop::Factory test_action_2_nop_factory =
489 TestActor2Nop::MakeFactory(test_event_loop_.get());
490
491 ActionQueue action_queue;
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800492
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800493 RunAt(monotonic_clock::time_point(chrono::seconds(0)), [&]() {
494 // Tick an empty queue and make sure it was not running.
495 action_queue.Tick();
496 EXPECT_FALSE(action_queue.Running());
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800497
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800498 actions::MyParamsT p;
499 p.param1 = 5.0;
500 p.param2 = 7;
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800501
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800502 action_queue.EnqueueAction(test_action_2_nop_factory.Make(p));
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800503
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800504 // We started an action and it should be running.
505 EXPECT_TRUE(action_queue.Running());
506
507 // Tick it and make sure it is still running.
508 action_queue.Tick();
509 EXPECT_TRUE(action_queue.Running());
510 });
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800511
512 // Run the action so it can signal completion.
Austin Schuh1bf8a212019-05-26 22:13:14 -0700513 // The actor takes no time, but running for a second is the best way to get it
514 // to go.
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800515 RunAt(monotonic_clock::time_point(chrono::seconds(1)), [&]() {
516 action_queue.Tick();
Austin Schuh1bf8a212019-05-26 22:13:14 -0700517
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800518 // Make sure it stopped.
519 EXPECT_FALSE(action_queue.Running());
520 });
Ben Fredrickson9fb2ab12015-02-16 16:42:08 -0800521
Austin Schuh02e2aeb2020-02-10 21:51:30 -0800522 event_loop_factory_.RunFor(chrono::seconds(2));
Brian Silverman237a5542015-03-29 17:59:29 -0400523}
524
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800525} // namespace aos::common::actions::testing