1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <stddef.h>
6 #include <stdint.h>
7 
8 #include <cstdlib>
9 #include <memory>
10 #include <set>
11 #include <utility>
12 #include <vector>
13 
14 #include "base/bind.h"
15 #include "base/callback.h"
16 #include "base/compiler_specific.h"
17 #include "base/files/file_util.h"
18 #include "base/location.h"
19 #include "base/macros.h"
20 #include "base/memory/ptr_util.h"
21 #include "base/metrics/metrics_hashes.h"
22 #include "base/profiler/profiler_buildflags.h"
23 #include "base/profiler/sample_metadata.h"
24 #include "base/profiler/stack_sampler.h"
25 #include "base/profiler/stack_sampling_profiler.h"
26 #include "base/profiler/stack_sampling_profiler_test_util.h"
27 #include "base/profiler/unwinder.h"
28 #include "base/ranges/algorithm.h"
29 #include "base/run_loop.h"
30 #include "base/scoped_native_library.h"
31 #include "base/stl_util.h"
32 #include "base/strings/utf_string_conversions.h"
33 #include "base/synchronization/lock.h"
34 #include "base/synchronization/waitable_event.h"
35 #include "base/test/bind.h"
36 #include "base/threading/simple_thread.h"
37 #include "base/time/time.h"
38 #include "build/build_config.h"
39 #include "testing/gtest/include/gtest/gtest.h"
40 
41 #if defined(OS_WIN)
42 #include <intrin.h>
43 #include <malloc.h>
44 #include <windows.h>
45 #elif !defined(OS_BSD)
46 #include <alloca.h>
47 #endif
48 
49 // STACK_SAMPLING_PROFILER_SUPPORTED is used to conditionally enable the tests
50 // below for supported platforms (currently Win x64 and Mac x64).
51 #if (defined(OS_WIN) && defined(ARCH_CPU_X86_64)) || \
52     (defined(OS_MAC) && defined(ARCH_CPU_X86_64)) || \
53     (defined(OS_ANDROID) && BUILDFLAG(ENABLE_ARM_CFI_TABLE))
54 #define STACK_SAMPLING_PROFILER_SUPPORTED 1
55 #endif
56 
57 namespace base {
58 
59 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED)
60 #define PROFILER_TEST_F(TestClass, TestName) TEST_F(TestClass, TestName)
61 #else
62 #define PROFILER_TEST_F(TestClass, TestName) \
63   TEST_F(TestClass, DISABLED_##TestName)
64 #endif
65 
66 using SamplingParams = StackSamplingProfiler::SamplingParams;
67 
68 namespace {
69 
70 // State provided to the ProfileBuilder's ApplyMetadataRetrospectively function.
71 struct RetrospectiveMetadata {
72   TimeTicks period_start;
73   TimeTicks period_end;
74   MetadataRecorder::Item item;
75 };
76 
77 // Profile consists of a set of samples and other sampling information.
78 struct Profile {
79   // The collected samples.
80   std::vector<std::vector<Frame>> samples;
81 
82   // The number of invocations of RecordMetadata().
83   int record_metadata_count;
84 
85   // The retrospective metadata requests.
86   std::vector<RetrospectiveMetadata> retrospective_metadata;
87 
88   // Duration of this profile.
89   TimeDelta profile_duration;
90 
91   // Time between samples.
92   TimeDelta sampling_period;
93 };
94 
95 // The callback type used to collect a profile. The passed Profile is move-only.
96 // Other threads, including the UI thread, may block on callback completion so
97 // this should run as quickly as possible.
98 using ProfileCompletedCallback = OnceCallback<void(Profile)>;
99 
100 // TestProfileBuilder collects samples produced by the profiler.
101 class TestProfileBuilder : public ProfileBuilder {
102  public:
103   TestProfileBuilder(ModuleCache* module_cache,
104                      ProfileCompletedCallback callback);
105 
106   ~TestProfileBuilder() override;
107 
108   // ProfileBuilder:
109   ModuleCache* GetModuleCache() override;
110   void RecordMetadata(
111       const MetadataRecorder::MetadataProvider& metadata_provider) override;
112   void ApplyMetadataRetrospectively(
113       TimeTicks period_start,
114       TimeTicks period_end,
115       const MetadataRecorder::Item& item) override;
116   void OnSampleCompleted(std::vector<Frame> sample,
117                          TimeTicks sample_timestamp) override;
118   void OnProfileCompleted(TimeDelta profile_duration,
119                           TimeDelta sampling_period) override;
120 
121  private:
122   ModuleCache* module_cache_;
123 
124   // The set of recorded samples.
125   std::vector<std::vector<Frame>> samples_;
126 
127   // The number of invocations of RecordMetadata().
128   int record_metadata_count_ = 0;
129 
130   // The retrospective metadata requests.
131   std::vector<RetrospectiveMetadata> retrospective_metadata_;
132 
133   // Callback made when sampling a profile completes.
134   ProfileCompletedCallback callback_;
135 
136   DISALLOW_COPY_AND_ASSIGN(TestProfileBuilder);
137 };
138 
TestProfileBuilder(ModuleCache * module_cache,ProfileCompletedCallback callback)139 TestProfileBuilder::TestProfileBuilder(ModuleCache* module_cache,
140                                        ProfileCompletedCallback callback)
141     : module_cache_(module_cache), callback_(std::move(callback)) {}
142 
143 TestProfileBuilder::~TestProfileBuilder() = default;
144 
GetModuleCache()145 ModuleCache* TestProfileBuilder::GetModuleCache() {
146   return module_cache_;
147 }
148 
RecordMetadata(const MetadataRecorder::MetadataProvider & metadata_provider)149 void TestProfileBuilder::RecordMetadata(
150     const MetadataRecorder::MetadataProvider& metadata_provider) {
151   ++record_metadata_count_;
152 }
153 
ApplyMetadataRetrospectively(TimeTicks period_start,TimeTicks period_end,const MetadataRecorder::Item & item)154 void TestProfileBuilder::ApplyMetadataRetrospectively(
155     TimeTicks period_start,
156     TimeTicks period_end,
157     const MetadataRecorder::Item& item) {
158   retrospective_metadata_.push_back(
159       RetrospectiveMetadata{period_start, period_end, item});
160 }
161 
OnSampleCompleted(std::vector<Frame> sample,TimeTicks sample_timestamp)162 void TestProfileBuilder::OnSampleCompleted(std::vector<Frame> sample,
163                                            TimeTicks sample_timestamp) {
164   samples_.push_back(std::move(sample));
165 }
166 
OnProfileCompleted(TimeDelta profile_duration,TimeDelta sampling_period)167 void TestProfileBuilder::OnProfileCompleted(TimeDelta profile_duration,
168                                             TimeDelta sampling_period) {
169   std::move(callback_).Run(Profile{samples_, record_metadata_count_,
170                                    retrospective_metadata_, profile_duration,
171                                    sampling_period});
172 }
173 
174 // Unloads |library| and returns when it has completed unloading. Unloading a
175 // library is asynchronous on Windows, so simply calling UnloadNativeLibrary()
176 // is insufficient to ensure it's been unloaded.
SynchronousUnloadNativeLibrary(NativeLibrary library)177 void SynchronousUnloadNativeLibrary(NativeLibrary library) {
178   UnloadNativeLibrary(library);
179 #if defined(OS_WIN)
180   // NativeLibrary is a typedef for HMODULE, which is actually the base address
181   // of the module.
182   uintptr_t module_base_address = reinterpret_cast<uintptr_t>(library);
183   HMODULE module_handle;
184   // Keep trying to get the module handle until the call fails.
185   while (::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
186                                  GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
187                              reinterpret_cast<LPCTSTR>(module_base_address),
188                              &module_handle) ||
189          ::GetLastError() != ERROR_MOD_NOT_FOUND) {
190     PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
191   }
192 #elif defined(OS_APPLE) || defined(OS_ANDROID)
193 // Unloading a library on Mac and Android is synchronous.
194 #else
195   NOTIMPLEMENTED();
196 #endif
197 }
198 
WithTargetThread(ProfileCallback profile_callback)199 void WithTargetThread(ProfileCallback profile_callback) {
200   UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
201   WithTargetThread(&scenario, std::move(profile_callback));
202 }
203 
204 struct TestProfilerInfo {
TestProfilerInfobase::__anon416616460111::TestProfilerInfo205   TestProfilerInfo(SamplingProfilerThreadToken thread_token,
206                    const SamplingParams& params,
207                    ModuleCache* module_cache,
208                    StackSamplerTestDelegate* delegate = nullptr)
209       : completed(WaitableEvent::ResetPolicy::MANUAL,
210                   WaitableEvent::InitialState::NOT_SIGNALED),
211         profiler(thread_token,
212                  params,
213                  std::make_unique<TestProfileBuilder>(
214                      module_cache,
215                      BindLambdaForTesting([this](Profile result_profile) {
216                        profile = std::move(result_profile);
217                        completed.Signal();
218                      })),
219                  CreateCoreUnwindersFactoryForTesting(module_cache),
220                  RepeatingClosure(),
221                  delegate) {}
222 
223   // The order here is important to ensure objects being referenced don't get
224   // destructed until after the objects referencing them.
225   Profile profile;
226   WaitableEvent completed;
227   StackSamplingProfiler profiler;
228 
229  private:
230   DISALLOW_COPY_AND_ASSIGN(TestProfilerInfo);
231 };
232 
233 // Creates multiple profilers based on a vector of parameters.
CreateProfilers(SamplingProfilerThreadToken target_thread_token,const std::vector<SamplingParams> & params,ModuleCache * module_cache)234 std::vector<std::unique_ptr<TestProfilerInfo>> CreateProfilers(
235     SamplingProfilerThreadToken target_thread_token,
236     const std::vector<SamplingParams>& params,
237     ModuleCache* module_cache) {
238   DCHECK(!params.empty());
239 
240   std::vector<std::unique_ptr<TestProfilerInfo>> profilers;
241   for (const auto& i : params) {
242     profilers.push_back(std::make_unique<TestProfilerInfo>(target_thread_token,
243                                                            i, module_cache));
244   }
245 
246   return profilers;
247 }
248 
249 // Captures samples as specified by |params| on the TargetThread, and returns
250 // them. Waits up to |profiler_wait_time| for the profiler to complete.
CaptureSamples(const SamplingParams & params,TimeDelta profiler_wait_time,ModuleCache * module_cache)251 std::vector<std::vector<Frame>> CaptureSamples(const SamplingParams& params,
252                                                TimeDelta profiler_wait_time,
253                                                ModuleCache* module_cache) {
254   std::vector<std::vector<Frame>> samples;
255   WithTargetThread(BindLambdaForTesting(
256       [&](SamplingProfilerThreadToken target_thread_token) {
257         TestProfilerInfo info(target_thread_token, params, module_cache);
258         info.profiler.Start();
259         info.completed.TimedWait(profiler_wait_time);
260         info.profiler.Stop();
261         info.completed.Wait();
262         samples = std::move(info.profile.samples);
263       }));
264 
265   return samples;
266 }
267 
268 // Waits for one of multiple samplings to complete.
WaitForSamplingComplete(const std::vector<std::unique_ptr<TestProfilerInfo>> & infos)269 size_t WaitForSamplingComplete(
270     const std::vector<std::unique_ptr<TestProfilerInfo>>& infos) {
271   // Map unique_ptrs to something that WaitMany can accept.
272   std::vector<WaitableEvent*> sampling_completed_rawptrs(infos.size());
273   ranges::transform(infos, sampling_completed_rawptrs.begin(),
274                     [](const std::unique_ptr<TestProfilerInfo>& info) {
275                       return &info.get()->completed;
276                     });
277   // Wait for one profiler to finish.
278   return WaitableEvent::WaitMany(sampling_completed_rawptrs.data(),
279                                  sampling_completed_rawptrs.size());
280 }
281 
282 // Returns a duration that is longer than the test timeout. We would use
283 // TimeDelta::Max() but https://crbug.com/465948.
AVeryLongTimeDelta()284 TimeDelta AVeryLongTimeDelta() {
285   return TimeDelta::FromDays(1);
286 }
287 
288 // Tests the scenario where the library is unloaded after copying the stack, but
289 // before walking it. If |wait_until_unloaded| is true, ensures that the
290 // asynchronous library loading has completed before walking the stack. If
291 // false, the unloading may still be occurring during the stack walk.
TestLibraryUnload(bool wait_until_unloaded,ModuleCache * module_cache)292 void TestLibraryUnload(bool wait_until_unloaded, ModuleCache* module_cache) {
293   // Test delegate that supports intervening between the copying of the stack
294   // and the walking of the stack.
295   class StackCopiedSignaler : public StackSamplerTestDelegate {
296    public:
297     StackCopiedSignaler(WaitableEvent* stack_copied,
298                         WaitableEvent* start_stack_walk,
299                         bool wait_to_walk_stack)
300         : stack_copied_(stack_copied),
301           start_stack_walk_(start_stack_walk),
302           wait_to_walk_stack_(wait_to_walk_stack) {}
303 
304     void OnPreStackWalk() override {
305       stack_copied_->Signal();
306       if (wait_to_walk_stack_)
307         start_stack_walk_->Wait();
308     }
309 
310    private:
311     WaitableEvent* const stack_copied_;
312     WaitableEvent* const start_stack_walk_;
313     const bool wait_to_walk_stack_;
314   };
315 
316   SamplingParams params;
317   params.sampling_interval = TimeDelta::FromMilliseconds(0);
318   params.samples_per_profile = 1;
319 
320   NativeLibrary other_library = LoadOtherLibrary();
321 
322   UnwindScenario scenario(
323       BindRepeating(&CallThroughOtherLibrary, Unretained(other_library)));
324 
325   UnwindScenario::SampleEvents events;
326   TargetThread target_thread(
327       BindLambdaForTesting([&]() { scenario.Execute(&events); }));
328 
329   PlatformThreadHandle target_thread_handle;
330   EXPECT_TRUE(PlatformThread::Create(0, &target_thread, &target_thread_handle));
331 
332   events.ready_for_sample.Wait();
333 
334   WaitableEvent sampling_thread_completed(
335       WaitableEvent::ResetPolicy::MANUAL,
336       WaitableEvent::InitialState::NOT_SIGNALED);
337   Profile profile;
338 
339   WaitableEvent stack_copied(WaitableEvent::ResetPolicy::MANUAL,
340                              WaitableEvent::InitialState::NOT_SIGNALED);
341   WaitableEvent start_stack_walk(WaitableEvent::ResetPolicy::MANUAL,
342                                  WaitableEvent::InitialState::NOT_SIGNALED);
343   StackCopiedSignaler test_delegate(&stack_copied, &start_stack_walk,
344                                     wait_until_unloaded);
345   StackSamplingProfiler profiler(
346       target_thread.thread_token(), params,
347       std::make_unique<TestProfileBuilder>(
348           module_cache,
349           BindLambdaForTesting(
350               [&profile, &sampling_thread_completed](Profile result_profile) {
351                 profile = std::move(result_profile);
352                 sampling_thread_completed.Signal();
353               })),
354       CreateCoreUnwindersFactoryForTesting(module_cache), RepeatingClosure(),
355       &test_delegate);
356 
357   profiler.Start();
358 
359   // Wait for the stack to be copied and the target thread to be resumed.
360   stack_copied.Wait();
361 
362   // Cause the target thread to finish, so that it's no longer executing code in
363   // the library we're about to unload.
364   events.sample_finished.Signal();
365   PlatformThread::Join(target_thread_handle);
366 
367   // Unload the library now that it's not being used.
368   if (wait_until_unloaded)
369     SynchronousUnloadNativeLibrary(other_library);
370   else
371     UnloadNativeLibrary(other_library);
372 
373   // Let the stack walk commence after unloading the library, if we're waiting
374   // on that event.
375   start_stack_walk.Signal();
376 
377   // Wait for the sampling thread to complete and fill out |profile|.
378   sampling_thread_completed.Wait();
379 
380   // Look up the sample.
381   ASSERT_EQ(1u, profile.samples.size());
382   const std::vector<Frame>& sample = profile.samples[0];
383 
384   if (wait_until_unloaded) {
385     // We expect the stack to look something like this, with the frame in the
386     // now-unloaded library having a null module.
387     //
388     // ... WaitableEvent and system frames ...
389     // WaitForSample()
390     // TargetThread::OtherLibraryCallback
391     // <frame in unloaded library>
392     EXPECT_EQ(nullptr, sample.back().module)
393         << "Stack:\n"
394         << FormatSampleForDiagnosticOutput(sample);
395 
396     ExpectStackContains(sample, {scenario.GetWaitForSampleAddressRange()});
397     ExpectStackDoesNotContain(sample,
398                               {scenario.GetSetupFunctionAddressRange(),
399                                scenario.GetOuterFunctionAddressRange()});
400   } else {
401     // We didn't wait for the asynchronous unloading to complete, so the results
402     // are non-deterministic: if the library finished unloading we should have
403     // the same stack as |wait_until_unloaded|, if not we should have the full
404     // stack. The important thing is that we should not crash.
405 
406     if (!sample.back().module) {
407       // This is the same case as |wait_until_unloaded|.
408       ExpectStackContains(sample, {scenario.GetWaitForSampleAddressRange()});
409       ExpectStackDoesNotContain(sample,
410                                 {scenario.GetSetupFunctionAddressRange(),
411                                  scenario.GetOuterFunctionAddressRange()});
412       return;
413     }
414 
415     ExpectStackContains(sample, {scenario.GetWaitForSampleAddressRange(),
416                                  scenario.GetSetupFunctionAddressRange(),
417                                  scenario.GetOuterFunctionAddressRange()});
418   }
419 }
420 
421 // Provide a suitable (and clean) environment for the tests below. All tests
422 // must use this class to ensure that proper clean-up is done and thus be
423 // usable in a later test.
424 class StackSamplingProfilerTest : public testing::Test {
425  public:
SetUp()426   void SetUp() override {
427     // The idle-shutdown time is too long for convenient (and accurate) testing.
428     // That behavior is checked instead by artificially triggering it through
429     // the TestPeer.
430     StackSamplingProfiler::TestPeer::DisableIdleShutdown();
431   }
432 
TearDown()433   void TearDown() override {
434     // Be a good citizen and clean up after ourselves. This also re-enables the
435     // idle-shutdown behavior.
436     StackSamplingProfiler::TestPeer::Reset();
437   }
438 
439  protected:
module_cache()440   ModuleCache* module_cache() { return &module_cache_; }
441 
442  private:
443   ModuleCache module_cache_;
444 };
445 
446 }  // namespace
447 
448 // Checks that the basic expected information is present in sampled frames.
449 //
450 // macOS ASAN is not yet supported - crbug.com/718628.
451 //
452 // TODO(https://crbug.com/1100175): Enable this test again for Android with
453 // ASAN. This is now disabled because the android-asan bot fails.
454 #if (defined(ADDRESS_SANITIZER) && defined(OS_APPLE)) || \
455     (defined(ADDRESS_SANITIZER) && defined(OS_ANDROID))
456 #define MAYBE_Basic DISABLED_Basic
457 #else
458 #define MAYBE_Basic Basic
459 #endif
PROFILER_TEST_F(StackSamplingProfilerTest,MAYBE_Basic)460 PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_Basic) {
461   UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
462   const std::vector<Frame>& sample = SampleScenario(&scenario, module_cache());
463 
464   // Check that all the modules are valid.
465   for (const auto& frame : sample)
466     EXPECT_NE(nullptr, frame.module);
467 
468   // The stack should contain a full unwind.
469   ExpectStackContains(sample, {scenario.GetWaitForSampleAddressRange(),
470                                scenario.GetSetupFunctionAddressRange(),
471                                scenario.GetOuterFunctionAddressRange()});
472 }
473 
474 // A simple unwinder that always generates one frame then aborts the stack walk.
475 class TestAuxUnwinder : public Unwinder {
476  public:
TestAuxUnwinder(const Frame & frame_to_report,base::RepeatingClosure add_initial_modules_callback)477   TestAuxUnwinder(const Frame& frame_to_report,
478                   base::RepeatingClosure add_initial_modules_callback)
479       : frame_to_report_(frame_to_report),
480         add_initial_modules_callback_(std::move(add_initial_modules_callback)) {
481   }
482 
483   TestAuxUnwinder(const TestAuxUnwinder&) = delete;
484   TestAuxUnwinder& operator=(const TestAuxUnwinder&) = delete;
485 
AddInitialModules(ModuleCache * module_cache)486   void AddInitialModules(ModuleCache* module_cache) override {
487     if (add_initial_modules_callback_)
488       add_initial_modules_callback_.Run();
489   }
CanUnwindFrom(const Frame & current_frame) const490   bool CanUnwindFrom(const Frame& current_frame) const override { return true; }
491 
TryUnwind(RegisterContext * thread_context,uintptr_t stack_top,ModuleCache * module_cache,std::vector<Frame> * stack) const492   UnwindResult TryUnwind(RegisterContext* thread_context,
493                          uintptr_t stack_top,
494                          ModuleCache* module_cache,
495                          std::vector<Frame>* stack) const override {
496     stack->push_back(frame_to_report_);
497     return UnwindResult::ABORTED;
498   }
499 
500  private:
501   const Frame frame_to_report_;
502   base::RepeatingClosure add_initial_modules_callback_;
503 };
504 
505 // Checks that the profiler handles stacks containing dynamically-allocated
506 // stack memory.
507 // macOS ASAN is not yet supported - crbug.com/718628.
508 // Android is not supported since Chrome unwind tables don't support dynamic
509 // frames.
510 #if (defined(ADDRESS_SANITIZER) && defined(OS_APPLE)) || defined(OS_ANDROID)
511 #define MAYBE_Alloca DISABLED_Alloca
512 #else
513 #define MAYBE_Alloca Alloca
514 #endif
PROFILER_TEST_F(StackSamplingProfilerTest,MAYBE_Alloca)515 PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_Alloca) {
516   UnwindScenario scenario(BindRepeating(&CallWithAlloca));
517   const std::vector<Frame>& sample = SampleScenario(&scenario, module_cache());
518 
519   // The stack should contain a full unwind.
520   ExpectStackContains(sample, {scenario.GetWaitForSampleAddressRange(),
521                                scenario.GetSetupFunctionAddressRange(),
522                                scenario.GetOuterFunctionAddressRange()});
523 }
524 
525 // Checks that a stack that runs through another library produces a stack with
526 // the expected functions.
527 // macOS ASAN is not yet supported - crbug.com/718628.
528 // Android is not supported when EXCLUDE_UNWIND_TABLES |other_library| doesn't
529 // have unwind tables.
530 // TODO(https://crbug.com/1100175): Enable this test again for Android with
531 // ASAN. This is now disabled because the android-asan bot fails.
532 #if (defined(ADDRESS_SANITIZER) && defined(OS_APPLE)) ||         \
533     (defined(OS_ANDROID) && BUILDFLAG(EXCLUDE_UNWIND_TABLES)) || \
534     (defined(OS_ANDROID) && defined(ADDRESS_SANITIZER))
535 #define MAYBE_OtherLibrary DISABLED_OtherLibrary
536 #else
537 #define MAYBE_OtherLibrary OtherLibrary
538 #endif
PROFILER_TEST_F(StackSamplingProfilerTest,MAYBE_OtherLibrary)539 PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_OtherLibrary) {
540   ScopedNativeLibrary other_library(LoadOtherLibrary());
541   UnwindScenario scenario(
542       BindRepeating(&CallThroughOtherLibrary, Unretained(other_library.get())));
543   const std::vector<Frame>& sample = SampleScenario(&scenario, module_cache());
544 
545   // The stack should contain a full unwind.
546   ExpectStackContains(sample, {scenario.GetWaitForSampleAddressRange(),
547                                scenario.GetSetupFunctionAddressRange(),
548                                scenario.GetOuterFunctionAddressRange()});
549 }
550 
551 // Checks that a stack that runs through a library that is unloading produces a
552 // stack, and doesn't crash.
553 // Unloading is synchronous on the Mac, so this test is inapplicable.
554 // Android is not supported when EXCLUDE_UNWIND_TABLES |other_library| doesn't
555 // have unwind tables.
556 // TODO(https://crbug.com/1100175): Enable this test again for Android with
557 // ASAN. This is now disabled because the android-asan bot fails.
558 #if defined(OS_APPLE) ||                                         \
559     (defined(OS_ANDROID) && BUILDFLAG(EXCLUDE_UNWIND_TABLES)) || \
560     (defined(OS_ANDROID) && defined(ADDRESS_SANITIZER))
561 #define MAYBE_UnloadingLibrary DISABLED_UnloadingLibrary
562 #else
563 #define MAYBE_UnloadingLibrary UnloadingLibrary
564 #endif
PROFILER_TEST_F(StackSamplingProfilerTest,MAYBE_UnloadingLibrary)565 PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_UnloadingLibrary) {
566   TestLibraryUnload(false, module_cache());
567 }
568 
569 // Checks that a stack that runs through a library that has been unloaded
570 // produces a stack, and doesn't crash.
571 // macOS ASAN is not yet supported - crbug.com/718628.
572 // Android is not supported since modules are found before unwinding.
573 #if (defined(ADDRESS_SANITIZER) && defined(OS_APPLE)) || defined(OS_ANDROID)
574 #define MAYBE_UnloadedLibrary DISABLED_UnloadedLibrary
575 #else
576 #define MAYBE_UnloadedLibrary UnloadedLibrary
577 #endif
PROFILER_TEST_F(StackSamplingProfilerTest,MAYBE_UnloadedLibrary)578 PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_UnloadedLibrary) {
579   TestLibraryUnload(true, module_cache());
580 }
581 
582 // Checks that a profiler can stop/destruct without ever having started.
PROFILER_TEST_F(StackSamplingProfilerTest,StopWithoutStarting)583 PROFILER_TEST_F(StackSamplingProfilerTest, StopWithoutStarting) {
584   WithTargetThread(BindLambdaForTesting(
585       [this](SamplingProfilerThreadToken target_thread_token) {
586         SamplingParams params;
587         params.sampling_interval = TimeDelta::FromMilliseconds(0);
588         params.samples_per_profile = 1;
589 
590         Profile profile;
591         WaitableEvent sampling_completed(
592             WaitableEvent::ResetPolicy::MANUAL,
593             WaitableEvent::InitialState::NOT_SIGNALED);
594 
595         StackSamplingProfiler profiler(
596             target_thread_token, params,
597             std::make_unique<TestProfileBuilder>(
598                 module_cache(),
599                 BindLambdaForTesting(
600                     [&profile, &sampling_completed](Profile result_profile) {
601                       profile = std::move(result_profile);
602                       sampling_completed.Signal();
603                     })),
604             CreateCoreUnwindersFactoryForTesting(module_cache()));
605 
606         profiler.Stop();  // Constructed but never started.
607         EXPECT_FALSE(sampling_completed.IsSignaled());
608       }));
609 }
610 
611 // Checks that its okay to stop a profiler before it finishes even when the
612 // sampling thread continues to run.
PROFILER_TEST_F(StackSamplingProfilerTest,StopSafely)613 PROFILER_TEST_F(StackSamplingProfilerTest, StopSafely) {
614   // Test delegate that counts samples.
615   class SampleRecordedCounter : public StackSamplerTestDelegate {
616    public:
617     SampleRecordedCounter() = default;
618 
619     void OnPreStackWalk() override {
620       AutoLock lock(lock_);
621       ++count_;
622     }
623 
624     size_t Get() {
625       AutoLock lock(lock_);
626       return count_;
627     }
628 
629    private:
630     Lock lock_;
631     size_t count_ = 0;
632   };
633 
634   WithTargetThread(BindLambdaForTesting(
635       [this](SamplingProfilerThreadToken target_thread_token) {
636         SamplingParams params[2];
637 
638         // Providing an initial delay makes it more likely that both will be
639         // scheduled before either starts to run. Once started, samples will
640         // run ordered by their scheduled, interleaved times regardless of
641         // whatever interval the thread wakes up.
642         params[0].initial_delay = TimeDelta::FromMilliseconds(10);
643         params[0].sampling_interval = TimeDelta::FromMilliseconds(1);
644         params[0].samples_per_profile = 100000;
645 
646         params[1].initial_delay = TimeDelta::FromMilliseconds(10);
647         params[1].sampling_interval = TimeDelta::FromMilliseconds(1);
648         params[1].samples_per_profile = 100000;
649 
650         SampleRecordedCounter samples_recorded[size(params)];
651 
652         TestProfilerInfo profiler_info0(target_thread_token, params[0],
653                                         module_cache(), &samples_recorded[0]);
654         TestProfilerInfo profiler_info1(target_thread_token, params[1],
655                                         module_cache(), &samples_recorded[1]);
656 
657         profiler_info0.profiler.Start();
658         profiler_info1.profiler.Start();
659 
660         // Wait for both to start accumulating samples. Using a WaitableEvent is
661         // possible but gets complicated later on because there's no way of
662         // knowing if 0 or 1 additional sample will be taken after Stop() and
663         // thus no way of knowing how many Wait() calls to make on it.
664         while (samples_recorded[0].Get() == 0 || samples_recorded[1].Get() == 0)
665           PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
666 
667         // Ensure that the first sampler can be safely stopped while the second
668         // continues to run. The stopped first profiler will still have a
669         // RecordSampleTask pending that will do nothing when executed because
670         // the collection will have been removed by Stop().
671         profiler_info0.profiler.Stop();
672         profiler_info0.completed.Wait();
673         size_t count0 = samples_recorded[0].Get();
674         size_t count1 = samples_recorded[1].Get();
675 
676         // Waiting for the second sampler to collect a couple samples ensures
677         // that the pending RecordSampleTask for the first has executed because
678         // tasks are always ordered by their next scheduled time.
679         while (samples_recorded[1].Get() < count1 + 2)
680           PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
681 
682         // Ensure that the first profiler didn't do anything since it was
683         // stopped.
684         EXPECT_EQ(count0, samples_recorded[0].Get());
685       }));
686 }
687 
688 // Checks that no sample are captured if the profiling is stopped during the
689 // initial delay.
PROFILER_TEST_F(StackSamplingProfilerTest,StopDuringInitialDelay)690 PROFILER_TEST_F(StackSamplingProfilerTest, StopDuringInitialDelay) {
691   SamplingParams params;
692   params.initial_delay = TimeDelta::FromSeconds(60);
693 
694   std::vector<std::vector<Frame>> samples =
695       CaptureSamples(params, TimeDelta::FromMilliseconds(0), module_cache());
696 
697   EXPECT_TRUE(samples.empty());
698 }
699 
700 // Checks that tasks can be stopped before completion and incomplete samples are
701 // captured.
PROFILER_TEST_F(StackSamplingProfilerTest,StopDuringInterSampleInterval)702 PROFILER_TEST_F(StackSamplingProfilerTest, StopDuringInterSampleInterval) {
703   // Test delegate that counts samples.
704   class SampleRecordedEvent : public StackSamplerTestDelegate {
705    public:
706     SampleRecordedEvent()
707         : sample_recorded_(WaitableEvent::ResetPolicy::MANUAL,
708                            WaitableEvent::InitialState::NOT_SIGNALED) {}
709 
710     void OnPreStackWalk() override { sample_recorded_.Signal(); }
711 
712     void WaitForSample() { sample_recorded_.Wait(); }
713 
714    private:
715     WaitableEvent sample_recorded_;
716   };
717 
718   WithTargetThread(BindLambdaForTesting(
719       [this](SamplingProfilerThreadToken target_thread_token) {
720         SamplingParams params;
721 
722         params.sampling_interval = AVeryLongTimeDelta();
723         params.samples_per_profile = 2;
724 
725         SampleRecordedEvent samples_recorded;
726         TestProfilerInfo profiler_info(target_thread_token, params,
727                                        module_cache(), &samples_recorded);
728 
729         profiler_info.profiler.Start();
730 
731         // Wait for profiler to start accumulating samples.
732         samples_recorded.WaitForSample();
733 
734         // Ensure that it can stop safely.
735         profiler_info.profiler.Stop();
736         profiler_info.completed.Wait();
737 
738         EXPECT_EQ(1u, profiler_info.profile.samples.size());
739       }));
740 }
741 
PROFILER_TEST_F(StackSamplingProfilerTest,GetNextSampleTime_NormalExecution)742 PROFILER_TEST_F(StackSamplingProfilerTest, GetNextSampleTime_NormalExecution) {
743   const auto& GetNextSampleTime =
744       StackSamplingProfiler::TestPeer::GetNextSampleTime;
745 
746   const TimeTicks scheduled_current_sample_time = TimeTicks::UnixEpoch();
747   const TimeDelta sampling_interval = TimeDelta::FromMilliseconds(10);
748 
749   // When executing the sample at exactly the scheduled time the next sample
750   // should be one interval later.
751   EXPECT_EQ(scheduled_current_sample_time + sampling_interval,
752             GetNextSampleTime(scheduled_current_sample_time, sampling_interval,
753                               scheduled_current_sample_time));
754 
755   // When executing the sample less than half an interval after the scheduled
756   // time the next sample also should be one interval later.
757   EXPECT_EQ(scheduled_current_sample_time + sampling_interval,
758             GetNextSampleTime(
759                 scheduled_current_sample_time, sampling_interval,
760                 scheduled_current_sample_time + 0.4 * sampling_interval));
761 
762   // When executing the sample less than half an interval before the scheduled
763   // time the next sample also should be one interval later. This is not
764   // expected to occur in practice since delayed tasks never run early.
765   EXPECT_EQ(scheduled_current_sample_time + sampling_interval,
766             GetNextSampleTime(
767                 scheduled_current_sample_time, sampling_interval,
768                 scheduled_current_sample_time - 0.4 * sampling_interval));
769 }
770 
PROFILER_TEST_F(StackSamplingProfilerTest,GetNextSampleTime_DelayedExecution)771 PROFILER_TEST_F(StackSamplingProfilerTest, GetNextSampleTime_DelayedExecution) {
772   const auto& GetNextSampleTime =
773       StackSamplingProfiler::TestPeer::GetNextSampleTime;
774 
775   const TimeTicks scheduled_current_sample_time = TimeTicks::UnixEpoch();
776   const TimeDelta sampling_interval = TimeDelta::FromMilliseconds(10);
777 
778   // When executing the sample between 0.5 and 1.5 intervals after the scheduled
779   // time the next sample should be two intervals later.
780   EXPECT_EQ(scheduled_current_sample_time + 2 * sampling_interval,
781             GetNextSampleTime(
782                 scheduled_current_sample_time, sampling_interval,
783                 scheduled_current_sample_time + 0.6 * sampling_interval));
784   EXPECT_EQ(scheduled_current_sample_time + 2 * sampling_interval,
785             GetNextSampleTime(
786                 scheduled_current_sample_time, sampling_interval,
787                 scheduled_current_sample_time + 1.0 * sampling_interval));
788   EXPECT_EQ(scheduled_current_sample_time + 2 * sampling_interval,
789             GetNextSampleTime(
790                 scheduled_current_sample_time, sampling_interval,
791                 scheduled_current_sample_time + 1.4 * sampling_interval));
792 
793   // Similarly when executing the sample between 9.5 and 10.5 intervals after
794   // the scheduled time the next sample should be 11 intervals later.
795   EXPECT_EQ(scheduled_current_sample_time + 11 * sampling_interval,
796             GetNextSampleTime(
797                 scheduled_current_sample_time, sampling_interval,
798                 scheduled_current_sample_time + 9.6 * sampling_interval));
799   EXPECT_EQ(scheduled_current_sample_time + 11 * sampling_interval,
800             GetNextSampleTime(
801                 scheduled_current_sample_time, sampling_interval,
802                 scheduled_current_sample_time + 10.0 * sampling_interval));
803   EXPECT_EQ(scheduled_current_sample_time + 11 * sampling_interval,
804             GetNextSampleTime(
805                 scheduled_current_sample_time, sampling_interval,
806                 scheduled_current_sample_time + 10.4 * sampling_interval));
807 }
808 
809 // Checks that we can destroy the profiler while profiling.
PROFILER_TEST_F(StackSamplingProfilerTest,DestroyProfilerWhileProfiling)810 PROFILER_TEST_F(StackSamplingProfilerTest, DestroyProfilerWhileProfiling) {
811   SamplingParams params;
812   params.sampling_interval = TimeDelta::FromMilliseconds(10);
813 
814   Profile profile;
815   WithTargetThread(BindLambdaForTesting([&, this](SamplingProfilerThreadToken
816                                                       target_thread_token) {
817     std::unique_ptr<StackSamplingProfiler> profiler;
818     auto profile_builder = std::make_unique<TestProfileBuilder>(
819         module_cache(),
820         BindLambdaForTesting([&profile](Profile result_profile) {
821           profile = std::move(result_profile);
822         }));
823     profiler.reset(new StackSamplingProfiler(
824         target_thread_token, params, std::move(profile_builder),
825         CreateCoreUnwindersFactoryForTesting(module_cache())));
826     profiler->Start();
827     profiler.reset();
828 
829     // Wait longer than a sample interval to catch any use-after-free actions by
830     // the profiler thread.
831     PlatformThread::Sleep(TimeDelta::FromMilliseconds(50));
832   }));
833 }
834 
835 // Checks that the different profilers may be run.
PROFILER_TEST_F(StackSamplingProfilerTest,CanRunMultipleProfilers)836 PROFILER_TEST_F(StackSamplingProfilerTest, CanRunMultipleProfilers) {
837   SamplingParams params;
838   params.sampling_interval = TimeDelta::FromMilliseconds(0);
839   params.samples_per_profile = 1;
840 
841   std::vector<std::vector<Frame>> samples =
842       CaptureSamples(params, AVeryLongTimeDelta(), module_cache());
843   ASSERT_EQ(1u, samples.size());
844 
845   samples = CaptureSamples(params, AVeryLongTimeDelta(), module_cache());
846   ASSERT_EQ(1u, samples.size());
847 }
848 
849 // Checks that a sampler can be started while another is running.
PROFILER_TEST_F(StackSamplingProfilerTest,MultipleStart)850 PROFILER_TEST_F(StackSamplingProfilerTest, MultipleStart) {
851   WithTargetThread(BindLambdaForTesting(
852       [this](SamplingProfilerThreadToken target_thread_token) {
853         std::vector<SamplingParams> params(2);
854 
855         params[0].initial_delay = AVeryLongTimeDelta();
856         params[0].samples_per_profile = 1;
857 
858         params[1].sampling_interval = TimeDelta::FromMilliseconds(1);
859         params[1].samples_per_profile = 1;
860 
861         std::vector<std::unique_ptr<TestProfilerInfo>> profiler_infos =
862             CreateProfilers(target_thread_token, params, module_cache());
863 
864         profiler_infos[0]->profiler.Start();
865         profiler_infos[1]->profiler.Start();
866         profiler_infos[1]->completed.Wait();
867         EXPECT_EQ(1u, profiler_infos[1]->profile.samples.size());
868       }));
869 }
870 
871 // Checks that the profile duration and the sampling interval are calculated
872 // correctly. Also checks that RecordMetadata() is invoked each time a sample
873 // is recorded.
PROFILER_TEST_F(StackSamplingProfilerTest,ProfileGeneralInfo)874 PROFILER_TEST_F(StackSamplingProfilerTest, ProfileGeneralInfo) {
875   WithTargetThread(BindLambdaForTesting(
876       [this](SamplingProfilerThreadToken target_thread_token) {
877         SamplingParams params;
878         params.sampling_interval = TimeDelta::FromMilliseconds(1);
879         params.samples_per_profile = 3;
880 
881         TestProfilerInfo profiler_info(target_thread_token, params,
882                                        module_cache());
883 
884         profiler_info.profiler.Start();
885         profiler_info.completed.Wait();
886         EXPECT_EQ(3u, profiler_info.profile.samples.size());
887 
888         // The profile duration should be greater than the total sampling
889         // intervals.
890         EXPECT_GT(profiler_info.profile.profile_duration,
891                   profiler_info.profile.sampling_period * 3);
892 
893         EXPECT_EQ(TimeDelta::FromMilliseconds(1),
894                   profiler_info.profile.sampling_period);
895 
896         // The number of invocations of RecordMetadata() should be equal to the
897         // number of samples recorded.
898         EXPECT_EQ(3, profiler_info.profile.record_metadata_count);
899       }));
900 }
901 
902 // Checks that the sampling thread can shut down.
PROFILER_TEST_F(StackSamplingProfilerTest,SamplerIdleShutdown)903 PROFILER_TEST_F(StackSamplingProfilerTest, SamplerIdleShutdown) {
904   SamplingParams params;
905   params.sampling_interval = TimeDelta::FromMilliseconds(0);
906   params.samples_per_profile = 1;
907 
908   std::vector<std::vector<Frame>> samples =
909       CaptureSamples(params, AVeryLongTimeDelta(), module_cache());
910   ASSERT_EQ(1u, samples.size());
911 
912   // Capture thread should still be running at this point.
913   ASSERT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
914 
915   // Initiate an "idle" shutdown and ensure it happens. Idle-shutdown was
916   // disabled by the test fixture so the test will fail due to a timeout if
917   // it does not exit.
918   StackSamplingProfiler::TestPeer::PerformSamplingThreadIdleShutdown(false);
919 
920   // While the shutdown has been initiated, the actual exit of the thread still
921   // happens asynchronously. Watch until the thread actually exits. This test
922   // will time-out in the case of failure.
923   while (StackSamplingProfiler::TestPeer::IsSamplingThreadRunning())
924     PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
925 }
926 
927 // Checks that additional requests will restart a stopped profiler.
PROFILER_TEST_F(StackSamplingProfilerTest,WillRestartSamplerAfterIdleShutdown)928 PROFILER_TEST_F(StackSamplingProfilerTest,
929                 WillRestartSamplerAfterIdleShutdown) {
930   SamplingParams params;
931   params.sampling_interval = TimeDelta::FromMilliseconds(0);
932   params.samples_per_profile = 1;
933 
934   std::vector<std::vector<Frame>> samples =
935       CaptureSamples(params, AVeryLongTimeDelta(), module_cache());
936   ASSERT_EQ(1u, samples.size());
937 
938   // Capture thread should still be running at this point.
939   ASSERT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
940 
941   // Post a ShutdownTask on the sampling thread which, when executed, will
942   // mark the thread as EXITING and begin shut down of the thread.
943   StackSamplingProfiler::TestPeer::PerformSamplingThreadIdleShutdown(false);
944 
945   // Ensure another capture will start the sampling thread and run.
946   samples = CaptureSamples(params, AVeryLongTimeDelta(), module_cache());
947   ASSERT_EQ(1u, samples.size());
948   EXPECT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
949 }
950 
951 // Checks that it's safe to stop a task after it's completed and the sampling
952 // thread has shut-down for being idle.
PROFILER_TEST_F(StackSamplingProfilerTest,StopAfterIdleShutdown)953 PROFILER_TEST_F(StackSamplingProfilerTest, StopAfterIdleShutdown) {
954   WithTargetThread(BindLambdaForTesting(
955       [this](SamplingProfilerThreadToken target_thread_token) {
956         SamplingParams params;
957 
958         params.sampling_interval = TimeDelta::FromMilliseconds(1);
959         params.samples_per_profile = 1;
960 
961         TestProfilerInfo profiler_info(target_thread_token, params,
962                                        module_cache());
963 
964         profiler_info.profiler.Start();
965         profiler_info.completed.Wait();
966 
967         // Capture thread should still be running at this point.
968         ASSERT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
969 
970         // Perform an idle shutdown.
971         StackSamplingProfiler::TestPeer::PerformSamplingThreadIdleShutdown(
972             false);
973 
974         // Stop should be safe though its impossible to know at this moment if
975         // the sampling thread has completely exited or will just "stop soon".
976         profiler_info.profiler.Stop();
977       }));
978 }
979 
980 // Checks that profilers can run both before and after the sampling thread has
981 // started.
PROFILER_TEST_F(StackSamplingProfilerTest,ProfileBeforeAndAfterSamplingThreadRunning)982 PROFILER_TEST_F(StackSamplingProfilerTest,
983                 ProfileBeforeAndAfterSamplingThreadRunning) {
984   WithTargetThread(BindLambdaForTesting(
985       [this](SamplingProfilerThreadToken target_thread_token) {
986         std::vector<SamplingParams> params(2);
987 
988         params[0].initial_delay = AVeryLongTimeDelta();
989         params[0].sampling_interval = TimeDelta::FromMilliseconds(1);
990         params[0].samples_per_profile = 1;
991 
992         params[1].initial_delay = TimeDelta::FromMilliseconds(0);
993         params[1].sampling_interval = TimeDelta::FromMilliseconds(1);
994         params[1].samples_per_profile = 1;
995 
996         std::vector<std::unique_ptr<TestProfilerInfo>> profiler_infos =
997             CreateProfilers(target_thread_token, params, module_cache());
998 
999         // First profiler is started when there has never been a sampling
1000         // thread.
1001         EXPECT_FALSE(
1002             StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
1003         profiler_infos[0]->profiler.Start();
1004         // Second profiler is started when sampling thread is already running.
1005         EXPECT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
1006         profiler_infos[1]->profiler.Start();
1007 
1008         // Only the second profiler should finish before test times out.
1009         size_t completed_profiler = WaitForSamplingComplete(profiler_infos);
1010         EXPECT_EQ(1U, completed_profiler);
1011       }));
1012 }
1013 
1014 // Checks that an idle-shutdown task will abort if a new profiler starts
1015 // between when it was posted and when it runs.
PROFILER_TEST_F(StackSamplingProfilerTest,IdleShutdownAbort)1016 PROFILER_TEST_F(StackSamplingProfilerTest, IdleShutdownAbort) {
1017   WithTargetThread(BindLambdaForTesting(
1018       [this](SamplingProfilerThreadToken target_thread_token) {
1019         SamplingParams params;
1020 
1021         params.sampling_interval = TimeDelta::FromMilliseconds(1);
1022         params.samples_per_profile = 1;
1023 
1024         TestProfilerInfo profiler_info(target_thread_token, params,
1025                                        module_cache());
1026 
1027         profiler_info.profiler.Start();
1028         profiler_info.completed.Wait();
1029         EXPECT_EQ(1u, profiler_info.profile.samples.size());
1030 
1031         // Perform an idle shutdown but simulate that a new capture is started
1032         // before it can actually run.
1033         StackSamplingProfiler::TestPeer::PerformSamplingThreadIdleShutdown(
1034             true);
1035 
1036         // Though the shutdown-task has been executed, any actual exit of the
1037         // thread is asynchronous so there is no way to detect that *didn't*
1038         // exit except to wait a reasonable amount of time and then check. Since
1039         // the thread was just running ("perform" blocked until it was), it
1040         // should finish almost immediately and without any waiting for tasks or
1041         // events.
1042         PlatformThread::Sleep(TimeDelta::FromMilliseconds(200));
1043         EXPECT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
1044 
1045         // Ensure that it's still possible to run another sampler.
1046         TestProfilerInfo another_info(target_thread_token, params,
1047                                       module_cache());
1048         another_info.profiler.Start();
1049         another_info.completed.Wait();
1050         EXPECT_EQ(1u, another_info.profile.samples.size());
1051       }));
1052 }
1053 
1054 // Checks that synchronized multiple sampling requests execute in parallel.
PROFILER_TEST_F(StackSamplingProfilerTest,ConcurrentProfiling_InSync)1055 PROFILER_TEST_F(StackSamplingProfilerTest, ConcurrentProfiling_InSync) {
1056   WithTargetThread(BindLambdaForTesting(
1057       [this](SamplingProfilerThreadToken target_thread_token) {
1058         std::vector<SamplingParams> params(2);
1059 
1060         // Providing an initial delay makes it more likely that both will be
1061         // scheduled before either starts to run. Once started, samples will
1062         // run ordered by their scheduled, interleaved times regardless of
1063         // whatever interval the thread wakes up. Thus, total execution time
1064         // will be 10ms (delay) + 10x1ms (sampling) + 1/2 timer minimum
1065         // interval.
1066         params[0].initial_delay = TimeDelta::FromMilliseconds(10);
1067         params[0].sampling_interval = TimeDelta::FromMilliseconds(1);
1068         params[0].samples_per_profile = 9;
1069 
1070         params[1].initial_delay = TimeDelta::FromMilliseconds(11);
1071         params[1].sampling_interval = TimeDelta::FromMilliseconds(1);
1072         params[1].samples_per_profile = 8;
1073 
1074         std::vector<std::unique_ptr<TestProfilerInfo>> profiler_infos =
1075             CreateProfilers(target_thread_token, params, module_cache());
1076 
1077         profiler_infos[0]->profiler.Start();
1078         profiler_infos[1]->profiler.Start();
1079 
1080         // Wait for one profiler to finish.
1081         size_t completed_profiler = WaitForSamplingComplete(profiler_infos);
1082 
1083         size_t other_profiler = 1 - completed_profiler;
1084         // Wait for the other profiler to finish.
1085         profiler_infos[other_profiler]->completed.Wait();
1086 
1087         // Ensure each got the correct number of samples.
1088         EXPECT_EQ(9u, profiler_infos[0]->profile.samples.size());
1089         EXPECT_EQ(8u, profiler_infos[1]->profile.samples.size());
1090       }));
1091 }
1092 
1093 // Checks that several mixed sampling requests execute in parallel.
PROFILER_TEST_F(StackSamplingProfilerTest,ConcurrentProfiling_Mixed)1094 PROFILER_TEST_F(StackSamplingProfilerTest, ConcurrentProfiling_Mixed) {
1095   WithTargetThread(BindLambdaForTesting(
1096       [this](SamplingProfilerThreadToken target_thread_token) {
1097         std::vector<SamplingParams> params(3);
1098 
1099         params[0].initial_delay = TimeDelta::FromMilliseconds(8);
1100         params[0].sampling_interval = TimeDelta::FromMilliseconds(4);
1101         params[0].samples_per_profile = 10;
1102 
1103         params[1].initial_delay = TimeDelta::FromMilliseconds(9);
1104         params[1].sampling_interval = TimeDelta::FromMilliseconds(3);
1105         params[1].samples_per_profile = 10;
1106 
1107         params[2].initial_delay = TimeDelta::FromMilliseconds(10);
1108         params[2].sampling_interval = TimeDelta::FromMilliseconds(2);
1109         params[2].samples_per_profile = 10;
1110 
1111         std::vector<std::unique_ptr<TestProfilerInfo>> profiler_infos =
1112             CreateProfilers(target_thread_token, params, module_cache());
1113 
1114         for (auto& i : profiler_infos)
1115           i->profiler.Start();
1116 
1117         // Wait for one profiler to finish.
1118         size_t completed_profiler = WaitForSamplingComplete(profiler_infos);
1119         EXPECT_EQ(10u,
1120                   profiler_infos[completed_profiler]->profile.samples.size());
1121         // Stop and destroy all profilers, always in the same order. Don't
1122         // crash.
1123         for (auto& i : profiler_infos)
1124           i->profiler.Stop();
1125         for (auto& i : profiler_infos)
1126           i.reset();
1127       }));
1128 }
1129 
1130 // Checks that different threads can be sampled in parallel.
PROFILER_TEST_F(StackSamplingProfilerTest,MultipleSampledThreads)1131 PROFILER_TEST_F(StackSamplingProfilerTest, MultipleSampledThreads) {
1132   UnwindScenario scenario1(BindRepeating(&CallWithPlainFunction));
1133   UnwindScenario::SampleEvents events1;
1134   TargetThread target_thread1(
1135       BindLambdaForTesting([&]() { scenario1.Execute(&events1); }));
1136   PlatformThreadHandle target_thread_handle1;
1137   EXPECT_TRUE(
1138       PlatformThread::Create(0, &target_thread1, &target_thread_handle1));
1139   events1.ready_for_sample.Wait();
1140 
1141   UnwindScenario scenario2(BindRepeating(&CallWithPlainFunction));
1142   UnwindScenario::SampleEvents events2;
1143   TargetThread target_thread2(
1144       BindLambdaForTesting([&]() { scenario2.Execute(&events2); }));
1145 
1146   PlatformThreadHandle target_thread_handle2;
1147   EXPECT_TRUE(
1148       PlatformThread::Create(0, &target_thread2, &target_thread_handle2));
1149   events2.ready_for_sample.Wait();
1150 
1151   // Providing an initial delay makes it more likely that both will be
1152   // scheduled before either starts to run. Once started, samples will
1153   // run ordered by their scheduled, interleaved times regardless of
1154   // whatever interval the thread wakes up.
1155   SamplingParams params1, params2;
1156   params1.initial_delay = TimeDelta::FromMilliseconds(10);
1157   params1.sampling_interval = TimeDelta::FromMilliseconds(1);
1158   params1.samples_per_profile = 9;
1159   params2.initial_delay = TimeDelta::FromMilliseconds(10);
1160   params2.sampling_interval = TimeDelta::FromMilliseconds(1);
1161   params2.samples_per_profile = 8;
1162 
1163   Profile profile1, profile2;
1164 
1165   WaitableEvent sampling_thread_completed1(
1166       WaitableEvent::ResetPolicy::MANUAL,
1167       WaitableEvent::InitialState::NOT_SIGNALED);
1168   StackSamplingProfiler profiler1(
1169       target_thread1.thread_token(), params1,
1170       std::make_unique<TestProfileBuilder>(
1171           module_cache(),
1172           BindLambdaForTesting(
1173               [&profile1, &sampling_thread_completed1](Profile result_profile) {
1174                 profile1 = std::move(result_profile);
1175                 sampling_thread_completed1.Signal();
1176               })),
1177       CreateCoreUnwindersFactoryForTesting(module_cache()));
1178 
1179   WaitableEvent sampling_thread_completed2(
1180       WaitableEvent::ResetPolicy::MANUAL,
1181       WaitableEvent::InitialState::NOT_SIGNALED);
1182   StackSamplingProfiler profiler2(
1183       target_thread2.thread_token(), params2,
1184       std::make_unique<TestProfileBuilder>(
1185           module_cache(),
1186           BindLambdaForTesting(
1187               [&profile2, &sampling_thread_completed2](Profile result_profile) {
1188                 profile2 = std::move(result_profile);
1189                 sampling_thread_completed2.Signal();
1190               })),
1191       CreateCoreUnwindersFactoryForTesting(module_cache()));
1192 
1193   // Finally the real work.
1194   profiler1.Start();
1195   profiler2.Start();
1196   sampling_thread_completed1.Wait();
1197   sampling_thread_completed2.Wait();
1198   EXPECT_EQ(9u, profile1.samples.size());
1199   EXPECT_EQ(8u, profile2.samples.size());
1200 
1201   events1.sample_finished.Signal();
1202   events2.sample_finished.Signal();
1203   PlatformThread::Join(target_thread_handle1);
1204   PlatformThread::Join(target_thread_handle2);
1205 }
1206 
1207 // A simple thread that runs a profiler on another thread.
1208 class ProfilerThread : public SimpleThread {
1209  public:
ProfilerThread(const std::string & name,SamplingProfilerThreadToken thread_token,const SamplingParams & params,ModuleCache * module_cache)1210   ProfilerThread(const std::string& name,
1211                  SamplingProfilerThreadToken thread_token,
1212                  const SamplingParams& params,
1213                  ModuleCache* module_cache)
1214       : SimpleThread(name, Options()),
1215         run_(WaitableEvent::ResetPolicy::MANUAL,
1216              WaitableEvent::InitialState::NOT_SIGNALED),
1217         completed_(WaitableEvent::ResetPolicy::MANUAL,
1218                    WaitableEvent::InitialState::NOT_SIGNALED),
1219         profiler_(thread_token,
1220                   params,
1221                   std::make_unique<TestProfileBuilder>(
1222                       module_cache,
1223                       BindLambdaForTesting([this](Profile result_profile) {
1224                         profile_ = std::move(result_profile);
1225                         completed_.Signal();
1226                       })),
1227                   CreateCoreUnwindersFactoryForTesting(module_cache)) {}
Run()1228   void Run() override {
1229     run_.Wait();
1230     profiler_.Start();
1231   }
1232 
Go()1233   void Go() { run_.Signal(); }
1234 
Wait()1235   void Wait() { completed_.Wait(); }
1236 
profile()1237   Profile& profile() { return profile_; }
1238 
1239  private:
1240   WaitableEvent run_;
1241 
1242   Profile profile_;
1243   WaitableEvent completed_;
1244   StackSamplingProfiler profiler_;
1245 };
1246 
1247 // Checks that different threads can run samplers in parallel.
PROFILER_TEST_F(StackSamplingProfilerTest,MultipleProfilerThreads)1248 PROFILER_TEST_F(StackSamplingProfilerTest, MultipleProfilerThreads) {
1249   WithTargetThread(
1250       BindLambdaForTesting([](SamplingProfilerThreadToken target_thread_token) {
1251         // Providing an initial delay makes it more likely that both will be
1252         // scheduled before either starts to run. Once started, samples will
1253         // run ordered by their scheduled, interleaved times regardless of
1254         // whatever interval the thread wakes up.
1255         SamplingParams params1, params2;
1256         params1.initial_delay = TimeDelta::FromMilliseconds(10);
1257         params1.sampling_interval = TimeDelta::FromMilliseconds(1);
1258         params1.samples_per_profile = 9;
1259         params2.initial_delay = TimeDelta::FromMilliseconds(10);
1260         params2.sampling_interval = TimeDelta::FromMilliseconds(1);
1261         params2.samples_per_profile = 8;
1262 
1263         // Start the profiler threads and give them a moment to get going.
1264         ModuleCache module_cache1;
1265         ProfilerThread profiler_thread1("profiler1", target_thread_token,
1266                                         params1, &module_cache1);
1267         ModuleCache module_cache2;
1268         ProfilerThread profiler_thread2("profiler2", target_thread_token,
1269                                         params2, &module_cache2);
1270         profiler_thread1.Start();
1271         profiler_thread2.Start();
1272         PlatformThread::Sleep(TimeDelta::FromMilliseconds(10));
1273 
1274         // This will (approximately) synchronize the two threads.
1275         profiler_thread1.Go();
1276         profiler_thread2.Go();
1277 
1278         // Wait for them both to finish and validate collection.
1279         profiler_thread1.Wait();
1280         profiler_thread2.Wait();
1281         EXPECT_EQ(9u, profiler_thread1.profile().samples.size());
1282         EXPECT_EQ(8u, profiler_thread2.profile().samples.size());
1283 
1284         profiler_thread1.Join();
1285         profiler_thread2.Join();
1286       }));
1287 }
1288 
PROFILER_TEST_F(StackSamplingProfilerTest,AddAuxUnwinder_BeforeStart)1289 PROFILER_TEST_F(StackSamplingProfilerTest, AddAuxUnwinder_BeforeStart) {
1290   SamplingParams params;
1291   params.sampling_interval = TimeDelta::FromMilliseconds(0);
1292   params.samples_per_profile = 1;
1293 
1294   UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
1295 
1296   int add_initial_modules_invocation_count = 0;
1297   const auto add_initial_modules_callback =
1298       [&add_initial_modules_invocation_count]() {
1299         ++add_initial_modules_invocation_count;
1300       };
1301 
1302   Profile profile;
1303   WithTargetThread(
1304       &scenario,
1305       BindLambdaForTesting(
1306           [&](SamplingProfilerThreadToken target_thread_token) {
1307             WaitableEvent sampling_thread_completed(
1308                 WaitableEvent::ResetPolicy::MANUAL,
1309                 WaitableEvent::InitialState::NOT_SIGNALED);
1310             StackSamplingProfiler profiler(
1311                 target_thread_token, params,
1312                 std::make_unique<TestProfileBuilder>(
1313                     module_cache(),
1314                     BindLambdaForTesting([&profile, &sampling_thread_completed](
1315                                              Profile result_profile) {
1316                       profile = std::move(result_profile);
1317                       sampling_thread_completed.Signal();
1318                     })),
1319                 CreateCoreUnwindersFactoryForTesting(module_cache()));
1320             profiler.AddAuxUnwinder(std::make_unique<TestAuxUnwinder>(
1321                 Frame(23, nullptr),
1322                 BindLambdaForTesting(add_initial_modules_callback)));
1323             profiler.Start();
1324             sampling_thread_completed.Wait();
1325           }));
1326 
1327   ASSERT_EQ(1, add_initial_modules_invocation_count);
1328 
1329   // The sample should have one frame from the context values and one from the
1330   // TestAuxUnwinder.
1331   ASSERT_EQ(1u, profile.samples.size());
1332   const std::vector<Frame>& frames = profile.samples[0];
1333 
1334   ASSERT_EQ(2u, frames.size());
1335   EXPECT_EQ(23u, frames[1].instruction_pointer);
1336   EXPECT_EQ(nullptr, frames[1].module);
1337 }
1338 
PROFILER_TEST_F(StackSamplingProfilerTest,AddAuxUnwinder_AfterStart)1339 PROFILER_TEST_F(StackSamplingProfilerTest, AddAuxUnwinder_AfterStart) {
1340   SamplingParams params;
1341   params.sampling_interval = TimeDelta::FromMilliseconds(0);
1342   params.samples_per_profile = 1;
1343 
1344   UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
1345 
1346   int add_initial_modules_invocation_count = 0;
1347   const auto add_initial_modules_callback =
1348       [&add_initial_modules_invocation_count]() {
1349         ++add_initial_modules_invocation_count;
1350       };
1351 
1352   Profile profile;
1353   WithTargetThread(
1354       &scenario,
1355       BindLambdaForTesting(
1356           [&](SamplingProfilerThreadToken target_thread_token) {
1357             WaitableEvent sampling_thread_completed(
1358                 WaitableEvent::ResetPolicy::MANUAL,
1359                 WaitableEvent::InitialState::NOT_SIGNALED);
1360             StackSamplingProfiler profiler(
1361                 target_thread_token, params,
1362                 std::make_unique<TestProfileBuilder>(
1363                     module_cache(),
1364                     BindLambdaForTesting([&profile, &sampling_thread_completed](
1365                                              Profile result_profile) {
1366                       profile = std::move(result_profile);
1367                       sampling_thread_completed.Signal();
1368                     })),
1369                 CreateCoreUnwindersFactoryForTesting(module_cache()));
1370             profiler.Start();
1371             profiler.AddAuxUnwinder(std::make_unique<TestAuxUnwinder>(
1372                 Frame(23, nullptr),
1373                 BindLambdaForTesting(add_initial_modules_callback)));
1374             sampling_thread_completed.Wait();
1375           }));
1376 
1377   ASSERT_EQ(1, add_initial_modules_invocation_count);
1378 
1379   // The sample should have one frame from the context values and one from the
1380   // TestAuxUnwinder.
1381   ASSERT_EQ(1u, profile.samples.size());
1382   const std::vector<Frame>& frames = profile.samples[0];
1383 
1384   ASSERT_EQ(2u, frames.size());
1385   EXPECT_EQ(23u, frames[1].instruction_pointer);
1386   EXPECT_EQ(nullptr, frames[1].module);
1387 }
1388 
PROFILER_TEST_F(StackSamplingProfilerTest,AddAuxUnwinder_AfterStop)1389 PROFILER_TEST_F(StackSamplingProfilerTest, AddAuxUnwinder_AfterStop) {
1390   SamplingParams params;
1391   params.sampling_interval = TimeDelta::FromMilliseconds(0);
1392   params.samples_per_profile = 1;
1393 
1394   UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
1395 
1396   Profile profile;
1397   WithTargetThread(
1398       &scenario,
1399       BindLambdaForTesting(
1400           [&](SamplingProfilerThreadToken target_thread_token) {
1401             WaitableEvent sampling_thread_completed(
1402                 WaitableEvent::ResetPolicy::MANUAL,
1403                 WaitableEvent::InitialState::NOT_SIGNALED);
1404             StackSamplingProfiler profiler(
1405                 target_thread_token, params,
1406                 std::make_unique<TestProfileBuilder>(
1407                     module_cache(),
1408                     BindLambdaForTesting([&profile, &sampling_thread_completed](
1409                                              Profile result_profile) {
1410                       profile = std::move(result_profile);
1411                       sampling_thread_completed.Signal();
1412                     })),
1413                 CreateCoreUnwindersFactoryForTesting(module_cache()));
1414             profiler.Start();
1415             profiler.Stop();
1416             profiler.AddAuxUnwinder(std::make_unique<TestAuxUnwinder>(
1417                 Frame(23, nullptr), base::RepeatingClosure()));
1418             sampling_thread_completed.Wait();
1419           }));
1420 
1421   // The AuxUnwinder should be accepted without error. It will have no effect
1422   // since the collection has stopped.
1423 }
1424 
1425 // Checks that requests to apply metadata to past samples are passed on to the
1426 // profile builder.
PROFILER_TEST_F(StackSamplingProfilerTest,ApplyMetadataToPastSamples_PassedToProfileBuilder)1427 PROFILER_TEST_F(StackSamplingProfilerTest,
1428                 ApplyMetadataToPastSamples_PassedToProfileBuilder) {
1429   // Runs the passed closure on the profiler thread after a sample is taken.
1430   class PostSampleInvoker : public StackSamplerTestDelegate {
1431    public:
1432     explicit PostSampleInvoker(RepeatingClosure post_sample_closure)
1433         : post_sample_closure_(std::move(post_sample_closure)) {}
1434 
1435     void OnPreStackWalk() override { post_sample_closure_.Run(); }
1436 
1437    private:
1438     RepeatingClosure post_sample_closure_;
1439   };
1440 
1441   // Thread-safe representation of the times that samples were taken.
1442   class SynchronizedSampleTimes {
1443    public:
1444     void AddNow() {
1445       AutoLock lock(lock_);
1446       times_.push_back(TimeTicks::Now());
1447     }
1448 
1449     std::vector<TimeTicks> GetTimes() {
1450       AutoLock lock(lock_);
1451       return times_;
1452     }
1453 
1454    private:
1455     Lock lock_;
1456     std::vector<TimeTicks> times_;
1457   };
1458 
1459   SamplingParams params;
1460   params.sampling_interval = TimeDelta::FromMilliseconds(10);
1461   // 10,000 samples ensures the profiler continues running until manually
1462   // stopped, after applying metadata.
1463   params.samples_per_profile = 10000;
1464 
1465   UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
1466 
1467   std::vector<TimeTicks> sample_times;
1468   Profile profile;
1469   WithTargetThread(
1470       &scenario,
1471       BindLambdaForTesting(
1472           [&](SamplingProfilerThreadToken target_thread_token) {
1473             SynchronizedSampleTimes synchronized_sample_times;
1474             WaitableEvent sample_seen(WaitableEvent::ResetPolicy::AUTOMATIC);
1475             PostSampleInvoker post_sample_invoker(BindLambdaForTesting([&]() {
1476               synchronized_sample_times.AddNow();
1477               sample_seen.Signal();
1478             }));
1479 
1480             StackSamplingProfiler profiler(
1481                 target_thread_token, params,
1482                 std::make_unique<TestProfileBuilder>(
1483                     module_cache(),
1484                     BindLambdaForTesting([&profile](Profile result_profile) {
1485                       profile = std::move(result_profile);
1486                     })),
1487                 CreateCoreUnwindersFactoryForTesting(module_cache()),
1488                 RepeatingClosure(), &post_sample_invoker);
1489             profiler.Start();
1490             // Wait for 5 samples to be collected.
1491             for (int i = 0; i < 5; ++i)
1492               sample_seen.Wait();
1493             sample_times = synchronized_sample_times.GetTimes();
1494             // Record metadata on past samples, with and without a key value.
1495             // The range [times[1], times[3]] is guaranteed to include only
1496             // samples 2 and 3, and likewise [times[2], times[4]] is guaranteed
1497             // to include only samples 3 and 4.
1498             ApplyMetadataToPastSamples(sample_times[1], sample_times[3],
1499                                        "TestMetadata1", 10);
1500             ApplyMetadataToPastSamples(sample_times[2], sample_times[4],
1501                                        "TestMetadata2", 100, 11);
1502             profiler.Stop();
1503           }));
1504 
1505   ASSERT_EQ(2u, profile.retrospective_metadata.size());
1506 
1507   const RetrospectiveMetadata& metadata1 = profile.retrospective_metadata[0];
1508   EXPECT_EQ(sample_times[1], metadata1.period_start);
1509   EXPECT_EQ(sample_times[3], metadata1.period_end);
1510   EXPECT_EQ(HashMetricName("TestMetadata1"), metadata1.item.name_hash);
1511   EXPECT_FALSE(metadata1.item.key.has_value());
1512   EXPECT_EQ(10, metadata1.item.value);
1513 
1514   const RetrospectiveMetadata& metadata2 = profile.retrospective_metadata[1];
1515   EXPECT_EQ(sample_times[2], metadata2.period_start);
1516   EXPECT_EQ(sample_times[4], metadata2.period_end);
1517   EXPECT_EQ(HashMetricName("TestMetadata2"), metadata2.item.name_hash);
1518   ASSERT_TRUE(metadata2.item.key.has_value());
1519   EXPECT_EQ(100, *metadata2.item.key);
1520   EXPECT_EQ(11, metadata2.item.value);
1521 }
1522 
1523 }  // namespace base
1524