make queue_testutils logging thread-safe and test it

Change-Id: I0d1ed4831cb3cfde4a172839bcc1f2b02756f5f3
diff --git a/aos/build/aos_all.gyp b/aos/build/aos_all.gyp
index 4d28c5c..10d5a5b 100644
--- a/aos/build/aos_all.gyp
+++ b/aos/build/aos_all.gyp
@@ -35,6 +35,7 @@
         '<(AOS)/common/common.gyp:condition_test',
         '<(AOS)/common/common.gyp:once_test',
         '<(AOS)/common/common.gyp:event_test',
+        '<(AOS)/common/common.gyp:queue_testutils_test',
         '<(AOS)/common/logging/logging.gyp:logging_impl_test',
         '<(AOS)/common/util/util.gyp:options_test',
         '<(AOS)/common/common.gyp:queue_test',
diff --git a/aos/common/common.gyp b/aos/common/common.gyp
index f5db470..461200e 100644
--- a/aos/common/common.gyp
+++ b/aos/common/common.gyp
@@ -21,6 +21,7 @@
         '<(AOS)/build/aos.gyp:logging',
         'once',
         '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:shared_mem',
+        'mutex',
       ],
       'export_dependent_settings': [
         '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:shared_mem',
@@ -244,11 +245,9 @@
       'dependencies': [
         '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:aos_sync',
         '<(AOS)/build/aos.gyp:logging_interface',
-        'die',
       ],
       'export_dependent_settings': [
         '<(AOS)/linux_code/ipc_lib/ipc_lib.gyp:aos_sync',
-        'die',
       ],
     },
     {
@@ -266,6 +265,18 @@
       ],
     },
     {
+      'target_name': 'queue_testutils_test',
+      'type': 'executable',
+      'sources': [
+        'queue_testutils_test.cc',
+      ],
+      'dependencies': [
+        '<(EXTERNALS):gtest',
+        'queue_testutils',
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+    },
+    {
       'target_name': 'mutex_test',
       'type': 'executable',
       'sources': [
diff --git a/aos/common/queue_testutils.cc b/aos/common/queue_testutils.cc
index d71d023..a40b5e9 100644
--- a/aos/common/queue_testutils.cc
+++ b/aos/common/queue_testutils.cc
@@ -10,6 +10,7 @@
 #include "aos/common/queue.h"
 #include "aos/common/logging/logging_impl.h"
 #include "aos/common/once.h"
+#include "aos/common/mutex.h"
 
 using ::aos::logging::LogMessage;
 
@@ -31,11 +32,13 @@
 
   // Clears out all of the messages already recorded.
   void ClearMessages() {
+    ::aos::MutexLocker locker(&messages_mutex_);
     messages_.clear();
   }
 
   // Prints out all of the messages (like when a test fails).
   void PrintAllMessages() {
+    ::aos::MutexLocker locker(&messages_mutex_);
     for (auto it = messages_.begin(); it != messages_.end(); ++it) {
       logging::internal::PrintMessage(stdout, *it);
     }
@@ -66,6 +69,7 @@
   }
 
   virtual void HandleMessage(const LogMessage &message) override {
+    ::aos::MutexLocker locker(&messages_mutex_);
     if (message.level == FATAL || print_as_messages_come_in_) {
       logging::internal::PrintMessage(output_file_, message);
     }
@@ -76,6 +80,7 @@
   ::std::vector<LogMessage> messages_;
   bool print_as_messages_come_in_ = false;
   FILE *output_file_ = stdout;
+  ::aos::Mutex messages_mutex_;
 };
 
 class MyTestEventListener : public ::testing::EmptyTestEventListener {
diff --git a/aos/common/queue_testutils_test.cc b/aos/common/queue_testutils_test.cc
new file mode 100644
index 0000000..2defe74
--- /dev/null
+++ b/aos/common/queue_testutils_test.cc
@@ -0,0 +1,31 @@
+#include "aos/common/queue_testutils.h"
+
+#include <thread>
+
+#include "gtest/gtest.h"
+
+#include "aos/common/logging/logging.h"
+
+namespace aos {
+namespace common {
+namespace testing {
+
+// Tests logging from multiple threads.
+// tsan used to complain about this.
+TEST(QueueTestutilsTest, MultithreadedLog) {
+  EnableTestLogging();
+
+  ::std::thread thread([]() {
+    for (int i = 0; i < 1000; ++i) {
+      LOG(INFO, "test from thread\n");
+    }
+  });
+  for (int i = 0; i < 1000; ++i) {
+    LOG(INFO, "not from thread\n");
+  }
+  thread.join();
+}
+
+}  // namespace testing
+}  // namespace common
+}  // namespace aos