Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(202)

Side by Side Diff: base/debug/activity_analyzer_unittest.cc

Issue 1980743002: Track thread activities in order to diagnose hangs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@readwrite-mmf
Patch Set: rebased Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/debug/activity_analyzer.cc ('k') | base/debug/activity_tracker.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 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 "base/debug/activity_analyzer.h"
6
7 #include <memory>
8
9 #include "base/bind.h"
10 #include "base/debug/activity_tracker.h"
11 #include "base/files/file.h"
12 #include "base/files/file_util.h"
13 #include "base/files/memory_mapped_file.h"
14 #include "base/files/scoped_temp_dir.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/pending_task.h"
17 #include "base/process/process.h"
18 #include "base/synchronization/condition_variable.h"
19 #include "base/synchronization/lock.h"
20 #include "base/synchronization/spin_wait.h"
21 #include "base/threading/platform_thread.h"
22 #include "base/threading/simple_thread.h"
23 #include "base/time/time.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 namespace base {
27 namespace debug {
28
29 namespace {
30
31 class TestActivityTracker : public ThreadActivityTracker {
32 public:
33 TestActivityTracker(std::unique_ptr<char[]> memory, size_t mem_size)
34 : ThreadActivityTracker(memset(memory.get(), 0, mem_size), mem_size),
35 mem_segment_(std::move(memory)) {}
36
37 ~TestActivityTracker() override {}
38
39 private:
40 std::unique_ptr<char[]> mem_segment_;
41 };
42
43 } // namespace
44
45
46 class ActivityAnalyzerTest : public testing::Test {
47 public:
48 const int kMemorySize = 1 << 10; // 1MiB
49 const int kStackSize = 1 << 10; // 1KiB
50
51 using Activity = ThreadActivityAnalyzer::Activity;
52
53 ActivityAnalyzerTest() {}
54
55 ~ActivityAnalyzerTest() override {
56 GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get();
57 if (global_tracker) {
58 global_tracker->ReleaseTrackerForCurrentThreadForTesting();
59 delete global_tracker;
60 }
61 }
62
63 std::unique_ptr<ThreadActivityTracker> CreateActivityTracker() {
64 std::unique_ptr<char[]> memory(new char[kStackSize]);
65 return WrapUnique(new TestActivityTracker(std::move(memory), kStackSize));
66 }
67
68 static void DoNothing() {}
69 };
70
71 TEST_F(ActivityAnalyzerTest, ThreadAnalyzerConstruction) {
72 std::unique_ptr<ThreadActivityTracker> tracker = CreateActivityTracker();
73 {
74 ThreadActivityAnalyzer analyzer(*tracker);
75 EXPECT_TRUE(analyzer.IsValid());
76 EXPECT_EQ(PlatformThread::GetName(), analyzer.GetThreadName());
77 }
78
79 // TODO(bcwhite): More tests once Analyzer does more.
80 }
81
82
83 // GlobalActivityAnalyzer tests below.
84
85 class SimpleActivityThread : public SimpleThread {
86 public:
87 SimpleActivityThread(const std::string& name,
88 const void* source,
89 ThreadActivityTracker::ActivityType activity,
90 const ThreadActivityTracker::ActivityData& data)
91 : SimpleThread(name, Options()),
92 source_(source),
93 activity_(activity),
94 data_(data),
95 exit_condition_(&lock_) {}
96
97 ~SimpleActivityThread() override {}
98
99 void Run() override {
100 GlobalActivityTracker::Get()
101 ->GetOrCreateTrackerForCurrentThread()
102 ->PushActivity(source_, activity_, data_);
103
104 {
105 AutoLock auto_lock(lock_);
106 ready_ = true;
107 while (!exit_)
108 exit_condition_.Wait();
109 }
110
111 GlobalActivityTracker::Get()
112 ->GetOrCreateTrackerForCurrentThread()
113 ->PopActivity();
114 }
115
116 void Exit() {
117 AutoLock auto_lock(lock_);
118 exit_ = true;
119 exit_condition_.Signal();
120 }
121
122 void WaitReady() {
123 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(ready_);
124 }
125
126 private:
127 const void* source_;
128 ThreadActivityTracker::ActivityType activity_;
129 ThreadActivityTracker::ActivityData data_;
130
131 bool ready_ = false;
132 bool exit_ = false;
133 Lock lock_;
134 ConditionVariable exit_condition_;
135
136 DISALLOW_COPY_AND_ASSIGN(SimpleActivityThread);
137 };
138
139 TEST_F(ActivityAnalyzerTest, GlobalAnalyzerConstruction) {
140 GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3);
141
142 PersistentMemoryAllocator* allocator =
143 GlobalActivityTracker::Get()->allocator();
144 GlobalActivityAnalyzer analyzer(WrapUnique(
145 new PersistentMemoryAllocator(const_cast<void*>(allocator->data()),
146 allocator->size(), 0, 0, "", true)));
147
148 // The only thread at thois point is the test thread.
149 ThreadActivityAnalyzer* ta1 = analyzer.GetFirstAnalyzer();
150 ASSERT_TRUE(ta1);
151 EXPECT_FALSE(analyzer.GetNextAnalyzer());
152 ThreadActivityAnalyzer::ThreadKey tk1 = ta1->GetThreadKey();
153 EXPECT_EQ(ta1, analyzer.GetAnalyzerForThread(tk1));
154
155 // Create a second thread that will do something.
156 SimpleActivityThread t2("t2", nullptr, ThreadActivityTracker::ACT_TASK,
157 ThreadActivityTracker::ActivityData::ForTask(11));
158 t2.Start();
159 t2.WaitReady();
160
161 // Now there should be two.
162 EXPECT_TRUE(analyzer.GetFirstAnalyzer());
163 EXPECT_TRUE(analyzer.GetNextAnalyzer());
164 EXPECT_FALSE(analyzer.GetNextAnalyzer());
165
166 // Let thread exit.
167 t2.Exit();
168 t2.Join();
169
170 // Now there should be only one again. Calling GetFirstAnalyzer invalidates
171 // any previously returned analyzer pointers.
172 ThreadActivityAnalyzer* ta2 = analyzer.GetFirstAnalyzer();
173 ASSERT_TRUE(ta2);
174 EXPECT_FALSE(analyzer.GetNextAnalyzer());
175 ThreadActivityAnalyzer::ThreadKey tk2 = ta2->GetThreadKey();
176 EXPECT_EQ(ta2, analyzer.GetAnalyzerForThread(tk2));
177 EXPECT_EQ(tk1, tk2);
178 }
179
180 } // namespace debug
181 } // namespace base
OLDNEW
« no previous file with comments | « base/debug/activity_analyzer.cc ('k') | base/debug/activity_tracker.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698