blob: 541e17f1b360a024100c3a588724af639de5e6d1 [file] [log] [blame]
James Kuszmaul9a816a72023-03-23 15:10:34 -07001#include "aos/starter/mock_starter.h"
2
Stephan Pleinesf63bde82024-01-13 15:59:33 -08003namespace aos::starter {
James Kuszmaul9a816a72023-03-23 15:10:34 -07004
5MockStarter::MockStarter(aos::EventLoop *event_loop)
6 : event_loop_(event_loop),
7 status_sender_(event_loop_->MakeSender<aos::starter::Status>("/aos")) {
8 aos::TimerHandler *send_timer =
9 event_loop_->AddTimer([this]() { SendStatus(); });
10
11 CHECK(aos::configuration::MultiNode(event_loop_->configuration()));
12
13 for (const aos::Node *node :
14 aos::configuration::GetNodes(event_loop_->configuration())) {
15 const aos::Channel *channel = aos::starter::StarterRpcChannelForNode(
16 event_loop_->configuration(), node);
17 if (aos::configuration::ChannelIsReadableOnNode(channel,
18 event_loop_->node())) {
19 std::string_view channel_name = channel->name()->string_view();
20 event_loop_->MakeWatcher(
21 channel_name, [this](const aos::starter::StarterRpc &command) {
22 for (const flatbuffers::String *node : *command.nodes()) {
23 if (node->string_view() ==
24 event_loop_->node()->name()->string_view()) {
25 CHECK(statuses_.count(command.name()->str()) > 0)
26 << "Unable to find " << command.name()->string_view()
27 << " in our list of applications.";
28 ApplicationStatus &status = statuses_[command.name()->str()];
29 switch (command.command()) {
30 case aos::starter::Command::START:
31 if (!status.running) {
James Kuszmaul75b09352023-02-03 16:21:25 -080032 VLOG(1) << "Starting " << command.name()->string_view()
33 << " at " << event_loop_->monotonic_now();
James Kuszmaul9a816a72023-03-23 15:10:34 -070034 status.running = true;
35 status.start_time = event_loop_->monotonic_now();
36 status.id = next_id_++;
37 }
38 break;
39 case aos::starter::Command::STOP:
James Kuszmaul75b09352023-02-03 16:21:25 -080040 if (status.running) {
41 VLOG(1) << "Stopping " << command.name()->string_view()
42 << " at " << event_loop_->monotonic_now();
43 }
James Kuszmaul9a816a72023-03-23 15:10:34 -070044 status.running = false;
45 break;
46 case aos::starter::Command::RESTART:
47 status.running = true;
James Kuszmaul75b09352023-02-03 16:21:25 -080048 VLOG(1) << "Restarting " << command.name()->string_view()
49 << " at " << event_loop_->monotonic_now();
James Kuszmaul9a816a72023-03-23 15:10:34 -070050 status.start_time = event_loop_->monotonic_now();
51 status.id = next_id_++;
52 }
53 SendStatus();
54 }
55 }
56 });
57 }
58 }
59
60 event_loop_->OnRun([this, send_timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -070061 send_timer->Schedule(event_loop_->monotonic_now(), std::chrono::seconds(1));
James Kuszmaul9a816a72023-03-23 15:10:34 -070062
63 for (const aos::Application *application :
64 *event_loop_->configuration()->applications()) {
65 if (aos::configuration::ApplicationShouldStart(
66 event_loop_->configuration(), event_loop_->node(), application)) {
67 statuses_[application->name()->str()] = ApplicationStatus{
68 next_id_++, application->autostart(), event_loop_->monotonic_now()};
69 }
70 }
71 });
72}
73
74void MockStarter::SendStatus() {
75 aos::Sender<aos::starter::Status>::Builder builder =
76 status_sender_.MakeBuilder();
77 std::vector<flatbuffers::Offset<aos::starter::ApplicationStatus>>
78 status_offsets;
79 for (const std::pair<const std::string, ApplicationStatus> &pair :
80 statuses_) {
81 const flatbuffers::Offset<flatbuffers::String> name_offset =
82 builder.fbb()->CreateString(pair.first);
83 aos::starter::ApplicationStatus::Builder status_builder =
84 builder.MakeBuilder<aos::starter::ApplicationStatus>();
85 status_builder.add_name(name_offset);
86 status_builder.add_state(pair.second.running
87 ? aos::starter::State::RUNNING
88 : aos::starter::State::STOPPED);
89 status_builder.add_last_exit_code(0);
90 status_builder.add_id(pair.second.id);
91 status_builder.add_last_stop_reason(
92 aos::starter::LastStopReason::STOP_REQUESTED);
93 status_builder.add_last_start_time(
94 pair.second.start_time.time_since_epoch().count());
95 if (pair.second.running) {
96 status_builder.add_pid(pair.second.id);
97 }
98 status_offsets.push_back(status_builder.Finish());
99 }
100 const flatbuffers::Offset<
101 flatbuffers::Vector<flatbuffers::Offset<aos::starter::ApplicationStatus>>>
102 statuses_offset = builder.fbb()->CreateVector(status_offsets);
103 aos::starter::Status::Builder status_builder =
104 builder.MakeBuilder<aos::starter::Status>();
105 status_builder.add_statuses(statuses_offset);
106 builder.CheckOk(builder.Send(status_builder.Finish()));
107}
108
109MockStarters::MockStarters(aos::SimulatedEventLoopFactory *event_loop_factory) {
110 CHECK(aos::configuration::MultiNode(event_loop_factory->configuration()));
111 for (const aos::Node *node :
112 aos::configuration::GetNodes(event_loop_factory->configuration())) {
113 event_loops_.emplace_back(
114 event_loop_factory->GetNodeEventLoopFactory(node)->MakeEventLoop(
115 "starterd"));
116 mock_starters_.emplace_back(
117 std::make_unique<MockStarter>(event_loops_.back().get()));
118 }
119}
120
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800121} // namespace aos::starter