Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(246)

Side by Side Diff: base/profiler/stack_sampling_profiler_unittest.cc

Issue 2702463003: NativeStackSampler implementation for Mac. (Closed)
Patch Set: 0u Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stddef.h> 5 #include <stddef.h>
6 #include <stdint.h> 6 #include <stdint.h>
7 7
8 #include <cstdlib> 8 #include <cstdlib>
9 #include <memory> 9 #include <memory>
10 #include <utility> 10 #include <utility>
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/compiler_specific.h" 14 #include "base/compiler_specific.h"
15 #include "base/files/file_util.h"
15 #include "base/macros.h" 16 #include "base/macros.h"
16 #include "base/memory/ptr_util.h" 17 #include "base/memory/ptr_util.h"
17 #include "base/message_loop/message_loop.h" 18 #include "base/message_loop/message_loop.h"
18 #include "base/native_library.h" 19 #include "base/native_library.h"
19 #include "base/path_service.h" 20 #include "base/path_service.h"
20 #include "base/profiler/native_stack_sampler.h" 21 #include "base/profiler/native_stack_sampler.h"
21 #include "base/profiler/stack_sampling_profiler.h" 22 #include "base/profiler/stack_sampling_profiler.h"
22 #include "base/run_loop.h" 23 #include "base/run_loop.h"
23 #include "base/scoped_native_library.h" 24 #include "base/scoped_native_library.h"
24 #include "base/strings/stringprintf.h" 25 #include "base/strings/stringprintf.h"
25 #include "base/strings/utf_string_conversions.h" 26 #include "base/strings/utf_string_conversions.h"
26 #include "base/synchronization/waitable_event.h" 27 #include "base/synchronization/waitable_event.h"
27 #include "base/threading/platform_thread.h" 28 #include "base/threading/platform_thread.h"
28 #include "base/time/time.h" 29 #include "base/time/time.h"
29 #include "build/build_config.h" 30 #include "build/build_config.h"
30 #include "testing/gtest/include/gtest/gtest.h" 31 #include "testing/gtest/include/gtest/gtest.h"
31 32
32 #if defined(OS_WIN) 33 #if defined(OS_WIN)
33 #include <intrin.h> 34 #include <intrin.h>
34 #include <malloc.h> 35 #include <malloc.h>
35 #include <windows.h> 36 #include <windows.h>
36 #else 37 #else
37 #include <alloca.h> 38 #include <alloca.h>
38 #endif 39 #endif
39 40
40 // STACK_SAMPLING_PROFILER_SUPPORTED is used to conditionally enable the tests 41 // STACK_SAMPLING_PROFILER_SUPPORTED is used to conditionally enable the tests
41 // below for supported platforms (currently Win x64). 42 // below for supported platforms (currently Win x64 and Mac x64).
42 #if defined(_WIN64) 43 #if defined(_WIN64) || defined(OS_MACOSX)
43 #define STACK_SAMPLING_PROFILER_SUPPORTED 1 44 #define STACK_SAMPLING_PROFILER_SUPPORTED 1
44 #endif 45 #endif
45 46
46 #if defined(OS_WIN) 47 #if defined(OS_WIN)
47 #pragma intrinsic(_ReturnAddress) 48 #pragma intrinsic(_ReturnAddress)
48 #endif 49 #endif
49 50
50 namespace base { 51 namespace base {
51 52
52 using SamplingParams = StackSamplingProfiler::SamplingParams; 53 using SamplingParams = StackSamplingProfiler::SamplingParams;
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 uintptr_t module_base_address = reinterpret_cast<uintptr_t>(library); 300 uintptr_t module_base_address = reinterpret_cast<uintptr_t>(library);
300 HMODULE module_handle; 301 HMODULE module_handle;
301 // Keep trying to get the module handle until the call fails. 302 // Keep trying to get the module handle until the call fails.
302 while (::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | 303 while (::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
303 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, 304 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
304 reinterpret_cast<LPCTSTR>(module_base_address), 305 reinterpret_cast<LPCTSTR>(module_base_address),
305 &module_handle) || 306 &module_handle) ||
306 ::GetLastError() != ERROR_MOD_NOT_FOUND) { 307 ::GetLastError() != ERROR_MOD_NOT_FOUND) {
307 PlatformThread::Sleep(TimeDelta::FromMilliseconds(1)); 308 PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
308 } 309 }
310 #elif defined(OS_MACOSX)
311 // Unloading a library on the Mac is synchronous.
309 #else 312 #else
310 NOTIMPLEMENTED(); 313 NOTIMPLEMENTED();
311 #endif 314 #endif
312 } 315 }
313 316
314 // Called on the profiler thread when complete, to collect profiles. 317 // Called on the profiler thread when complete, to collect profiles.
315 void SaveProfiles(CallStackProfiles* profiles, 318 void SaveProfiles(CallStackProfiles* profiles,
316 CallStackProfiles pending_profiles) { 319 CallStackProfiles pending_profiles) {
317 *profiles = std::move(pending_profiles); 320 *profiles = std::move(pending_profiles);
318 } 321 }
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 // SignalAndWaitUntilSignaled. The frame in the now-unloaded library is not 538 // SignalAndWaitUntilSignaled. The frame in the now-unloaded library is not
536 // recorded since we can't get module information. 539 // recorded since we can't get module information.
537 // 540 //
538 // ... WaitableEvent and system frames ... 541 // ... WaitableEvent and system frames ...
539 // TargetThread::SignalAndWaitUntilSignaled 542 // TargetThread::SignalAndWaitUntilSignaled
540 // TargetThread::OtherLibraryCallback 543 // TargetThread::OtherLibraryCallback
541 EXPECT_EQ(2, sample.frames.end() - end_frame) 544 EXPECT_EQ(2, sample.frames.end() - end_frame)
542 << "Stack:\n" 545 << "Stack:\n"
543 << FormatSampleForDiagnosticOutput(sample, profile.modules); 546 << FormatSampleForDiagnosticOutput(sample, profile.modules);
544 } else { 547 } else {
545 // We didn't wait for the asynchonous unloading to complete, so the results 548 // We didn't wait for the asynchronous unloading to complete, so the results
546 // are non-deterministic: if the library finished unloading we should have 549 // are non-deterministic: if the library finished unloading we should have
547 // the same stack as |wait_until_unloaded|, if not we should have the full 550 // the same stack as |wait_until_unloaded|, if not we should have the full
548 // stack. The important thing is that we should not crash. 551 // stack. The important thing is that we should not crash.
549 552
550 if ((sample.frames.end() - 1) - end_frame == 2) { 553 if ((sample.frames.end() - 1) - end_frame == 2) {
551 // This is the same case as |wait_until_unloaded|. 554 // This is the same case as |wait_until_unloaded|.
Avi (use Gerrit) 2017/02/16 06:11:15 FYI this isn't the same as above. Above is: EXPE
Mike Wittman 2017/02/16 21:51:34 Good catch. This should be just "if (sample.frames
Avi (use Gerrit) 2017/02/17 03:41:09 Spinning off into a separate review.
552 return; 555 return;
553 } 556 }
554 557
555 // Check that the stack contains a frame for 558 // Check that the stack contains a frame for
556 // TargetThread::CallThroughOtherLibrary(). 559 // TargetThread::CallThroughOtherLibrary().
557 Frames::const_iterator other_library_frame = FindFirstFrameWithinFunction( 560 Frames::const_iterator other_library_frame = FindFirstFrameWithinFunction(
558 sample, &TargetThread::CallThroughOtherLibrary); 561 sample, &TargetThread::CallThroughOtherLibrary);
559 ASSERT_TRUE(other_library_frame != sample.frames.end()) 562 ASSERT_TRUE(other_library_frame != sample.frames.end())
560 << "Function at " 563 << "Function at "
561 << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>( 564 << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 Frames::const_iterator loc = FindFirstFrameWithinFunction( 618 Frames::const_iterator loc = FindFirstFrameWithinFunction(
616 sample, &TargetThread::SignalAndWaitUntilSignaled); 619 sample, &TargetThread::SignalAndWaitUntilSignaled);
617 ASSERT_TRUE(loc != sample.frames.end()) 620 ASSERT_TRUE(loc != sample.frames.end())
618 << "Function at " 621 << "Function at "
619 << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>( 622 << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
620 &TargetThread::SignalAndWaitUntilSignaled)) 623 &TargetThread::SignalAndWaitUntilSignaled))
621 << " was not found in stack:\n" 624 << " was not found in stack:\n"
622 << FormatSampleForDiagnosticOutput(sample, profile.modules); 625 << FormatSampleForDiagnosticOutput(sample, profile.modules);
623 FilePath executable_path; 626 FilePath executable_path;
624 EXPECT_TRUE(PathService::Get(FILE_EXE, &executable_path)); 627 EXPECT_TRUE(PathService::Get(FILE_EXE, &executable_path));
625 EXPECT_EQ(executable_path, profile.modules[loc->module_index].filename); 628 EXPECT_EQ(executable_path,
629 MakeAbsoluteFilePath(profile.modules[loc->module_index].filename));
626 } 630 }
627 631
628 // Checks that annotations are recorded in samples. 632 // Checks that annotations are recorded in samples.
629 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED) 633 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED)
630 #define MAYBE_Annotations Annotations 634 #define MAYBE_Annotations Annotations
631 #else 635 #else
632 #define MAYBE_Annotations DISABLED_Annotations 636 #define MAYBE_Annotations DISABLED_Annotations
633 #endif 637 #endif
634 TEST(StackSamplingProfilerTest, MAYBE_Annotations) { 638 TEST(StackSamplingProfilerTest, MAYBE_Annotations) {
635 StackSamplingProfiler::ResetAnnotationsForTesting(); 639 StackSamplingProfiler::ResetAnnotationsForTesting();
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after
996 // TargetThread::SignalAndWaitUntilSignaled 1000 // TargetThread::SignalAndWaitUntilSignaled
997 // TargetThread::OtherLibraryCallback 1001 // TargetThread::OtherLibraryCallback
998 // InvokeCallbackFunction (in other library) 1002 // InvokeCallbackFunction (in other library)
999 // TargetThread::CallThroughOtherLibrary 1003 // TargetThread::CallThroughOtherLibrary
1000 EXPECT_EQ(3, other_library_frame - end_frame) 1004 EXPECT_EQ(3, other_library_frame - end_frame)
1001 << "Stack:\n" << FormatSampleForDiagnosticOutput(sample, profile.modules); 1005 << "Stack:\n" << FormatSampleForDiagnosticOutput(sample, profile.modules);
1002 } 1006 }
1003 1007
1004 // Checks that a stack that runs through a library that is unloading produces a 1008 // Checks that a stack that runs through a library that is unloading produces a
1005 // stack, and doesn't crash. 1009 // stack, and doesn't crash.
1006 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED) 1010 // Unloading is synchronous on the Mac, so this test is inapplicable.
1011 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED) && !defined(OS_MACOSX)
1007 #define MAYBE_UnloadingLibrary UnloadingLibrary 1012 #define MAYBE_UnloadingLibrary UnloadingLibrary
1008 #else 1013 #else
1009 #define MAYBE_UnloadingLibrary DISABLED_UnloadingLibrary 1014 #define MAYBE_UnloadingLibrary DISABLED_UnloadingLibrary
1010 #endif 1015 #endif
1011 TEST(StackSamplingProfilerTest, MAYBE_UnloadingLibrary) { 1016 TEST(StackSamplingProfilerTest, MAYBE_UnloadingLibrary) {
1012 TestLibraryUnload(false); 1017 TestLibraryUnload(false);
1013 } 1018 }
1014 1019
1015 // Checks that a stack that runs through a library that has been unloaded 1020 // Checks that a stack that runs through a library that has been unloaded
1016 // produces a stack, and doesn't crash. 1021 // produces a stack, and doesn't crash.
1017 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED) 1022 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED)
1018 #define MAYBE_UnloadedLibrary UnloadedLibrary 1023 #define MAYBE_UnloadedLibrary UnloadedLibrary
1019 #else 1024 #else
1020 #define MAYBE_UnloadedLibrary DISABLED_UnloadedLibrary 1025 #define MAYBE_UnloadedLibrary DISABLED_UnloadedLibrary
1021 #endif 1026 #endif
1022 TEST(StackSamplingProfilerTest, MAYBE_UnloadedLibrary) { 1027 TEST(StackSamplingProfilerTest, MAYBE_UnloadedLibrary) {
1023 TestLibraryUnload(true); 1028 TestLibraryUnload(true);
1024 } 1029 }
1025 1030
1026 } // namespace base 1031 } // namespace base
OLDNEW
« base/profiler/native_stack_sampler_mac.cc ('K') | « base/profiler/native_stack_sampler_mac.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698