Home | History | Annotate | Download | only in cygprofile
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "tools/cygprofile/cygprofile.h"
      6 
      7 #include <vector>
      8 
      9 #include <sys/time.h>
     10 
     11 #include "base/bind.h"
     12 #include "base/callback.h"
     13 #include "base/logging.h"
     14 #include "base/synchronization/waitable_event.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 
     17 namespace cygprofile {
     18 namespace {
     19 
     20 void FlushEntries(std::vector<LogEntry>* destination,
     21                   std::vector<LogEntry>* entries) {
     22   CHECK_EQ(0U, destination->size());
     23   // Move the provided |entries| vector to the provided |destination| so that
     24   // the unit test that triggered the flush can check it.
     25   destination->swap(*entries);
     26 }
     27 
     28 // Flush callback that should not be invoked.
     29 void CheckFlushDoesNotHappen(std::vector<LogEntry>* entries) {
     30   NOTREACHED();
     31 }
     32 
     33 uint64_t GetUsecSecTimeFromTimeSpec(struct timespec timespec) {
     34   return timespec.tv_sec * 1000 * 1000 + timespec.tv_nsec / 1000;
     35 }
     36 
     37 TEST(CygprofileTest, ThreadLogBasic) {
     38   ThreadLog thread_log(base::Bind(&CheckFlushDoesNotHappen));
     39 
     40   thread_log.AddEntry(reinterpret_cast<void*>(0x2));
     41   thread_log.AddEntry(reinterpret_cast<void*>(0x1));
     42 
     43   std::vector<LogEntry> entries;
     44   thread_log.TakeEntries(&entries);
     45 
     46   ASSERT_EQ(2U, entries.size());
     47   // The entries should appear in their insertion order.
     48   const LogEntry& first_entry = entries[0];
     49   ASSERT_EQ(reinterpret_cast<int>(first_entry.address), 2);
     50   ASSERT_EQ(getpid(), first_entry.pid);
     51   ASSERT_LT(0, first_entry.tid);
     52 
     53   const LogEntry& second_entry = entries[1];
     54   ASSERT_EQ(1, reinterpret_cast<int>(second_entry.address));
     55   ASSERT_EQ(first_entry.pid, second_entry.pid);
     56   ASSERT_EQ(first_entry.tid, second_entry.tid);
     57 
     58   ASSERT_GE(GetUsecSecTimeFromTimeSpec(second_entry.time),
     59             GetUsecSecTimeFromTimeSpec(first_entry.time));
     60 }
     61 
     62 TEST(CygprofileTest, ManagerBasic) {
     63   base::WaitableEvent wait_event(true, false);
     64   base::WaitableEvent notify_event(true, false);
     65 
     66   ThreadLogsManager manager(
     67       base::Bind(&base::WaitableEvent::Wait, base::Unretained(&wait_event)),
     68       base::Bind(&base::WaitableEvent::Signal,
     69                  base::Unretained(&notify_event)));
     70 
     71   std::vector<LogEntry> entries;
     72   scoped_ptr<ThreadLog> thread_log(
     73       new ThreadLog(base::Bind(&FlushEntries, base::Unretained(&entries))));
     74 
     75   thread_log->AddEntry(reinterpret_cast<void*>(0x2));
     76   thread_log->AddEntry(reinterpret_cast<void*>(0x3));
     77 
     78   // This should make the manager spawn its internal flush thread which will
     79   // wait for a notification before it starts doing some work.
     80   manager.AddLog(thread_log.Pass());
     81 
     82   EXPECT_EQ(0U, entries.size());
     83   // This will wake up the internal thread.
     84   wait_event.Signal();
     85   // Now it's our turn to wait until it performed the flush.
     86   notify_event.Wait();
     87 
     88   // The flush should have moved the data to the local vector of entries.
     89   EXPECT_EQ(2U, entries.size());
     90   ASSERT_EQ(2, reinterpret_cast<int>(entries[0].address));
     91   ASSERT_EQ(3, reinterpret_cast<int>(entries[1].address));
     92 }
     93 
     94 }  // namespace
     95 }  // namespace cygprofile
     96 
     97 // Custom runner implementation since base's one requires JNI on Android.
     98 int main(int argc, char** argv) {
     99   testing::InitGoogleTest(&argc, argv);
    100   return RUN_ALL_TESTS();
    101 }
    102