blob: f17403212ac4486f95af20b921fbea08016a886d [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 })
159 ->Setup(watcher_loop.monotonic_now() + std::chrono::seconds(7));
160
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) {
176 test_stage = 1;
177 ASSERT_TRUE(app_status->has_pid());
178 ASSERT_TRUE(kill(app_status->pid(), SIGINT) != -1);
179 ASSERT_TRUE(app_status->has_id());
180 id = app_status->id();
181 }
182 break;
183 }
184
185 case 1: {
186 if (app_status->has_state() &&
187 app_status->state() == aos::starter::State::RUNNING &&
188 app_status->has_id() && app_status->id() != id) {
189 watcher_loop.Exit();
190 SUCCEED();
191 }
192 break;
193 }
194 }
195 });
196
197 std::thread starterd_thread([&starter] { starter.Run(); });
198 watcher_loop.Run();
199
200 starter.Cleanup();
201 starterd_thread.join();
202}
Austin Schuh5f79a5a2021-10-12 17:46:50 -0700203
204TEST(StarterdTest, Autostart) {
205 const std::string config_file =
206 ArtifactPath("aos/events/pingpong_config.json");
207
208 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
209 aos::configuration::ReadConfig(config_file);
210
211 const std::string test_dir = aos::testing::TestTmpDir();
212
213 auto new_config = aos::configuration::MergeWithConfig(
214 &config.message(), absl::StrFormat(
215 R"({"applications": [
216 {
217 "name": "ping",
218 "executable_name": "%s",
219 "args": ["--shm_base", "%s/aos"],
220 "autostart": false
221 },
222 {
223 "name": "pong",
224 "executable_name": "%s",
225 "args": ["--shm_base", "%s/aos"]
226 }
227 ]})",
228 ArtifactPath("aos/events/ping"), test_dir,
229 ArtifactPath("aos/events/pong"), test_dir));
230
231 const aos::Configuration *config_msg = &new_config.message();
232
233 // Set up starter with config file
234 aos::starter::Starter starter(config_msg);
235
236 // Create an event loop to watch for the application starting up.
237 aos::ShmEventLoop watcher_loop(config_msg);
238 watcher_loop.SkipAosLog();
239
240 watcher_loop
241 .AddTimer([&watcher_loop] {
242 watcher_loop.Exit();
243 FAIL();
244 })
245 ->Setup(watcher_loop.monotonic_now() + std::chrono::seconds(7));
246
247 watcher_loop.MakeWatcher(
248 "/aos", [&watcher_loop](const aos::starter::Status &status) {
249 const aos::starter::ApplicationStatus *ping_app_status =
250 FindApplicationStatus(status, "ping");
251 const aos::starter::ApplicationStatus *pong_app_status =
252 FindApplicationStatus(status, "pong");
253 if (ping_app_status == nullptr || pong_app_status == nullptr) {
254 return;
255 }
256
257 if (ping_app_status->has_state() &&
258 ping_app_status->state() != aos::starter::State::STOPPED) {
259 watcher_loop.Exit();
260 FAIL();
261 }
262 if (pong_app_status->has_state() &&
263 pong_app_status->state() == aos::starter::State::RUNNING) {
264 watcher_loop.Exit();
265 SUCCEED();
266 }
267 });
268
269 std::thread starterd_thread([&starter] { starter.Run(); });
270 watcher_loop.Run();
271
272 starter.Cleanup();
273 starterd_thread.join();
274}
275
276} // namespace starter
277} // namespace aos