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