1*6777b538SAndroid Build Coastguard Worker // Copyright 2019 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include <algorithm>
6*6777b538SAndroid Build Coastguard Worker #include <cstring>
7*6777b538SAndroid Build Coastguard Worker #include <iterator>
8*6777b538SAndroid Build Coastguard Worker #include <memory>
9*6777b538SAndroid Build Coastguard Worker #include <numeric>
10*6777b538SAndroid Build Coastguard Worker #include <utility>
11*6777b538SAndroid Build Coastguard Worker
12*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ref.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/profiler/module_cache.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/profiler/profile_builder.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/profiler/stack_buffer.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/profiler/stack_copier.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/profiler/stack_sampler.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/profiler/stack_sampling_profiler_test_util.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/profiler/suspendable_thread_delegate.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/profiler/unwinder.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/test/metrics/histogram_tester.h"
25*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
26*6777b538SAndroid Build Coastguard Worker #include "testing/gmock/include/gmock/gmock.h"
27*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
28*6777b538SAndroid Build Coastguard Worker
29*6777b538SAndroid Build Coastguard Worker namespace base {
30*6777b538SAndroid Build Coastguard Worker
31*6777b538SAndroid Build Coastguard Worker namespace {
32*6777b538SAndroid Build Coastguard Worker
33*6777b538SAndroid Build Coastguard Worker using ::testing::ElementsAre;
34*6777b538SAndroid Build Coastguard Worker
35*6777b538SAndroid Build Coastguard Worker class TestProfileBuilder : public ProfileBuilder {
36*6777b538SAndroid Build Coastguard Worker public:
TestProfileBuilder(ModuleCache * module_cache)37*6777b538SAndroid Build Coastguard Worker TestProfileBuilder(ModuleCache* module_cache) : module_cache_(module_cache) {}
38*6777b538SAndroid Build Coastguard Worker
39*6777b538SAndroid Build Coastguard Worker TestProfileBuilder(const TestProfileBuilder&) = delete;
40*6777b538SAndroid Build Coastguard Worker TestProfileBuilder& operator=(const TestProfileBuilder&) = delete;
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker // ProfileBuilder
GetModuleCache()43*6777b538SAndroid Build Coastguard Worker ModuleCache* GetModuleCache() override { return module_cache_; }
RecordMetadata(const MetadataRecorder::MetadataProvider & metadata_provider)44*6777b538SAndroid Build Coastguard Worker void RecordMetadata(
45*6777b538SAndroid Build Coastguard Worker const MetadataRecorder::MetadataProvider& metadata_provider) override {}
46*6777b538SAndroid Build Coastguard Worker
OnSampleCompleted(std::vector<Frame> frames,TimeTicks sample_timestamp)47*6777b538SAndroid Build Coastguard Worker void OnSampleCompleted(std::vector<Frame> frames,
48*6777b538SAndroid Build Coastguard Worker TimeTicks sample_timestamp) override {
49*6777b538SAndroid Build Coastguard Worker last_timestamp_ = sample_timestamp;
50*6777b538SAndroid Build Coastguard Worker }
51*6777b538SAndroid Build Coastguard Worker
OnProfileCompleted(TimeDelta profile_duration,TimeDelta sampling_period)52*6777b538SAndroid Build Coastguard Worker void OnProfileCompleted(TimeDelta profile_duration,
53*6777b538SAndroid Build Coastguard Worker TimeDelta sampling_period) override {}
54*6777b538SAndroid Build Coastguard Worker
last_timestamp()55*6777b538SAndroid Build Coastguard Worker TimeTicks last_timestamp() { return last_timestamp_; }
56*6777b538SAndroid Build Coastguard Worker
57*6777b538SAndroid Build Coastguard Worker private:
58*6777b538SAndroid Build Coastguard Worker raw_ptr<ModuleCache> module_cache_;
59*6777b538SAndroid Build Coastguard Worker TimeTicks last_timestamp_;
60*6777b538SAndroid Build Coastguard Worker };
61*6777b538SAndroid Build Coastguard Worker
62*6777b538SAndroid Build Coastguard Worker // A stack copier for use in tests that provides the expected behavior when
63*6777b538SAndroid Build Coastguard Worker // operating on the supplied fake stack.
64*6777b538SAndroid Build Coastguard Worker class TestStackCopier : public StackCopier {
65*6777b538SAndroid Build Coastguard Worker public:
TestStackCopier(const std::vector<uintptr_t> & fake_stack,TimeTicks timestamp=TimeTicks ())66*6777b538SAndroid Build Coastguard Worker TestStackCopier(const std::vector<uintptr_t>& fake_stack,
67*6777b538SAndroid Build Coastguard Worker TimeTicks timestamp = TimeTicks())
68*6777b538SAndroid Build Coastguard Worker : fake_stack_(fake_stack), timestamp_(timestamp) {}
69*6777b538SAndroid Build Coastguard Worker
CopyStack(StackBuffer * stack_buffer,uintptr_t * stack_top,TimeTicks * timestamp,RegisterContext * thread_context,Delegate * delegate)70*6777b538SAndroid Build Coastguard Worker bool CopyStack(StackBuffer* stack_buffer,
71*6777b538SAndroid Build Coastguard Worker uintptr_t* stack_top,
72*6777b538SAndroid Build Coastguard Worker TimeTicks* timestamp,
73*6777b538SAndroid Build Coastguard Worker RegisterContext* thread_context,
74*6777b538SAndroid Build Coastguard Worker Delegate* delegate) override {
75*6777b538SAndroid Build Coastguard Worker std::memcpy(stack_buffer->buffer(), &(*fake_stack_)[0],
76*6777b538SAndroid Build Coastguard Worker fake_stack_->size() * sizeof((*fake_stack_)[0]));
77*6777b538SAndroid Build Coastguard Worker *stack_top = reinterpret_cast<uintptr_t>(stack_buffer->buffer() +
78*6777b538SAndroid Build Coastguard Worker fake_stack_->size());
79*6777b538SAndroid Build Coastguard Worker // Set the stack pointer to be consistent with the copied stack.
80*6777b538SAndroid Build Coastguard Worker *thread_context = {};
81*6777b538SAndroid Build Coastguard Worker RegisterContextStackPointer(thread_context) =
82*6777b538SAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(stack_buffer->buffer());
83*6777b538SAndroid Build Coastguard Worker
84*6777b538SAndroid Build Coastguard Worker *timestamp = timestamp_;
85*6777b538SAndroid Build Coastguard Worker
86*6777b538SAndroid Build Coastguard Worker return true;
87*6777b538SAndroid Build Coastguard Worker }
88*6777b538SAndroid Build Coastguard Worker
89*6777b538SAndroid Build Coastguard Worker private:
90*6777b538SAndroid Build Coastguard Worker // Must be a reference to retain the underlying allocation from the vector
91*6777b538SAndroid Build Coastguard Worker // passed to the constructor.
92*6777b538SAndroid Build Coastguard Worker const raw_ref<const std::vector<uintptr_t>> fake_stack_;
93*6777b538SAndroid Build Coastguard Worker
94*6777b538SAndroid Build Coastguard Worker const TimeTicks timestamp_;
95*6777b538SAndroid Build Coastguard Worker };
96*6777b538SAndroid Build Coastguard Worker
97*6777b538SAndroid Build Coastguard Worker // A StackCopier that just invokes the expected functions on the delegate.
98*6777b538SAndroid Build Coastguard Worker class DelegateInvokingStackCopier : public StackCopier {
99*6777b538SAndroid Build Coastguard Worker public:
CopyStack(StackBuffer * stack_buffer,uintptr_t * stack_top,TimeTicks * timestamp,RegisterContext * thread_context,Delegate * delegate)100*6777b538SAndroid Build Coastguard Worker bool CopyStack(StackBuffer* stack_buffer,
101*6777b538SAndroid Build Coastguard Worker uintptr_t* stack_top,
102*6777b538SAndroid Build Coastguard Worker TimeTicks* timestamp,
103*6777b538SAndroid Build Coastguard Worker RegisterContext* thread_context,
104*6777b538SAndroid Build Coastguard Worker Delegate* delegate) override {
105*6777b538SAndroid Build Coastguard Worker *stack_top = reinterpret_cast<uintptr_t>(stack_buffer->buffer()) +
106*6777b538SAndroid Build Coastguard Worker 10; // Make msan happy.
107*6777b538SAndroid Build Coastguard Worker delegate->OnStackCopy();
108*6777b538SAndroid Build Coastguard Worker return true;
109*6777b538SAndroid Build Coastguard Worker }
110*6777b538SAndroid Build Coastguard Worker };
111*6777b538SAndroid Build Coastguard Worker
112*6777b538SAndroid Build Coastguard Worker // Trivial unwinder implementation for testing.
113*6777b538SAndroid Build Coastguard Worker class TestUnwinder : public Unwinder {
114*6777b538SAndroid Build Coastguard Worker public:
TestUnwinder(std::vector<uintptr_t> * stack_copy)115*6777b538SAndroid Build Coastguard Worker explicit TestUnwinder(std::vector<uintptr_t>* stack_copy)
116*6777b538SAndroid Build Coastguard Worker : stack_copy_(stack_copy) {}
117*6777b538SAndroid Build Coastguard Worker
CanUnwindFrom(const Frame & current_frame) const118*6777b538SAndroid Build Coastguard Worker bool CanUnwindFrom(const Frame& current_frame) const override { return true; }
119*6777b538SAndroid Build Coastguard Worker
TryUnwind(RegisterContext * thread_context,uintptr_t stack_top,std::vector<Frame> * stack)120*6777b538SAndroid Build Coastguard Worker UnwindResult TryUnwind(RegisterContext* thread_context,
121*6777b538SAndroid Build Coastguard Worker uintptr_t stack_top,
122*6777b538SAndroid Build Coastguard Worker std::vector<Frame>* stack) override {
123*6777b538SAndroid Build Coastguard Worker auto* bottom = reinterpret_cast<uintptr_t*>(
124*6777b538SAndroid Build Coastguard Worker RegisterContextStackPointer(thread_context));
125*6777b538SAndroid Build Coastguard Worker *stack_copy_ =
126*6777b538SAndroid Build Coastguard Worker std::vector<uintptr_t>(bottom, reinterpret_cast<uintptr_t*>(stack_top));
127*6777b538SAndroid Build Coastguard Worker return UnwindResult::kCompleted;
128*6777b538SAndroid Build Coastguard Worker }
129*6777b538SAndroid Build Coastguard Worker
130*6777b538SAndroid Build Coastguard Worker private:
131*6777b538SAndroid Build Coastguard Worker raw_ptr<std::vector<uintptr_t>> stack_copy_;
132*6777b538SAndroid Build Coastguard Worker };
133*6777b538SAndroid Build Coastguard Worker
134*6777b538SAndroid Build Coastguard Worker // Records invocations of calls to OnStackCapture()/UpdateModules().
135*6777b538SAndroid Build Coastguard Worker class CallRecordingUnwinder : public Unwinder {
136*6777b538SAndroid Build Coastguard Worker public:
OnStackCapture()137*6777b538SAndroid Build Coastguard Worker void OnStackCapture() override { on_stack_capture_was_invoked_ = true; }
138*6777b538SAndroid Build Coastguard Worker
UpdateModules()139*6777b538SAndroid Build Coastguard Worker void UpdateModules() override { update_modules_was_invoked_ = true; }
140*6777b538SAndroid Build Coastguard Worker
CanUnwindFrom(const Frame & current_frame) const141*6777b538SAndroid Build Coastguard Worker bool CanUnwindFrom(const Frame& current_frame) const override { return true; }
142*6777b538SAndroid Build Coastguard Worker
TryUnwind(RegisterContext * thread_context,uintptr_t stack_top,std::vector<Frame> * stack)143*6777b538SAndroid Build Coastguard Worker UnwindResult TryUnwind(RegisterContext* thread_context,
144*6777b538SAndroid Build Coastguard Worker uintptr_t stack_top,
145*6777b538SAndroid Build Coastguard Worker std::vector<Frame>* stack) override {
146*6777b538SAndroid Build Coastguard Worker return UnwindResult::kUnrecognizedFrame;
147*6777b538SAndroid Build Coastguard Worker }
148*6777b538SAndroid Build Coastguard Worker
on_stack_capture_was_invoked() const149*6777b538SAndroid Build Coastguard Worker bool on_stack_capture_was_invoked() const {
150*6777b538SAndroid Build Coastguard Worker return on_stack_capture_was_invoked_;
151*6777b538SAndroid Build Coastguard Worker }
152*6777b538SAndroid Build Coastguard Worker
update_modules_was_invoked() const153*6777b538SAndroid Build Coastguard Worker bool update_modules_was_invoked() const {
154*6777b538SAndroid Build Coastguard Worker return update_modules_was_invoked_;
155*6777b538SAndroid Build Coastguard Worker }
156*6777b538SAndroid Build Coastguard Worker
157*6777b538SAndroid Build Coastguard Worker private:
158*6777b538SAndroid Build Coastguard Worker bool on_stack_capture_was_invoked_ = false;
159*6777b538SAndroid Build Coastguard Worker bool update_modules_was_invoked_ = false;
160*6777b538SAndroid Build Coastguard Worker };
161*6777b538SAndroid Build Coastguard Worker
162*6777b538SAndroid Build Coastguard Worker // Utility function to form a vector from a single module.
ToModuleVector(std::unique_ptr<const ModuleCache::Module> module)163*6777b538SAndroid Build Coastguard Worker std::vector<std::unique_ptr<const ModuleCache::Module>> ToModuleVector(
164*6777b538SAndroid Build Coastguard Worker std::unique_ptr<const ModuleCache::Module> module) {
165*6777b538SAndroid Build Coastguard Worker return std::vector<std::unique_ptr<const ModuleCache::Module>>(
166*6777b538SAndroid Build Coastguard Worker std::make_move_iterator(&module), std::make_move_iterator(&module + 1));
167*6777b538SAndroid Build Coastguard Worker }
168*6777b538SAndroid Build Coastguard Worker
169*6777b538SAndroid Build Coastguard Worker // Injects a fake module covering the initial instruction pointer value, to
170*6777b538SAndroid Build Coastguard Worker // avoid asking the OS to look it up. Windows doesn't return a consistent error
171*6777b538SAndroid Build Coastguard Worker // code when doing so, and we DCHECK_EQ the expected error code.
InjectModuleForContextInstructionPointer(const std::vector<uintptr_t> & stack,ModuleCache * module_cache)172*6777b538SAndroid Build Coastguard Worker void InjectModuleForContextInstructionPointer(
173*6777b538SAndroid Build Coastguard Worker const std::vector<uintptr_t>& stack,
174*6777b538SAndroid Build Coastguard Worker ModuleCache* module_cache) {
175*6777b538SAndroid Build Coastguard Worker module_cache->AddCustomNativeModule(
176*6777b538SAndroid Build Coastguard Worker std::make_unique<TestModule>(stack[0], sizeof(uintptr_t)));
177*6777b538SAndroid Build Coastguard Worker }
178*6777b538SAndroid Build Coastguard Worker
179*6777b538SAndroid Build Coastguard Worker // Returns a plausible instruction pointer value for use in tests that don't
180*6777b538SAndroid Build Coastguard Worker // care about the instruction pointer value in the context, and hence don't need
181*6777b538SAndroid Build Coastguard Worker // InjectModuleForContextInstructionPointer().
GetTestInstructionPointer()182*6777b538SAndroid Build Coastguard Worker uintptr_t GetTestInstructionPointer() {
183*6777b538SAndroid Build Coastguard Worker return reinterpret_cast<uintptr_t>(&GetTestInstructionPointer);
184*6777b538SAndroid Build Coastguard Worker }
185*6777b538SAndroid Build Coastguard Worker
186*6777b538SAndroid Build Coastguard Worker // An unwinder fake that replays the provided outputs.
187*6777b538SAndroid Build Coastguard Worker class FakeTestUnwinder : public Unwinder {
188*6777b538SAndroid Build Coastguard Worker public:
189*6777b538SAndroid Build Coastguard Worker struct Result {
Resultbase::__anon7fa9c2390111::FakeTestUnwinder::Result190*6777b538SAndroid Build Coastguard Worker Result(bool can_unwind)
191*6777b538SAndroid Build Coastguard Worker : can_unwind(can_unwind), result(UnwindResult::kUnrecognizedFrame) {}
192*6777b538SAndroid Build Coastguard Worker
Resultbase::__anon7fa9c2390111::FakeTestUnwinder::Result193*6777b538SAndroid Build Coastguard Worker Result(UnwindResult result, std::vector<uintptr_t> instruction_pointers)
194*6777b538SAndroid Build Coastguard Worker : can_unwind(true),
195*6777b538SAndroid Build Coastguard Worker result(result),
196*6777b538SAndroid Build Coastguard Worker instruction_pointers(instruction_pointers) {}
197*6777b538SAndroid Build Coastguard Worker
198*6777b538SAndroid Build Coastguard Worker bool can_unwind;
199*6777b538SAndroid Build Coastguard Worker UnwindResult result;
200*6777b538SAndroid Build Coastguard Worker std::vector<uintptr_t> instruction_pointers;
201*6777b538SAndroid Build Coastguard Worker };
202*6777b538SAndroid Build Coastguard Worker
203*6777b538SAndroid Build Coastguard Worker // Construct the unwinder with the outputs. The relevant unwinder functions
204*6777b538SAndroid Build Coastguard Worker // are expected to be invoked at least as many times as the number of values
205*6777b538SAndroid Build Coastguard Worker // specified in the arrays (except for CanUnwindFrom() which will always
206*6777b538SAndroid Build Coastguard Worker // return true if provided an empty array.
FakeTestUnwinder(std::vector<Result> results)207*6777b538SAndroid Build Coastguard Worker explicit FakeTestUnwinder(std::vector<Result> results)
208*6777b538SAndroid Build Coastguard Worker : results_(std::move(results)) {}
209*6777b538SAndroid Build Coastguard Worker
210*6777b538SAndroid Build Coastguard Worker FakeTestUnwinder(const FakeTestUnwinder&) = delete;
211*6777b538SAndroid Build Coastguard Worker FakeTestUnwinder& operator=(const FakeTestUnwinder&) = delete;
212*6777b538SAndroid Build Coastguard Worker
CanUnwindFrom(const Frame & current_frame) const213*6777b538SAndroid Build Coastguard Worker bool CanUnwindFrom(const Frame& current_frame) const override {
214*6777b538SAndroid Build Coastguard Worker bool can_unwind = results_[current_unwind_].can_unwind;
215*6777b538SAndroid Build Coastguard Worker // NB: If CanUnwindFrom() returns false then TryUnwind() will not be
216*6777b538SAndroid Build Coastguard Worker // invoked, so current_unwind_ is guarantee to be incremented only once for
217*6777b538SAndroid Build Coastguard Worker // each result.
218*6777b538SAndroid Build Coastguard Worker if (!can_unwind)
219*6777b538SAndroid Build Coastguard Worker ++current_unwind_;
220*6777b538SAndroid Build Coastguard Worker return can_unwind;
221*6777b538SAndroid Build Coastguard Worker }
222*6777b538SAndroid Build Coastguard Worker
TryUnwind(RegisterContext * thread_context,uintptr_t stack_top,std::vector<Frame> * stack)223*6777b538SAndroid Build Coastguard Worker UnwindResult TryUnwind(RegisterContext* thread_context,
224*6777b538SAndroid Build Coastguard Worker uintptr_t stack_top,
225*6777b538SAndroid Build Coastguard Worker std::vector<Frame>* stack) override {
226*6777b538SAndroid Build Coastguard Worker CHECK_LT(current_unwind_, results_.size());
227*6777b538SAndroid Build Coastguard Worker const Result& current_result = results_[current_unwind_];
228*6777b538SAndroid Build Coastguard Worker ++current_unwind_;
229*6777b538SAndroid Build Coastguard Worker CHECK(current_result.can_unwind);
230*6777b538SAndroid Build Coastguard Worker for (const auto instruction_pointer : current_result.instruction_pointers)
231*6777b538SAndroid Build Coastguard Worker stack->emplace_back(
232*6777b538SAndroid Build Coastguard Worker instruction_pointer,
233*6777b538SAndroid Build Coastguard Worker module_cache()->GetModuleForAddress(instruction_pointer));
234*6777b538SAndroid Build Coastguard Worker return current_result.result;
235*6777b538SAndroid Build Coastguard Worker }
236*6777b538SAndroid Build Coastguard Worker
237*6777b538SAndroid Build Coastguard Worker private:
238*6777b538SAndroid Build Coastguard Worker mutable size_t current_unwind_ = 0;
239*6777b538SAndroid Build Coastguard Worker std::vector<Result> results_;
240*6777b538SAndroid Build Coastguard Worker };
241*6777b538SAndroid Build Coastguard Worker
MakeUnwindersFactory(std::unique_ptr<Unwinder> unwinder)242*6777b538SAndroid Build Coastguard Worker StackSampler::UnwindersFactory MakeUnwindersFactory(
243*6777b538SAndroid Build Coastguard Worker std::unique_ptr<Unwinder> unwinder) {
244*6777b538SAndroid Build Coastguard Worker return BindOnce(
245*6777b538SAndroid Build Coastguard Worker [](std::unique_ptr<Unwinder> unwinder) {
246*6777b538SAndroid Build Coastguard Worker std::vector<std::unique_ptr<Unwinder>> unwinders;
247*6777b538SAndroid Build Coastguard Worker unwinders.push_back(std::move(unwinder));
248*6777b538SAndroid Build Coastguard Worker return unwinders;
249*6777b538SAndroid Build Coastguard Worker },
250*6777b538SAndroid Build Coastguard Worker std::move(unwinder));
251*6777b538SAndroid Build Coastguard Worker }
252*6777b538SAndroid Build Coastguard Worker
MakeUnwinderCircularDeque(std::unique_ptr<Unwinder> native_unwinder,std::unique_ptr<Unwinder> aux_unwinder)253*6777b538SAndroid Build Coastguard Worker base::circular_deque<std::unique_ptr<Unwinder>> MakeUnwinderCircularDeque(
254*6777b538SAndroid Build Coastguard Worker std::unique_ptr<Unwinder> native_unwinder,
255*6777b538SAndroid Build Coastguard Worker std::unique_ptr<Unwinder> aux_unwinder) {
256*6777b538SAndroid Build Coastguard Worker base::circular_deque<std::unique_ptr<Unwinder>> unwinders;
257*6777b538SAndroid Build Coastguard Worker if (native_unwinder)
258*6777b538SAndroid Build Coastguard Worker unwinders.push_front(std::move(native_unwinder));
259*6777b538SAndroid Build Coastguard Worker if (aux_unwinder)
260*6777b538SAndroid Build Coastguard Worker unwinders.push_front(std::move(aux_unwinder));
261*6777b538SAndroid Build Coastguard Worker return unwinders;
262*6777b538SAndroid Build Coastguard Worker }
263*6777b538SAndroid Build Coastguard Worker
264*6777b538SAndroid Build Coastguard Worker } // namespace
265*6777b538SAndroid Build Coastguard Worker
TEST(StackSamplerTest,CopyStack)266*6777b538SAndroid Build Coastguard Worker TEST(StackSamplerTest, CopyStack) {
267*6777b538SAndroid Build Coastguard Worker ModuleCache module_cache;
268*6777b538SAndroid Build Coastguard Worker const std::vector<uintptr_t> stack = {0, 1, 2, 3, 4};
269*6777b538SAndroid Build Coastguard Worker InjectModuleForContextInstructionPointer(stack, &module_cache);
270*6777b538SAndroid Build Coastguard Worker std::vector<uintptr_t> stack_copy;
271*6777b538SAndroid Build Coastguard Worker std::unique_ptr<StackSampler> stack_sampler = StackSampler::CreateForTesting(
272*6777b538SAndroid Build Coastguard Worker std::make_unique<TestStackCopier>(stack),
273*6777b538SAndroid Build Coastguard Worker MakeUnwindersFactory(std::make_unique<TestUnwinder>(&stack_copy)),
274*6777b538SAndroid Build Coastguard Worker &module_cache);
275*6777b538SAndroid Build Coastguard Worker
276*6777b538SAndroid Build Coastguard Worker stack_sampler->Initialize();
277*6777b538SAndroid Build Coastguard Worker
278*6777b538SAndroid Build Coastguard Worker std::unique_ptr<StackBuffer> stack_buffer =
279*6777b538SAndroid Build Coastguard Worker std::make_unique<StackBuffer>(stack.size() * sizeof(uintptr_t));
280*6777b538SAndroid Build Coastguard Worker TestProfileBuilder profile_builder(&module_cache);
281*6777b538SAndroid Build Coastguard Worker stack_sampler->RecordStackFrames(stack_buffer.get(), &profile_builder,
282*6777b538SAndroid Build Coastguard Worker PlatformThread::CurrentId());
283*6777b538SAndroid Build Coastguard Worker
284*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(stack, stack_copy);
285*6777b538SAndroid Build Coastguard Worker }
286*6777b538SAndroid Build Coastguard Worker
287*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_CHROMEOS)
TEST(StackSamplerTest,RecordStackFramesUMAMetric)288*6777b538SAndroid Build Coastguard Worker TEST(StackSamplerTest, RecordStackFramesUMAMetric) {
289*6777b538SAndroid Build Coastguard Worker HistogramTester histogram_tester;
290*6777b538SAndroid Build Coastguard Worker ModuleCache module_cache;
291*6777b538SAndroid Build Coastguard Worker std::vector<uintptr_t> stack;
292*6777b538SAndroid Build Coastguard Worker constexpr size_t UIntPtrsPerKilobyte = 1024 / sizeof(uintptr_t);
293*6777b538SAndroid Build Coastguard Worker // kExpectedSizeKB needs to be a fairly large number of kilobytes. The buckets
294*6777b538SAndroid Build Coastguard Worker // in UmaHistogramMemoryKB are big enough that small values are in the same
295*6777b538SAndroid Build Coastguard Worker // bucket as zero and less than zero, and testing that we added a sample in
296*6777b538SAndroid Build Coastguard Worker // that bucket means that the test won't fail if, for example, the
297*6777b538SAndroid Build Coastguard Worker // |stack_top - stack_bottom| subtraction was reversed and got a negative
298*6777b538SAndroid Build Coastguard Worker // value.
299*6777b538SAndroid Build Coastguard Worker constexpr int kExpectedSizeKB = 2048;
300*6777b538SAndroid Build Coastguard Worker for (uintptr_t i = 0; i <= (kExpectedSizeKB * UIntPtrsPerKilobyte) + 1; i++) {
301*6777b538SAndroid Build Coastguard Worker stack.push_back(i);
302*6777b538SAndroid Build Coastguard Worker }
303*6777b538SAndroid Build Coastguard Worker InjectModuleForContextInstructionPointer(stack, &module_cache);
304*6777b538SAndroid Build Coastguard Worker std::vector<uintptr_t> stack_copy;
305*6777b538SAndroid Build Coastguard Worker std::unique_ptr<StackSampler> stack_sampler = StackSampler::CreateForTesting(
306*6777b538SAndroid Build Coastguard Worker std::make_unique<TestStackCopier>(stack),
307*6777b538SAndroid Build Coastguard Worker MakeUnwindersFactory(std::make_unique<TestUnwinder>(&stack_copy)),
308*6777b538SAndroid Build Coastguard Worker &module_cache);
309*6777b538SAndroid Build Coastguard Worker
310*6777b538SAndroid Build Coastguard Worker stack_sampler->Initialize();
311*6777b538SAndroid Build Coastguard Worker
312*6777b538SAndroid Build Coastguard Worker std::unique_ptr<StackBuffer> stack_buffer =
313*6777b538SAndroid Build Coastguard Worker std::make_unique<StackBuffer>(stack.size() * sizeof(uintptr_t));
314*6777b538SAndroid Build Coastguard Worker TestProfileBuilder profile_builder(&module_cache);
315*6777b538SAndroid Build Coastguard Worker
316*6777b538SAndroid Build Coastguard Worker for (uint32_t i = 0; i < StackSampler::kUMAHistogramDownsampleAmount - 1;
317*6777b538SAndroid Build Coastguard Worker i++) {
318*6777b538SAndroid Build Coastguard Worker stack_sampler->RecordStackFrames(stack_buffer.get(), &profile_builder,
319*6777b538SAndroid Build Coastguard Worker PlatformThread::CurrentId());
320*6777b538SAndroid Build Coastguard Worker
321*6777b538SAndroid Build Coastguard Worker // Should have no new samples in the
322*6777b538SAndroid Build Coastguard Worker // Memory.StackSamplingProfiler.StackSampleSize2 histogram.
323*6777b538SAndroid Build Coastguard Worker histogram_tester.ExpectUniqueSample(
324*6777b538SAndroid Build Coastguard Worker "Memory.StackSamplingProfiler.StackSampleSize2", kExpectedSizeKB, 0);
325*6777b538SAndroid Build Coastguard Worker }
326*6777b538SAndroid Build Coastguard Worker
327*6777b538SAndroid Build Coastguard Worker stack_sampler->RecordStackFrames(stack_buffer.get(), &profile_builder,
328*6777b538SAndroid Build Coastguard Worker PlatformThread::CurrentId());
329*6777b538SAndroid Build Coastguard Worker
330*6777b538SAndroid Build Coastguard Worker histogram_tester.ExpectUniqueSample(
331*6777b538SAndroid Build Coastguard Worker "Memory.StackSamplingProfiler.StackSampleSize2", kExpectedSizeKB, 1);
332*6777b538SAndroid Build Coastguard Worker }
333*6777b538SAndroid Build Coastguard Worker #endif // #if BUILDFLAG(IS_CHROMEOS)
334*6777b538SAndroid Build Coastguard Worker
TEST(StackSamplerTest,CopyStackTimestamp)335*6777b538SAndroid Build Coastguard Worker TEST(StackSamplerTest, CopyStackTimestamp) {
336*6777b538SAndroid Build Coastguard Worker ModuleCache module_cache;
337*6777b538SAndroid Build Coastguard Worker const std::vector<uintptr_t> stack = {0};
338*6777b538SAndroid Build Coastguard Worker InjectModuleForContextInstructionPointer(stack, &module_cache);
339*6777b538SAndroid Build Coastguard Worker std::vector<uintptr_t> stack_copy;
340*6777b538SAndroid Build Coastguard Worker TimeTicks timestamp = TimeTicks::UnixEpoch();
341*6777b538SAndroid Build Coastguard Worker std::unique_ptr<StackSampler> stack_sampler = StackSampler::CreateForTesting(
342*6777b538SAndroid Build Coastguard Worker std::make_unique<TestStackCopier>(stack, timestamp),
343*6777b538SAndroid Build Coastguard Worker MakeUnwindersFactory(std::make_unique<TestUnwinder>(&stack_copy)),
344*6777b538SAndroid Build Coastguard Worker &module_cache);
345*6777b538SAndroid Build Coastguard Worker
346*6777b538SAndroid Build Coastguard Worker stack_sampler->Initialize();
347*6777b538SAndroid Build Coastguard Worker
348*6777b538SAndroid Build Coastguard Worker std::unique_ptr<StackBuffer> stack_buffer =
349*6777b538SAndroid Build Coastguard Worker std::make_unique<StackBuffer>(stack.size() * sizeof(uintptr_t));
350*6777b538SAndroid Build Coastguard Worker TestProfileBuilder profile_builder(&module_cache);
351*6777b538SAndroid Build Coastguard Worker stack_sampler->RecordStackFrames(stack_buffer.get(), &profile_builder,
352*6777b538SAndroid Build Coastguard Worker PlatformThread::CurrentId());
353*6777b538SAndroid Build Coastguard Worker
354*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(timestamp, profile_builder.last_timestamp());
355*6777b538SAndroid Build Coastguard Worker }
356*6777b538SAndroid Build Coastguard Worker
TEST(StackSamplerTest,UnwinderInvokedWhileRecordingStackFrames)357*6777b538SAndroid Build Coastguard Worker TEST(StackSamplerTest, UnwinderInvokedWhileRecordingStackFrames) {
358*6777b538SAndroid Build Coastguard Worker std::unique_ptr<StackBuffer> stack_buffer = std::make_unique<StackBuffer>(10);
359*6777b538SAndroid Build Coastguard Worker auto owned_unwinder = std::make_unique<CallRecordingUnwinder>();
360*6777b538SAndroid Build Coastguard Worker CallRecordingUnwinder* unwinder = owned_unwinder.get();
361*6777b538SAndroid Build Coastguard Worker ModuleCache module_cache;
362*6777b538SAndroid Build Coastguard Worker TestProfileBuilder profile_builder(&module_cache);
363*6777b538SAndroid Build Coastguard Worker std::unique_ptr<StackSampler> stack_sampler = StackSampler::CreateForTesting(
364*6777b538SAndroid Build Coastguard Worker std::make_unique<DelegateInvokingStackCopier>(),
365*6777b538SAndroid Build Coastguard Worker MakeUnwindersFactory(std::move(owned_unwinder)), &module_cache);
366*6777b538SAndroid Build Coastguard Worker
367*6777b538SAndroid Build Coastguard Worker stack_sampler->Initialize();
368*6777b538SAndroid Build Coastguard Worker
369*6777b538SAndroid Build Coastguard Worker stack_sampler->RecordStackFrames(stack_buffer.get(), &profile_builder,
370*6777b538SAndroid Build Coastguard Worker PlatformThread::CurrentId());
371*6777b538SAndroid Build Coastguard Worker
372*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(unwinder->on_stack_capture_was_invoked());
373*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(unwinder->update_modules_was_invoked());
374*6777b538SAndroid Build Coastguard Worker }
375*6777b538SAndroid Build Coastguard Worker
TEST(StackSamplerTest,AuxUnwinderInvokedWhileRecordingStackFrames)376*6777b538SAndroid Build Coastguard Worker TEST(StackSamplerTest, AuxUnwinderInvokedWhileRecordingStackFrames) {
377*6777b538SAndroid Build Coastguard Worker std::unique_ptr<StackBuffer> stack_buffer = std::make_unique<StackBuffer>(10);
378*6777b538SAndroid Build Coastguard Worker ModuleCache module_cache;
379*6777b538SAndroid Build Coastguard Worker TestProfileBuilder profile_builder(&module_cache);
380*6777b538SAndroid Build Coastguard Worker std::unique_ptr<StackSampler> stack_sampler = StackSampler::CreateForTesting(
381*6777b538SAndroid Build Coastguard Worker std::make_unique<DelegateInvokingStackCopier>(),
382*6777b538SAndroid Build Coastguard Worker MakeUnwindersFactory(std::make_unique<CallRecordingUnwinder>()),
383*6777b538SAndroid Build Coastguard Worker &module_cache);
384*6777b538SAndroid Build Coastguard Worker
385*6777b538SAndroid Build Coastguard Worker stack_sampler->Initialize();
386*6777b538SAndroid Build Coastguard Worker
387*6777b538SAndroid Build Coastguard Worker auto owned_aux_unwinder = std::make_unique<CallRecordingUnwinder>();
388*6777b538SAndroid Build Coastguard Worker CallRecordingUnwinder* aux_unwinder = owned_aux_unwinder.get();
389*6777b538SAndroid Build Coastguard Worker stack_sampler->AddAuxUnwinder(std::move(owned_aux_unwinder));
390*6777b538SAndroid Build Coastguard Worker
391*6777b538SAndroid Build Coastguard Worker stack_sampler->RecordStackFrames(stack_buffer.get(), &profile_builder,
392*6777b538SAndroid Build Coastguard Worker PlatformThread::CurrentId());
393*6777b538SAndroid Build Coastguard Worker
394*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(aux_unwinder->on_stack_capture_was_invoked());
395*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(aux_unwinder->update_modules_was_invoked());
396*6777b538SAndroid Build Coastguard Worker }
397*6777b538SAndroid Build Coastguard Worker
TEST(StackSamplerTest,WalkStack_Completed)398*6777b538SAndroid Build Coastguard Worker TEST(StackSamplerTest, WalkStack_Completed) {
399*6777b538SAndroid Build Coastguard Worker ModuleCache module_cache;
400*6777b538SAndroid Build Coastguard Worker RegisterContext thread_context;
401*6777b538SAndroid Build Coastguard Worker RegisterContextInstructionPointer(&thread_context) =
402*6777b538SAndroid Build Coastguard Worker GetTestInstructionPointer();
403*6777b538SAndroid Build Coastguard Worker module_cache.AddCustomNativeModule(std::make_unique<TestModule>(1u, 1u));
404*6777b538SAndroid Build Coastguard Worker auto native_unwinder =
405*6777b538SAndroid Build Coastguard Worker WrapUnique(new FakeTestUnwinder({{UnwindResult::kCompleted, {1u}}}));
406*6777b538SAndroid Build Coastguard Worker native_unwinder->Initialize(&module_cache);
407*6777b538SAndroid Build Coastguard Worker
408*6777b538SAndroid Build Coastguard Worker std::vector<Frame> stack = StackSampler::WalkStackForTesting(
409*6777b538SAndroid Build Coastguard Worker &module_cache, &thread_context, 0u,
410*6777b538SAndroid Build Coastguard Worker MakeUnwinderCircularDeque(std::move(native_unwinder), nullptr));
411*6777b538SAndroid Build Coastguard Worker
412*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(2u, stack.size());
413*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, stack[1].instruction_pointer);
414*6777b538SAndroid Build Coastguard Worker }
415*6777b538SAndroid Build Coastguard Worker
TEST(StackSamplerTest,WalkStack_Aborted)416*6777b538SAndroid Build Coastguard Worker TEST(StackSamplerTest, WalkStack_Aborted) {
417*6777b538SAndroid Build Coastguard Worker ModuleCache module_cache;
418*6777b538SAndroid Build Coastguard Worker RegisterContext thread_context;
419*6777b538SAndroid Build Coastguard Worker RegisterContextInstructionPointer(&thread_context) =
420*6777b538SAndroid Build Coastguard Worker GetTestInstructionPointer();
421*6777b538SAndroid Build Coastguard Worker module_cache.AddCustomNativeModule(std::make_unique<TestModule>(1u, 1u));
422*6777b538SAndroid Build Coastguard Worker auto native_unwinder =
423*6777b538SAndroid Build Coastguard Worker WrapUnique(new FakeTestUnwinder({{UnwindResult::kAborted, {1u}}}));
424*6777b538SAndroid Build Coastguard Worker native_unwinder->Initialize(&module_cache);
425*6777b538SAndroid Build Coastguard Worker
426*6777b538SAndroid Build Coastguard Worker std::vector<Frame> stack = StackSampler::WalkStackForTesting(
427*6777b538SAndroid Build Coastguard Worker &module_cache, &thread_context, 0u,
428*6777b538SAndroid Build Coastguard Worker MakeUnwinderCircularDeque(std::move(native_unwinder), nullptr));
429*6777b538SAndroid Build Coastguard Worker
430*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(2u, stack.size());
431*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, stack[1].instruction_pointer);
432*6777b538SAndroid Build Coastguard Worker }
433*6777b538SAndroid Build Coastguard Worker
TEST(StackSamplerTest,WalkStack_NotUnwound)434*6777b538SAndroid Build Coastguard Worker TEST(StackSamplerTest, WalkStack_NotUnwound) {
435*6777b538SAndroid Build Coastguard Worker ModuleCache module_cache;
436*6777b538SAndroid Build Coastguard Worker RegisterContext thread_context;
437*6777b538SAndroid Build Coastguard Worker RegisterContextInstructionPointer(&thread_context) =
438*6777b538SAndroid Build Coastguard Worker GetTestInstructionPointer();
439*6777b538SAndroid Build Coastguard Worker auto native_unwinder = WrapUnique(
440*6777b538SAndroid Build Coastguard Worker new FakeTestUnwinder({{UnwindResult::kUnrecognizedFrame, {}}}));
441*6777b538SAndroid Build Coastguard Worker native_unwinder->Initialize(&module_cache);
442*6777b538SAndroid Build Coastguard Worker
443*6777b538SAndroid Build Coastguard Worker std::vector<Frame> stack = StackSampler::WalkStackForTesting(
444*6777b538SAndroid Build Coastguard Worker &module_cache, &thread_context, 0u,
445*6777b538SAndroid Build Coastguard Worker MakeUnwinderCircularDeque(std::move(native_unwinder), nullptr));
446*6777b538SAndroid Build Coastguard Worker
447*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(1u, stack.size());
448*6777b538SAndroid Build Coastguard Worker }
449*6777b538SAndroid Build Coastguard Worker
TEST(StackSamplerTest,WalkStack_AuxUnwind)450*6777b538SAndroid Build Coastguard Worker TEST(StackSamplerTest, WalkStack_AuxUnwind) {
451*6777b538SAndroid Build Coastguard Worker ModuleCache module_cache;
452*6777b538SAndroid Build Coastguard Worker RegisterContext thread_context;
453*6777b538SAndroid Build Coastguard Worker RegisterContextInstructionPointer(&thread_context) =
454*6777b538SAndroid Build Coastguard Worker GetTestInstructionPointer();
455*6777b538SAndroid Build Coastguard Worker
456*6777b538SAndroid Build Coastguard Worker // Treat the context instruction pointer as being in the aux unwinder's
457*6777b538SAndroid Build Coastguard Worker // non-native module.
458*6777b538SAndroid Build Coastguard Worker module_cache.UpdateNonNativeModules(
459*6777b538SAndroid Build Coastguard Worker {}, ToModuleVector(std::make_unique<TestModule>(
460*6777b538SAndroid Build Coastguard Worker GetTestInstructionPointer(), 1u, false)));
461*6777b538SAndroid Build Coastguard Worker
462*6777b538SAndroid Build Coastguard Worker auto aux_unwinder =
463*6777b538SAndroid Build Coastguard Worker WrapUnique(new FakeTestUnwinder({{UnwindResult::kAborted, {1u}}}));
464*6777b538SAndroid Build Coastguard Worker aux_unwinder->Initialize(&module_cache);
465*6777b538SAndroid Build Coastguard Worker std::vector<Frame> stack = StackSampler::WalkStackForTesting(
466*6777b538SAndroid Build Coastguard Worker &module_cache, &thread_context, 0u,
467*6777b538SAndroid Build Coastguard Worker MakeUnwinderCircularDeque(nullptr, std::move(aux_unwinder)));
468*6777b538SAndroid Build Coastguard Worker
469*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(2u, stack.size());
470*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(GetTestInstructionPointer(), stack[0].instruction_pointer);
471*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, stack[1].instruction_pointer);
472*6777b538SAndroid Build Coastguard Worker }
473*6777b538SAndroid Build Coastguard Worker
TEST(StackSamplerTest,WalkStack_AuxThenNative)474*6777b538SAndroid Build Coastguard Worker TEST(StackSamplerTest, WalkStack_AuxThenNative) {
475*6777b538SAndroid Build Coastguard Worker ModuleCache module_cache;
476*6777b538SAndroid Build Coastguard Worker RegisterContext thread_context;
477*6777b538SAndroid Build Coastguard Worker RegisterContextInstructionPointer(&thread_context) = 0u;
478*6777b538SAndroid Build Coastguard Worker
479*6777b538SAndroid Build Coastguard Worker // Treat the context instruction pointer as being in the aux unwinder's
480*6777b538SAndroid Build Coastguard Worker // non-native module.
481*6777b538SAndroid Build Coastguard Worker module_cache.UpdateNonNativeModules(
482*6777b538SAndroid Build Coastguard Worker {}, ToModuleVector(std::make_unique<TestModule>(0u, 1u, false)));
483*6777b538SAndroid Build Coastguard Worker // Inject a fake native module for the second frame.
484*6777b538SAndroid Build Coastguard Worker module_cache.AddCustomNativeModule(std::make_unique<TestModule>(1u, 1u));
485*6777b538SAndroid Build Coastguard Worker
486*6777b538SAndroid Build Coastguard Worker auto aux_unwinder = WrapUnique(
487*6777b538SAndroid Build Coastguard Worker new FakeTestUnwinder({{UnwindResult::kUnrecognizedFrame, {1u}}, false}));
488*6777b538SAndroid Build Coastguard Worker aux_unwinder->Initialize(&module_cache);
489*6777b538SAndroid Build Coastguard Worker auto native_unwinder =
490*6777b538SAndroid Build Coastguard Worker WrapUnique(new FakeTestUnwinder({{UnwindResult::kCompleted, {2u}}}));
491*6777b538SAndroid Build Coastguard Worker native_unwinder->Initialize(&module_cache);
492*6777b538SAndroid Build Coastguard Worker
493*6777b538SAndroid Build Coastguard Worker std::vector<Frame> stack = StackSampler::WalkStackForTesting(
494*6777b538SAndroid Build Coastguard Worker &module_cache, &thread_context, 0u,
495*6777b538SAndroid Build Coastguard Worker MakeUnwinderCircularDeque(std::move(native_unwinder),
496*6777b538SAndroid Build Coastguard Worker std::move(aux_unwinder)));
497*6777b538SAndroid Build Coastguard Worker
498*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(3u, stack.size());
499*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0u, stack[0].instruction_pointer);
500*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, stack[1].instruction_pointer);
501*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(2u, stack[2].instruction_pointer);
502*6777b538SAndroid Build Coastguard Worker }
503*6777b538SAndroid Build Coastguard Worker
TEST(StackSamplerTest,WalkStack_NativeThenAux)504*6777b538SAndroid Build Coastguard Worker TEST(StackSamplerTest, WalkStack_NativeThenAux) {
505*6777b538SAndroid Build Coastguard Worker ModuleCache module_cache;
506*6777b538SAndroid Build Coastguard Worker RegisterContext thread_context;
507*6777b538SAndroid Build Coastguard Worker RegisterContextInstructionPointer(&thread_context) = 0u;
508*6777b538SAndroid Build Coastguard Worker
509*6777b538SAndroid Build Coastguard Worker // Inject fake native modules for the instruction pointer from the context and
510*6777b538SAndroid Build Coastguard Worker // the third frame.
511*6777b538SAndroid Build Coastguard Worker module_cache.AddCustomNativeModule(std::make_unique<TestModule>(0u, 1u));
512*6777b538SAndroid Build Coastguard Worker module_cache.AddCustomNativeModule(std::make_unique<TestModule>(2u, 1u));
513*6777b538SAndroid Build Coastguard Worker // Treat the second frame's pointer as being in the aux unwinder's non-native
514*6777b538SAndroid Build Coastguard Worker // module.
515*6777b538SAndroid Build Coastguard Worker module_cache.UpdateNonNativeModules(
516*6777b538SAndroid Build Coastguard Worker {}, ToModuleVector(std::make_unique<TestModule>(1u, 1u, false)));
517*6777b538SAndroid Build Coastguard Worker
518*6777b538SAndroid Build Coastguard Worker auto aux_unwinder = WrapUnique(new FakeTestUnwinder(
519*6777b538SAndroid Build Coastguard Worker {{false}, {UnwindResult::kUnrecognizedFrame, {2u}}, {false}}));
520*6777b538SAndroid Build Coastguard Worker aux_unwinder->Initialize(&module_cache);
521*6777b538SAndroid Build Coastguard Worker auto native_unwinder =
522*6777b538SAndroid Build Coastguard Worker WrapUnique(new FakeTestUnwinder({{UnwindResult::kUnrecognizedFrame, {1u}},
523*6777b538SAndroid Build Coastguard Worker {UnwindResult::kCompleted, {3u}}}));
524*6777b538SAndroid Build Coastguard Worker native_unwinder->Initialize(&module_cache);
525*6777b538SAndroid Build Coastguard Worker
526*6777b538SAndroid Build Coastguard Worker std::vector<Frame> stack = StackSampler::WalkStackForTesting(
527*6777b538SAndroid Build Coastguard Worker &module_cache, &thread_context, 0u,
528*6777b538SAndroid Build Coastguard Worker MakeUnwinderCircularDeque(std::move(native_unwinder),
529*6777b538SAndroid Build Coastguard Worker std::move(aux_unwinder)));
530*6777b538SAndroid Build Coastguard Worker
531*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(4u, stack.size());
532*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0u, stack[0].instruction_pointer);
533*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, stack[1].instruction_pointer);
534*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(2u, stack[2].instruction_pointer);
535*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(3u, stack[3].instruction_pointer);
536*6777b538SAndroid Build Coastguard Worker }
537*6777b538SAndroid Build Coastguard Worker
538*6777b538SAndroid Build Coastguard Worker } // namespace base
539