blob: 935c591a15355d9724533152dfe2751e2dc80158 [file] [log] [blame]
Tyler Chatowa79419d2020-08-12 20:12:11 -07001#include <signal.h>
2
3#include <future>
4#include <thread>
5
6#include "aos/events/ping_generated.h"
7#include "aos/events/pong_generated.h"
8#include "aos/testing/tmpdir.h"
9#include "gtest/gtest.h"
10#include "starter_rpc_lib.h"
11#include "starterd_lib.h"
12
13TEST(StarterdTest, StartStopTest) {
14 const std::string config_file = "aos/events/pingpong_config.json";
15
16 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
17 aos::configuration::ReadConfig(config_file);
18
19 const std::string test_dir = aos::testing::TestTmpDir();
20
21 auto new_config = aos::configuration::MergeWithConfig(
22 &config.message(), absl::StrFormat(
23 R"({"applications": [
24 {
25 "name": "ping",
26 "executable_name": "aos/events/ping",
27 "args": ["--shm_base", "%s/aos"]
28 },
29 {
30 "name": "pong",
31 "executable_name": "aos/events/pong",
32 "args": ["--shm_base", "%s/aos"]
33 }
34 ]})",
35 test_dir, test_dir));
36
37 const aos::Configuration *config_msg = &new_config.message();
38
39 // Set up starter with config file
40 aos::starter::Starter starter(config_msg);
41
42 // Create an event loop to watch for ping messages, verifying it actually
43 // started.
44 aos::ShmEventLoop watcher_loop(config_msg);
45 watcher_loop.SkipAosLog();
46
47 watcher_loop
48 .AddTimer([&watcher_loop] {
49 watcher_loop.Exit();
50 FAIL();
51 })
52 ->Setup(watcher_loop.monotonic_now() + std::chrono::seconds(7));
53
54 int test_stage = 0;
55 watcher_loop.MakeWatcher(
56 "/test", [&test_stage, config_msg](const aos::examples::Ping &) {
57 switch (test_stage) {
58 case 1: {
59 test_stage = 2;
60 break;
61 }
62 case 2: {
63 std::thread([config_msg] {
64 LOG(INFO) << "Send command";
65 ASSERT_TRUE(aos::starter::SendCommandBlocking(
66 aos::starter::Command::STOP, "ping", config_msg,
67 std::chrono::seconds(3)));
68 }).detach();
69 test_stage = 3;
70 break;
71 }
72 }
73 });
74
75 watcher_loop.MakeWatcher(
76 "/aos", [&test_stage, &watcher_loop](const aos::starter::Status &status) {
77 const aos::starter::ApplicationStatus *app_status =
78 FindApplicationStatus(status, "ping");
79 if (app_status == nullptr) {
80 return;
81 }
82
83 switch (test_stage) {
84 case 0: {
85 if (app_status->has_state() &&
86 app_status->state() == aos::starter::State::RUNNING) {
87 test_stage = 1;
88 }
89 break;
90 }
91
92 case 3: {
93 if (app_status->has_state() &&
94 app_status->state() == aos::starter::State::STOPPED) {
95 watcher_loop.Exit();
96 SUCCEED();
97 }
98 break;
99 }
100 }
101 });
102
103 std::thread starterd_thread([&starter] { starter.Run(); });
104 watcher_loop.Run();
105
106 starter.Cleanup();
107 starterd_thread.join();
108}
109
110TEST(StarterdTest, DeathTest) {
111 const std::string config_file = "aos/events/pingpong_config.json";
112
113 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
114 aos::configuration::ReadConfig(config_file);
115
116 const std::string test_dir = aos::testing::TestTmpDir();
117
118 auto new_config = aos::configuration::MergeWithConfig(
119 &config.message(), absl::StrFormat(
120 R"({"applications": [
121 {
122 "name": "ping",
123 "executable_name": "aos/events/ping",
124 "args": ["--shm_base", "%s/aos"]
125 },
126 {
127 "name": "pong",
128 "executable_name": "aos/events/pong",
129 "args": ["--shm_base", "%s/aos"]
130 }
131 ]})",
132 test_dir, test_dir));
133
134 const aos::Configuration *config_msg = &new_config.message();
135
136 // Set up starter with config file
137 aos::starter::Starter starter(config_msg);
138
139 // Create an event loop to watch for ping messages, verifying it actually
140 // started.
141 aos::ShmEventLoop watcher_loop(config_msg);
142 watcher_loop.SkipAosLog();
143
144 watcher_loop
145 .AddTimer([&watcher_loop] {
146 watcher_loop.Exit();
147 FAIL();
148 })
149 ->Setup(watcher_loop.monotonic_now() + std::chrono::seconds(7));
150
151 int test_stage = 0;
152 uint64_t id;
153
154 watcher_loop.MakeWatcher("/aos", [&test_stage, &watcher_loop,
155 &id](const aos::starter::Status &status) {
156 const aos::starter::ApplicationStatus *app_status =
157 FindApplicationStatus(status, "ping");
158 if (app_status == nullptr) {
159 return;
160 }
161
162 switch (test_stage) {
163 case 0: {
164 if (app_status->has_state() &&
165 app_status->state() == aos::starter::State::RUNNING) {
166 test_stage = 1;
167 ASSERT_TRUE(app_status->has_pid());
168 ASSERT_TRUE(kill(app_status->pid(), SIGINT) != -1);
169 ASSERT_TRUE(app_status->has_id());
170 id = app_status->id();
171 }
172 break;
173 }
174
175 case 1: {
176 if (app_status->has_state() &&
177 app_status->state() == aos::starter::State::RUNNING &&
178 app_status->has_id() && app_status->id() != id) {
179 watcher_loop.Exit();
180 SUCCEED();
181 }
182 break;
183 }
184 }
185 });
186
187 std::thread starterd_thread([&starter] { starter.Run(); });
188 watcher_loop.Run();
189
190 starter.Cleanup();
191 starterd_thread.join();
192}