146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// found in the LICENSE file. 446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "tools/cygprofile/cygprofile.h" 646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include <vector> 846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include <sys/time.h> 1046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 1146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/bind.h" 1246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/callback.h" 1346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/logging.h" 1446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/synchronization/waitable_event.h" 1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 1746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace cygprofile { 1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace { 1946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void FlushEntries(std::vector<LogEntry>* destination, 2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::vector<LogEntry>* entries) { 2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) CHECK_EQ(0U, destination->size()); 2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Move the provided |entries| vector to the provided |destination| so that 2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // the unit test that triggered the flush can check it. 2546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) destination->swap(*entries); 2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Flush callback that should not be invoked. 2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void CheckFlushDoesNotHappen(std::vector<LogEntry>* entries) { 3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) NOTREACHED(); 3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)uint64_t GetUsecSecTimeFromTimeSpec(struct timespec timespec) { 3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return timespec.tv_sec * 1000 * 1000 + timespec.tv_nsec / 1000; 3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST(CygprofileTest, ThreadLogBasic) { 3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ThreadLog thread_log(base::Bind(&CheckFlushDoesNotHappen)); 3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) thread_log.AddEntry(reinterpret_cast<void*>(0x2)); 4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) thread_log.AddEntry(reinterpret_cast<void*>(0x1)); 4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::vector<LogEntry> entries; 4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) thread_log.TakeEntries(&entries); 4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ASSERT_EQ(2U, entries.size()); 4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // The entries should appear in their insertion order. 4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const LogEntry& first_entry = entries[0]; 4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ASSERT_EQ(reinterpret_cast<int>(first_entry.address), 2); 5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ASSERT_EQ(getpid(), first_entry.pid); 5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ASSERT_LT(0, first_entry.tid); 5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const LogEntry& second_entry = entries[1]; 5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ASSERT_EQ(1, reinterpret_cast<int>(second_entry.address)); 5546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ASSERT_EQ(first_entry.pid, second_entry.pid); 5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ASSERT_EQ(first_entry.tid, second_entry.tid); 5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ASSERT_GE(GetUsecSecTimeFromTimeSpec(second_entry.time), 5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) GetUsecSecTimeFromTimeSpec(first_entry.time)); 6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST(CygprofileTest, ManagerBasic) { 6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::WaitableEvent wait_event(true, false); 6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::WaitableEvent notify_event(true, false); 6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ThreadLogsManager manager( 6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&base::WaitableEvent::Wait, base::Unretained(&wait_event)), 6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&base::WaitableEvent::Signal, 6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Unretained(¬ify_event))); 7046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::vector<LogEntry> entries; 7246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<ThreadLog> thread_log( 7346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new ThreadLog(base::Bind(&FlushEntries, base::Unretained(&entries)))); 7446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 7546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) thread_log->AddEntry(reinterpret_cast<void*>(0x2)); 7646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) thread_log->AddEntry(reinterpret_cast<void*>(0x3)); 7746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 7846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // This should make the manager spawn its internal flush thread which will 7946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // wait for a notification before it starts doing some work. 8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) manager.AddLog(thread_log.Pass()); 8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(0U, entries.size()); 8346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // This will wake up the internal thread. 8446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) wait_event.Signal(); 8546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Now it's our turn to wait until it performed the flush. 8646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) notify_event.Wait(); 8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // The flush should have moved the data to the local vector of entries. 8946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_EQ(2U, entries.size()); 9046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ASSERT_EQ(2, reinterpret_cast<int>(entries[0].address)); 9146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ASSERT_EQ(3, reinterpret_cast<int>(entries[1].address)); 9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 9346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 9446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} // namespace 9546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} // namespace cygprofile 9646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 9746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Custom runner implementation since base's one requires JNI on Android. 9846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)int main(int argc, char** argv) { 9946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) testing::InitGoogleTest(&argc, argv); 10046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return RUN_ALL_TESTS(); 10146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 102