fixed more bugginess with ReadMessageIndex and added tests for it
diff --git a/aos/linux_code/ipc_lib/ipc_lib.gyp b/aos/linux_code/ipc_lib/ipc_lib.gyp
index 08e8df8..fe8b2e0 100644
--- a/aos/linux_code/ipc_lib/ipc_lib.gyp
+++ b/aos/linux_code/ipc_lib/ipc_lib.gyp
@@ -51,7 +51,7 @@
       'target_name': 'raw_queue_test',
       'type': 'executable',
       'sources': [
-        'queue_test.cc',
+        'raw_queue_test.cc',
       ],
       'dependencies': [
         '<(EXTERNALS):gtest',
diff --git a/aos/linux_code/ipc_lib/queue_test.cc b/aos/linux_code/ipc_lib/raw_queue_test.cc
similarity index 85%
rename from aos/linux_code/ipc_lib/queue_test.cc
rename to aos/linux_code/ipc_lib/raw_queue_test.cc
index d05b20a..2ba1df0 100644
--- a/aos/linux_code/ipc_lib/queue_test.cc
+++ b/aos/linux_code/ipc_lib/raw_queue_test.cc
@@ -25,7 +25,7 @@
 namespace aos {
 namespace testing {
 
-class QueueTest : public ::testing::Test {
+class RawQueueTest : public ::testing::Test {
  protected:
   static const size_t kFailureSize = 400;
   static char *fatal_failure;
@@ -297,15 +297,22 @@
     }
   }
 
+  void PushMessage(RawQueue *queue, uint16_t data) {
+    TestMessage *message = static_cast<TestMessage *>(queue->GetMessage());
+    message->data = data;
+    ASSERT_TRUE(queue->WriteMessage(message, RawQueue::kNonBlock));
+  }
+
  private:
   GlobalCoreInstance my_core;
 };
-char *QueueTest::fatal_failure;
-std::map<QueueTest::ChildID, QueueTest::ForkedProcess *> QueueTest::children_;
-constexpr time::Time QueueTest::kHangTime;
-constexpr time::Time QueueTest::kForkSleep;
+char *RawQueueTest::fatal_failure;
+std::map<RawQueueTest::ChildID, RawQueueTest::ForkedProcess *>
+    RawQueueTest::children_;
+constexpr time::Time RawQueueTest::kHangTime;
+constexpr time::Time RawQueueTest::kForkSleep;
 
-TEST_F(QueueTest, Reading) {
+TEST_F(RawQueueTest, Reading) {
   RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
   MessageArgs args{queue, 0, -1};
 
@@ -337,7 +344,7 @@
   args.data = 971;
   EXPECT_RETURNS_FAILS(ReadTestMessage, &args);
 }
-TEST_F(QueueTest, Writing) {
+TEST_F(RawQueueTest, Writing) {
   RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
   MessageArgs args{queue, 0, 973};
 
@@ -368,7 +375,7 @@
   EXPECT_RETURNS(ReadTestMessage, &args);
 }
 
-TEST_F(QueueTest, MultiRead) {
+TEST_F(RawQueueTest, MultiRead) {
   RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
   MessageArgs args{queue, 0, 1323};
 
@@ -383,7 +390,7 @@
 
 // There used to be a bug where reading first without an index and then with an
 // index would crash. This test makes sure that's fixed.
-TEST_F(QueueTest, ReadIndexAndNot) {
+TEST_F(RawQueueTest, ReadIndexAndNot) {
   RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
 
   // Write a message, read it (with ReadMessage), and then write another
@@ -406,7 +413,7 @@
       << "We already took that message out of the queue.";
 }
 
-TEST_F(QueueTest, Recycle) {
+TEST_F(RawQueueTest, Recycle) {
   // TODO(brians) basic test of recycle queue
   // include all of the ways a message can get into the recycle queue
   RawQueue *recycle_queue = reinterpret_cast<RawQueue *>(23);
@@ -451,7 +458,7 @@
 
 // Makes sure that when a message doesn't get written with kNonBlock it does get
 // freed.
-TEST_F(QueueTest, NonBlockFailFree) {
+TEST_F(RawQueueTest, NonBlockFailFree) {
   RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
 
   void *message1 = queue->GetMessage();
@@ -461,5 +468,67 @@
   EXPECT_EQ(message2, queue->GetMessage());
 }
 
+TEST_F(RawQueueTest, ReadIndexLittleBehind) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
+  const TestMessage *message;
+
+  PushMessage(queue, 971);
+  PushMessage(queue, 1768);
+
+  int index = 0;
+  message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(971, message->data);
+}
+
+TEST_F(RawQueueTest, ReadIndexMoreBehind) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
+  const TestMessage *message;
+
+  PushMessage(queue, 971);
+  PushMessage(queue, 1768);
+  ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
+  PushMessage(queue, 254);
+
+  int index = 0;
+
+  message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(1768, message->data);
+  EXPECT_EQ(2, index);
+  message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(254, message->data);
+  EXPECT_EQ(3, index);
+}
+
+TEST_F(RawQueueTest, ReadIndexLotBehind) {
+  RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 2);
+  const TestMessage *message;
+
+  PushMessage(queue, 971);
+  PushMessage(queue, 1768);
+  ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
+  PushMessage(queue, 254);
+  ASSERT_NE(nullptr, queue->ReadMessage(RawQueue::kNonBlock));
+  PushMessage(queue, 973);
+
+  int index = 0;
+
+  message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(254, message->data);
+  EXPECT_EQ(3, index);
+  message = static_cast<const TestMessage *>(
+      queue->ReadMessageIndex(RawQueue::kNonBlock, &index));
+  ASSERT_NE(nullptr, message);
+  EXPECT_EQ(973, message->data);
+  EXPECT_EQ(4, index);
+}
+
 }  // namespace testing
 }  // namespace aos