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