blob: aa3b3356d9a47cf32f76bc6ebd434e95996f7848 [file] [log] [blame]
John Park398c74a2018-10-20 21:17:39 -07001#include "aos/ipc_lib/queue.h"
Brian Silvermana6d1b562013-09-01 14:39:39 -07002
brians343bc112013-02-10 01:53:46 +00003#include <unistd.h>
4#include <sys/mman.h>
5#include <inttypes.h>
6
Austin Schuhf2a50ba2016-12-24 16:16:26 -08007#include <chrono>
brians343bc112013-02-10 01:53:46 +00008#include <ostream>
9#include <memory>
10#include <map>
11
12#include "gtest/gtest.h"
13
John Park398c74a2018-10-20 21:17:39 -070014#include "aos/ipc_lib/core_lib.h"
John Park33858a32018-09-28 23:05:48 -070015#include "aos/type_traits/type_traits.h"
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -050016#include "aos/testing/test_shm.h"
John Park33858a32018-09-28 23:05:48 -070017#include "aos/time/time.h"
18#include "aos/logging/logging.h"
19#include "aos/die.h"
20#include "aos/util/thread.h"
21#include "aos/util/options.h"
22#include "aos/util/death_test_log_implementation.h"
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -050023#include "aos/testing/prevent_exit.h"
brians343bc112013-02-10 01:53:46 +000024
Brian Silvermana6d1b562013-09-01 14:39:39 -070025using ::testing::AssertionResult;
26using ::testing::AssertionSuccess;
27using ::testing::AssertionFailure;
28
29namespace aos {
30namespace testing {
brians343bc112013-02-10 01:53:46 +000031
Austin Schuhf2a50ba2016-12-24 16:16:26 -080032namespace chrono = ::std::chrono;
33namespace this_thread = ::std::this_thread;
34
Brian Silvermanc2e04222014-03-22 12:43:44 -070035// The same constant from queue.cc. This will have to be updated if that one is.
36const int kExtraMessages = 20;
37
Brian Silvermanac3aedc2014-03-13 22:53:38 -070038class RawQueueTest : public ::testing::Test {
brians343bc112013-02-10 01:53:46 +000039 protected:
40 static const size_t kFailureSize = 400;
41 static char *fatal_failure;
42 private:
brians343bc112013-02-10 01:53:46 +000043 enum class ResultType : uint8_t {
44 NotCalled,
45 Called,
46 Returned,
47 };
48 const std::string ResultTypeString(volatile const ResultType &result) {
49 switch (result) {
50 case ResultType::Returned:
51 return "Returned";
52 case ResultType::Called:
53 return "Called";
54 case ResultType::NotCalled:
55 return "NotCalled";
56 default:
Brian Silvermanf7986142014-04-21 17:42:35 -070057 return std::string("unknown(") +
58 ::std::to_string(static_cast<uint8_t>(result)) + ")";
brians343bc112013-02-10 01:53:46 +000059 }
60 }
Brian Silvermana6d1b562013-09-01 14:39:39 -070061 static_assert(aos::shm_ok<ResultType>::value,
62 "this will get put in shared memory");
Brian Silvermana6d1b562013-09-01 14:39:39 -070063 template<typename T>
64 struct FunctionToCall {
Brian Silvermandc1eb272014-08-19 14:25:59 -040065 FunctionToCall() : result(ResultType::NotCalled), started() {
Brian Silvermaneeb62ca2013-09-11 15:08:03 -070066 }
67
68 volatile ResultType result;
brians343bc112013-02-10 01:53:46 +000069 bool expected;
70 void (*function)(T*, char*);
71 T *arg;
72 volatile char failure[kFailureSize];
Brian Silvermandc1eb272014-08-19 14:25:59 -040073 aos_futex started;
brians343bc112013-02-10 01:53:46 +000074 };
Brian Silvermana6d1b562013-09-01 14:39:39 -070075 template<typename T>
Brian Silvermaneeb62ca2013-09-11 15:08:03 -070076 static void Hangs_(FunctionToCall<T> *const to_call) {
Austin Schuhf2a50ba2016-12-24 16:16:26 -080077 this_thread::sleep_for(chrono::milliseconds(10));
Brian Silvermandc1eb272014-08-19 14:25:59 -040078 ASSERT_EQ(1, futex_set(&to_call->started));
brians343bc112013-02-10 01:53:46 +000079 to_call->result = ResultType::Called;
80 to_call->function(to_call->arg, const_cast<char *>(to_call->failure));
81 to_call->result = ResultType::Returned;
82 }
83
Brian Silvermaneeb62ca2013-09-11 15:08:03 -070084 // How long until a function is considered to have hung.
Austin Schuhf2a50ba2016-12-24 16:16:26 -080085 static constexpr chrono::nanoseconds kHangTime = chrono::milliseconds(90);
Brian Silvermaneeb62ca2013-09-11 15:08:03 -070086 // How long to sleep after forking (for debugging).
Austin Schuhf2a50ba2016-12-24 16:16:26 -080087 static constexpr chrono::nanoseconds kForkSleep = chrono::milliseconds(0);
brians343bc112013-02-10 01:53:46 +000088
89 // Represents a process that has been forked off. The destructor kills the
90 // process and wait(2)s for it.
91 class ForkedProcess {
brians343bc112013-02-10 01:53:46 +000092 public:
Brian Silvermandc1eb272014-08-19 14:25:59 -040093 ForkedProcess(pid_t pid, aos_futex *done)
94 : pid_(pid), done_(done), exiting_(false) {};
brians343bc112013-02-10 01:53:46 +000095 ~ForkedProcess() {
Brian Silvermandc1eb272014-08-19 14:25:59 -040096 if (!exiting_) {
97 if (kill(pid_, SIGTERM) == -1) {
98 if (errno == ESRCH) {
99 printf("process %jd was already dead\n",
100 static_cast<intmax_t>(pid_));
101 } else {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700102 AOS_PLOG(FATAL, "kill(SIGKILL, %jd) failed",
103 static_cast<intmax_t>(pid_));
Brian Silvermandc1eb272014-08-19 14:25:59 -0400104 }
brians343bc112013-02-10 01:53:46 +0000105 }
brians343bc112013-02-10 01:53:46 +0000106 }
107 const pid_t ret = wait(NULL);
108 if (ret == -1) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700109 AOS_LOG(WARNING,
110 "wait(NULL) failed."
111 " child %jd might still be alive\n",
112 static_cast<intmax_t>(pid_));
brians343bc112013-02-10 01:53:46 +0000113 } else if (ret == 0) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700114 AOS_LOG(WARNING, "child %jd wasn't waitable. it might still be alive\n",
115 static_cast<intmax_t>(pid_));
brians343bc112013-02-10 01:53:46 +0000116 } else if (ret != pid_) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700117 AOS_LOG(WARNING,
118 "child %d is now confirmed dead"
119 ", but child %jd might still be alive\n",
120 ret, static_cast<intmax_t>(pid_));
brians343bc112013-02-10 01:53:46 +0000121 }
122 }
123
124 enum class JoinResult {
125 Finished, Hung, Error
126 };
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800127 JoinResult Join(chrono::nanoseconds timeout = kHangTime) {
128 struct timespec done_timeout;
129 {
130 auto full_timeout = kForkSleep + timeout;
131 ::std::chrono::seconds sec =
132 ::std::chrono::duration_cast<::std::chrono::seconds>(full_timeout);
133 ::std::chrono::nanoseconds nsec =
134 ::std::chrono::duration_cast<::std::chrono::nanoseconds>(
135 full_timeout - sec);
136 done_timeout.tv_sec = sec.count();
137 done_timeout.tv_nsec = nsec.count();
138 }
139
Brian Silvermandc1eb272014-08-19 14:25:59 -0400140 switch (futex_wait_timeout(done_, &done_timeout)) {
brians343bc112013-02-10 01:53:46 +0000141 case 2:
142 return JoinResult::Hung;
143 case 0:
Brian Silvermandc1eb272014-08-19 14:25:59 -0400144 exiting_ = true;
brians343bc112013-02-10 01:53:46 +0000145 return JoinResult::Finished;
146 default:
147 return JoinResult::Error;
148 }
149 }
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700150
151 private:
152 const pid_t pid_;
Brian Silvermandc1eb272014-08-19 14:25:59 -0400153 aos_futex *const done_;
154 // True iff we know that the process is already exiting.
155 bool exiting_;
brians343bc112013-02-10 01:53:46 +0000156 } __attribute__((unused));
157
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700158 // State for HangsFork and HangsCheck.
brians343bc112013-02-10 01:53:46 +0000159 typedef uint8_t ChildID;
160 static void ReapExitHandler() {
161 for (auto it = children_.begin(); it != children_.end(); ++it) {
162 delete it->second;
163 }
164 }
165 static std::map<ChildID, ForkedProcess *> children_;
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700166 std::map<ChildID, FunctionToCall<void> *> to_calls_;
brians343bc112013-02-10 01:53:46 +0000167
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700168 void SetUp() override {
169 ::testing::Test::SetUp();
Brian Silverman5f8c4922014-02-11 21:22:38 -0800170
171 SetDieTestMode(true);
172
Brian Silvermana6d1b562013-09-01 14:39:39 -0700173 fatal_failure = static_cast<char *>(shm_malloc(sizeof(fatal_failure)));
brians343bc112013-02-10 01:53:46 +0000174 static bool registered = false;
175 if (!registered) {
176 atexit(ReapExitHandler);
177 registered = true;
178 }
179 }
180
181 protected:
Brian Silverman797e71e2013-09-06 17:29:39 -0700182 // function gets called with arg in a forked process.
brians343bc112013-02-10 01:53:46 +0000183 // Leaks shared memory.
brians343bc112013-02-10 01:53:46 +0000184 template<typename T> __attribute__((warn_unused_result))
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700185 std::unique_ptr<ForkedProcess> ForkExecute(void (*function)(T*), T *arg) {
Brian Silvermandc1eb272014-08-19 14:25:59 -0400186 aos_futex *done = static_cast<aos_futex *>(shm_malloc_aligned(
187 sizeof(*done), alignof(aos_futex)));
188 *done = 0;
brians343bc112013-02-10 01:53:46 +0000189 const pid_t pid = fork();
190 switch (pid) {
Brian Silverman797e71e2013-09-06 17:29:39 -0700191 case 0: // child
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800192 if (kForkSleep != chrono::milliseconds(0)) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700193 AOS_LOG(INFO, "pid %jd sleeping for %" PRId64 "ns\n",
194 static_cast<intmax_t>(getpid()), kForkSleep.count());
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800195 this_thread::sleep_for(kForkSleep);
brians343bc112013-02-10 01:53:46 +0000196 }
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -0500197 ::aos::testing::PreventExit();
brians343bc112013-02-10 01:53:46 +0000198 function(arg);
Austin Schuhf257f3c2019-10-27 21:00:43 -0700199 AOS_CHECK_NE(-1, futex_set(done));
brians343bc112013-02-10 01:53:46 +0000200 exit(EXIT_SUCCESS);
Brian Silverman797e71e2013-09-06 17:29:39 -0700201 case -1: // parent failure
Austin Schuhf257f3c2019-10-27 21:00:43 -0700202 AOS_PLOG(ERROR, "fork() failed");
brians343bc112013-02-10 01:53:46 +0000203 return std::unique_ptr<ForkedProcess>();
Brian Silverman797e71e2013-09-06 17:29:39 -0700204 default: // parent
Brian Silvermandc1eb272014-08-19 14:25:59 -0400205 return std::unique_ptr<ForkedProcess>(new ForkedProcess(pid, done));
brians343bc112013-02-10 01:53:46 +0000206 }
207 }
208
209 // Checks whether or not the given function hangs.
210 // expected is whether to return success or failure if the function hangs
211 // NOTE: There are other reasons for it to return a failure than the function
212 // doing the wrong thing.
213 // Leaks shared memory.
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700214 template<typename T>
215 AssertionResult Hangs(void (*function)(T*, char*), T *arg, bool expected) {
brians343bc112013-02-10 01:53:46 +0000216 AssertionResult fork_result(HangsFork<T>(function, arg, expected, 0));
217 if (!fork_result) {
218 return fork_result;
219 }
220 return HangsCheck(0);
221 }
222 // Starts the first part of Hangs.
223 // Use HangsCheck to get the result.
224 // Returns whether the fork succeeded or not, NOT whether or not the hang
225 // check succeeded.
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700226 template<typename T>
227 AssertionResult HangsFork(void (*function)(T*, char *), T *arg,
228 bool expected, ChildID id) {
brians343bc112013-02-10 01:53:46 +0000229 static_assert(aos::shm_ok<FunctionToCall<T>>::value,
230 "this is going into shared memory");
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700231 FunctionToCall<T> *const to_call =
232 static_cast<FunctionToCall<T> *>(
233 shm_malloc_aligned(sizeof(*to_call), alignof(FunctionToCall<T>)));
234 new (to_call) FunctionToCall<T>();
brians343bc112013-02-10 01:53:46 +0000235 to_call->function = function;
236 to_call->arg = arg;
237 to_call->expected = expected;
238 to_call->failure[0] = '\0';
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700239 static_cast<char *>(fatal_failure)[0] = '\0';
brians343bc112013-02-10 01:53:46 +0000240 children_[id] = ForkExecute(Hangs_, to_call).release();
241 if (!children_[id]) return AssertionFailure() << "ForkExecute failed";
Austin Schuhf257f3c2019-10-27 21:00:43 -0700242 AOS_CHECK_EQ(0, futex_wait(&to_call->started));
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700243 to_calls_[id] = reinterpret_cast<FunctionToCall<void> *>(to_call);
brians343bc112013-02-10 01:53:46 +0000244 return AssertionSuccess();
245 }
246 // Checks whether or not a function hung like it was supposed to.
247 // Use HangsFork first.
248 // NOTE: calls to HangsFork and HangsCheck with the same id argument will
249 // correspond, but they do not nest. Also, id 0 is used by Hangs.
250 // Return value is the same as Hangs.
251 AssertionResult HangsCheck(ChildID id) {
252 std::unique_ptr<ForkedProcess> child(children_[id]);
253 children_.erase(id);
254 const ForkedProcess::JoinResult result = child->Join();
255 if (to_calls_[id]->failure[0] != '\0') {
256 return AssertionFailure() << "function says: "
257 << const_cast<char *>(to_calls_[id]->failure);
258 }
259 if (result == ForkedProcess::JoinResult::Finished) {
260 return !to_calls_[id]->expected ? AssertionSuccess() : (AssertionFailure()
261 << "something happened and the the test only got to "
262 << ResultTypeString(to_calls_[id]->result));
263 } else {
264 if (to_calls_[id]->result == ResultType::Called) {
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700265 return to_calls_[id]->expected ? AssertionSuccess() :
266 AssertionFailure();
267 } else if (result == ForkedProcess::JoinResult::Error) {
268 return AssertionFailure() << "error joining child";
brians343bc112013-02-10 01:53:46 +0000269 } else {
Brian Silvermandc1eb272014-08-19 14:25:59 -0400270 if (to_calls_[id]->result == ResultType::NotCalled) {
271 return AssertionFailure() << "stuff took too long getting started";
272 }
brians343bc112013-02-10 01:53:46 +0000273 return AssertionFailure() << "something weird happened";
274 }
275 }
276 }
277#define EXPECT_HANGS(function, arg) \
278 EXPECT_HANGS_COND(function, arg, true, EXPECT_TRUE)
279#define EXPECT_RETURNS(function, arg) \
280 EXPECT_HANGS_COND(function, arg, false, EXPECT_TRUE)
281#define EXPECT_RETURNS_FAILS(function, arg) \
282 EXPECT_HANGS_COND(function, arg, false, EXPECT_FALSE)
283#define EXPECT_HANGS_COND(function, arg, hangs, cond) do { \
284 cond(Hangs(function, arg, hangs)); \
285 if (fatal_failure[0] != '\0') { \
286 FAIL() << fatal_failure; \
287 } \
288} while (false)
289
290 struct TestMessage {
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700291 // Some contents because we don't really want to test empty messages.
292 int16_t data;
brians343bc112013-02-10 01:53:46 +0000293 };
294 struct MessageArgs {
Brian Silverman08661c72013-09-01 17:24:38 -0700295 RawQueue *const queue;
Brian Silverman7faaec72014-05-26 16:25:38 -0700296 Options<RawQueue> flags;
Brian Silverman797e71e2013-09-06 17:29:39 -0700297 int16_t data; // -1 means NULL expected
brians343bc112013-02-10 01:53:46 +0000298 };
299 static void WriteTestMessage(MessageArgs *args, char *failure) {
Brian Silvermana6d1b562013-09-01 14:39:39 -0700300 TestMessage *msg = static_cast<TestMessage *>(args->queue->GetMessage());
brians343bc112013-02-10 01:53:46 +0000301 if (msg == NULL) {
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700302 snprintf(fatal_failure, kFailureSize,
303 "couldn't get_msg from %p", args->queue);
brians343bc112013-02-10 01:53:46 +0000304 return;
305 }
306 msg->data = args->data;
Brian Silvermana6d1b562013-09-01 14:39:39 -0700307 if (!args->queue->WriteMessage(msg, args->flags)) {
Brian Silverman7faaec72014-05-26 16:25:38 -0700308 snprintf(failure, kFailureSize, "%p->WriteMessage(%p, %x) failed",
309 args->queue, msg, args->flags.printable());
brians343bc112013-02-10 01:53:46 +0000310 }
311 }
312 static void ReadTestMessage(MessageArgs *args, char *failure) {
Brian Silvermana6d1b562013-09-01 14:39:39 -0700313 const TestMessage *msg = static_cast<const TestMessage *>(
314 args->queue->ReadMessage(args->flags));
brians343bc112013-02-10 01:53:46 +0000315 if (msg == NULL) {
316 if (args->data != -1) {
Brian Silverman08661c72013-09-01 17:24:38 -0700317 snprintf(failure, kFailureSize,
318 "expected data of %" PRId16 " but got NULL message",
brians343bc112013-02-10 01:53:46 +0000319 args->data);
320 }
321 } else {
322 if (args->data != msg->data) {
323 snprintf(failure, kFailureSize,
Brian Silverman08661c72013-09-01 17:24:38 -0700324 "expected data of %" PRId16 " but got %" PRId16 " instead",
brians343bc112013-02-10 01:53:46 +0000325 args->data, msg->data);
326 }
Brian Silvermana6d1b562013-09-01 14:39:39 -0700327 args->queue->FreeMessage(msg);
brians343bc112013-02-10 01:53:46 +0000328 }
329 }
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700330
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700331 void PushMessage(RawQueue *queue, uint16_t data) {
332 TestMessage *message = static_cast<TestMessage *>(queue->GetMessage());
333 message->data = data;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700334 ASSERT_TRUE(queue->WriteMessage(message, RawQueue::kOverride));
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700335 }
336
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700337 private:
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -0500338 ::aos::testing::TestSharedMemory my_shm_;
brians343bc112013-02-10 01:53:46 +0000339};
Brian Silverman7faaec72014-05-26 16:25:38 -0700340
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700341char *RawQueueTest::fatal_failure;
342std::map<RawQueueTest::ChildID, RawQueueTest::ForkedProcess *>
343 RawQueueTest::children_;
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800344constexpr chrono::nanoseconds RawQueueTest::kHangTime;
345constexpr chrono::nanoseconds RawQueueTest::kForkSleep;
brians343bc112013-02-10 01:53:46 +0000346
Brian Silverman7faaec72014-05-26 16:25:38 -0700347typedef RawQueueTest RawQueueDeathTest;
348
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700349TEST_F(RawQueueTest, Reading) {
Brian Silverman08661c72013-09-01 17:24:38 -0700350 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
Brian Silverman7faaec72014-05-26 16:25:38 -0700351 MessageArgs args{queue, RawQueue::kBlock, -1};
brians343bc112013-02-10 01:53:46 +0000352
Brian Silverman08661c72013-09-01 17:24:38 -0700353 args.flags = RawQueue::kNonBlock;
brians343bc112013-02-10 01:53:46 +0000354 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700355 args.flags = RawQueue::kNonBlock | RawQueue::kPeek;
brians343bc112013-02-10 01:53:46 +0000356 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700357 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000358 EXPECT_HANGS(ReadTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700359 args.flags = RawQueue::kPeek | RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000360 EXPECT_HANGS(ReadTestMessage, &args);
361 args.data = 254;
Brian Silverman08661c72013-09-01 17:24:38 -0700362 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000363 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700364 args.flags = RawQueue::kPeek | RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000365 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700366 args.flags = RawQueue::kPeek | RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000367 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700368 args.flags = RawQueue::kPeek | RawQueue::kNonBlock;
brians343bc112013-02-10 01:53:46 +0000369 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700370 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000371 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700372 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000373 args.data = -1;
374 EXPECT_HANGS(ReadTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700375 args.flags = RawQueue::kNonBlock;
brians343bc112013-02-10 01:53:46 +0000376 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700377 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000378 args.data = 971;
379 EXPECT_RETURNS_FAILS(ReadTestMessage, &args);
380}
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700381TEST_F(RawQueueTest, Writing) {
Brian Silverman08661c72013-09-01 17:24:38 -0700382 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
Brian Silverman7faaec72014-05-26 16:25:38 -0700383 MessageArgs args{queue, RawQueue::kBlock, 973};
brians343bc112013-02-10 01:53:46 +0000384
Brian Silverman08661c72013-09-01 17:24:38 -0700385 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000386 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700387 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000388 EXPECT_HANGS(WriteTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700389 args.flags = RawQueue::kNonBlock;
brians343bc112013-02-10 01:53:46 +0000390 EXPECT_RETURNS_FAILS(WriteTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700391 args.flags = RawQueue::kNonBlock;
brians343bc112013-02-10 01:53:46 +0000392 EXPECT_RETURNS_FAILS(WriteTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700393 args.flags = RawQueue::kPeek | RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000394 EXPECT_RETURNS(ReadTestMessage, &args);
395 args.data = 971;
Brian Silverman08661c72013-09-01 17:24:38 -0700396 args.flags = RawQueue::kOverride;
brians343bc112013-02-10 01:53:46 +0000397 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700398 args.flags = RawQueue::kOverride;
brians343bc112013-02-10 01:53:46 +0000399 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700400 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000401 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700402 args.flags = RawQueue::kNonBlock;
brians343bc112013-02-10 01:53:46 +0000403 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700404 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000405 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700406 args.flags = RawQueue::kOverride;
brians343bc112013-02-10 01:53:46 +0000407 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700408 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000409 EXPECT_RETURNS(ReadTestMessage, &args);
410}
411
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700412TEST_F(RawQueueTest, MultiRead) {
Brian Silverman08661c72013-09-01 17:24:38 -0700413 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
Brian Silverman7faaec72014-05-26 16:25:38 -0700414 MessageArgs args{queue, RawQueue::kBlock, 1323};
brians343bc112013-02-10 01:53:46 +0000415
Brian Silverman08661c72013-09-01 17:24:38 -0700416 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000417 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700418 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000419 ASSERT_TRUE(HangsFork(ReadTestMessage, &args, true, 1));
420 ASSERT_TRUE(HangsFork(ReadTestMessage, &args, true, 2));
Brian Silvermandc1eb272014-08-19 14:25:59 -0400421 AssertionResult one = HangsCheck(1);
422 AssertionResult two = HangsCheck(2);
423 EXPECT_TRUE(one != two) << "'" <<
424 one.failure_message() << "' vs '" << two.failure_message() << "'";
brians343bc112013-02-10 01:53:46 +0000425 // TODO(brians) finish this
426}
427
Brian Silvermanc39e2bd2014-02-21 09:17:35 -0800428// There used to be a bug where reading first without an index and then with an
429// index would crash. This test makes sure that's fixed.
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700430TEST_F(RawQueueTest, ReadIndexAndNot) {
Brian Silvermanc39e2bd2014-02-21 09:17:35 -0800431 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
432
433 // Write a message, read it (with ReadMessage), and then write another
434 // message (before freeing the read one so the queue allocates a distinct
435 // message to use for it).
436 TestMessage *msg = static_cast<TestMessage *>(queue->GetMessage());
437 ASSERT_NE(nullptr, msg);
Brian Silverman7faaec72014-05-26 16:25:38 -0700438 ASSERT_TRUE(queue->WriteMessage(msg, RawQueue::kBlock));
439 const void *read_msg = queue->ReadMessage(RawQueue::kBlock);
Brian Silvermanc39e2bd2014-02-21 09:17:35 -0800440 EXPECT_NE(nullptr, read_msg);
441 msg = static_cast<TestMessage *>(queue->GetMessage());
442 queue->FreeMessage(read_msg);
443 ASSERT_NE(nullptr, msg);
Brian Silverman7faaec72014-05-26 16:25:38 -0700444 ASSERT_TRUE(queue->WriteMessage(msg, RawQueue::kBlock));
Brian Silvermanc39e2bd2014-02-21 09:17:35 -0800445
446 int index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700447 const void *second_read_msg =
448 queue->ReadMessageIndex(RawQueue::kBlock, &index);
Brian Silvermanc39e2bd2014-02-21 09:17:35 -0800449 EXPECT_NE(nullptr, second_read_msg);
450 EXPECT_NE(read_msg, second_read_msg)
451 << "We already took that message out of the queue.";
452}
453
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700454TEST_F(RawQueueTest, Recycle) {
brians343bc112013-02-10 01:53:46 +0000455 // TODO(brians) basic test of recycle queue
456 // include all of the ways a message can get into the recycle queue
Brian Silverman08661c72013-09-01 17:24:38 -0700457 RawQueue *recycle_queue = reinterpret_cast<RawQueue *>(23);
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700458 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage),
459 1, 2, 2, 2, &recycle_queue);
Brian Silverman08661c72013-09-01 17:24:38 -0700460 ASSERT_NE(reinterpret_cast<RawQueue *>(23), recycle_queue);
Brian Silverman7faaec72014-05-26 16:25:38 -0700461 MessageArgs args{queue, RawQueue::kBlock, 973},
462 recycle{recycle_queue, RawQueue::kBlock, 973};
brians343bc112013-02-10 01:53:46 +0000463
Brian Silverman08661c72013-09-01 17:24:38 -0700464 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000465 EXPECT_RETURNS(WriteTestMessage, &args);
466 EXPECT_HANGS(ReadTestMessage, &recycle);
467 args.data = 254;
468 EXPECT_RETURNS(WriteTestMessage, &args);
469 EXPECT_HANGS(ReadTestMessage, &recycle);
470 args.data = 971;
Brian Silverman08661c72013-09-01 17:24:38 -0700471 args.flags = RawQueue::kOverride;
brians343bc112013-02-10 01:53:46 +0000472 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700473 recycle.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000474 EXPECT_RETURNS(ReadTestMessage, &recycle);
475
476 EXPECT_HANGS(ReadTestMessage, &recycle);
477
Brian Silvermana6d1b562013-09-01 14:39:39 -0700478 TestMessage *msg = static_cast<TestMessage *>(queue->GetMessage());
brians343bc112013-02-10 01:53:46 +0000479 ASSERT_TRUE(msg != NULL);
480 msg->data = 341;
Brian Silvermana6d1b562013-09-01 14:39:39 -0700481 queue->FreeMessage(msg);
brians343bc112013-02-10 01:53:46 +0000482 recycle.data = 341;
483 EXPECT_RETURNS(ReadTestMessage, &recycle);
484
485 EXPECT_HANGS(ReadTestMessage, &recycle);
486
487 args.data = 254;
Brian Silverman7faaec72014-05-26 16:25:38 -0700488 args.flags = RawQueue::kPeek | RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000489 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700490 recycle.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000491 EXPECT_HANGS(ReadTestMessage, &recycle);
Brian Silverman08661c72013-09-01 17:24:38 -0700492 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000493 EXPECT_RETURNS(ReadTestMessage, &args);
494 recycle.data = 254;
495 EXPECT_RETURNS(ReadTestMessage, &recycle);
496}
497
Brian Silverman358c49f2014-03-05 16:56:34 -0800498// Makes sure that when a message doesn't get written with kNonBlock it does get
499// freed.
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700500TEST_F(RawQueueTest, NonBlockFailFree) {
Brian Silverman358c49f2014-03-05 16:56:34 -0800501 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
502
503 void *message1 = queue->GetMessage();
504 void *message2 = queue->GetMessage();
505 ASSERT_TRUE(queue->WriteMessage(message1, RawQueue::kNonBlock));
506 ASSERT_FALSE(queue->WriteMessage(message2, RawQueue::kNonBlock));
507 EXPECT_EQ(message2, queue->GetMessage());
508}
509
Brian Silverman35a14fd2014-03-24 16:57:44 -0700510// All of the tests from here down are designed to test every branch to
511// make sure it does what it's supposed to. They are generally pretty repetitive
512// and boring, and some of them may duplicate other tests above, but these ones
513// make it a lot easier to figure out what's wrong with bugs not related to race
514// conditions.
515
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700516TEST_F(RawQueueTest, ReadIndexNotFull) {
517 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700518 const TestMessage *message, *peek_message;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700519
Brian Silvermanc2e04222014-03-22 12:43:44 -0700520 EXPECT_EQ(0, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700521 PushMessage(queue, 971);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700522 EXPECT_EQ(1, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700523
524 int index = 0;
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700525 peek_message = static_cast<const TestMessage *>(
526 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700527 message = static_cast<const TestMessage *>(
528 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
529 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700530 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700531 EXPECT_EQ(971, message->data);
532 EXPECT_EQ(1, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700533 queue->FreeMessage(message);
534 queue->FreeMessage(peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700535
536 PushMessage(queue, 1768);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700537 EXPECT_EQ(2, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700538 peek_message = static_cast<const TestMessage *>(
539 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700540 message = static_cast<const TestMessage *>(
541 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
542 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700543 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700544 EXPECT_EQ(1768, message->data);
545 EXPECT_EQ(2, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700546 queue->FreeMessage(message);
547 queue->FreeMessage(peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700548
549 PushMessage(queue, 254);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700550 peek_message = static_cast<const TestMessage *>(
551 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700552 message = static_cast<const TestMessage *>(
553 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
554 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700555 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700556 EXPECT_EQ(254, message->data);
557 EXPECT_EQ(3, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700558 queue->FreeMessage(message);
559 queue->FreeMessage(peek_message);
560
Brian Silvermanad290d82014-03-19 17:22:05 -0700561 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700562 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
563 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700564 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
565 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
566 ASSERT_NE(nullptr, message);
567 EXPECT_EQ(message, peek_message);
568 EXPECT_EQ(254, message->data);
569 EXPECT_EQ(3, index);
570 queue->FreeMessage(message);
571 queue->FreeMessage(peek_message);
572
Brian Silvermanc2e04222014-03-22 12:43:44 -0700573 EXPECT_EQ(2, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700574}
575
576TEST_F(RawQueueTest, ReadIndexNotBehind) {
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700577 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700578 const TestMessage *message, *peek_message;
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700579
Brian Silvermanc2e04222014-03-22 12:43:44 -0700580 EXPECT_EQ(0, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700581 PushMessage(queue, 971);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700582 EXPECT_EQ(1, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700583 PushMessage(queue, 1768);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700584 EXPECT_EQ(2, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700585
586 int index = 0;
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700587 peek_message = static_cast<const TestMessage *>(
588 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700589 message = static_cast<const TestMessage *>(
590 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
591 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700592 EXPECT_EQ(message, peek_message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700593 EXPECT_EQ(971, message->data);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700594 EXPECT_EQ(1, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700595 queue->FreeMessage(message);
596 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700597
598 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700599 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
600 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700601 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
602 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
603 ASSERT_NE(nullptr, message);
604 EXPECT_EQ(message, peek_message);
605 EXPECT_EQ(1768, message->data);
606 EXPECT_EQ(2, index);
607 queue->FreeMessage(message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700608}
609
610TEST_F(RawQueueTest, ReadIndexLittleBehindNotFull) {
611 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700612 const TestMessage *message, *peek_message;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700613
614 PushMessage(queue, 971);
615 PushMessage(queue, 1768);
616 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
617
618 int index = 0;
619
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700620 peek_message = static_cast<const TestMessage *>(
621 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700622 message = static_cast<const TestMessage *>(
623 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
624 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700625 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700626 EXPECT_EQ(1768, message->data);
627 EXPECT_EQ(2, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700628 queue->FreeMessage(message);
629 queue->FreeMessage(peek_message);
630
Brian Silvermanad290d82014-03-19 17:22:05 -0700631 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700632 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
633 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700634 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
635 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
636 ASSERT_NE(nullptr, message);
637 EXPECT_EQ(message, peek_message);
638 EXPECT_EQ(1768, message->data);
639 EXPECT_EQ(2, index);
640 queue->FreeMessage(message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700641}
642
643TEST_F(RawQueueTest, ReadIndexMoreBehind) {
644 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700645 const TestMessage *message, *peek_message;
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700646
647 PushMessage(queue, 971);
648 PushMessage(queue, 1768);
649 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
650 PushMessage(queue, 254);
651
652 int index = 0;
653
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700654 peek_message = static_cast<const TestMessage *>(
655 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700656 message = static_cast<const TestMessage *>(
657 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
658 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700659 EXPECT_EQ(message, peek_message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700660 EXPECT_EQ(1768, message->data);
661 EXPECT_EQ(2, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700662 queue->FreeMessage(message);
663 queue->FreeMessage(peek_message);
664
665 peek_message = static_cast<const TestMessage *>(
666 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700667 message = static_cast<const TestMessage *>(
668 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
669 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700670 EXPECT_EQ(message, peek_message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700671 EXPECT_EQ(254, message->data);
672 EXPECT_EQ(3, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700673 queue->FreeMessage(message);
674 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700675
676 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700677 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
678 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700679 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
680 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
681 ASSERT_NE(nullptr, message);
682 EXPECT_EQ(message, peek_message);
683 EXPECT_EQ(254, message->data);
684 EXPECT_EQ(3, index);
685 queue->FreeMessage(message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700686}
687
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700688TEST_F(RawQueueTest, ReadIndexMoreBehindNotFull) {
689 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700690 const TestMessage *message, *peek_message;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700691
692 PushMessage(queue, 971);
693 PushMessage(queue, 1768);
694 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
695 PushMessage(queue, 254);
696 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
697
698 int index = 0;
699
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700700 peek_message = static_cast<const TestMessage *>(
701 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700702 message = static_cast<const TestMessage *>(
703 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
704 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700705 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700706 EXPECT_EQ(254, message->data);
707 EXPECT_EQ(3, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700708 queue->FreeMessage(message);
709 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700710
711 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700712 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
713 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700714 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
715 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
716 ASSERT_NE(nullptr, message);
717 EXPECT_EQ(message, peek_message);
718 EXPECT_EQ(254, message->data);
719 EXPECT_EQ(3, index);
720 queue->FreeMessage(message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700721}
722
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700723TEST_F(RawQueueTest, ReadIndexLotBehind) {
724 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700725 const TestMessage *message, *peek_message;
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700726
727 PushMessage(queue, 971);
728 PushMessage(queue, 1768);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700729 {
730 const void *message1, *message2;
731 message1 = queue->ReadMessage(RawQueue::kNonBlock);
732 ASSERT_NE(nullptr, message1);
733 PushMessage(queue, 254);
734 message2 = queue->ReadMessage(RawQueue::kNonBlock);
735 ASSERT_NE(nullptr, message2);
736 PushMessage(queue, 973);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700737 EXPECT_EQ(4, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700738 queue->FreeMessage(message1);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700739 EXPECT_EQ(3, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700740 queue->FreeMessage(message2);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700741 EXPECT_EQ(2, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700742 }
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700743
744 int index = 0;
745
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700746 peek_message = static_cast<const TestMessage *>(
747 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700748 message = static_cast<const TestMessage *>(
749 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
750 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700751 EXPECT_EQ(message, peek_message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700752 EXPECT_EQ(254, message->data);
753 EXPECT_EQ(3, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700754 queue->FreeMessage(message);
755 queue->FreeMessage(peek_message);
756
757 peek_message = static_cast<const TestMessage *>(
758 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700759 message = static_cast<const TestMessage *>(
760 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
761 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700762 EXPECT_EQ(message, peek_message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700763 EXPECT_EQ(973, message->data);
764 EXPECT_EQ(4, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700765 queue->FreeMessage(message);
766 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700767
768 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700769 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
770 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700771 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
772 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
773 ASSERT_NE(nullptr, message);
774 EXPECT_EQ(message, peek_message);
775 EXPECT_EQ(973, message->data);
776 EXPECT_EQ(4, index);
777 queue->FreeMessage(message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700778}
779
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700780TEST_F(RawQueueTest, ReadIndexLotBehindNotFull) {
781 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700782 const TestMessage *message, *peek_message;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700783
784 PushMessage(queue, 971);
785 PushMessage(queue, 1768);
786 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
787 PushMessage(queue, 254);
788 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
789 PushMessage(queue, 973);
790 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
791
792 int index = 0;
793
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700794 peek_message = static_cast<const TestMessage *>(
795 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700796 message = static_cast<const TestMessage *>(
797 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
798 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700799 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700800 EXPECT_EQ(973, message->data);
801 EXPECT_EQ(4, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700802 queue->FreeMessage(message);
803 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700804
805 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700806 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
807 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700808 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
809 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
810 ASSERT_NE(nullptr, message);
811 EXPECT_EQ(message, peek_message);
812 EXPECT_EQ(973, message->data);
813 EXPECT_EQ(4, index);
814 queue->FreeMessage(message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700815}
816
817TEST_F(RawQueueTest, ReadIndexEvenMoreBehind) {
818 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700819 const TestMessage *message, *peek_message;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700820
821 PushMessage(queue, 971);
822 PushMessage(queue, 1768);
823 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
824 PushMessage(queue, 254);
825 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
826 PushMessage(queue, 973);
827 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
828 PushMessage(queue, 1114);
829
830 int index = 0;
831
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700832 peek_message = static_cast<const TestMessage *>(
833 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700834 message = static_cast<const TestMessage *>(
835 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
836 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700837 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700838 EXPECT_EQ(973, message->data);
839 EXPECT_EQ(4, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700840 queue->FreeMessage(message);
841 queue->FreeMessage(peek_message);
842
843 peek_message = static_cast<const TestMessage *>(
844 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700845 message = static_cast<const TestMessage *>(
846 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
847 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700848 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700849 EXPECT_EQ(1114, message->data);
850 EXPECT_EQ(5, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700851 queue->FreeMessage(message);
852 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700853
854 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700855 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
856 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700857 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
858 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
859 ASSERT_NE(nullptr, message);
860 EXPECT_EQ(message, peek_message);
861 EXPECT_EQ(1114, message->data);
862 EXPECT_EQ(5, index);
863 queue->FreeMessage(message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700864}
865
866TEST_F(RawQueueTest, ReadIndexEvenMoreBehindNotFull) {
867 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700868 const TestMessage *message, *peek_message;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700869
870 PushMessage(queue, 971);
871 PushMessage(queue, 1768);
872 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
873 PushMessage(queue, 254);
874 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
875 PushMessage(queue, 973);
876 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
877 PushMessage(queue, 1114);
878 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
879
880 int index = 0;
881
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700882 peek_message = static_cast<const TestMessage *>(
883 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700884 message = static_cast<const TestMessage *>(
885 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
886 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700887 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700888 EXPECT_EQ(1114, message->data);
889 EXPECT_EQ(5, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700890 queue->FreeMessage(message);
891 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700892
893 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700894 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
895 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700896 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
897 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
898 ASSERT_NE(nullptr, message);
899 EXPECT_EQ(message, peek_message);
900 EXPECT_EQ(1114, message->data);
901 EXPECT_EQ(5, index);
902 queue->FreeMessage(message);
903}
904
905TEST_F(RawQueueTest, MessageReferenceCounts) {
906 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
907 const void *message1, *message2;
908
Brian Silvermanc2e04222014-03-22 12:43:44 -0700909 EXPECT_EQ(0, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanad290d82014-03-19 17:22:05 -0700910 message1 = queue->GetMessage();
911 EXPECT_NE(nullptr, message1);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700912 EXPECT_EQ(1, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanad290d82014-03-19 17:22:05 -0700913 message2 = queue->GetMessage();
914 EXPECT_NE(nullptr, message2);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700915 EXPECT_EQ(2, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanad290d82014-03-19 17:22:05 -0700916 queue->FreeMessage(message1);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700917 EXPECT_EQ(1, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanad290d82014-03-19 17:22:05 -0700918 queue->FreeMessage(message2);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700919 EXPECT_EQ(0, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700920}
921
Brian Silverman35a14fd2014-03-24 16:57:44 -0700922// Tests that writing with kNonBlock fails and frees the message.
923TEST_F(RawQueueTest, WriteDontBlock) {
924 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
925 void *message;
926
927 PushMessage(queue, 971);
928 int free_before = queue->FreeMessages();
929 message = queue->GetMessage();
930 ASSERT_NE(nullptr, message);
931 EXPECT_NE(free_before, queue->FreeMessages());
932 EXPECT_FALSE(queue->WriteMessage(message, RawQueue::kNonBlock));
933 EXPECT_EQ(free_before, queue->FreeMessages());
934}
935
936// Tests that writing with kOverride pushes the last message out of the queue.
937TEST_F(RawQueueTest, WriteOverride) {
938 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
939 TestMessage *message1;
940
941 PushMessage(queue, 971);
942 PushMessage(queue, 1768);
943 int free_before = queue->FreeMessages();
944 message1 = static_cast<TestMessage *>(queue->GetMessage());
945 ASSERT_NE(nullptr, message1);
946 EXPECT_NE(free_before, queue->FreeMessages());
947 message1->data = 254;
948 EXPECT_TRUE(queue->WriteMessage(message1, RawQueue::kOverride));
949 EXPECT_EQ(free_before, queue->FreeMessages());
950
951 const TestMessage *message2;
952 message2 =
953 static_cast<const TestMessage *>(queue->ReadMessage(RawQueue::kNonBlock));
954 EXPECT_EQ(1768, message2->data);
955 queue->FreeMessage(message2);
956 EXPECT_EQ(free_before + 1, queue->FreeMessages());
957 message2 =
958 static_cast<const TestMessage *>(queue->ReadMessage(RawQueue::kNonBlock));
959 EXPECT_EQ(254, message2->data);
960 queue->FreeMessage(message2);
961 EXPECT_EQ(free_before + 2, queue->FreeMessages());
962}
963
Brian Silverman653491d2014-05-13 16:53:29 -0700964// Makes sure that ThreadSanitizer doesn't catch any issues freeing from
965// multiple threads at once.
966TEST_F(RawQueueTest, MultiThreadedFree) {
967 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
968 PushMessage(queue, 971);
969 int free_before = queue->FreeMessages();
970
Brian Silverman7faaec72014-05-26 16:25:38 -0700971 const void *const message1 =
972 queue->ReadMessage(RawQueue::kPeek | RawQueue::kNonBlock);
973 const void *const message2 =
974 queue->ReadMessage(RawQueue::kPeek | RawQueue::kNonBlock);
975 ASSERT_NE(nullptr, message1);
976 ASSERT_NE(nullptr, message2);
Brian Silverman653491d2014-05-13 16:53:29 -0700977 EXPECT_EQ(free_before, queue->FreeMessages());
978 util::FunctionThread t1([message1, queue](util::Thread *) {
979 queue->FreeMessage(message1);
980 });
981 util::FunctionThread t2([message2, queue](util::Thread *) {
982 queue->FreeMessage(message2);
983 });
984 t1.Start();
985 t2.Start();
986 t1.WaitUntilDone();
987 t2.WaitUntilDone();
988 EXPECT_EQ(free_before, queue->FreeMessages());
989}
990
Brian Silverman7faaec72014-05-26 16:25:38 -0700991TEST_F(RawQueueDeathTest, OptionsValidation) {
992 RawQueue *const queue = RawQueue::Fetch("Queue", 1, 1, 1);
993
994 EXPECT_DEATH(
995 {
996 logging::AddImplementation(new util::DeathTestLogImplementation());
997 queue->WriteMessage(nullptr, RawQueue::kPeek);
998 },
999 ".*illegal write option.*");
1000 EXPECT_DEATH(
1001 {
1002 logging::AddImplementation(new util::DeathTestLogImplementation());
1003 queue->WriteMessage(nullptr, RawQueue::kFromEnd);
1004 },
1005 ".*illegal write option.*");
1006 EXPECT_DEATH(
1007 {
1008 logging::AddImplementation(new util::DeathTestLogImplementation());
1009 queue->WriteMessage(nullptr, RawQueue::kPeek | RawQueue::kFromEnd);
1010 },
1011 ".*illegal write option.*");
1012 EXPECT_DEATH(
1013 {
1014 logging::AddImplementation(new util::DeathTestLogImplementation());
1015 queue->WriteMessage(nullptr, RawQueue::kNonBlock | RawQueue::kBlock);
1016 },
1017 ".*invalid write option.*");
1018
1019 EXPECT_DEATH(
1020 {
1021 logging::AddImplementation(new util::DeathTestLogImplementation());
1022 queue->ReadMessageIndex(
1023 RawQueue::kBlock | RawQueue::kFromEnd | RawQueue::kPeek, nullptr);
1024 },
1025 ".*ReadMessageIndex.*is not allowed.*");
1026 EXPECT_DEATH(
1027 {
1028 logging::AddImplementation(new util::DeathTestLogImplementation());
1029 queue->ReadMessageIndex(RawQueue::kOverride, nullptr);
1030 },
1031 ".*illegal read option.*");
1032 EXPECT_DEATH(
1033 {
1034 logging::AddImplementation(new util::DeathTestLogImplementation());
1035 queue->ReadMessageIndex(RawQueue::kOverride | RawQueue::kBlock,
1036 nullptr);
1037 },
1038 ".*illegal read option.*");
1039 EXPECT_DEATH(
1040 {
1041 logging::AddImplementation(new util::DeathTestLogImplementation());
1042 queue->ReadMessage(RawQueue::kNonBlock | RawQueue::kBlock);
1043 },
1044 ".*invalid read option.*");
1045}
1046
Brian Silvermana6d1b562013-09-01 14:39:39 -07001047} // namespace testing
1048} // namespace aos