blob: 1c4ebddab2c6ff4a3cd64fcf8c51845f3dd15f6c [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001#include <unistd.h>
2
Austin Schuhf2a50ba2016-12-24 16:16:26 -08003#include <chrono>
brians343bc112013-02-10 01:53:46 +00004#include <memory>
5
6#include "gtest/gtest.h"
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -05007
John Park33858a32018-09-28 23:05:48 -07008#include "aos/die.h"
9#include "aos/test_queue.q.h"
10#include "aos/util/thread.h"
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -050011#include "aos/testing/test_shm.h"
brians343bc112013-02-10 01:53:46 +000012
brians343bc112013-02-10 01:53:46 +000013namespace aos {
14namespace common {
brians343bc112013-02-10 01:53:46 +000015namespace testing {
16
Austin Schuhf2a50ba2016-12-24 16:16:26 -080017namespace chrono = ::std::chrono;
18
brians343bc112013-02-10 01:53:46 +000019class QueueTest : public ::testing::Test {
20 protected:
Brian Silverman8d2e56e2013-09-23 17:55:03 -070021 void SetUp() override {
22 SetDieTestMode(true);
23 }
24
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -050025 ::aos::testing::TestSharedMemory my_shm_;
brians343bc112013-02-10 01:53:46 +000026 // Create a new instance of the test queue so that it invalidates the queue
27 // that it points to. Otherwise, we will have a pointer to shared memory that
28 // is no longer valid.
29 ::aos::Queue<TestingMessage> my_test_queue;
30
31 QueueTest() : my_test_queue(".aos.common.testing.test_queue") {}
32};
33
Brian Silverman798c7782013-03-28 16:48:02 -070034class MyThread : public util::Thread {
brians343bc112013-02-10 01:53:46 +000035 public:
36 MyThread() : threaded_test_queue(".aos.common.testing.test_queue") {}
37
38 virtual void Run() {
Brian Silverman428de562014-04-10 15:59:19 -070039 threaded_test_queue.FetchNextBlocking();
brians343bc112013-02-10 01:53:46 +000040 EXPECT_TRUE(threaded_test_queue->test_bool);
41 EXPECT_EQ(0x971, threaded_test_queue->test_int);
42 }
43
44 ::aos::Queue<TestingMessage> threaded_test_queue;
45 private:
46 DISALLOW_COPY_AND_ASSIGN(MyThread);
47};
48
49
50// Tests that we can send a message to another thread and it blocking receives
51// it at the correct time.
52TEST_F(QueueTest, FetchBlocking) {
53 MyThread t;
54 t.Start();
55 usleep(50000);
56 my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
57 t.Join();
Austin Schuhf2a50ba2016-12-24 16:16:26 -080058 EXPECT_LE(t.threaded_test_queue.Age(), chrono::milliseconds(57));
brians343bc112013-02-10 01:53:46 +000059}
60
61// Tests that we can send a message with the message pointer and get it back.
62TEST_F(QueueTest, SendMessage) {
63 ScopedMessagePtr<TestingMessage> msg = my_test_queue.MakeMessage();
64 msg->test_bool = true;
65 msg->test_int = 0x971;
66 msg.Send();
67
68 ASSERT_TRUE(my_test_queue.FetchLatest());
69 EXPECT_TRUE(my_test_queue->test_bool);
70 EXPECT_EQ(0x971, my_test_queue->test_int);
71}
72
brians343bc112013-02-10 01:53:46 +000073// Tests that we can send a message with the builder and get it back.
74TEST_F(QueueTest, SendWithBuilder) {
75 my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
76
77 ASSERT_TRUE(my_test_queue.FetchLatest());
78 EXPECT_EQ(true, my_test_queue->test_bool);
79 EXPECT_EQ(0x971, my_test_queue->test_int);
Austin Schuhf2a50ba2016-12-24 16:16:26 -080080 EXPECT_EQ(true, my_test_queue.IsNewerThan(chrono::milliseconds(10000)));
brians343bc112013-02-10 01:53:46 +000081}
82
Brian Silverman89c609d2015-04-03 16:14:15 -040083// Tests that multiple queue instances don't break each other.
84TEST_F(QueueTest, MultipleQueues) {
85 my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
86 ASSERT_TRUE(my_test_queue.FetchLatest());
87 EXPECT_TRUE(my_test_queue.get());
88
89 {
90 ::aos::Queue<TestingMessage> my_other_test_queue(
91 ".aos.common.testing.queue_name");
92 my_other_test_queue.MakeMessage();
93 EXPECT_FALSE(my_other_test_queue.FetchLatest());
94 EXPECT_FALSE(my_test_queue.FetchLatest());
95 }
96
97 EXPECT_TRUE(my_test_queue.get());
98}
99
100// Tests that using a queue from multiple threads works correctly.
101TEST_F(QueueTest, MultipleThreads) {
102 my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
103 ASSERT_TRUE(my_test_queue.FetchLatest());
104 my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x254).Send();
105 EXPECT_EQ(0x971, my_test_queue->test_int);
106
107 ::aos::util::FunctionThread::RunInOtherThread([this]() {
108 ASSERT_TRUE(my_test_queue.FetchLatest());
109 EXPECT_EQ(0x254, my_test_queue->test_int);
110 });
111 EXPECT_EQ(0x254, my_test_queue->test_int);
112}
113
Brian Silverman42456d82014-08-19 12:43:59 -0400114// Makes sure that MakeWithBuilder zeros the message initially.
115// This might randomly succeed sometimes, but it will fail with asan if it
116// doesn't.
117TEST_F(QueueTest, BuilderZero) {
118 my_test_queue.MakeWithBuilder().Send();
119
120 ASSERT_TRUE(my_test_queue.FetchLatest());
121 EXPECT_FALSE(my_test_queue->test_bool);
122 EXPECT_EQ(0, my_test_queue->test_int);
123}
124
brians343bc112013-02-10 01:53:46 +0000125// Tests that various pointer deref functions at least seem to work.
126TEST_F(QueueTest, PointerDeref) {
127 my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
128
129 ASSERT_TRUE(my_test_queue.FetchLatest());
130 const TestingMessage *msg_ptr = my_test_queue.get();
131 ASSERT_NE(static_cast<TestingMessage*>(NULL), msg_ptr);
132 EXPECT_EQ(0x971, msg_ptr->test_int);
133 EXPECT_EQ(msg_ptr, &(*my_test_queue));
134}
135
136// Tests that FetchNext doesn't miss any messages.
137TEST_F(QueueTest, FetchNext) {
138 for (int i = 0; i < 10; ++i) {
139 my_test_queue.MakeWithBuilder().test_bool(true).test_int(i).Send();
140 }
141
142 for (int i = 0; i < 10; ++i) {
143 ASSERT_TRUE(my_test_queue.FetchNext());
144 EXPECT_EQ(i, my_test_queue->test_int);
145 }
146}
147
148// Tests that FetchLatest skips a missing message.
149TEST_F(QueueTest, FetchLatest) {
150 my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x254).Send();
151 my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
152
153 ASSERT_TRUE(my_test_queue.FetchLatest());
154 EXPECT_EQ(0x971, my_test_queue->test_int);
155}
156
157// Tests that FetchLatest works with multiple readers.
158TEST_F(QueueTest, FetchLatestMultiple) {
159 ::aos::Queue<TestingMessage> my_second_test_queue(
160 ".aos.common.testing.test_queue");
161 my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x254).Send();
162 my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
163
164 ASSERT_TRUE(my_test_queue.FetchLatest());
165 EXPECT_EQ(0x971, my_test_queue->test_int);
166 ASSERT_TRUE(my_second_test_queue.FetchLatest());
167 ASSERT_TRUE(my_second_test_queue.get() != NULL);
168 EXPECT_EQ(0x971, my_second_test_queue->test_int);
169}
170
171
172// Tests that fetching without a new message returns false.
173TEST_F(QueueTest, FetchLatestWithoutMessage) {
174 my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x254).Send();
175 EXPECT_TRUE(my_test_queue.FetchLatest());
176 EXPECT_FALSE(my_test_queue.FetchLatest());
177 EXPECT_FALSE(my_test_queue.FetchLatest());
178 EXPECT_EQ(0x254, my_test_queue->test_int);
179}
180
181// Tests that fetching without a message returns false.
182TEST_F(QueueTest, FetchOnFreshQueue) {
183 EXPECT_FALSE(my_test_queue.FetchLatest());
184 EXPECT_EQ(static_cast<TestingMessage*>(NULL), my_test_queue.get());
185}
186
187// Tests that fetch next without a message returns false.
188TEST_F(QueueTest, FetchNextOnFreshQueue) {
189 EXPECT_FALSE(my_test_queue.FetchNext());
190 EXPECT_EQ(static_cast<TestingMessage*>(NULL), my_test_queue.get());
191}
192
193// Tests that fetch next without a new message returns false.
194TEST_F(QueueTest, FetchNextWithoutMessage) {
195 my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x254).Send();
196 EXPECT_TRUE(my_test_queue.FetchNext());
197 EXPECT_FALSE(my_test_queue.FetchNext());
198 EXPECT_NE(static_cast<TestingMessage*>(NULL), my_test_queue.get());
199}
200
201// Tests that age makes some sense.
202TEST_F(QueueTest, Age) {
203 my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
204
205 ASSERT_TRUE(my_test_queue.FetchLatest());
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800206 EXPECT_TRUE(my_test_queue.IsNewerThan(chrono::milliseconds(100)));
207 const auto age = my_test_queue.Age();
208 EXPECT_GE(chrono::nanoseconds(100000000), age);
brians343bc112013-02-10 01:53:46 +0000209}
210
211
212class GroupTest : public ::testing::Test {
213 protected:
brians343bc112013-02-10 01:53:46 +0000214 GroupTest()
215 : my_test_queuegroup(".aos.common.testing.test_queuegroup",
brians343bc112013-02-10 01:53:46 +0000216 ".aos.common.testing.test_queuegroup.first",
217 ".aos.common.testing.test_queuegroup.second") {}
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -0500218
219 // Create a new instance of the test group so that it invalidates the queue
220 // that it points to. Otherwise, we will have a pointer to shared memory that
221 // is no longer valid.
222 TwoQueues my_test_queuegroup;
223
224 private:
225 ::aos::testing::TestSharedMemory my_shm_;
brians343bc112013-02-10 01:53:46 +0000226};
227
brians343bc112013-02-10 01:53:46 +0000228// Tests that name works.
229TEST_F(GroupTest, Name) {
230 EXPECT_EQ(std::string(".aos.common.testing.test_queuegroup"),
231 std::string(my_test_queuegroup.name()));
232}
233
234
235class MessageTest : public ::testing::Test {
236 public:
237 TestingMessage msg;
238};
239
240TEST_F(MessageTest, Zeroing) {
241 msg.test_bool = true;
242 msg.test_int = 0x254;
243 msg.SetTimeToNow();
244
245 msg.Zero();
246
247 EXPECT_FALSE(msg.test_bool);
248 EXPECT_EQ(0, msg.test_int);
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800249 EXPECT_EQ(monotonic_clock::min_time, msg.sent_time);
brians343bc112013-02-10 01:53:46 +0000250}
251
252TEST_F(MessageTest, Size) {
253 EXPECT_EQ(static_cast<size_t>(13), msg.Size());
254}
255
256TEST_F(MessageTest, Serialize) {
257 char serialized_data[msg.Size()];
258 msg.test_bool = true;
259 msg.test_int = 0x254;
260 msg.SetTimeToNow();
261
262 msg.Serialize(serialized_data);
263
264 TestingMessage new_msg;
265 new_msg.Deserialize(serialized_data);
266
267 EXPECT_EQ(msg.test_bool, new_msg.test_bool);
268 EXPECT_EQ(msg.test_int, new_msg.test_int);
269 EXPECT_EQ(msg.sent_time, new_msg.sent_time);
270}
271
272// Tests that Print prints out a message nicely.
273TEST_F(MessageTest, Print) {
274 char printdata[1024];
275 msg.test_bool = true;
276 msg.test_int = 2056;
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800277 msg.sent_time = monotonic_clock::time_point(chrono::seconds(971) +
278 chrono::nanoseconds(254));
brians343bc112013-02-10 01:53:46 +0000279
Brian Silverman981a7bb2014-02-16 21:17:04 -0800280 std::string golden("971.000000254s, T, 2056");
brians343bc112013-02-10 01:53:46 +0000281 EXPECT_EQ(golden.size(), msg.Print(printdata, sizeof(printdata)));
282
283 EXPECT_EQ(golden, std::string(printdata));
284}
285
286// Tests that the hash never changes. If it changes, then someone broke the
287// hash routine or changed the message declaration. Both changes need to be
288// validated by hand.
289TEST_F(MessageTest, Hash) {
Brian Silverman981a7bb2014-02-16 21:17:04 -0800290 EXPECT_EQ(static_cast<uint32_t>(0xc33651ac),
brians343bc112013-02-10 01:53:46 +0000291 static_cast<uint32_t>(TestingMessage::kHash));
292}
293
294TEST_F(MessageTest, SetNow) {
295 msg.SetTimeToNow();
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800296 EXPECT_LE(msg.sent_time - monotonic_clock::now(), chrono::milliseconds(20));
brians343bc112013-02-10 01:53:46 +0000297}
298
Brian Silverman203a0fc2015-03-16 15:21:00 -0700299// Tests that EqualsNoTime works.
300TEST_F(MessageTest, EqualsNoTime) {
301 msg.test_bool = true;
302 msg.test_int = 971;
303 TestingMessage other;
304 other.test_int = 971;
305 EXPECT_FALSE(other.EqualsNoTime(msg));
306 EXPECT_FALSE(msg.EqualsNoTime(other));
307 other.test_bool = true;
308 EXPECT_TRUE(other.EqualsNoTime(msg));
309 EXPECT_TRUE(msg.EqualsNoTime(other));
310 msg.SetTimeToNow();
311 EXPECT_TRUE(msg.EqualsNoTime(other));
312}
313
brians343bc112013-02-10 01:53:46 +0000314} // namespace testing
315} // namespace common
316} // namespace aos