blob: a6f9204b10a6147af7c70471bffbb0f6ac5ada84 [file] [log] [blame]
Tyler Chatowbf0609c2021-07-31 16:13:27 -07001#include <csignal>
Tyler Chatowa79419d2020-08-12 20:12:11 -07002#include <future>
3#include <thread>
4
5#include "aos/events/ping_generated.h"
6#include "aos/events/pong_generated.h"
Austin Schuh373f1762021-06-02 21:07:09 -07007#include "aos/testing/path.h"
Tyler Chatowa79419d2020-08-12 20:12:11 -07008#include "aos/testing/tmpdir.h"
9#include "gtest/gtest.h"
10#include "starter_rpc_lib.h"
11#include "starterd_lib.h"
12
Austin Schuh373f1762021-06-02 21:07:09 -070013using aos::testing::ArtifactPath;
14
Austin Schuh5f79a5a2021-10-12 17:46:50 -070015namespace aos {
16namespace starter {
17
Tyler Chatowa79419d2020-08-12 20:12:11 -070018TEST(StarterdTest, StartStopTest) {
Austin Schuh373f1762021-06-02 21:07:09 -070019 const std::string config_file =
20 ArtifactPath("aos/events/pingpong_config.json");
Tyler Chatowa79419d2020-08-12 20:12:11 -070021
22 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
23 aos::configuration::ReadConfig(config_file);
24
25 const std::string test_dir = aos::testing::TestTmpDir();
26
27 auto new_config = aos::configuration::MergeWithConfig(
28 &config.message(), absl::StrFormat(
29 R"({"applications": [
30 {
31 "name": "ping",
Austin Schuh373f1762021-06-02 21:07:09 -070032 "executable_name": "%s",
Tyler Chatowa79419d2020-08-12 20:12:11 -070033 "args": ["--shm_base", "%s/aos"]
34 },
35 {
36 "name": "pong",
Austin Schuh373f1762021-06-02 21:07:09 -070037 "executable_name": "%s",
Tyler Chatowa79419d2020-08-12 20:12:11 -070038 "args": ["--shm_base", "%s/aos"]
39 }
40 ]})",
Austin Schuh373f1762021-06-02 21:07:09 -070041 ArtifactPath("aos/events/ping"), test_dir,
42 ArtifactPath("aos/events/pong"), test_dir));
Tyler Chatowa79419d2020-08-12 20:12:11 -070043
44 const aos::Configuration *config_msg = &new_config.message();
45
46 // Set up starter with config file
47 aos::starter::Starter starter(config_msg);
48
49 // Create an event loop to watch for ping messages, verifying it actually
50 // started.
51 aos::ShmEventLoop watcher_loop(config_msg);
52 watcher_loop.SkipAosLog();
53
54 watcher_loop
55 .AddTimer([&watcher_loop] {
56 watcher_loop.Exit();
57 FAIL();
58 })
59 ->Setup(watcher_loop.monotonic_now() + std::chrono::seconds(7));
60
61 int test_stage = 0;
62 watcher_loop.MakeWatcher(
63 "/test", [&test_stage, config_msg](const aos::examples::Ping &) {
64 switch (test_stage) {
65 case 1: {
66 test_stage = 2;
67 break;
68 }
69 case 2: {
70 std::thread([config_msg] {
71 LOG(INFO) << "Send command";
72 ASSERT_TRUE(aos::starter::SendCommandBlocking(
73 aos::starter::Command::STOP, "ping", config_msg,
74 std::chrono::seconds(3)));
Austin Schuh5f79a5a2021-10-12 17:46:50 -070075 })
76 .detach();
Tyler Chatowa79419d2020-08-12 20:12:11 -070077 test_stage = 3;
78 break;
79 }
80 }
81 });
82
83 watcher_loop.MakeWatcher(
84 "/aos", [&test_stage, &watcher_loop](const aos::starter::Status &status) {
85 const aos::starter::ApplicationStatus *app_status =
86 FindApplicationStatus(status, "ping");
87 if (app_status == nullptr) {
88 return;
89 }
90
91 switch (test_stage) {
92 case 0: {
93 if (app_status->has_state() &&
94 app_status->state() == aos::starter::State::RUNNING) {
95 test_stage = 1;
96 }
97 break;
98 }
99
100 case 3: {
101 if (app_status->has_state() &&
102 app_status->state() == aos::starter::State::STOPPED) {
103 watcher_loop.Exit();
104 SUCCEED();
105 }
106 break;
107 }
108 }
109 });
110
111 std::thread starterd_thread([&starter] { starter.Run(); });
112 watcher_loop.Run();
113
114 starter.Cleanup();
115 starterd_thread.join();
116}
117
118TEST(StarterdTest, DeathTest) {
Austin Schuh373f1762021-06-02 21:07:09 -0700119 const std::string config_file =
120 ArtifactPath("aos/events/pingpong_config.json");
Tyler Chatowa79419d2020-08-12 20:12:11 -0700121
122 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
123 aos::configuration::ReadConfig(config_file);
124
125 const std::string test_dir = aos::testing::TestTmpDir();
126
127 auto new_config = aos::configuration::MergeWithConfig(
128 &config.message(), absl::StrFormat(
129 R"({"applications": [
130 {
131 "name": "ping",
Austin Schuh373f1762021-06-02 21:07:09 -0700132 "executable_name": "%s",
Tyler Chatowa79419d2020-08-12 20:12:11 -0700133 "args": ["--shm_base", "%s/aos"]
134 },
135 {
136 "name": "pong",
Austin Schuh373f1762021-06-02 21:07:09 -0700137 "executable_name": "%s",
Tyler Chatowa79419d2020-08-12 20:12:11 -0700138 "args": ["--shm_base", "%s/aos"]
139 }
140 ]})",
Austin Schuh373f1762021-06-02 21:07:09 -0700141 ArtifactPath("aos/events/ping"), test_dir,
142 ArtifactPath("aos/events/pong"), test_dir));
Tyler Chatowa79419d2020-08-12 20:12:11 -0700143
144 const aos::Configuration *config_msg = &new_config.message();
145
146 // Set up starter with config file
147 aos::starter::Starter starter(config_msg);
148
149 // Create an event loop to watch for ping messages, verifying it actually
150 // started.
151 aos::ShmEventLoop watcher_loop(config_msg);
152 watcher_loop.SkipAosLog();
153
154 watcher_loop
155 .AddTimer([&watcher_loop] {
156 watcher_loop.Exit();
157 FAIL();
158 })
Austin Schuha07b3ce2021-10-10 12:33:21 -0700159 ->Setup(watcher_loop.monotonic_now() + std::chrono::seconds(11));
Tyler Chatowa79419d2020-08-12 20:12:11 -0700160
161 int test_stage = 0;
162 uint64_t id;
163
164 watcher_loop.MakeWatcher("/aos", [&test_stage, &watcher_loop,
165 &id](const aos::starter::Status &status) {
166 const aos::starter::ApplicationStatus *app_status =
167 FindApplicationStatus(status, "ping");
168 if (app_status == nullptr) {
169 return;
170 }
171
172 switch (test_stage) {
173 case 0: {
174 if (app_status->has_state() &&
175 app_status->state() == aos::starter::State::RUNNING) {
Austin Schuha07b3ce2021-10-10 12:33:21 -0700176 LOG(INFO) << "Ping is running";
Tyler Chatowa79419d2020-08-12 20:12:11 -0700177 test_stage = 1;
178 ASSERT_TRUE(app_status->has_pid());
179 ASSERT_TRUE(kill(app_status->pid(), SIGINT) != -1);
180 ASSERT_TRUE(app_status->has_id());
181 id = app_status->id();
182 }
183 break;
184 }
185
186 case 1: {
187 if (app_status->has_state() &&
188 app_status->state() == aos::starter::State::RUNNING &&
189 app_status->has_id() && app_status->id() != id) {
Austin Schuha07b3ce2021-10-10 12:33:21 -0700190 LOG(INFO) << "Ping restarted";
Tyler Chatowa79419d2020-08-12 20:12:11 -0700191 watcher_loop.Exit();
192 SUCCEED();
193 }
194 break;
195 }
196 }
197 });
198
199 std::thread starterd_thread([&starter] { starter.Run(); });
200 watcher_loop.Run();
201
202 starter.Cleanup();
203 starterd_thread.join();
204}
Austin Schuh5f79a5a2021-10-12 17:46:50 -0700205
206TEST(StarterdTest, Autostart) {
207 const std::string config_file =
208 ArtifactPath("aos/events/pingpong_config.json");
209
210 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
211 aos::configuration::ReadConfig(config_file);
212
213 const std::string test_dir = aos::testing::TestTmpDir();
214
215 auto new_config = aos::configuration::MergeWithConfig(
216 &config.message(), absl::StrFormat(
217 R"({"applications": [
218 {
219 "name": "ping",
220 "executable_name": "%s",
221 "args": ["--shm_base", "%s/aos"],
222 "autostart": false
223 },
224 {
225 "name": "pong",
226 "executable_name": "%s",
227 "args": ["--shm_base", "%s/aos"]
228 }
229 ]})",
230 ArtifactPath("aos/events/ping"), test_dir,
231 ArtifactPath("aos/events/pong"), test_dir));
232
233 const aos::Configuration *config_msg = &new_config.message();
234
235 // Set up starter with config file
236 aos::starter::Starter starter(config_msg);
237
238 // Create an event loop to watch for the application starting up.
239 aos::ShmEventLoop watcher_loop(config_msg);
240 watcher_loop.SkipAosLog();
241
242 watcher_loop
243 .AddTimer([&watcher_loop] {
244 watcher_loop.Exit();
245 FAIL();
246 })
247 ->Setup(watcher_loop.monotonic_now() + std::chrono::seconds(7));
248
249 watcher_loop.MakeWatcher(
250 "/aos", [&watcher_loop](const aos::starter::Status &status) {
251 const aos::starter::ApplicationStatus *ping_app_status =
252 FindApplicationStatus(status, "ping");
253 const aos::starter::ApplicationStatus *pong_app_status =
254 FindApplicationStatus(status, "pong");
255 if (ping_app_status == nullptr || pong_app_status == nullptr) {
256 return;
257 }
258
259 if (ping_app_status->has_state() &&
260 ping_app_status->state() != aos::starter::State::STOPPED) {
261 watcher_loop.Exit();
262 FAIL();
263 }
264 if (pong_app_status->has_state() &&
265 pong_app_status->state() == aos::starter::State::RUNNING) {
266 watcher_loop.Exit();
267 SUCCEED();
268 }
269 });
270
271 std::thread starterd_thread([&starter] { starter.Run(); });
272 watcher_loop.Run();
273
274 starter.Cleanup();
275 starterd_thread.join();
276}
277
278} // namespace starter
279} // namespace aos