blob: 6fced6d886cc5e8e3f5744a074c68b0bef1d5c7a [file] [log] [blame]
Brian Silverman74b92d52021-10-14 13:12:02 -07001#include "aos/events/glib_main_loop.h"
2
3#include <thread>
4
Brian Silverman74b92d52021-10-14 13:12:02 -07005#include "glib-2.0/glib.h"
6#include "glog/logging.h"
7#include "gtest/gtest.h"
8
Philipp Schrader790cb542023-07-05 21:06:52 -07009#include "aos/configuration.h"
10#include "aos/events/shm_event_loop.h"
11#include "aos/testing/path.h"
12
Stephan Pleinesf63bde82024-01-13 15:59:33 -080013namespace aos::testing {
Brian Silverman74b92d52021-10-14 13:12:02 -070014using aos::testing::ArtifactPath;
15
16const FlatbufferDetachedBuffer<Configuration> &Config() {
17 static const FlatbufferDetachedBuffer<Configuration> result =
Austin Schuhc5fa6d92022-02-25 14:36:28 -080018 configuration::ReadConfig(ArtifactPath("aos/events/aos_config.json"));
Brian Silverman74b92d52021-10-14 13:12:02 -070019 return result;
20}
21
22// Tests just creating and destroying without running.
23TEST(GlibMainLoopTest, CreateDestroy) {
24 ShmEventLoop event_loop(Config());
25 GlibMainLoop glib_main_loop(&event_loop);
26}
27
28// Tests just creating, running, and then destroying, without adding any
29// events from the glib side.
30TEST(GlibMainLoopTest, CreateRunDestroy) {
31 ShmEventLoop event_loop(Config());
32 GlibMainLoop glib_main_loop(&event_loop);
33 bool ran = false;
34 event_loop
35 .AddTimer([&event_loop, &ran]() {
36 event_loop.Exit();
37 ran = true;
38 })
Philipp Schradera6712522023-07-05 20:25:11 -070039 ->Schedule(event_loop.monotonic_now() + std::chrono::milliseconds(100));
Brian Silverman74b92d52021-10-14 13:12:02 -070040 event_loop.Run();
41 EXPECT_TRUE(ran);
42}
43
44// Tests just a single idle source.
45TEST(GlibMainLoopTest, IdleSource) {
46 ShmEventLoop event_loop(Config());
47 GlibMainLoop glib_main_loop(&event_loop);
48 int runs = 0;
49 const auto callback =
50 glib_main_loop.AddIdle([&event_loop, &runs]() -> gboolean {
51 if (runs++ >= 100) {
52 event_loop.Exit();
53 }
54 return true;
55 });
56 event_loop.Run();
57 EXPECT_GT(runs, 100);
58 // It can run a few extra times, but not too many.
59 EXPECT_LT(runs, 110);
60}
61
62// Tests just a single timeout which calls exit on the ShmEventLoop side.
63TEST(GlibMainLoopTest, TimeoutExitShm) {
64 ShmEventLoop event_loop(Config());
65 GlibMainLoop glib_main_loop(&event_loop);
66 int runs = 0;
67 const auto callback = glib_main_loop.AddTimeout(
68 [&event_loop, &runs]() -> gboolean {
69 if (runs++ >= 3) {
70 event_loop.Exit();
71 }
72 return true;
73 },
74 50);
75 const auto before = event_loop.monotonic_now();
76 event_loop.Run();
77 const auto after = event_loop.monotonic_now();
78 EXPECT_EQ(runs, 4);
79 // Verify it took at least this long, but don't bother putting an upper bound
80 // because it can take arbitrarily long due to scheduling delays.
81 EXPECT_GE(after - before, std::chrono::milliseconds(200));
82}
83
84// Tests just a single timeout which calls exit on the glib side.
85TEST(GlibMainLoopTest, TimeoutExitGlib) {
86 ShmEventLoop event_loop(Config());
87 GlibMainLoop glib_main_loop(&event_loop);
88 int runs = 0;
89 const auto callback = glib_main_loop.AddTimeout(
90 [&glib_main_loop, &runs]() -> gboolean {
91 if (runs++ >= 3) {
92 g_main_loop_quit(glib_main_loop.g_main_loop());
93 }
94 return true;
95 },
96 50);
97 const auto before = event_loop.monotonic_now();
98 event_loop.Run();
99 const auto after = event_loop.monotonic_now();
100 EXPECT_EQ(runs, 4);
101 // Verify it took at least this long, but don't bother putting an upper bound
102 // because it can take arbitrarily long due to scheduling delays.
103 EXPECT_GE(after - before, std::chrono::milliseconds(200));
104}
105
106// Tests a single timeout which removes itself, and a ShmEventLoop timer to end
107// the test.
108TEST(GlibMainLoopTest, TimeoutRemoveSelf) {
109 ShmEventLoop event_loop(Config());
110 GlibMainLoop glib_main_loop(&event_loop);
111 int runs = 0;
112 const auto callback = glib_main_loop.AddTimeout(
113 [&runs]() -> gboolean {
114 ++runs;
115 return false;
116 },
117 50);
118 bool ran = false;
119 event_loop
120 .AddTimer([&event_loop, &ran]() {
121 event_loop.Exit();
122 ran = true;
123 })
Philipp Schradera6712522023-07-05 20:25:11 -0700124 ->Schedule(event_loop.monotonic_now() + std::chrono::milliseconds(100));
Brian Silverman74b92d52021-10-14 13:12:02 -0700125 event_loop.Run();
126 EXPECT_TRUE(ran);
127 EXPECT_EQ(runs, 1);
128}
129
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800130} // namespace aos::testing