xref: /aosp_15_r20/external/cronet/base/profiler/stack_sampler_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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