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(¬ify_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