copied everything over from 2012 and removed all of the actual robot code except the drivetrain stuff


git-svn-id: https://robotics.mvla.net/svn/frc971/2013/trunk/src@4078 f308d9b7-e957-4cde-b6ac-9a88185e7312
diff --git a/aos/common/queue_test.cc b/aos/common/queue_test.cc
new file mode 100644
index 0000000..b24fcd5
--- /dev/null
+++ b/aos/common/queue_test.cc
@@ -0,0 +1,327 @@
+#include <unistd.h>
+
+#include <memory>
+
+#include "gtest/gtest.h"
+#include "aos/common/test_queue.q.h"
+#include "aos/common/queue_testutils.h"
+
+
+using ::aos::time::Time;
+
+namespace aos {
+namespace common {
+
+// TODO(aschuh): Pull this out somewhere and test it.
+class Thread {
+ public:
+  Thread () {
+    started_ = false;
+    joined_ = false;
+  }
+
+  ~Thread() {
+    if (!joined_ && started_) {
+      assert(false);
+    }
+  }
+
+  void Start() {
+    assert(!started_);
+    pthread_create(&thread_, NULL, &Thread::StaticRun, this);
+    started_ = true;
+  }
+
+  virtual void Run() = 0;
+
+  void Join() {
+    assert(!joined_);
+    pthread_join(thread_, NULL);
+    joined_ = true;
+  }
+ private:
+  static void *StaticRun(void *thread_class) {
+    static_cast<Thread *>(thread_class)->Run();
+    return NULL;
+  }
+
+  pthread_t thread_;
+  bool started_;
+  bool joined_;
+
+  DISALLOW_COPY_AND_ASSIGN(Thread);
+};
+
+namespace testing {
+
+class QueueTest : public ::testing::Test {
+ protected:
+  GlobalCoreInstance my_core;
+  // Create a new instance of the test queue so that it invalidates the queue
+  // that it points to.  Otherwise, we will have a pointer to shared memory that
+  // is no longer valid.
+  ::aos::Queue<TestingMessage> my_test_queue;
+
+  QueueTest() : my_test_queue(".aos.common.testing.test_queue") {}
+};
+
+class MyThread : public Thread {
+ public:
+  MyThread() : threaded_test_queue(".aos.common.testing.test_queue") {}
+
+  virtual void Run() {
+    ASSERT_TRUE(threaded_test_queue.FetchNextBlocking());
+    EXPECT_TRUE(threaded_test_queue->test_bool);
+    EXPECT_EQ(0x971, threaded_test_queue->test_int);
+  }
+
+  ::aos::Queue<TestingMessage> threaded_test_queue;
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MyThread);
+};
+
+
+// Tests that we can send a message to another thread and it blocking receives
+// it at the correct time.
+TEST_F(QueueTest, FetchBlocking) {
+  MyThread t;
+  t.Start();
+  usleep(50000);
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
+  t.Join();
+  EXPECT_EQ(true, t.threaded_test_queue.IsNewerThanMS(20));
+}
+
+// Tests that we can send a message with the message pointer and get it back.
+TEST_F(QueueTest, SendMessage) {
+  ScopedMessagePtr<TestingMessage> msg = my_test_queue.MakeMessage();
+  msg->test_bool = true;
+  msg->test_int = 0x971;
+  msg.Send();
+
+  ASSERT_TRUE(my_test_queue.FetchLatest());
+  EXPECT_TRUE(my_test_queue->test_bool);
+  EXPECT_EQ(0x971, my_test_queue->test_int);
+}
+
+// Tests that we can send a message with the message pointer and get it back.
+TEST_F(QueueTest, SendMessageBlockingSafe) {
+  SafeScopedMessagePtr<TestingMessage> msg = my_test_queue.SafeMakeMessage();
+  msg->test_bool = true;
+  msg->test_int = 0x971;
+  ASSERT_TRUE(msg.SendBlocking());
+
+  ASSERT_TRUE(my_test_queue.FetchLatest());
+  EXPECT_TRUE(my_test_queue->test_bool);
+  EXPECT_EQ(0x971, my_test_queue->test_int);
+}
+
+// Tests that we can send a message with the message pointer and get it back.
+TEST_F(QueueTest, SendMessageSafe) {
+  SafeScopedMessagePtr<TestingMessage> msg = my_test_queue.SafeMakeMessage();
+  msg->test_bool = true;
+  msg->test_int = 0x971;
+  msg.Send();
+
+  ASSERT_TRUE(my_test_queue.FetchLatest());
+  EXPECT_TRUE(my_test_queue->test_bool);
+  EXPECT_EQ(0x971, my_test_queue->test_int);
+}
+
+// Tests that we can send a message with the builder and get it back.
+TEST_F(QueueTest, SendWithBuilder) {
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
+
+  ASSERT_TRUE(my_test_queue.FetchLatest());
+  EXPECT_EQ(true, my_test_queue->test_bool);
+  EXPECT_EQ(0x971, my_test_queue->test_int);
+  EXPECT_EQ(true, my_test_queue.IsNewerThanMS(10000));
+}
+
+// Tests that various pointer deref functions at least seem to work.
+TEST_F(QueueTest, PointerDeref) {
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
+
+  ASSERT_TRUE(my_test_queue.FetchLatest());
+  const TestingMessage *msg_ptr = my_test_queue.get();
+  ASSERT_NE(static_cast<TestingMessage*>(NULL), msg_ptr);
+  EXPECT_EQ(0x971, msg_ptr->test_int);
+  EXPECT_EQ(msg_ptr, &(*my_test_queue));
+}
+
+// Tests that FetchNext doesn't miss any messages.
+TEST_F(QueueTest, FetchNext) {
+  for (int i = 0; i < 10; ++i) {
+    my_test_queue.MakeWithBuilder().test_bool(true).test_int(i).Send();
+  }
+
+  for (int i = 0; i < 10; ++i) {
+    ASSERT_TRUE(my_test_queue.FetchNext());
+    EXPECT_EQ(i, my_test_queue->test_int);
+  }
+}
+
+// Tests that FetchLatest skips a missing message.
+TEST_F(QueueTest, FetchLatest) {
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x254).Send();
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
+
+  ASSERT_TRUE(my_test_queue.FetchLatest());
+  EXPECT_EQ(0x971, my_test_queue->test_int);
+}
+
+// Tests that FetchLatest works with multiple readers.
+TEST_F(QueueTest, FetchLatestMultiple) {
+  ::aos::Queue<TestingMessage> my_second_test_queue(
+      ".aos.common.testing.test_queue");
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x254).Send();
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
+
+  ASSERT_TRUE(my_test_queue.FetchLatest());
+  EXPECT_EQ(0x971, my_test_queue->test_int);
+  ASSERT_TRUE(my_second_test_queue.FetchLatest());
+  ASSERT_TRUE(my_second_test_queue.get() != NULL);
+  EXPECT_EQ(0x971, my_second_test_queue->test_int);
+}
+
+
+// Tests that fetching without a new message returns false.
+TEST_F(QueueTest, FetchLatestWithoutMessage) {
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x254).Send();
+  EXPECT_TRUE(my_test_queue.FetchLatest());
+  EXPECT_FALSE(my_test_queue.FetchLatest());
+  EXPECT_FALSE(my_test_queue.FetchLatest());
+  EXPECT_EQ(0x254, my_test_queue->test_int);
+}
+
+// Tests that fetching without a message returns false.
+TEST_F(QueueTest, FetchOnFreshQueue) {
+  EXPECT_FALSE(my_test_queue.FetchLatest());
+  EXPECT_EQ(static_cast<TestingMessage*>(NULL), my_test_queue.get());
+}
+
+// Tests that fetch next without a message returns false.
+TEST_F(QueueTest, FetchNextOnFreshQueue) {
+  EXPECT_FALSE(my_test_queue.FetchNext());
+  EXPECT_EQ(static_cast<TestingMessage*>(NULL), my_test_queue.get());
+}
+
+// Tests that fetch next without a new message returns false.
+TEST_F(QueueTest, FetchNextWithoutMessage) {
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x254).Send();
+  EXPECT_TRUE(my_test_queue.FetchNext());
+  EXPECT_FALSE(my_test_queue.FetchNext());
+  EXPECT_NE(static_cast<TestingMessage*>(NULL), my_test_queue.get());
+}
+
+// Tests that age makes some sense.
+TEST_F(QueueTest, Age) {
+  my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
+
+  ASSERT_TRUE(my_test_queue.FetchLatest());
+  EXPECT_TRUE(my_test_queue.IsNewerThanMS(100));
+  const Time age = my_test_queue.Age();
+  EXPECT_EQ(0, age.sec());
+  EXPECT_GE(100000000, age.nsec());
+}
+
+
+class GroupTest : public ::testing::Test {
+ protected:
+  GlobalCoreInstance my_core;
+  // Create a new instance of the test group so that it invalidates the queue
+  // that it points to.  Otherwise, we will have a pointer to shared memory that
+  // is no longer valid.
+  TwoQueues my_test_queuegroup;
+
+  GroupTest()
+      : my_test_queuegroup(".aos.common.testing.test_queuegroup",
+                           0x20561114,
+                           ".aos.common.testing.test_queuegroup.first",
+                           ".aos.common.testing.test_queuegroup.second") {}
+};
+
+// Tests that the hash gets preserved.
+TEST_F(GroupTest, Hash) {
+  EXPECT_EQ(static_cast<uint32_t>(0x20561114), my_test_queuegroup.hash());
+}
+
+// Tests that the hash works.
+TEST_F(GroupTest, RealHash) {
+  EXPECT_EQ(static_cast<uint32_t>(0x5b25097f), test_queuegroup.hash());
+}
+
+// Tests that name works.
+TEST_F(GroupTest, Name) {
+  EXPECT_EQ(std::string(".aos.common.testing.test_queuegroup"),
+            std::string(my_test_queuegroup.name()));
+}
+
+
+class MessageTest : public ::testing::Test {
+ public:
+  TestingMessage msg;
+};
+
+TEST_F(MessageTest, Zeroing) {
+  msg.test_bool = true;
+  msg.test_int = 0x254;
+  msg.SetTimeToNow();
+
+  msg.Zero();
+
+  EXPECT_FALSE(msg.test_bool);
+  EXPECT_EQ(0, msg.test_int);
+  EXPECT_EQ(0, msg.sent_time.sec());
+  EXPECT_EQ(0, msg.sent_time.nsec());
+}
+
+TEST_F(MessageTest, Size) {
+  EXPECT_EQ(static_cast<size_t>(13), msg.Size());
+}
+
+TEST_F(MessageTest, Serialize) {
+  char serialized_data[msg.Size()];
+  msg.test_bool = true;
+  msg.test_int = 0x254;
+  msg.SetTimeToNow();
+
+  msg.Serialize(serialized_data);
+
+  TestingMessage new_msg;
+  new_msg.Deserialize(serialized_data);
+
+  EXPECT_EQ(msg.test_bool, new_msg.test_bool);
+  EXPECT_EQ(msg.test_int, new_msg.test_int);
+  EXPECT_EQ(msg.sent_time, new_msg.sent_time);
+}
+
+// Tests that Print prints out a message nicely.
+TEST_F(MessageTest, Print) {
+  char printdata[1024];
+  msg.test_bool = true;
+  msg.test_int = 2056;
+  msg.sent_time = Time(971, 254);
+
+  std::string golden("971.000000254s, t, 2056");
+  EXPECT_EQ(golden.size(), msg.Print(printdata, sizeof(printdata)));
+
+  EXPECT_EQ(golden, std::string(printdata));
+}
+
+// Tests that the hash never changes.  If it changes, then someone broke the
+// hash routine or changed the message declaration.  Both changes need to be
+// validated by hand.
+TEST_F(MessageTest, Hash) {
+  EXPECT_EQ(static_cast<uint32_t>(0xcf740cc1),
+            static_cast<uint32_t>(TestingMessage::kHash));
+}
+
+TEST_F(MessageTest, SetNow) {
+  msg.SetTimeToNow();
+  EXPECT_LE(msg.sent_time - Time::Now(), Time::InMS(20));
+}
+
+}  // namespace testing
+}  // namespace common
+}  // namespace aos