blob: ab98b1f37994f851baa78c87dc1ad53d51e6b18c [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 {
102 PLOG(FATAL, "kill(SIGKILL, %jd) failed",
103 static_cast<intmax_t>(pid_));
104 }
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) {
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700109 LOG(WARNING, "wait(NULL) failed."
110 " child %jd might still be alive\n",
111 static_cast<intmax_t>(pid_));
brians343bc112013-02-10 01:53:46 +0000112 } else if (ret == 0) {
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700113 LOG(WARNING, "child %jd wasn't waitable. it might still be alive\n",
114 static_cast<intmax_t>(pid_));
brians343bc112013-02-10 01:53:46 +0000115 } else if (ret != pid_) {
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700116 LOG(WARNING, "child %d is now confirmed dead"
117 ", but child %jd might still be alive\n",
118 ret, static_cast<intmax_t>(pid_));
brians343bc112013-02-10 01:53:46 +0000119 }
120 }
121
122 enum class JoinResult {
123 Finished, Hung, Error
124 };
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800125 JoinResult Join(chrono::nanoseconds timeout = kHangTime) {
126 struct timespec done_timeout;
127 {
128 auto full_timeout = kForkSleep + timeout;
129 ::std::chrono::seconds sec =
130 ::std::chrono::duration_cast<::std::chrono::seconds>(full_timeout);
131 ::std::chrono::nanoseconds nsec =
132 ::std::chrono::duration_cast<::std::chrono::nanoseconds>(
133 full_timeout - sec);
134 done_timeout.tv_sec = sec.count();
135 done_timeout.tv_nsec = nsec.count();
136 }
137
Brian Silvermandc1eb272014-08-19 14:25:59 -0400138 switch (futex_wait_timeout(done_, &done_timeout)) {
brians343bc112013-02-10 01:53:46 +0000139 case 2:
140 return JoinResult::Hung;
141 case 0:
Brian Silvermandc1eb272014-08-19 14:25:59 -0400142 exiting_ = true;
brians343bc112013-02-10 01:53:46 +0000143 return JoinResult::Finished;
144 default:
145 return JoinResult::Error;
146 }
147 }
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700148
149 private:
150 const pid_t pid_;
Brian Silvermandc1eb272014-08-19 14:25:59 -0400151 aos_futex *const done_;
152 // True iff we know that the process is already exiting.
153 bool exiting_;
brians343bc112013-02-10 01:53:46 +0000154 } __attribute__((unused));
155
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700156 // State for HangsFork and HangsCheck.
brians343bc112013-02-10 01:53:46 +0000157 typedef uint8_t ChildID;
158 static void ReapExitHandler() {
159 for (auto it = children_.begin(); it != children_.end(); ++it) {
160 delete it->second;
161 }
162 }
163 static std::map<ChildID, ForkedProcess *> children_;
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700164 std::map<ChildID, FunctionToCall<void> *> to_calls_;
brians343bc112013-02-10 01:53:46 +0000165
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700166 void SetUp() override {
167 ::testing::Test::SetUp();
Brian Silverman5f8c4922014-02-11 21:22:38 -0800168
169 SetDieTestMode(true);
170
Brian Silvermana6d1b562013-09-01 14:39:39 -0700171 fatal_failure = static_cast<char *>(shm_malloc(sizeof(fatal_failure)));
brians343bc112013-02-10 01:53:46 +0000172 static bool registered = false;
173 if (!registered) {
174 atexit(ReapExitHandler);
175 registered = true;
176 }
177 }
178
179 protected:
Brian Silverman797e71e2013-09-06 17:29:39 -0700180 // function gets called with arg in a forked process.
brians343bc112013-02-10 01:53:46 +0000181 // Leaks shared memory.
brians343bc112013-02-10 01:53:46 +0000182 template<typename T> __attribute__((warn_unused_result))
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700183 std::unique_ptr<ForkedProcess> ForkExecute(void (*function)(T*), T *arg) {
Brian Silvermandc1eb272014-08-19 14:25:59 -0400184 aos_futex *done = static_cast<aos_futex *>(shm_malloc_aligned(
185 sizeof(*done), alignof(aos_futex)));
186 *done = 0;
brians343bc112013-02-10 01:53:46 +0000187 const pid_t pid = fork();
188 switch (pid) {
Brian Silverman797e71e2013-09-06 17:29:39 -0700189 case 0: // child
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800190 if (kForkSleep != chrono::milliseconds(0)) {
191 LOG(INFO, "pid %jd sleeping for %" PRId64 "ns\n",
192 static_cast<intmax_t>(getpid()), kForkSleep.count());
193 this_thread::sleep_for(kForkSleep);
brians343bc112013-02-10 01:53:46 +0000194 }
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -0500195 ::aos::testing::PreventExit();
brians343bc112013-02-10 01:53:46 +0000196 function(arg);
Brian Silvermandc1eb272014-08-19 14:25:59 -0400197 CHECK_NE(-1, futex_set(done));
brians343bc112013-02-10 01:53:46 +0000198 exit(EXIT_SUCCESS);
Brian Silverman797e71e2013-09-06 17:29:39 -0700199 case -1: // parent failure
Brian Silverman01be0002014-05-10 15:44:38 -0700200 PLOG(ERROR, "fork() failed");
brians343bc112013-02-10 01:53:46 +0000201 return std::unique_ptr<ForkedProcess>();
Brian Silverman797e71e2013-09-06 17:29:39 -0700202 default: // parent
Brian Silvermandc1eb272014-08-19 14:25:59 -0400203 return std::unique_ptr<ForkedProcess>(new ForkedProcess(pid, done));
brians343bc112013-02-10 01:53:46 +0000204 }
205 }
206
207 // Checks whether or not the given function hangs.
208 // expected is whether to return success or failure if the function hangs
209 // NOTE: There are other reasons for it to return a failure than the function
210 // doing the wrong thing.
211 // Leaks shared memory.
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700212 template<typename T>
213 AssertionResult Hangs(void (*function)(T*, char*), T *arg, bool expected) {
brians343bc112013-02-10 01:53:46 +0000214 AssertionResult fork_result(HangsFork<T>(function, arg, expected, 0));
215 if (!fork_result) {
216 return fork_result;
217 }
218 return HangsCheck(0);
219 }
220 // Starts the first part of Hangs.
221 // Use HangsCheck to get the result.
222 // Returns whether the fork succeeded or not, NOT whether or not the hang
223 // check succeeded.
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700224 template<typename T>
225 AssertionResult HangsFork(void (*function)(T*, char *), T *arg,
226 bool expected, ChildID id) {
brians343bc112013-02-10 01:53:46 +0000227 static_assert(aos::shm_ok<FunctionToCall<T>>::value,
228 "this is going into shared memory");
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700229 FunctionToCall<T> *const to_call =
230 static_cast<FunctionToCall<T> *>(
231 shm_malloc_aligned(sizeof(*to_call), alignof(FunctionToCall<T>)));
232 new (to_call) FunctionToCall<T>();
brians343bc112013-02-10 01:53:46 +0000233 to_call->function = function;
234 to_call->arg = arg;
235 to_call->expected = expected;
236 to_call->failure[0] = '\0';
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700237 static_cast<char *>(fatal_failure)[0] = '\0';
brians343bc112013-02-10 01:53:46 +0000238 children_[id] = ForkExecute(Hangs_, to_call).release();
239 if (!children_[id]) return AssertionFailure() << "ForkExecute failed";
Brian Silvermandc1eb272014-08-19 14:25:59 -0400240 CHECK_EQ(0, futex_wait(&to_call->started));
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700241 to_calls_[id] = reinterpret_cast<FunctionToCall<void> *>(to_call);
brians343bc112013-02-10 01:53:46 +0000242 return AssertionSuccess();
243 }
244 // Checks whether or not a function hung like it was supposed to.
245 // Use HangsFork first.
246 // NOTE: calls to HangsFork and HangsCheck with the same id argument will
247 // correspond, but they do not nest. Also, id 0 is used by Hangs.
248 // Return value is the same as Hangs.
249 AssertionResult HangsCheck(ChildID id) {
250 std::unique_ptr<ForkedProcess> child(children_[id]);
251 children_.erase(id);
252 const ForkedProcess::JoinResult result = child->Join();
253 if (to_calls_[id]->failure[0] != '\0') {
254 return AssertionFailure() << "function says: "
255 << const_cast<char *>(to_calls_[id]->failure);
256 }
257 if (result == ForkedProcess::JoinResult::Finished) {
258 return !to_calls_[id]->expected ? AssertionSuccess() : (AssertionFailure()
259 << "something happened and the the test only got to "
260 << ResultTypeString(to_calls_[id]->result));
261 } else {
262 if (to_calls_[id]->result == ResultType::Called) {
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700263 return to_calls_[id]->expected ? AssertionSuccess() :
264 AssertionFailure();
265 } else if (result == ForkedProcess::JoinResult::Error) {
266 return AssertionFailure() << "error joining child";
brians343bc112013-02-10 01:53:46 +0000267 } else {
Brian Silvermandc1eb272014-08-19 14:25:59 -0400268 if (to_calls_[id]->result == ResultType::NotCalled) {
269 return AssertionFailure() << "stuff took too long getting started";
270 }
brians343bc112013-02-10 01:53:46 +0000271 return AssertionFailure() << "something weird happened";
272 }
273 }
274 }
275#define EXPECT_HANGS(function, arg) \
276 EXPECT_HANGS_COND(function, arg, true, EXPECT_TRUE)
277#define EXPECT_RETURNS(function, arg) \
278 EXPECT_HANGS_COND(function, arg, false, EXPECT_TRUE)
279#define EXPECT_RETURNS_FAILS(function, arg) \
280 EXPECT_HANGS_COND(function, arg, false, EXPECT_FALSE)
281#define EXPECT_HANGS_COND(function, arg, hangs, cond) do { \
282 cond(Hangs(function, arg, hangs)); \
283 if (fatal_failure[0] != '\0') { \
284 FAIL() << fatal_failure; \
285 } \
286} while (false)
287
288 struct TestMessage {
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700289 // Some contents because we don't really want to test empty messages.
290 int16_t data;
brians343bc112013-02-10 01:53:46 +0000291 };
292 struct MessageArgs {
Brian Silverman08661c72013-09-01 17:24:38 -0700293 RawQueue *const queue;
Brian Silverman7faaec72014-05-26 16:25:38 -0700294 Options<RawQueue> flags;
Brian Silverman797e71e2013-09-06 17:29:39 -0700295 int16_t data; // -1 means NULL expected
brians343bc112013-02-10 01:53:46 +0000296 };
297 static void WriteTestMessage(MessageArgs *args, char *failure) {
Brian Silvermana6d1b562013-09-01 14:39:39 -0700298 TestMessage *msg = static_cast<TestMessage *>(args->queue->GetMessage());
brians343bc112013-02-10 01:53:46 +0000299 if (msg == NULL) {
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700300 snprintf(fatal_failure, kFailureSize,
301 "couldn't get_msg from %p", args->queue);
brians343bc112013-02-10 01:53:46 +0000302 return;
303 }
304 msg->data = args->data;
Brian Silvermana6d1b562013-09-01 14:39:39 -0700305 if (!args->queue->WriteMessage(msg, args->flags)) {
Brian Silverman7faaec72014-05-26 16:25:38 -0700306 snprintf(failure, kFailureSize, "%p->WriteMessage(%p, %x) failed",
307 args->queue, msg, args->flags.printable());
brians343bc112013-02-10 01:53:46 +0000308 }
309 }
310 static void ReadTestMessage(MessageArgs *args, char *failure) {
Brian Silvermana6d1b562013-09-01 14:39:39 -0700311 const TestMessage *msg = static_cast<const TestMessage *>(
312 args->queue->ReadMessage(args->flags));
brians343bc112013-02-10 01:53:46 +0000313 if (msg == NULL) {
314 if (args->data != -1) {
Brian Silverman08661c72013-09-01 17:24:38 -0700315 snprintf(failure, kFailureSize,
316 "expected data of %" PRId16 " but got NULL message",
brians343bc112013-02-10 01:53:46 +0000317 args->data);
318 }
319 } else {
320 if (args->data != msg->data) {
321 snprintf(failure, kFailureSize,
Brian Silverman08661c72013-09-01 17:24:38 -0700322 "expected data of %" PRId16 " but got %" PRId16 " instead",
brians343bc112013-02-10 01:53:46 +0000323 args->data, msg->data);
324 }
Brian Silvermana6d1b562013-09-01 14:39:39 -0700325 args->queue->FreeMessage(msg);
brians343bc112013-02-10 01:53:46 +0000326 }
327 }
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700328
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700329 void PushMessage(RawQueue *queue, uint16_t data) {
330 TestMessage *message = static_cast<TestMessage *>(queue->GetMessage());
331 message->data = data;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700332 ASSERT_TRUE(queue->WriteMessage(message, RawQueue::kOverride));
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700333 }
334
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700335 private:
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -0500336 ::aos::testing::TestSharedMemory my_shm_;
brians343bc112013-02-10 01:53:46 +0000337};
Brian Silverman7faaec72014-05-26 16:25:38 -0700338
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700339char *RawQueueTest::fatal_failure;
340std::map<RawQueueTest::ChildID, RawQueueTest::ForkedProcess *>
341 RawQueueTest::children_;
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800342constexpr chrono::nanoseconds RawQueueTest::kHangTime;
343constexpr chrono::nanoseconds RawQueueTest::kForkSleep;
brians343bc112013-02-10 01:53:46 +0000344
Brian Silverman7faaec72014-05-26 16:25:38 -0700345typedef RawQueueTest RawQueueDeathTest;
346
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700347TEST_F(RawQueueTest, Reading) {
Brian Silverman08661c72013-09-01 17:24:38 -0700348 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
Brian Silverman7faaec72014-05-26 16:25:38 -0700349 MessageArgs args{queue, RawQueue::kBlock, -1};
brians343bc112013-02-10 01:53:46 +0000350
Brian Silverman08661c72013-09-01 17:24:38 -0700351 args.flags = RawQueue::kNonBlock;
brians343bc112013-02-10 01:53:46 +0000352 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700353 args.flags = RawQueue::kNonBlock | RawQueue::kPeek;
brians343bc112013-02-10 01:53:46 +0000354 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700355 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000356 EXPECT_HANGS(ReadTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700357 args.flags = RawQueue::kPeek | RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000358 EXPECT_HANGS(ReadTestMessage, &args);
359 args.data = 254;
Brian Silverman08661c72013-09-01 17:24:38 -0700360 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000361 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700362 args.flags = RawQueue::kPeek | RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000363 EXPECT_RETURNS(ReadTestMessage, &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 Silverman08661c72013-09-01 17:24:38 -0700366 args.flags = RawQueue::kPeek | RawQueue::kNonBlock;
brians343bc112013-02-10 01:53:46 +0000367 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700368 args.flags = RawQueue::kBlock;
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 args.data = -1;
372 EXPECT_HANGS(ReadTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700373 args.flags = RawQueue::kNonBlock;
brians343bc112013-02-10 01:53:46 +0000374 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700375 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000376 args.data = 971;
377 EXPECT_RETURNS_FAILS(ReadTestMessage, &args);
378}
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700379TEST_F(RawQueueTest, Writing) {
Brian Silverman08661c72013-09-01 17:24:38 -0700380 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
Brian Silverman7faaec72014-05-26 16:25:38 -0700381 MessageArgs args{queue, RawQueue::kBlock, 973};
brians343bc112013-02-10 01:53:46 +0000382
Brian Silverman08661c72013-09-01 17:24:38 -0700383 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000384 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700385 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000386 EXPECT_HANGS(WriteTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700387 args.flags = RawQueue::kNonBlock;
brians343bc112013-02-10 01:53:46 +0000388 EXPECT_RETURNS_FAILS(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 Silverman7faaec72014-05-26 16:25:38 -0700391 args.flags = RawQueue::kPeek | RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000392 EXPECT_RETURNS(ReadTestMessage, &args);
393 args.data = 971;
Brian Silverman08661c72013-09-01 17:24:38 -0700394 args.flags = RawQueue::kOverride;
brians343bc112013-02-10 01:53:46 +0000395 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700396 args.flags = RawQueue::kOverride;
brians343bc112013-02-10 01:53:46 +0000397 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700398 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000399 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700400 args.flags = RawQueue::kNonBlock;
brians343bc112013-02-10 01:53:46 +0000401 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700402 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000403 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700404 args.flags = RawQueue::kOverride;
brians343bc112013-02-10 01:53:46 +0000405 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700406 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000407 EXPECT_RETURNS(ReadTestMessage, &args);
408}
409
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700410TEST_F(RawQueueTest, MultiRead) {
Brian Silverman08661c72013-09-01 17:24:38 -0700411 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
Brian Silverman7faaec72014-05-26 16:25:38 -0700412 MessageArgs args{queue, RawQueue::kBlock, 1323};
brians343bc112013-02-10 01:53:46 +0000413
Brian Silverman08661c72013-09-01 17:24:38 -0700414 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000415 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700416 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000417 ASSERT_TRUE(HangsFork(ReadTestMessage, &args, true, 1));
418 ASSERT_TRUE(HangsFork(ReadTestMessage, &args, true, 2));
Brian Silvermandc1eb272014-08-19 14:25:59 -0400419 AssertionResult one = HangsCheck(1);
420 AssertionResult two = HangsCheck(2);
421 EXPECT_TRUE(one != two) << "'" <<
422 one.failure_message() << "' vs '" << two.failure_message() << "'";
brians343bc112013-02-10 01:53:46 +0000423 // TODO(brians) finish this
424}
425
Brian Silvermanc39e2bd2014-02-21 09:17:35 -0800426// There used to be a bug where reading first without an index and then with an
427// index would crash. This test makes sure that's fixed.
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700428TEST_F(RawQueueTest, ReadIndexAndNot) {
Brian Silvermanc39e2bd2014-02-21 09:17:35 -0800429 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
430
431 // Write a message, read it (with ReadMessage), and then write another
432 // message (before freeing the read one so the queue allocates a distinct
433 // message to use for it).
434 TestMessage *msg = static_cast<TestMessage *>(queue->GetMessage());
435 ASSERT_NE(nullptr, msg);
Brian Silverman7faaec72014-05-26 16:25:38 -0700436 ASSERT_TRUE(queue->WriteMessage(msg, RawQueue::kBlock));
437 const void *read_msg = queue->ReadMessage(RawQueue::kBlock);
Brian Silvermanc39e2bd2014-02-21 09:17:35 -0800438 EXPECT_NE(nullptr, read_msg);
439 msg = static_cast<TestMessage *>(queue->GetMessage());
440 queue->FreeMessage(read_msg);
441 ASSERT_NE(nullptr, msg);
Brian Silverman7faaec72014-05-26 16:25:38 -0700442 ASSERT_TRUE(queue->WriteMessage(msg, RawQueue::kBlock));
Brian Silvermanc39e2bd2014-02-21 09:17:35 -0800443
444 int index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700445 const void *second_read_msg =
446 queue->ReadMessageIndex(RawQueue::kBlock, &index);
Brian Silvermanc39e2bd2014-02-21 09:17:35 -0800447 EXPECT_NE(nullptr, second_read_msg);
448 EXPECT_NE(read_msg, second_read_msg)
449 << "We already took that message out of the queue.";
450}
451
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700452TEST_F(RawQueueTest, Recycle) {
brians343bc112013-02-10 01:53:46 +0000453 // TODO(brians) basic test of recycle queue
454 // include all of the ways a message can get into the recycle queue
Brian Silverman08661c72013-09-01 17:24:38 -0700455 RawQueue *recycle_queue = reinterpret_cast<RawQueue *>(23);
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700456 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage),
457 1, 2, 2, 2, &recycle_queue);
Brian Silverman08661c72013-09-01 17:24:38 -0700458 ASSERT_NE(reinterpret_cast<RawQueue *>(23), recycle_queue);
Brian Silverman7faaec72014-05-26 16:25:38 -0700459 MessageArgs args{queue, RawQueue::kBlock, 973},
460 recycle{recycle_queue, RawQueue::kBlock, 973};
brians343bc112013-02-10 01:53:46 +0000461
Brian Silverman08661c72013-09-01 17:24:38 -0700462 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000463 EXPECT_RETURNS(WriteTestMessage, &args);
464 EXPECT_HANGS(ReadTestMessage, &recycle);
465 args.data = 254;
466 EXPECT_RETURNS(WriteTestMessage, &args);
467 EXPECT_HANGS(ReadTestMessage, &recycle);
468 args.data = 971;
Brian Silverman08661c72013-09-01 17:24:38 -0700469 args.flags = RawQueue::kOverride;
brians343bc112013-02-10 01:53:46 +0000470 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700471 recycle.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000472 EXPECT_RETURNS(ReadTestMessage, &recycle);
473
474 EXPECT_HANGS(ReadTestMessage, &recycle);
475
Brian Silvermana6d1b562013-09-01 14:39:39 -0700476 TestMessage *msg = static_cast<TestMessage *>(queue->GetMessage());
brians343bc112013-02-10 01:53:46 +0000477 ASSERT_TRUE(msg != NULL);
478 msg->data = 341;
Brian Silvermana6d1b562013-09-01 14:39:39 -0700479 queue->FreeMessage(msg);
brians343bc112013-02-10 01:53:46 +0000480 recycle.data = 341;
481 EXPECT_RETURNS(ReadTestMessage, &recycle);
482
483 EXPECT_HANGS(ReadTestMessage, &recycle);
484
485 args.data = 254;
Brian Silverman7faaec72014-05-26 16:25:38 -0700486 args.flags = RawQueue::kPeek | RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000487 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700488 recycle.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000489 EXPECT_HANGS(ReadTestMessage, &recycle);
Brian Silverman08661c72013-09-01 17:24:38 -0700490 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000491 EXPECT_RETURNS(ReadTestMessage, &args);
492 recycle.data = 254;
493 EXPECT_RETURNS(ReadTestMessage, &recycle);
494}
495
Brian Silverman358c49f2014-03-05 16:56:34 -0800496// Makes sure that when a message doesn't get written with kNonBlock it does get
497// freed.
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700498TEST_F(RawQueueTest, NonBlockFailFree) {
Brian Silverman358c49f2014-03-05 16:56:34 -0800499 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
500
501 void *message1 = queue->GetMessage();
502 void *message2 = queue->GetMessage();
503 ASSERT_TRUE(queue->WriteMessage(message1, RawQueue::kNonBlock));
504 ASSERT_FALSE(queue->WriteMessage(message2, RawQueue::kNonBlock));
505 EXPECT_EQ(message2, queue->GetMessage());
506}
507
Brian Silverman35a14fd2014-03-24 16:57:44 -0700508// All of the tests from here down are designed to test every branch to
509// make sure it does what it's supposed to. They are generally pretty repetitive
510// and boring, and some of them may duplicate other tests above, but these ones
511// make it a lot easier to figure out what's wrong with bugs not related to race
512// conditions.
513
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700514TEST_F(RawQueueTest, ReadIndexNotFull) {
515 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700516 const TestMessage *message, *peek_message;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700517
Brian Silvermanc2e04222014-03-22 12:43:44 -0700518 EXPECT_EQ(0, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700519 PushMessage(queue, 971);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700520 EXPECT_EQ(1, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700521
522 int index = 0;
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700523 peek_message = static_cast<const TestMessage *>(
524 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700525 message = static_cast<const TestMessage *>(
526 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
527 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700528 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700529 EXPECT_EQ(971, message->data);
530 EXPECT_EQ(1, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700531 queue->FreeMessage(message);
532 queue->FreeMessage(peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700533
534 PushMessage(queue, 1768);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700535 EXPECT_EQ(2, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700536 peek_message = static_cast<const TestMessage *>(
537 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700538 message = static_cast<const TestMessage *>(
539 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
540 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700541 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700542 EXPECT_EQ(1768, message->data);
543 EXPECT_EQ(2, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700544 queue->FreeMessage(message);
545 queue->FreeMessage(peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700546
547 PushMessage(queue, 254);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700548 peek_message = static_cast<const TestMessage *>(
549 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700550 message = static_cast<const TestMessage *>(
551 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
552 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700553 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700554 EXPECT_EQ(254, message->data);
555 EXPECT_EQ(3, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700556 queue->FreeMessage(message);
557 queue->FreeMessage(peek_message);
558
Brian Silvermanad290d82014-03-19 17:22:05 -0700559 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700560 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
561 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700562 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
563 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
564 ASSERT_NE(nullptr, message);
565 EXPECT_EQ(message, peek_message);
566 EXPECT_EQ(254, message->data);
567 EXPECT_EQ(3, index);
568 queue->FreeMessage(message);
569 queue->FreeMessage(peek_message);
570
Brian Silvermanc2e04222014-03-22 12:43:44 -0700571 EXPECT_EQ(2, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700572}
573
574TEST_F(RawQueueTest, ReadIndexNotBehind) {
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700575 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700576 const TestMessage *message, *peek_message;
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700577
Brian Silvermanc2e04222014-03-22 12:43:44 -0700578 EXPECT_EQ(0, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700579 PushMessage(queue, 971);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700580 EXPECT_EQ(1, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700581 PushMessage(queue, 1768);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700582 EXPECT_EQ(2, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700583
584 int index = 0;
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700585 peek_message = static_cast<const TestMessage *>(
586 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700587 message = static_cast<const TestMessage *>(
588 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
589 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700590 EXPECT_EQ(message, peek_message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700591 EXPECT_EQ(971, message->data);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700592 EXPECT_EQ(1, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700593 queue->FreeMessage(message);
594 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700595
596 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700597 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
598 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700599 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
600 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
601 ASSERT_NE(nullptr, message);
602 EXPECT_EQ(message, peek_message);
603 EXPECT_EQ(1768, message->data);
604 EXPECT_EQ(2, index);
605 queue->FreeMessage(message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700606}
607
608TEST_F(RawQueueTest, ReadIndexLittleBehindNotFull) {
609 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700610 const TestMessage *message, *peek_message;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700611
612 PushMessage(queue, 971);
613 PushMessage(queue, 1768);
614 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
615
616 int index = 0;
617
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700618 peek_message = static_cast<const TestMessage *>(
619 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700620 message = static_cast<const TestMessage *>(
621 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
622 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700623 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700624 EXPECT_EQ(1768, message->data);
625 EXPECT_EQ(2, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700626 queue->FreeMessage(message);
627 queue->FreeMessage(peek_message);
628
Brian Silvermanad290d82014-03-19 17:22:05 -0700629 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700630 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
631 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700632 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
633 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
634 ASSERT_NE(nullptr, message);
635 EXPECT_EQ(message, peek_message);
636 EXPECT_EQ(1768, message->data);
637 EXPECT_EQ(2, index);
638 queue->FreeMessage(message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700639}
640
641TEST_F(RawQueueTest, ReadIndexMoreBehind) {
642 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700643 const TestMessage *message, *peek_message;
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700644
645 PushMessage(queue, 971);
646 PushMessage(queue, 1768);
647 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
648 PushMessage(queue, 254);
649
650 int index = 0;
651
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700652 peek_message = static_cast<const TestMessage *>(
653 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700654 message = static_cast<const TestMessage *>(
655 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
656 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700657 EXPECT_EQ(message, peek_message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700658 EXPECT_EQ(1768, message->data);
659 EXPECT_EQ(2, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700660 queue->FreeMessage(message);
661 queue->FreeMessage(peek_message);
662
663 peek_message = static_cast<const TestMessage *>(
664 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700665 message = static_cast<const TestMessage *>(
666 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
667 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700668 EXPECT_EQ(message, peek_message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700669 EXPECT_EQ(254, message->data);
670 EXPECT_EQ(3, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700671 queue->FreeMessage(message);
672 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700673
674 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700675 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
676 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700677 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
678 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
679 ASSERT_NE(nullptr, message);
680 EXPECT_EQ(message, peek_message);
681 EXPECT_EQ(254, message->data);
682 EXPECT_EQ(3, index);
683 queue->FreeMessage(message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700684}
685
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700686TEST_F(RawQueueTest, ReadIndexMoreBehindNotFull) {
687 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700688 const TestMessage *message, *peek_message;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700689
690 PushMessage(queue, 971);
691 PushMessage(queue, 1768);
692 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
693 PushMessage(queue, 254);
694 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
695
696 int index = 0;
697
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700698 peek_message = static_cast<const TestMessage *>(
699 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700700 message = static_cast<const TestMessage *>(
701 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
702 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700703 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700704 EXPECT_EQ(254, message->data);
705 EXPECT_EQ(3, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700706 queue->FreeMessage(message);
707 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700708
709 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700710 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
711 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700712 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
713 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
714 ASSERT_NE(nullptr, message);
715 EXPECT_EQ(message, peek_message);
716 EXPECT_EQ(254, message->data);
717 EXPECT_EQ(3, index);
718 queue->FreeMessage(message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700719}
720
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700721TEST_F(RawQueueTest, ReadIndexLotBehind) {
722 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700723 const TestMessage *message, *peek_message;
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700724
725 PushMessage(queue, 971);
726 PushMessage(queue, 1768);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700727 {
728 const void *message1, *message2;
729 message1 = queue->ReadMessage(RawQueue::kNonBlock);
730 ASSERT_NE(nullptr, message1);
731 PushMessage(queue, 254);
732 message2 = queue->ReadMessage(RawQueue::kNonBlock);
733 ASSERT_NE(nullptr, message2);
734 PushMessage(queue, 973);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700735 EXPECT_EQ(4, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700736 queue->FreeMessage(message1);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700737 EXPECT_EQ(3, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700738 queue->FreeMessage(message2);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700739 EXPECT_EQ(2, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700740 }
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700741
742 int index = 0;
743
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700744 peek_message = static_cast<const TestMessage *>(
745 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700746 message = static_cast<const TestMessage *>(
747 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
748 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700749 EXPECT_EQ(message, peek_message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700750 EXPECT_EQ(254, message->data);
751 EXPECT_EQ(3, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700752 queue->FreeMessage(message);
753 queue->FreeMessage(peek_message);
754
755 peek_message = static_cast<const TestMessage *>(
756 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700757 message = static_cast<const TestMessage *>(
758 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
759 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700760 EXPECT_EQ(message, peek_message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700761 EXPECT_EQ(973, message->data);
762 EXPECT_EQ(4, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700763 queue->FreeMessage(message);
764 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700765
766 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700767 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
768 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700769 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
770 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
771 ASSERT_NE(nullptr, message);
772 EXPECT_EQ(message, peek_message);
773 EXPECT_EQ(973, message->data);
774 EXPECT_EQ(4, index);
775 queue->FreeMessage(message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700776}
777
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700778TEST_F(RawQueueTest, ReadIndexLotBehindNotFull) {
779 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700780 const TestMessage *message, *peek_message;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700781
782 PushMessage(queue, 971);
783 PushMessage(queue, 1768);
784 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
785 PushMessage(queue, 254);
786 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
787 PushMessage(queue, 973);
788 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
789
790 int index = 0;
791
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700792 peek_message = static_cast<const TestMessage *>(
793 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700794 message = static_cast<const TestMessage *>(
795 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
796 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700797 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700798 EXPECT_EQ(973, message->data);
799 EXPECT_EQ(4, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700800 queue->FreeMessage(message);
801 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700802
803 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700804 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
805 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700806 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
807 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
808 ASSERT_NE(nullptr, message);
809 EXPECT_EQ(message, peek_message);
810 EXPECT_EQ(973, message->data);
811 EXPECT_EQ(4, index);
812 queue->FreeMessage(message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700813}
814
815TEST_F(RawQueueTest, ReadIndexEvenMoreBehind) {
816 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700817 const TestMessage *message, *peek_message;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700818
819 PushMessage(queue, 971);
820 PushMessage(queue, 1768);
821 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
822 PushMessage(queue, 254);
823 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
824 PushMessage(queue, 973);
825 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
826 PushMessage(queue, 1114);
827
828 int index = 0;
829
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700830 peek_message = static_cast<const TestMessage *>(
831 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700832 message = static_cast<const TestMessage *>(
833 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
834 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700835 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700836 EXPECT_EQ(973, message->data);
837 EXPECT_EQ(4, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700838 queue->FreeMessage(message);
839 queue->FreeMessage(peek_message);
840
841 peek_message = static_cast<const TestMessage *>(
842 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700843 message = static_cast<const TestMessage *>(
844 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
845 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700846 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700847 EXPECT_EQ(1114, message->data);
848 EXPECT_EQ(5, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700849 queue->FreeMessage(message);
850 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700851
852 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700853 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
854 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700855 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
856 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
857 ASSERT_NE(nullptr, message);
858 EXPECT_EQ(message, peek_message);
859 EXPECT_EQ(1114, message->data);
860 EXPECT_EQ(5, index);
861 queue->FreeMessage(message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700862}
863
864TEST_F(RawQueueTest, ReadIndexEvenMoreBehindNotFull) {
865 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700866 const TestMessage *message, *peek_message;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700867
868 PushMessage(queue, 971);
869 PushMessage(queue, 1768);
870 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
871 PushMessage(queue, 254);
872 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
873 PushMessage(queue, 973);
874 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
875 PushMessage(queue, 1114);
876 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
877
878 int index = 0;
879
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700880 peek_message = static_cast<const TestMessage *>(
881 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700882 message = static_cast<const TestMessage *>(
883 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
884 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700885 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700886 EXPECT_EQ(1114, message->data);
887 EXPECT_EQ(5, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700888 queue->FreeMessage(message);
889 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700890
891 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700892 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
893 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700894 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
895 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
896 ASSERT_NE(nullptr, message);
897 EXPECT_EQ(message, peek_message);
898 EXPECT_EQ(1114, message->data);
899 EXPECT_EQ(5, index);
900 queue->FreeMessage(message);
901}
902
903TEST_F(RawQueueTest, MessageReferenceCounts) {
904 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
905 const void *message1, *message2;
906
Brian Silvermanc2e04222014-03-22 12:43:44 -0700907 EXPECT_EQ(0, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanad290d82014-03-19 17:22:05 -0700908 message1 = queue->GetMessage();
909 EXPECT_NE(nullptr, message1);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700910 EXPECT_EQ(1, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanad290d82014-03-19 17:22:05 -0700911 message2 = queue->GetMessage();
912 EXPECT_NE(nullptr, message2);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700913 EXPECT_EQ(2, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanad290d82014-03-19 17:22:05 -0700914 queue->FreeMessage(message1);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700915 EXPECT_EQ(1, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanad290d82014-03-19 17:22:05 -0700916 queue->FreeMessage(message2);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700917 EXPECT_EQ(0, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700918}
919
Brian Silverman35a14fd2014-03-24 16:57:44 -0700920// Tests that writing with kNonBlock fails and frees the message.
921TEST_F(RawQueueTest, WriteDontBlock) {
922 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
923 void *message;
924
925 PushMessage(queue, 971);
926 int free_before = queue->FreeMessages();
927 message = queue->GetMessage();
928 ASSERT_NE(nullptr, message);
929 EXPECT_NE(free_before, queue->FreeMessages());
930 EXPECT_FALSE(queue->WriteMessage(message, RawQueue::kNonBlock));
931 EXPECT_EQ(free_before, queue->FreeMessages());
932}
933
934// Tests that writing with kOverride pushes the last message out of the queue.
935TEST_F(RawQueueTest, WriteOverride) {
936 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
937 TestMessage *message1;
938
939 PushMessage(queue, 971);
940 PushMessage(queue, 1768);
941 int free_before = queue->FreeMessages();
942 message1 = static_cast<TestMessage *>(queue->GetMessage());
943 ASSERT_NE(nullptr, message1);
944 EXPECT_NE(free_before, queue->FreeMessages());
945 message1->data = 254;
946 EXPECT_TRUE(queue->WriteMessage(message1, RawQueue::kOverride));
947 EXPECT_EQ(free_before, queue->FreeMessages());
948
949 const TestMessage *message2;
950 message2 =
951 static_cast<const TestMessage *>(queue->ReadMessage(RawQueue::kNonBlock));
952 EXPECT_EQ(1768, message2->data);
953 queue->FreeMessage(message2);
954 EXPECT_EQ(free_before + 1, queue->FreeMessages());
955 message2 =
956 static_cast<const TestMessage *>(queue->ReadMessage(RawQueue::kNonBlock));
957 EXPECT_EQ(254, message2->data);
958 queue->FreeMessage(message2);
959 EXPECT_EQ(free_before + 2, queue->FreeMessages());
960}
961
Brian Silverman653491d2014-05-13 16:53:29 -0700962// Makes sure that ThreadSanitizer doesn't catch any issues freeing from
963// multiple threads at once.
964TEST_F(RawQueueTest, MultiThreadedFree) {
965 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
966 PushMessage(queue, 971);
967 int free_before = queue->FreeMessages();
968
Brian Silverman7faaec72014-05-26 16:25:38 -0700969 const void *const message1 =
970 queue->ReadMessage(RawQueue::kPeek | RawQueue::kNonBlock);
971 const void *const message2 =
972 queue->ReadMessage(RawQueue::kPeek | RawQueue::kNonBlock);
973 ASSERT_NE(nullptr, message1);
974 ASSERT_NE(nullptr, message2);
Brian Silverman653491d2014-05-13 16:53:29 -0700975 EXPECT_EQ(free_before, queue->FreeMessages());
976 util::FunctionThread t1([message1, queue](util::Thread *) {
977 queue->FreeMessage(message1);
978 });
979 util::FunctionThread t2([message2, queue](util::Thread *) {
980 queue->FreeMessage(message2);
981 });
982 t1.Start();
983 t2.Start();
984 t1.WaitUntilDone();
985 t2.WaitUntilDone();
986 EXPECT_EQ(free_before, queue->FreeMessages());
987}
988
Brian Silverman7faaec72014-05-26 16:25:38 -0700989TEST_F(RawQueueDeathTest, OptionsValidation) {
990 RawQueue *const queue = RawQueue::Fetch("Queue", 1, 1, 1);
991
992 EXPECT_DEATH(
993 {
994 logging::AddImplementation(new util::DeathTestLogImplementation());
995 queue->WriteMessage(nullptr, RawQueue::kPeek);
996 },
997 ".*illegal write option.*");
998 EXPECT_DEATH(
999 {
1000 logging::AddImplementation(new util::DeathTestLogImplementation());
1001 queue->WriteMessage(nullptr, RawQueue::kFromEnd);
1002 },
1003 ".*illegal write option.*");
1004 EXPECT_DEATH(
1005 {
1006 logging::AddImplementation(new util::DeathTestLogImplementation());
1007 queue->WriteMessage(nullptr, RawQueue::kPeek | RawQueue::kFromEnd);
1008 },
1009 ".*illegal write option.*");
1010 EXPECT_DEATH(
1011 {
1012 logging::AddImplementation(new util::DeathTestLogImplementation());
1013 queue->WriteMessage(nullptr, RawQueue::kNonBlock | RawQueue::kBlock);
1014 },
1015 ".*invalid write option.*");
1016
1017 EXPECT_DEATH(
1018 {
1019 logging::AddImplementation(new util::DeathTestLogImplementation());
1020 queue->ReadMessageIndex(
1021 RawQueue::kBlock | RawQueue::kFromEnd | RawQueue::kPeek, nullptr);
1022 },
1023 ".*ReadMessageIndex.*is not allowed.*");
1024 EXPECT_DEATH(
1025 {
1026 logging::AddImplementation(new util::DeathTestLogImplementation());
1027 queue->ReadMessageIndex(RawQueue::kOverride, nullptr);
1028 },
1029 ".*illegal read option.*");
1030 EXPECT_DEATH(
1031 {
1032 logging::AddImplementation(new util::DeathTestLogImplementation());
1033 queue->ReadMessageIndex(RawQueue::kOverride | RawQueue::kBlock,
1034 nullptr);
1035 },
1036 ".*illegal read option.*");
1037 EXPECT_DEATH(
1038 {
1039 logging::AddImplementation(new util::DeathTestLogImplementation());
1040 queue->ReadMessage(RawQueue::kNonBlock | RawQueue::kBlock);
1041 },
1042 ".*invalid read option.*");
1043}
1044
Brian Silvermana6d1b562013-09-01 14:39:39 -07001045} // namespace testing
1046} // namespace aos