blob: 1c02c536748066e9892ca44211c7f1a8767930db [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",
Alex Perrycb7da4b2019-08-28 19:35:56 -0700194 static_cast<intmax_t>(getpid()),
195 static_cast<int64_t>(kForkSleep.count()));
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800196 this_thread::sleep_for(kForkSleep);
brians343bc112013-02-10 01:53:46 +0000197 }
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -0500198 ::aos::testing::PreventExit();
brians343bc112013-02-10 01:53:46 +0000199 function(arg);
Austin Schuhf257f3c2019-10-27 21:00:43 -0700200 AOS_CHECK_NE(-1, futex_set(done));
brians343bc112013-02-10 01:53:46 +0000201 exit(EXIT_SUCCESS);
Brian Silverman797e71e2013-09-06 17:29:39 -0700202 case -1: // parent failure
Austin Schuhf257f3c2019-10-27 21:00:43 -0700203 AOS_PLOG(ERROR, "fork() failed");
brians343bc112013-02-10 01:53:46 +0000204 return std::unique_ptr<ForkedProcess>();
Brian Silverman797e71e2013-09-06 17:29:39 -0700205 default: // parent
Brian Silvermandc1eb272014-08-19 14:25:59 -0400206 return std::unique_ptr<ForkedProcess>(new ForkedProcess(pid, done));
brians343bc112013-02-10 01:53:46 +0000207 }
208 }
209
210 // Checks whether or not the given function hangs.
211 // expected is whether to return success or failure if the function hangs
212 // NOTE: There are other reasons for it to return a failure than the function
213 // doing the wrong thing.
214 // Leaks shared memory.
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700215 template<typename T>
216 AssertionResult Hangs(void (*function)(T*, char*), T *arg, bool expected) {
brians343bc112013-02-10 01:53:46 +0000217 AssertionResult fork_result(HangsFork<T>(function, arg, expected, 0));
218 if (!fork_result) {
219 return fork_result;
220 }
221 return HangsCheck(0);
222 }
223 // Starts the first part of Hangs.
224 // Use HangsCheck to get the result.
225 // Returns whether the fork succeeded or not, NOT whether or not the hang
226 // check succeeded.
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700227 template<typename T>
228 AssertionResult HangsFork(void (*function)(T*, char *), T *arg,
229 bool expected, ChildID id) {
brians343bc112013-02-10 01:53:46 +0000230 static_assert(aos::shm_ok<FunctionToCall<T>>::value,
231 "this is going into shared memory");
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700232 FunctionToCall<T> *const to_call =
233 static_cast<FunctionToCall<T> *>(
234 shm_malloc_aligned(sizeof(*to_call), alignof(FunctionToCall<T>)));
235 new (to_call) FunctionToCall<T>();
brians343bc112013-02-10 01:53:46 +0000236 to_call->function = function;
237 to_call->arg = arg;
238 to_call->expected = expected;
239 to_call->failure[0] = '\0';
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700240 static_cast<char *>(fatal_failure)[0] = '\0';
brians343bc112013-02-10 01:53:46 +0000241 children_[id] = ForkExecute(Hangs_, to_call).release();
242 if (!children_[id]) return AssertionFailure() << "ForkExecute failed";
Austin Schuhf257f3c2019-10-27 21:00:43 -0700243 AOS_CHECK_EQ(0, futex_wait(&to_call->started));
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700244 to_calls_[id] = reinterpret_cast<FunctionToCall<void> *>(to_call);
brians343bc112013-02-10 01:53:46 +0000245 return AssertionSuccess();
246 }
247 // Checks whether or not a function hung like it was supposed to.
248 // Use HangsFork first.
249 // NOTE: calls to HangsFork and HangsCheck with the same id argument will
250 // correspond, but they do not nest. Also, id 0 is used by Hangs.
251 // Return value is the same as Hangs.
252 AssertionResult HangsCheck(ChildID id) {
253 std::unique_ptr<ForkedProcess> child(children_[id]);
254 children_.erase(id);
255 const ForkedProcess::JoinResult result = child->Join();
256 if (to_calls_[id]->failure[0] != '\0') {
257 return AssertionFailure() << "function says: "
258 << const_cast<char *>(to_calls_[id]->failure);
259 }
260 if (result == ForkedProcess::JoinResult::Finished) {
261 return !to_calls_[id]->expected ? AssertionSuccess() : (AssertionFailure()
262 << "something happened and the the test only got to "
263 << ResultTypeString(to_calls_[id]->result));
264 } else {
265 if (to_calls_[id]->result == ResultType::Called) {
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700266 return to_calls_[id]->expected ? AssertionSuccess() :
267 AssertionFailure();
268 } else if (result == ForkedProcess::JoinResult::Error) {
269 return AssertionFailure() << "error joining child";
brians343bc112013-02-10 01:53:46 +0000270 } else {
Brian Silvermandc1eb272014-08-19 14:25:59 -0400271 if (to_calls_[id]->result == ResultType::NotCalled) {
272 return AssertionFailure() << "stuff took too long getting started";
273 }
brians343bc112013-02-10 01:53:46 +0000274 return AssertionFailure() << "something weird happened";
275 }
276 }
277 }
278#define EXPECT_HANGS(function, arg) \
279 EXPECT_HANGS_COND(function, arg, true, EXPECT_TRUE)
280#define EXPECT_RETURNS(function, arg) \
281 EXPECT_HANGS_COND(function, arg, false, EXPECT_TRUE)
282#define EXPECT_RETURNS_FAILS(function, arg) \
283 EXPECT_HANGS_COND(function, arg, false, EXPECT_FALSE)
284#define EXPECT_HANGS_COND(function, arg, hangs, cond) do { \
285 cond(Hangs(function, arg, hangs)); \
286 if (fatal_failure[0] != '\0') { \
287 FAIL() << fatal_failure; \
288 } \
289} while (false)
290
291 struct TestMessage {
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700292 // Some contents because we don't really want to test empty messages.
293 int16_t data;
brians343bc112013-02-10 01:53:46 +0000294 };
295 struct MessageArgs {
Brian Silverman08661c72013-09-01 17:24:38 -0700296 RawQueue *const queue;
Brian Silverman7faaec72014-05-26 16:25:38 -0700297 Options<RawQueue> flags;
Brian Silverman797e71e2013-09-06 17:29:39 -0700298 int16_t data; // -1 means NULL expected
brians343bc112013-02-10 01:53:46 +0000299 };
300 static void WriteTestMessage(MessageArgs *args, char *failure) {
Brian Silvermana6d1b562013-09-01 14:39:39 -0700301 TestMessage *msg = static_cast<TestMessage *>(args->queue->GetMessage());
brians343bc112013-02-10 01:53:46 +0000302 if (msg == NULL) {
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700303 snprintf(fatal_failure, kFailureSize,
304 "couldn't get_msg from %p", args->queue);
brians343bc112013-02-10 01:53:46 +0000305 return;
306 }
307 msg->data = args->data;
Brian Silvermana6d1b562013-09-01 14:39:39 -0700308 if (!args->queue->WriteMessage(msg, args->flags)) {
Brian Silverman7faaec72014-05-26 16:25:38 -0700309 snprintf(failure, kFailureSize, "%p->WriteMessage(%p, %x) failed",
310 args->queue, msg, args->flags.printable());
brians343bc112013-02-10 01:53:46 +0000311 }
312 }
313 static void ReadTestMessage(MessageArgs *args, char *failure) {
Brian Silvermana6d1b562013-09-01 14:39:39 -0700314 const TestMessage *msg = static_cast<const TestMessage *>(
315 args->queue->ReadMessage(args->flags));
brians343bc112013-02-10 01:53:46 +0000316 if (msg == NULL) {
317 if (args->data != -1) {
Brian Silverman08661c72013-09-01 17:24:38 -0700318 snprintf(failure, kFailureSize,
319 "expected data of %" PRId16 " but got NULL message",
brians343bc112013-02-10 01:53:46 +0000320 args->data);
321 }
322 } else {
323 if (args->data != msg->data) {
324 snprintf(failure, kFailureSize,
Brian Silverman08661c72013-09-01 17:24:38 -0700325 "expected data of %" PRId16 " but got %" PRId16 " instead",
brians343bc112013-02-10 01:53:46 +0000326 args->data, msg->data);
327 }
Brian Silvermana6d1b562013-09-01 14:39:39 -0700328 args->queue->FreeMessage(msg);
brians343bc112013-02-10 01:53:46 +0000329 }
330 }
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700331
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700332 void PushMessage(RawQueue *queue, uint16_t data) {
333 TestMessage *message = static_cast<TestMessage *>(queue->GetMessage());
334 message->data = data;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700335 ASSERT_TRUE(queue->WriteMessage(message, RawQueue::kOverride));
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700336 }
337
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700338 private:
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -0500339 ::aos::testing::TestSharedMemory my_shm_;
brians343bc112013-02-10 01:53:46 +0000340};
Brian Silverman7faaec72014-05-26 16:25:38 -0700341
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700342char *RawQueueTest::fatal_failure;
343std::map<RawQueueTest::ChildID, RawQueueTest::ForkedProcess *>
344 RawQueueTest::children_;
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800345constexpr chrono::nanoseconds RawQueueTest::kHangTime;
346constexpr chrono::nanoseconds RawQueueTest::kForkSleep;
brians343bc112013-02-10 01:53:46 +0000347
Brian Silverman7faaec72014-05-26 16:25:38 -0700348typedef RawQueueTest RawQueueDeathTest;
349
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700350TEST_F(RawQueueTest, Reading) {
Brian Silverman08661c72013-09-01 17:24:38 -0700351 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
Brian Silverman7faaec72014-05-26 16:25:38 -0700352 MessageArgs args{queue, RawQueue::kBlock, -1};
brians343bc112013-02-10 01:53:46 +0000353
Brian Silverman08661c72013-09-01 17:24:38 -0700354 args.flags = RawQueue::kNonBlock;
brians343bc112013-02-10 01:53:46 +0000355 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700356 args.flags = RawQueue::kNonBlock | RawQueue::kPeek;
brians343bc112013-02-10 01:53:46 +0000357 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700358 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000359 EXPECT_HANGS(ReadTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700360 args.flags = RawQueue::kPeek | RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000361 EXPECT_HANGS(ReadTestMessage, &args);
362 args.data = 254;
Brian Silverman08661c72013-09-01 17:24:38 -0700363 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000364 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700365 args.flags = RawQueue::kPeek | RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000366 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700367 args.flags = RawQueue::kPeek | RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000368 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700369 args.flags = RawQueue::kPeek | RawQueue::kNonBlock;
brians343bc112013-02-10 01:53:46 +0000370 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700371 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000372 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700373 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000374 args.data = -1;
375 EXPECT_HANGS(ReadTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700376 args.flags = RawQueue::kNonBlock;
brians343bc112013-02-10 01:53:46 +0000377 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700378 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000379 args.data = 971;
380 EXPECT_RETURNS_FAILS(ReadTestMessage, &args);
381}
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700382TEST_F(RawQueueTest, Writing) {
Brian Silverman08661c72013-09-01 17:24:38 -0700383 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
Brian Silverman7faaec72014-05-26 16:25:38 -0700384 MessageArgs args{queue, RawQueue::kBlock, 973};
brians343bc112013-02-10 01:53:46 +0000385
Brian Silverman08661c72013-09-01 17:24:38 -0700386 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000387 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700388 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000389 EXPECT_HANGS(WriteTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700390 args.flags = RawQueue::kNonBlock;
brians343bc112013-02-10 01:53:46 +0000391 EXPECT_RETURNS_FAILS(WriteTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700392 args.flags = RawQueue::kNonBlock;
brians343bc112013-02-10 01:53:46 +0000393 EXPECT_RETURNS_FAILS(WriteTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700394 args.flags = RawQueue::kPeek | RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000395 EXPECT_RETURNS(ReadTestMessage, &args);
396 args.data = 971;
Brian Silverman08661c72013-09-01 17:24:38 -0700397 args.flags = RawQueue::kOverride;
brians343bc112013-02-10 01:53:46 +0000398 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700399 args.flags = RawQueue::kOverride;
brians343bc112013-02-10 01:53:46 +0000400 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700401 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000402 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700403 args.flags = RawQueue::kNonBlock;
brians343bc112013-02-10 01:53:46 +0000404 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700405 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000406 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700407 args.flags = RawQueue::kOverride;
brians343bc112013-02-10 01:53:46 +0000408 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman7faaec72014-05-26 16:25:38 -0700409 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000410 EXPECT_RETURNS(ReadTestMessage, &args);
411}
412
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700413TEST_F(RawQueueTest, MultiRead) {
Brian Silverman08661c72013-09-01 17:24:38 -0700414 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
Brian Silverman7faaec72014-05-26 16:25:38 -0700415 MessageArgs args{queue, RawQueue::kBlock, 1323};
brians343bc112013-02-10 01:53:46 +0000416
Brian Silverman08661c72013-09-01 17:24:38 -0700417 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000418 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700419 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000420 ASSERT_TRUE(HangsFork(ReadTestMessage, &args, true, 1));
421 ASSERT_TRUE(HangsFork(ReadTestMessage, &args, true, 2));
Brian Silvermandc1eb272014-08-19 14:25:59 -0400422 AssertionResult one = HangsCheck(1);
423 AssertionResult two = HangsCheck(2);
424 EXPECT_TRUE(one != two) << "'" <<
425 one.failure_message() << "' vs '" << two.failure_message() << "'";
brians343bc112013-02-10 01:53:46 +0000426 // TODO(brians) finish this
427}
428
Brian Silvermanc39e2bd2014-02-21 09:17:35 -0800429// There used to be a bug where reading first without an index and then with an
430// index would crash. This test makes sure that's fixed.
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700431TEST_F(RawQueueTest, ReadIndexAndNot) {
Brian Silvermanc39e2bd2014-02-21 09:17:35 -0800432 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
433
434 // Write a message, read it (with ReadMessage), and then write another
435 // message (before freeing the read one so the queue allocates a distinct
436 // message to use for it).
437 TestMessage *msg = static_cast<TestMessage *>(queue->GetMessage());
438 ASSERT_NE(nullptr, msg);
Brian Silverman7faaec72014-05-26 16:25:38 -0700439 ASSERT_TRUE(queue->WriteMessage(msg, RawQueue::kBlock));
440 const void *read_msg = queue->ReadMessage(RawQueue::kBlock);
Brian Silvermanc39e2bd2014-02-21 09:17:35 -0800441 EXPECT_NE(nullptr, read_msg);
442 msg = static_cast<TestMessage *>(queue->GetMessage());
443 queue->FreeMessage(read_msg);
444 ASSERT_NE(nullptr, msg);
Brian Silverman7faaec72014-05-26 16:25:38 -0700445 ASSERT_TRUE(queue->WriteMessage(msg, RawQueue::kBlock));
Brian Silvermanc39e2bd2014-02-21 09:17:35 -0800446
447 int index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700448 const void *second_read_msg =
449 queue->ReadMessageIndex(RawQueue::kBlock, &index);
Brian Silvermanc39e2bd2014-02-21 09:17:35 -0800450 EXPECT_NE(nullptr, second_read_msg);
451 EXPECT_NE(read_msg, second_read_msg)
452 << "We already took that message out of the queue.";
453}
454
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700455TEST_F(RawQueueTest, Recycle) {
brians343bc112013-02-10 01:53:46 +0000456 // TODO(brians) basic test of recycle queue
457 // include all of the ways a message can get into the recycle queue
Brian Silverman08661c72013-09-01 17:24:38 -0700458 RawQueue *recycle_queue = reinterpret_cast<RawQueue *>(23);
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700459 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage),
460 1, 2, 2, 2, &recycle_queue);
Brian Silverman08661c72013-09-01 17:24:38 -0700461 ASSERT_NE(reinterpret_cast<RawQueue *>(23), recycle_queue);
Brian Silverman7faaec72014-05-26 16:25:38 -0700462 MessageArgs args{queue, RawQueue::kBlock, 973},
463 recycle{recycle_queue, RawQueue::kBlock, 973};
brians343bc112013-02-10 01:53:46 +0000464
Brian Silverman08661c72013-09-01 17:24:38 -0700465 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000466 EXPECT_RETURNS(WriteTestMessage, &args);
467 EXPECT_HANGS(ReadTestMessage, &recycle);
468 args.data = 254;
469 EXPECT_RETURNS(WriteTestMessage, &args);
470 EXPECT_HANGS(ReadTestMessage, &recycle);
471 args.data = 971;
Brian Silverman08661c72013-09-01 17:24:38 -0700472 args.flags = RawQueue::kOverride;
brians343bc112013-02-10 01:53:46 +0000473 EXPECT_RETURNS(WriteTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700474 recycle.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000475 EXPECT_RETURNS(ReadTestMessage, &recycle);
476
477 EXPECT_HANGS(ReadTestMessage, &recycle);
478
Brian Silvermana6d1b562013-09-01 14:39:39 -0700479 TestMessage *msg = static_cast<TestMessage *>(queue->GetMessage());
brians343bc112013-02-10 01:53:46 +0000480 ASSERT_TRUE(msg != NULL);
481 msg->data = 341;
Brian Silvermana6d1b562013-09-01 14:39:39 -0700482 queue->FreeMessage(msg);
brians343bc112013-02-10 01:53:46 +0000483 recycle.data = 341;
484 EXPECT_RETURNS(ReadTestMessage, &recycle);
485
486 EXPECT_HANGS(ReadTestMessage, &recycle);
487
488 args.data = 254;
Brian Silverman7faaec72014-05-26 16:25:38 -0700489 args.flags = RawQueue::kPeek | RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000490 EXPECT_RETURNS(ReadTestMessage, &args);
Brian Silverman08661c72013-09-01 17:24:38 -0700491 recycle.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000492 EXPECT_HANGS(ReadTestMessage, &recycle);
Brian Silverman08661c72013-09-01 17:24:38 -0700493 args.flags = RawQueue::kBlock;
brians343bc112013-02-10 01:53:46 +0000494 EXPECT_RETURNS(ReadTestMessage, &args);
495 recycle.data = 254;
496 EXPECT_RETURNS(ReadTestMessage, &recycle);
497}
498
Brian Silverman358c49f2014-03-05 16:56:34 -0800499// Makes sure that when a message doesn't get written with kNonBlock it does get
500// freed.
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700501TEST_F(RawQueueTest, NonBlockFailFree) {
Brian Silverman358c49f2014-03-05 16:56:34 -0800502 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
503
504 void *message1 = queue->GetMessage();
505 void *message2 = queue->GetMessage();
506 ASSERT_TRUE(queue->WriteMessage(message1, RawQueue::kNonBlock));
507 ASSERT_FALSE(queue->WriteMessage(message2, RawQueue::kNonBlock));
508 EXPECT_EQ(message2, queue->GetMessage());
509}
510
Brian Silverman35a14fd2014-03-24 16:57:44 -0700511// All of the tests from here down are designed to test every branch to
512// make sure it does what it's supposed to. They are generally pretty repetitive
513// and boring, and some of them may duplicate other tests above, but these ones
514// make it a lot easier to figure out what's wrong with bugs not related to race
515// conditions.
516
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700517TEST_F(RawQueueTest, ReadIndexNotFull) {
518 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700519 const TestMessage *message, *peek_message;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700520
Brian Silvermanc2e04222014-03-22 12:43:44 -0700521 EXPECT_EQ(0, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700522 PushMessage(queue, 971);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700523 EXPECT_EQ(1, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700524
525 int index = 0;
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700526 peek_message = static_cast<const TestMessage *>(
527 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700528 message = static_cast<const TestMessage *>(
529 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
530 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700531 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700532 EXPECT_EQ(971, message->data);
533 EXPECT_EQ(1, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700534 queue->FreeMessage(message);
535 queue->FreeMessage(peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700536
537 PushMessage(queue, 1768);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700538 EXPECT_EQ(2, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700539 peek_message = static_cast<const TestMessage *>(
540 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700541 message = static_cast<const TestMessage *>(
542 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
543 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700544 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700545 EXPECT_EQ(1768, message->data);
546 EXPECT_EQ(2, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700547 queue->FreeMessage(message);
548 queue->FreeMessage(peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700549
550 PushMessage(queue, 254);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700551 peek_message = static_cast<const TestMessage *>(
552 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700553 message = static_cast<const TestMessage *>(
554 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
555 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700556 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700557 EXPECT_EQ(254, message->data);
558 EXPECT_EQ(3, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700559 queue->FreeMessage(message);
560 queue->FreeMessage(peek_message);
561
Brian Silvermanad290d82014-03-19 17:22:05 -0700562 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700563 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
564 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700565 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
566 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
567 ASSERT_NE(nullptr, message);
568 EXPECT_EQ(message, peek_message);
569 EXPECT_EQ(254, message->data);
570 EXPECT_EQ(3, index);
571 queue->FreeMessage(message);
572 queue->FreeMessage(peek_message);
573
Brian Silvermanc2e04222014-03-22 12:43:44 -0700574 EXPECT_EQ(2, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700575}
576
577TEST_F(RawQueueTest, ReadIndexNotBehind) {
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700578 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700579 const TestMessage *message, *peek_message;
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700580
Brian Silvermanc2e04222014-03-22 12:43:44 -0700581 EXPECT_EQ(0, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700582 PushMessage(queue, 971);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700583 EXPECT_EQ(1, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700584 PushMessage(queue, 1768);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700585 EXPECT_EQ(2, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700586
587 int index = 0;
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700588 peek_message = static_cast<const TestMessage *>(
589 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700590 message = static_cast<const TestMessage *>(
591 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
592 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700593 EXPECT_EQ(message, peek_message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700594 EXPECT_EQ(971, message->data);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700595 EXPECT_EQ(1, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700596 queue->FreeMessage(message);
597 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700598
599 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700600 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
601 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700602 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
603 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
604 ASSERT_NE(nullptr, message);
605 EXPECT_EQ(message, peek_message);
606 EXPECT_EQ(1768, message->data);
607 EXPECT_EQ(2, index);
608 queue->FreeMessage(message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700609}
610
611TEST_F(RawQueueTest, ReadIndexLittleBehindNotFull) {
612 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700613 const TestMessage *message, *peek_message;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700614
615 PushMessage(queue, 971);
616 PushMessage(queue, 1768);
617 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
618
619 int index = 0;
620
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700621 peek_message = static_cast<const TestMessage *>(
622 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700623 message = static_cast<const TestMessage *>(
624 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
625 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700626 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700627 EXPECT_EQ(1768, message->data);
628 EXPECT_EQ(2, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700629 queue->FreeMessage(message);
630 queue->FreeMessage(peek_message);
631
Brian Silvermanad290d82014-03-19 17:22:05 -0700632 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700633 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
634 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700635 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
636 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
637 ASSERT_NE(nullptr, message);
638 EXPECT_EQ(message, peek_message);
639 EXPECT_EQ(1768, message->data);
640 EXPECT_EQ(2, index);
641 queue->FreeMessage(message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700642}
643
644TEST_F(RawQueueTest, ReadIndexMoreBehind) {
645 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700646 const TestMessage *message, *peek_message;
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700647
648 PushMessage(queue, 971);
649 PushMessage(queue, 1768);
650 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
651 PushMessage(queue, 254);
652
653 int index = 0;
654
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700655 peek_message = static_cast<const TestMessage *>(
656 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700657 message = static_cast<const TestMessage *>(
658 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
659 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700660 EXPECT_EQ(message, peek_message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700661 EXPECT_EQ(1768, message->data);
662 EXPECT_EQ(2, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700663 queue->FreeMessage(message);
664 queue->FreeMessage(peek_message);
665
666 peek_message = static_cast<const TestMessage *>(
667 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700668 message = static_cast<const TestMessage *>(
669 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
670 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700671 EXPECT_EQ(message, peek_message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700672 EXPECT_EQ(254, message->data);
673 EXPECT_EQ(3, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700674 queue->FreeMessage(message);
675 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700676
677 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700678 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
679 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700680 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
681 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
682 ASSERT_NE(nullptr, message);
683 EXPECT_EQ(message, peek_message);
684 EXPECT_EQ(254, message->data);
685 EXPECT_EQ(3, index);
686 queue->FreeMessage(message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700687}
688
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700689TEST_F(RawQueueTest, ReadIndexMoreBehindNotFull) {
690 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700691 const TestMessage *message, *peek_message;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700692
693 PushMessage(queue, 971);
694 PushMessage(queue, 1768);
695 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
696 PushMessage(queue, 254);
697 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
698
699 int index = 0;
700
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700701 peek_message = static_cast<const TestMessage *>(
702 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700703 message = static_cast<const TestMessage *>(
704 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
705 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700706 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700707 EXPECT_EQ(254, message->data);
708 EXPECT_EQ(3, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700709 queue->FreeMessage(message);
710 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700711
712 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700713 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
714 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700715 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
716 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
717 ASSERT_NE(nullptr, message);
718 EXPECT_EQ(message, peek_message);
719 EXPECT_EQ(254, message->data);
720 EXPECT_EQ(3, index);
721 queue->FreeMessage(message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700722}
723
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700724TEST_F(RawQueueTest, ReadIndexLotBehind) {
725 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700726 const TestMessage *message, *peek_message;
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700727
728 PushMessage(queue, 971);
729 PushMessage(queue, 1768);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700730 {
731 const void *message1, *message2;
732 message1 = queue->ReadMessage(RawQueue::kNonBlock);
733 ASSERT_NE(nullptr, message1);
734 PushMessage(queue, 254);
735 message2 = queue->ReadMessage(RawQueue::kNonBlock);
736 ASSERT_NE(nullptr, message2);
737 PushMessage(queue, 973);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700738 EXPECT_EQ(4, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700739 queue->FreeMessage(message1);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700740 EXPECT_EQ(3, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700741 queue->FreeMessage(message2);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700742 EXPECT_EQ(2, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700743 }
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700744
745 int index = 0;
746
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700747 peek_message = static_cast<const TestMessage *>(
748 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700749 message = static_cast<const TestMessage *>(
750 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
751 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700752 EXPECT_EQ(message, peek_message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700753 EXPECT_EQ(254, message->data);
754 EXPECT_EQ(3, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700755 queue->FreeMessage(message);
756 queue->FreeMessage(peek_message);
757
758 peek_message = static_cast<const TestMessage *>(
759 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700760 message = static_cast<const TestMessage *>(
761 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
762 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700763 EXPECT_EQ(message, peek_message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700764 EXPECT_EQ(973, message->data);
765 EXPECT_EQ(4, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700766 queue->FreeMessage(message);
767 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700768
769 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700770 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
771 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700772 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
773 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
774 ASSERT_NE(nullptr, message);
775 EXPECT_EQ(message, peek_message);
776 EXPECT_EQ(973, message->data);
777 EXPECT_EQ(4, index);
778 queue->FreeMessage(message);
Brian Silvermanac3aedc2014-03-13 22:53:38 -0700779}
780
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700781TEST_F(RawQueueTest, ReadIndexLotBehindNotFull) {
782 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700783 const TestMessage *message, *peek_message;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700784
785 PushMessage(queue, 971);
786 PushMessage(queue, 1768);
787 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
788 PushMessage(queue, 254);
789 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
790 PushMessage(queue, 973);
791 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
792
793 int index = 0;
794
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700795 peek_message = static_cast<const TestMessage *>(
796 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700797 message = static_cast<const TestMessage *>(
798 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
799 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700800 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700801 EXPECT_EQ(973, message->data);
802 EXPECT_EQ(4, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700803 queue->FreeMessage(message);
804 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700805
806 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700807 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
808 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700809 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
810 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
811 ASSERT_NE(nullptr, message);
812 EXPECT_EQ(message, peek_message);
813 EXPECT_EQ(973, message->data);
814 EXPECT_EQ(4, index);
815 queue->FreeMessage(message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700816}
817
818TEST_F(RawQueueTest, ReadIndexEvenMoreBehind) {
819 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700820 const TestMessage *message, *peek_message;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700821
822 PushMessage(queue, 971);
823 PushMessage(queue, 1768);
824 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
825 PushMessage(queue, 254);
826 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
827 PushMessage(queue, 973);
828 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
829 PushMessage(queue, 1114);
830
831 int index = 0;
832
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700833 peek_message = static_cast<const TestMessage *>(
834 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700835 message = static_cast<const TestMessage *>(
836 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
837 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700838 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700839 EXPECT_EQ(973, message->data);
840 EXPECT_EQ(4, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700841 queue->FreeMessage(message);
842 queue->FreeMessage(peek_message);
843
844 peek_message = static_cast<const TestMessage *>(
845 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700846 message = static_cast<const TestMessage *>(
847 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
848 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700849 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700850 EXPECT_EQ(1114, message->data);
851 EXPECT_EQ(5, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700852 queue->FreeMessage(message);
853 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700854
855 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700856 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
857 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700858 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
859 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
860 ASSERT_NE(nullptr, message);
861 EXPECT_EQ(message, peek_message);
862 EXPECT_EQ(1114, message->data);
863 EXPECT_EQ(5, index);
864 queue->FreeMessage(message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700865}
866
867TEST_F(RawQueueTest, ReadIndexEvenMoreBehindNotFull) {
868 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700869 const TestMessage *message, *peek_message;
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700870
871 PushMessage(queue, 971);
872 PushMessage(queue, 1768);
873 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
874 PushMessage(queue, 254);
875 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
876 PushMessage(queue, 973);
877 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
878 PushMessage(queue, 1114);
879 ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
880
881 int index = 0;
882
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700883 peek_message = static_cast<const TestMessage *>(
884 queue->ReadMessageIndex(RawQueue::kNonBlock | RawQueue::kPeek, &index));
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700885 message = static_cast<const TestMessage *>(
886 queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
887 ASSERT_NE(nullptr, message);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700888 EXPECT_EQ(message, peek_message);
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700889 EXPECT_EQ(1114, message->data);
890 EXPECT_EQ(5, index);
Brian Silvermaneb51cbb2014-03-14 22:57:08 -0700891 queue->FreeMessage(message);
892 queue->FreeMessage(peek_message);
Brian Silvermanad290d82014-03-19 17:22:05 -0700893
894 index = 0;
Brian Silverman7faaec72014-05-26 16:25:38 -0700895 peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
896 RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
Brian Silvermanad290d82014-03-19 17:22:05 -0700897 message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
898 RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
899 ASSERT_NE(nullptr, message);
900 EXPECT_EQ(message, peek_message);
901 EXPECT_EQ(1114, message->data);
902 EXPECT_EQ(5, index);
903 queue->FreeMessage(message);
904}
905
906TEST_F(RawQueueTest, MessageReferenceCounts) {
907 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
908 const void *message1, *message2;
909
Brian Silvermanc2e04222014-03-22 12:43:44 -0700910 EXPECT_EQ(0, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanad290d82014-03-19 17:22:05 -0700911 message1 = queue->GetMessage();
912 EXPECT_NE(nullptr, message1);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700913 EXPECT_EQ(1, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanad290d82014-03-19 17:22:05 -0700914 message2 = queue->GetMessage();
915 EXPECT_NE(nullptr, message2);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700916 EXPECT_EQ(2, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanad290d82014-03-19 17:22:05 -0700917 queue->FreeMessage(message1);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700918 EXPECT_EQ(1, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermanad290d82014-03-19 17:22:05 -0700919 queue->FreeMessage(message2);
Brian Silvermanc2e04222014-03-22 12:43:44 -0700920 EXPECT_EQ(0, kExtraMessages + 2 - queue->FreeMessages());
Brian Silvermancd2d84c2014-03-13 23:30:58 -0700921}
922
Brian Silverman35a14fd2014-03-24 16:57:44 -0700923// Tests that writing with kNonBlock fails and frees the message.
924TEST_F(RawQueueTest, WriteDontBlock) {
925 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
926 void *message;
927
928 PushMessage(queue, 971);
929 int free_before = queue->FreeMessages();
930 message = queue->GetMessage();
931 ASSERT_NE(nullptr, message);
932 EXPECT_NE(free_before, queue->FreeMessages());
933 EXPECT_FALSE(queue->WriteMessage(message, RawQueue::kNonBlock));
934 EXPECT_EQ(free_before, queue->FreeMessages());
935}
936
937// Tests that writing with kOverride pushes the last message out of the queue.
938TEST_F(RawQueueTest, WriteOverride) {
939 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
940 TestMessage *message1;
941
942 PushMessage(queue, 971);
943 PushMessage(queue, 1768);
944 int free_before = queue->FreeMessages();
945 message1 = static_cast<TestMessage *>(queue->GetMessage());
946 ASSERT_NE(nullptr, message1);
947 EXPECT_NE(free_before, queue->FreeMessages());
948 message1->data = 254;
949 EXPECT_TRUE(queue->WriteMessage(message1, RawQueue::kOverride));
950 EXPECT_EQ(free_before, queue->FreeMessages());
951
952 const TestMessage *message2;
953 message2 =
954 static_cast<const TestMessage *>(queue->ReadMessage(RawQueue::kNonBlock));
955 EXPECT_EQ(1768, message2->data);
956 queue->FreeMessage(message2);
957 EXPECT_EQ(free_before + 1, queue->FreeMessages());
958 message2 =
959 static_cast<const TestMessage *>(queue->ReadMessage(RawQueue::kNonBlock));
960 EXPECT_EQ(254, message2->data);
961 queue->FreeMessage(message2);
962 EXPECT_EQ(free_before + 2, queue->FreeMessages());
963}
964
Brian Silverman653491d2014-05-13 16:53:29 -0700965// Makes sure that ThreadSanitizer doesn't catch any issues freeing from
966// multiple threads at once.
967TEST_F(RawQueueTest, MultiThreadedFree) {
968 RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
969 PushMessage(queue, 971);
970 int free_before = queue->FreeMessages();
971
Brian Silverman7faaec72014-05-26 16:25:38 -0700972 const void *const message1 =
973 queue->ReadMessage(RawQueue::kPeek | RawQueue::kNonBlock);
974 const void *const message2 =
975 queue->ReadMessage(RawQueue::kPeek | RawQueue::kNonBlock);
976 ASSERT_NE(nullptr, message1);
977 ASSERT_NE(nullptr, message2);
Brian Silverman653491d2014-05-13 16:53:29 -0700978 EXPECT_EQ(free_before, queue->FreeMessages());
979 util::FunctionThread t1([message1, queue](util::Thread *) {
980 queue->FreeMessage(message1);
981 });
982 util::FunctionThread t2([message2, queue](util::Thread *) {
983 queue->FreeMessage(message2);
984 });
985 t1.Start();
986 t2.Start();
987 t1.WaitUntilDone();
988 t2.WaitUntilDone();
989 EXPECT_EQ(free_before, queue->FreeMessages());
990}
991
Brian Silverman7faaec72014-05-26 16:25:38 -0700992TEST_F(RawQueueDeathTest, OptionsValidation) {
993 RawQueue *const queue = RawQueue::Fetch("Queue", 1, 1, 1);
994
995 EXPECT_DEATH(
996 {
Tyler Chatow4b471e12020-01-05 20:19:36 -0800997 logging::SetImplementation(new util::DeathTestLogImplementation());
Brian Silverman7faaec72014-05-26 16:25:38 -0700998 queue->WriteMessage(nullptr, RawQueue::kPeek);
999 },
1000 ".*illegal write option.*");
1001 EXPECT_DEATH(
1002 {
Tyler Chatow4b471e12020-01-05 20:19:36 -08001003 logging::SetImplementation(new util::DeathTestLogImplementation());
Brian Silverman7faaec72014-05-26 16:25:38 -07001004 queue->WriteMessage(nullptr, RawQueue::kFromEnd);
1005 },
1006 ".*illegal write option.*");
1007 EXPECT_DEATH(
1008 {
Tyler Chatow4b471e12020-01-05 20:19:36 -08001009 logging::SetImplementation(new util::DeathTestLogImplementation());
Brian Silverman7faaec72014-05-26 16:25:38 -07001010 queue->WriteMessage(nullptr, RawQueue::kPeek | RawQueue::kFromEnd);
1011 },
1012 ".*illegal write option.*");
1013 EXPECT_DEATH(
1014 {
Tyler Chatow4b471e12020-01-05 20:19:36 -08001015 logging::SetImplementation(new util::DeathTestLogImplementation());
Brian Silverman7faaec72014-05-26 16:25:38 -07001016 queue->WriteMessage(nullptr, RawQueue::kNonBlock | RawQueue::kBlock);
1017 },
1018 ".*invalid write option.*");
1019
1020 EXPECT_DEATH(
1021 {
Tyler Chatow4b471e12020-01-05 20:19:36 -08001022 logging::SetImplementation(new util::DeathTestLogImplementation());
Brian Silverman7faaec72014-05-26 16:25:38 -07001023 queue->ReadMessageIndex(
1024 RawQueue::kBlock | RawQueue::kFromEnd | RawQueue::kPeek, nullptr);
1025 },
1026 ".*ReadMessageIndex.*is not allowed.*");
1027 EXPECT_DEATH(
1028 {
Tyler Chatow4b471e12020-01-05 20:19:36 -08001029 logging::SetImplementation(new util::DeathTestLogImplementation());
Brian Silverman7faaec72014-05-26 16:25:38 -07001030 queue->ReadMessageIndex(RawQueue::kOverride, nullptr);
1031 },
1032 ".*illegal read option.*");
1033 EXPECT_DEATH(
1034 {
Tyler Chatow4b471e12020-01-05 20:19:36 -08001035 logging::SetImplementation(new util::DeathTestLogImplementation());
Brian Silverman7faaec72014-05-26 16:25:38 -07001036 queue->ReadMessageIndex(RawQueue::kOverride | RawQueue::kBlock,
1037 nullptr);
1038 },
1039 ".*illegal read option.*");
1040 EXPECT_DEATH(
1041 {
Tyler Chatow4b471e12020-01-05 20:19:36 -08001042 logging::SetImplementation(new util::DeathTestLogImplementation());
Brian Silverman7faaec72014-05-26 16:25:38 -07001043 queue->ReadMessage(RawQueue::kNonBlock | RawQueue::kBlock);
1044 },
1045 ".*invalid read option.*");
1046}
1047
Brian Silvermana6d1b562013-09-01 14:39:39 -07001048} // namespace testing
1049} // namespace aos