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