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(&notify_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