blob: 41c812644b47ad718f25ef0c2346b093d446cfcd [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"
James Cook500a245e2019-10-02 19:18:3513#include "base/process/process_handle.h"
Erik Chen9d81094d2017-11-20 17:40:0914#include "base/synchronization/waitable_event.h"
Alexei Filippove48985e2019-02-01 00:27:4115#include "components/services/heap_profiling/public/cpp/settings.h"
Erik Chen74cba8c2018-04-16 18:49:4916#include "components/services/heap_profiling/public/mojom/heap_profiling_client.mojom.h"
Erik Chen9d81094d2017-11-20 17:40:0917
18namespace base {
19class Value;
20} // namespace base
21
erikchen102fe212018-04-06 13:02:1022namespace heap_profiling {
Erik Chen9d81094d2017-11-20 17:40:0923
Erik Chen74cba8c2018-04-16 18:49:4924// This class runs tests for the Heap Profiling Service, a cross-platform,
25// multi-process component.
26//
27// Chrome on Android does not support browser_tests. It does support
28// content_browsertests, but those are not multi-process tests. On Android,
29// processes have to be started via the Activity mechanism, and the test
30// infrastructure does not support this.
Erik Chen9d81094d2017-11-20 17:40:0931//
32// To avoid test-code duplication, all tests are pulled into this class.
33// browser_tests will directly call this class. The android
34// chrome_public_test_apk will invoke this class via a JNI shim. Since the
35// latter is not running within the gtest framework, this class cannot use
36// EXPECT* and ASSERT* macros. Instead, this class will return a bool indicating
37// success of the entire test. On failure, errors will be output via LOG(ERROR).
38// These will show up in the browser_tests output stream, and will be captured
39// by logcat [the Android logging facility]. The latter is already the canonical
40// mechanism for investigating test failures.
41//
42// Note: Outputting to stderr will not have the desired effect, since that is
43// not captured by logcat.
Erik Chen74cba8c2018-04-16 18:49:4944class TestDriver {
Erik Chen9d81094d2017-11-20 17:40:0945 public:
46 struct Options {
47 // The profiling mode to test.
Alexei Filippove48985e2019-02-01 00:27:4148 Mode mode = Mode::kBrowser;
Erik Chen9d81094d2017-11-20 17:40:0949
Erik Chen3303fd0232018-01-11 20:29:0550 // The stack profiling mode to test.
Alexei Filippove48985e2019-02-01 00:27:4151 mojom::StackMode stack_mode = mojom::StackMode::NATIVE_WITHOUT_THREAD_NAMES;
52
Erik Chen9d81094d2017-11-20 17:40:0953 // Whether the caller has already started profiling with the given mode.
erikchen011ad3f2018-01-26 17:54:5554 // When false, the test driver is responsible for starting profiling.
Alexei Filippove48985e2019-02-01 00:27:4155 bool profiling_already_started = false;
Erik Chen9d81094d2017-11-20 17:40:0956 };
57
Erik Chen74cba8c2018-04-16 18:49:4958 TestDriver();
59 ~TestDriver();
Erik Chen9d81094d2017-11-20 17:40:0960
61 // If this is called on the content::BrowserThread::UI thread, then the
62 // platform must support nested message loops. [This is currently not
63 // supported on Android].
64 //
65 // Returns whether the test run was successful. Expectation/Assertion failures
66 // will be printed via LOG(ERROR).
67 bool RunTest(const Options& options);
68
69 private:
Erik Chen74cba8c2018-04-16 18:49:4970 // Populates |has_started_| and then signals |wait_for_ui_thread_|.
71 void GetHasStartedOnUIThread();
72
Erik Chen9d81094d2017-11-20 17:40:0973 // Populates |initialization_success_| with the result of
74 // |RunInitializationOnUIThread|, and then signals |wait_for_ui_thread_|.
Erik Chen3303fd0232018-01-11 20:29:0575 void CheckOrStartProfilingOnUIThreadAndSignal();
Erik Chen9d81094d2017-11-20 17:40:0976
77 // If profiling is expected to already be started, confirm it.
78 // Otherwise, start profiling with the given mode.
Erik Chen06a20b52018-04-17 19:05:3279 // This method must only be called on platforms that supported nested run
80 // loops on the UI thread.
81 bool CheckOrStartProfilingOnUIThreadWithNestedRunLoops();
82
83 // If profiling is expected to already be started, confirm it.
84 // Otherwise, start profiling with the given mode.
85 // This method must only be called on platforms that are running the
86 // TestDriver from a non-UI thread, which allows for async signalling.
87 bool CheckOrStartProfilingOnUIThreadWithAsyncSignalling();
Erik Chen9d81094d2017-11-20 17:40:0988
89 // Performs allocations. These are expected to be profiled.
90 void MakeTestAllocations();
91
92 // Collects a trace that contains a heap dump. The result is stored in
93 // |serialized_trace_|.
94 //
95 // When |synchronous| is true, this method spins a nested message loop. When
96 // |synchronous| is false, this method posts some tasks that will eventually
97 // signal |wait_for_ui_thread_|.
98 void CollectResults(bool synchronous);
99
Ken Rockot2ade11d72019-12-20 18:37:16100 void TraceFinished(base::OnceClosure closure,
erikchen872446d2017-11-29 00:34:40101 bool success,
102 std::string trace_json);
103
Erik Chen9d81094d2017-11-20 17:40:09104 bool ValidateBrowserAllocations(base::Value* dump_json);
105 bool ValidateRendererAllocations(base::Value* dump_json);
106
Erik Chen3303fd0232018-01-11 20:29:05107 bool ShouldProfileBrowser();
erikchenee0a0072018-01-19 21:52:04108 bool ShouldProfileRenderer();
erikchen011ad3f2018-01-26 17:54:55109 bool ShouldIncludeNativeThreadNames();
Erik Chen3303fd0232018-01-11 20:29:05110 bool HasPseudoFrames();
erikchen080ebb12018-03-21 22:21:01111 bool HasNativeFrames();
Erik Chen3303fd0232018-01-11 20:29:05112
Erik Chen7e4cccd62019-12-05 23:58:58113 void WaitForProfilingToStartForBrowserUIThread();
erikchenee0a0072018-01-19 21:52:04114 void WaitForProfilingToStartForAllRenderersUIThread();
115
116 // Android does not support nested RunLoops. Instead, it signals
117 // |wait_for_ui_thread_| when finished.
118 void WaitForProfilingToStartForAllRenderersUIThreadAndSignal();
119 void WaitForProfilingToStartForAllRenderersUIThreadCallback(
120 std::vector<base::ProcessId> results);
121
Erik Chen9d81094d2017-11-20 17:40:09122 Options options_;
123
124 // Allocations made by this class. Intentionally leaked, since deallocating
125 // them would trigger a large number of IPCs, which is slow.
126 std::vector<char*> leaks_;
127
128 // Sum of size of all variadic allocations.
129 size_t total_variadic_allocations_ = 0;
130
131 // Use to make PA allocations, which should also be shimmed.
132 base::PartitionAllocatorGeneric partition_allocator_;
133
134 // Contains nothing until |CollectResults| has been called.
erikchen872446d2017-11-29 00:34:40135 std::string serialized_trace_;
Erik Chen9d81094d2017-11-20 17:40:09136
137 // Whether the test was invoked on the ui thread.
138 bool running_on_ui_thread_ = true;
139
Erik Chen74cba8c2018-04-16 18:49:49140 // Whether the supervisor has started.
141 bool has_started_ = false;
142
Erik Chen9d81094d2017-11-20 17:40:09143 // Whether an error has occurred.
144 bool initialization_success_ = false;
145
Erik Chen3303fd0232018-01-11 20:29:05146 // When |true|, initialization will wait for the allocator shim to enable
147 // before continuing.
148 bool wait_for_profiling_to_start_ = false;
149
Erik Chen9d81094d2017-11-20 17:40:09150 base::WaitableEvent wait_for_ui_thread_;
151
Erik Chen74cba8c2018-04-16 18:49:49152 DISALLOW_COPY_AND_ASSIGN(TestDriver);
Erik Chen9d81094d2017-11-20 17:40:09153};
154
erikchen102fe212018-04-06 13:02:10155} // namespace heap_profiling
Erik Chen9d81094d2017-11-20 17:40:09156
Erik Chen74cba8c2018-04-16 18:49:49157#endif // COMPONENTS_HEAP_PROFILING_TEST_DRIVER_H_