blob: 03e447b4e3a61026a69beab3d12b97782957e3e0 [file] [log] [blame]
Erik Chen9d81094d2017-11-20 17:40:091// Copyright 2017 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
Erik Chen74cba8c2018-04-16 18:49:495#ifndef COMPONENTS_HEAP_PROFILING_TEST_DRIVER_H_
6#define COMPONENTS_HEAP_PROFILING_TEST_DRIVER_H_
Erik Chen9d81094d2017-11-20 17:40:097
8#include <vector>
9
10#include "base/allocator/partition_allocator/partition_alloc.h"
11#include "base/macros.h"
12#include "base/memory/ref_counted_memory.h"
13#include "base/synchronization/waitable_event.h"
Alexei Filippove48985e2019-02-01 00:27:4114#include "components/services/heap_profiling/public/cpp/settings.h"
Erik Chen74cba8c2018-04-16 18:49:4915#include "components/services/heap_profiling/public/mojom/heap_profiling_client.mojom.h"
Erik Chen9d81094d2017-11-20 17:40:0916
17namespace base {
18class Value;
19} // namespace base
20
erikchen102fe212018-04-06 13:02:1021namespace heap_profiling {
Erik Chen9d81094d2017-11-20 17:40:0922
Erik Chen74cba8c2018-04-16 18:49:4923// This class runs tests for the Heap Profiling Service, a cross-platform,
24// multi-process component.
25//
26// Chrome on Android does not support browser_tests. It does support
27// content_browsertests, but those are not multi-process tests. On Android,
28// processes have to be started via the Activity mechanism, and the test
29// infrastructure does not support this.
Erik Chen9d81094d2017-11-20 17:40:0930//
31// To avoid test-code duplication, all tests are pulled into this class.
32// browser_tests will directly call this class. The android
33// chrome_public_test_apk will invoke this class via a JNI shim. Since the
34// latter is not running within the gtest framework, this class cannot use
35// EXPECT* and ASSERT* macros. Instead, this class will return a bool indicating
36// success of the entire test. On failure, errors will be output via LOG(ERROR).
37// These will show up in the browser_tests output stream, and will be captured
38// by logcat [the Android logging facility]. The latter is already the canonical
39// mechanism for investigating test failures.
40//
41// Note: Outputting to stderr will not have the desired effect, since that is
42// not captured by logcat.
Erik Chen74cba8c2018-04-16 18:49:4943class TestDriver {
Erik Chen9d81094d2017-11-20 17:40:0944 public:
45 struct Options {
46 // The profiling mode to test.
Alexei Filippove48985e2019-02-01 00:27:4147 Mode mode = Mode::kBrowser;
Erik Chen9d81094d2017-11-20 17:40:0948
Erik Chen3303fd0232018-01-11 20:29:0549 // The stack profiling mode to test.
Alexei Filippove48985e2019-02-01 00:27:4150 mojom::StackMode stack_mode = mojom::StackMode::NATIVE_WITHOUT_THREAD_NAMES;
51
52 // Whether the client should stream samples as they are collected through
53 // the provided pipe. When false the samples are accumulated on the client
54 // side and can be retrieved later.
55 bool stream_samples = true;
Erik Chen3303fd0232018-01-11 20:29:0556
Erik Chen9d81094d2017-11-20 17:40:0957 // Whether the caller has already started profiling with the given mode.
erikchen011ad3f2018-01-26 17:54:5558 // When false, the test driver is responsible for starting profiling.
Alexei Filippove48985e2019-02-01 00:27:4159 bool profiling_already_started = false;
erikchen8bc20d82018-02-14 03:21:5160
61 // Whether to test sampling.
Alexei Filippove48985e2019-02-01 00:27:4162 bool should_sample = true;
erikchen8bc20d82018-02-14 03:21:5163
64 // When set to true, the internal sampling_rate is set to 2. While this
65 // doesn't record all allocations, it should record all test allocations
66 // made in this file with exponentially high probability.
67 // When set to false, the internal sampling rate is set to 10000.
Alexei Filippove48985e2019-02-01 00:27:4168 bool sample_everything = false;
Erik Chen9d81094d2017-11-20 17:40:0969 };
70
Erik Chen74cba8c2018-04-16 18:49:4971 TestDriver();
72 ~TestDriver();
Erik Chen9d81094d2017-11-20 17:40:0973
74 // If this is called on the content::BrowserThread::UI thread, then the
75 // platform must support nested message loops. [This is currently not
76 // supported on Android].
77 //
78 // Returns whether the test run was successful. Expectation/Assertion failures
79 // will be printed via LOG(ERROR).
80 bool RunTest(const Options& options);
81
82 private:
Erik Chen74cba8c2018-04-16 18:49:4983 // Populates |has_started_| and then signals |wait_for_ui_thread_|.
84 void GetHasStartedOnUIThread();
85
Erik Chen9d81094d2017-11-20 17:40:0986 // Populates |initialization_success_| with the result of
87 // |RunInitializationOnUIThread|, and then signals |wait_for_ui_thread_|.
Erik Chen3303fd0232018-01-11 20:29:0588 void CheckOrStartProfilingOnUIThreadAndSignal();
Erik Chen9d81094d2017-11-20 17:40:0989
Erik Chen74cba8c2018-04-16 18:49:4990 // Calls Supervisor::SetKeepSmallAllocations() and then signals
91 // |wait_for_ui_thread_|.
92 void SetKeepSmallAllocationsOnUIThreadAndSignal();
93
Erik Chen9d81094d2017-11-20 17:40:0994 // If profiling is expected to already be started, confirm it.
95 // Otherwise, start profiling with the given mode.
Erik Chen06a20b52018-04-17 19:05:3296 // This method must only be called on platforms that supported nested run
97 // loops on the UI thread.
98 bool CheckOrStartProfilingOnUIThreadWithNestedRunLoops();
99
100 // If profiling is expected to already be started, confirm it.
101 // Otherwise, start profiling with the given mode.
102 // This method must only be called on platforms that are running the
103 // TestDriver from a non-UI thread, which allows for async signalling.
104 bool CheckOrStartProfilingOnUIThreadWithAsyncSignalling();
Erik Chen9d81094d2017-11-20 17:40:09105
106 // Performs allocations. These are expected to be profiled.
107 void MakeTestAllocations();
108
109 // Collects a trace that contains a heap dump. The result is stored in
110 // |serialized_trace_|.
111 //
112 // When |synchronous| is true, this method spins a nested message loop. When
113 // |synchronous| is false, this method posts some tasks that will eventually
114 // signal |wait_for_ui_thread_|.
115 void CollectResults(bool synchronous);
116
erikchen872446d2017-11-29 00:34:40117 void TraceFinished(base::Closure closure,
118 bool success,
119 std::string trace_json);
120
Erik Chen9d81094d2017-11-20 17:40:09121 bool ValidateBrowserAllocations(base::Value* dump_json);
122 bool ValidateRendererAllocations(base::Value* dump_json);
123
Erik Chen3303fd0232018-01-11 20:29:05124 bool ShouldProfileBrowser();
erikchenee0a0072018-01-19 21:52:04125 bool ShouldProfileRenderer();
erikchen011ad3f2018-01-26 17:54:55126 bool ShouldIncludeNativeThreadNames();
Erik Chen3303fd0232018-01-11 20:29:05127 bool HasPseudoFrames();
erikchen080ebb12018-03-21 22:21:01128 bool HasNativeFrames();
erikchen8bc20d82018-02-14 03:21:51129 bool IsRecordingAllAllocations();
Erik Chen3303fd0232018-01-11 20:29:05130
erikchenee0a0072018-01-19 21:52:04131 void WaitForProfilingToStartForAllRenderersUIThread();
132
133 // Android does not support nested RunLoops. Instead, it signals
134 // |wait_for_ui_thread_| when finished.
135 void WaitForProfilingToStartForAllRenderersUIThreadAndSignal();
136 void WaitForProfilingToStartForAllRenderersUIThreadCallback(
137 std::vector<base::ProcessId> results);
138
Erik Chen9d81094d2017-11-20 17:40:09139 Options options_;
140
141 // Allocations made by this class. Intentionally leaked, since deallocating
142 // them would trigger a large number of IPCs, which is slow.
143 std::vector<char*> leaks_;
144
145 // Sum of size of all variadic allocations.
146 size_t total_variadic_allocations_ = 0;
147
148 // Use to make PA allocations, which should also be shimmed.
149 base::PartitionAllocatorGeneric partition_allocator_;
150
151 // Contains nothing until |CollectResults| has been called.
erikchen872446d2017-11-29 00:34:40152 std::string serialized_trace_;
Erik Chen9d81094d2017-11-20 17:40:09153
154 // Whether the test was invoked on the ui thread.
155 bool running_on_ui_thread_ = true;
156
Erik Chen74cba8c2018-04-16 18:49:49157 // Whether the supervisor has started.
158 bool has_started_ = false;
159
Erik Chen9d81094d2017-11-20 17:40:09160 // Whether an error has occurred.
161 bool initialization_success_ = false;
162
Erik Chen3303fd0232018-01-11 20:29:05163 // When |true|, initialization will wait for the allocator shim to enable
164 // before continuing.
165 bool wait_for_profiling_to_start_ = false;
166
Erik Chen9d81094d2017-11-20 17:40:09167 base::WaitableEvent wait_for_ui_thread_;
168
Erik Chen74cba8c2018-04-16 18:49:49169 DISALLOW_COPY_AND_ASSIGN(TestDriver);
Erik Chen9d81094d2017-11-20 17:40:09170};
171
erikchen102fe212018-04-06 13:02:10172} // namespace heap_profiling
Erik Chen9d81094d2017-11-20 17:40:09173
Erik Chen74cba8c2018-04-16 18:49:49174#endif // COMPONENTS_HEAP_PROFILING_TEST_DRIVER_H_