| OLD | NEW |
| 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 <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 #endif | 42 #endif |
| 43 | 43 |
| 44 #if defined(OS_WIN) | 44 #if defined(OS_WIN) |
| 45 #pragma intrinsic(_ReturnAddress) | 45 #pragma intrinsic(_ReturnAddress) |
| 46 #endif | 46 #endif |
| 47 | 47 |
| 48 namespace base { | 48 namespace base { |
| 49 | 49 |
| 50 using SamplingParams = StackSamplingProfiler::SamplingParams; | 50 using SamplingParams = StackSamplingProfiler::SamplingParams; |
| 51 using Frame = StackSamplingProfiler::Frame; | 51 using Frame = StackSamplingProfiler::Frame; |
| 52 using Frames = std::vector<StackSamplingProfiler::Frame>; |
| 52 using Module = StackSamplingProfiler::Module; | 53 using Module = StackSamplingProfiler::Module; |
| 53 using Sample = StackSamplingProfiler::Sample; | 54 using Sample = StackSamplingProfiler::Sample; |
| 54 using CallStackProfile = StackSamplingProfiler::CallStackProfile; | 55 using CallStackProfile = StackSamplingProfiler::CallStackProfile; |
| 55 using CallStackProfiles = StackSamplingProfiler::CallStackProfiles; | 56 using CallStackProfiles = StackSamplingProfiler::CallStackProfiles; |
| 56 | 57 |
| 57 namespace { | 58 namespace { |
| 58 | 59 |
| 59 // Configuration for the frames that appear on the stack. | 60 // Configuration for the frames that appear on the stack. |
| 60 struct StackConfiguration { | 61 struct StackConfiguration { |
| 61 enum Config { NORMAL, WITH_ALLOCA, WITH_OTHER_LIBRARY }; | 62 enum Config { NORMAL, WITH_ALLOCA, WITH_OTHER_LIBRARY }; |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 reinterpret_cast<const unsigned char*>(offset + 1); | 390 reinterpret_cast<const unsigned char*>(offset + 1); |
| 390 return next_instruction + *offset; | 391 return next_instruction + *offset; |
| 391 } | 392 } |
| 392 #endif | 393 #endif |
| 393 return function_address; | 394 return function_address; |
| 394 } | 395 } |
| 395 | 396 |
| 396 // Searches through the frames in |sample|, returning an iterator to the first | 397 // Searches through the frames in |sample|, returning an iterator to the first |
| 397 // frame that has an instruction pointer within |target_function|. Returns | 398 // frame that has an instruction pointer within |target_function|. Returns |
| 398 // sample.end() if no such frames are found. | 399 // sample.end() if no such frames are found. |
| 399 Sample::const_iterator FindFirstFrameWithinFunction( | 400 Frames::const_iterator FindFirstFrameWithinFunction( |
| 400 const Sample& sample, | 401 const Sample& sample, |
| 401 TargetFunction target_function) { | 402 TargetFunction target_function) { |
| 402 uintptr_t function_start = reinterpret_cast<uintptr_t>( | 403 uintptr_t function_start = reinterpret_cast<uintptr_t>( |
| 403 MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>( | 404 MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>( |
| 404 target_function))); | 405 target_function))); |
| 405 uintptr_t function_end = | 406 uintptr_t function_end = |
| 406 reinterpret_cast<uintptr_t>(target_function(nullptr, nullptr, nullptr)); | 407 reinterpret_cast<uintptr_t>(target_function(nullptr, nullptr, nullptr)); |
| 407 for (auto it = sample.begin(); it != sample.end(); ++it) { | 408 for (auto it = sample.frames.begin(); it != sample.frames.end(); ++it) { |
| 408 if ((it->instruction_pointer >= function_start) && | 409 if ((it->instruction_pointer >= function_start) && |
| 409 (it->instruction_pointer <= function_end)) | 410 (it->instruction_pointer <= function_end)) |
| 410 return it; | 411 return it; |
| 411 } | 412 } |
| 412 return sample.end(); | 413 return sample.frames.end(); |
| 413 } | 414 } |
| 414 | 415 |
| 415 // Formats a sample into a string that can be output for test diagnostics. | 416 // Formats a sample into a string that can be output for test diagnostics. |
| 416 std::string FormatSampleForDiagnosticOutput( | 417 std::string FormatSampleForDiagnosticOutput( |
| 417 const Sample& sample, | 418 const Sample& sample, |
| 418 const std::vector<Module>& modules) { | 419 const std::vector<Module>& modules) { |
| 419 std::string output; | 420 std::string output; |
| 420 for (const Frame& frame : sample) { | 421 for (const Frame& frame : sample.frames) { |
| 421 output += StringPrintf( | 422 output += StringPrintf( |
| 422 "0x%p %s\n", reinterpret_cast<const void*>(frame.instruction_pointer), | 423 "0x%p %s\n", reinterpret_cast<const void*>(frame.instruction_pointer), |
| 423 modules[frame.module_index].filename.AsUTF8Unsafe().c_str()); | 424 modules[frame.module_index].filename.AsUTF8Unsafe().c_str()); |
| 424 } | 425 } |
| 425 return output; | 426 return output; |
| 426 } | 427 } |
| 427 | 428 |
| 428 // Returns a duration that is longer than the test timeout. We would use | 429 // Returns a duration that is longer than the test timeout. We would use |
| 429 // TimeDelta::Max() but https://crbug.com/465948. | 430 // TimeDelta::Max() but https://crbug.com/465948. |
| 430 TimeDelta AVeryLongTimeDelta() { return TimeDelta::FromDays(1); } | 431 TimeDelta AVeryLongTimeDelta() { return TimeDelta::FromDays(1); } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 511 sampling_thread_completed.Wait(); | 512 sampling_thread_completed.Wait(); |
| 512 | 513 |
| 513 // Look up the sample. | 514 // Look up the sample. |
| 514 ASSERT_EQ(1u, profiles.size()); | 515 ASSERT_EQ(1u, profiles.size()); |
| 515 const CallStackProfile& profile = profiles[0]; | 516 const CallStackProfile& profile = profiles[0]; |
| 516 ASSERT_EQ(1u, profile.samples.size()); | 517 ASSERT_EQ(1u, profile.samples.size()); |
| 517 const Sample& sample = profile.samples[0]; | 518 const Sample& sample = profile.samples[0]; |
| 518 | 519 |
| 519 // Check that the stack contains a frame for | 520 // Check that the stack contains a frame for |
| 520 // TargetThread::SignalAndWaitUntilSignaled(). | 521 // TargetThread::SignalAndWaitUntilSignaled(). |
| 521 Sample::const_iterator end_frame = FindFirstFrameWithinFunction( | 522 Frames::const_iterator end_frame = FindFirstFrameWithinFunction( |
| 522 sample, | 523 sample, &TargetThread::SignalAndWaitUntilSignaled); |
| 523 &TargetThread::SignalAndWaitUntilSignaled); | 524 ASSERT_TRUE(end_frame != sample.frames.end()) |
| 524 ASSERT_TRUE(end_frame != sample.end()) | |
| 525 << "Function at " | 525 << "Function at " |
| 526 << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>( | 526 << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>( |
| 527 &TargetThread::SignalAndWaitUntilSignaled)) | 527 &TargetThread::SignalAndWaitUntilSignaled)) |
| 528 << " was not found in stack:\n" | 528 << " was not found in stack:\n" |
| 529 << FormatSampleForDiagnosticOutput(sample, profile.modules); | 529 << FormatSampleForDiagnosticOutput(sample, profile.modules); |
| 530 | 530 |
| 531 if (wait_until_unloaded) { | 531 if (wait_until_unloaded) { |
| 532 // The stack should look like this, resulting one frame after | 532 // The stack should look like this, resulting one frame after |
| 533 // SignalAndWaitUntilSignaled. The frame in the now-unloaded library is not | 533 // SignalAndWaitUntilSignaled. The frame in the now-unloaded library is not |
| 534 // recorded since we can't get module information. | 534 // recorded since we can't get module information. |
| 535 // | 535 // |
| 536 // ... WaitableEvent and system frames ... | 536 // ... WaitableEvent and system frames ... |
| 537 // TargetThread::SignalAndWaitUntilSignaled | 537 // TargetThread::SignalAndWaitUntilSignaled |
| 538 // TargetThread::OtherLibraryCallback | 538 // TargetThread::OtherLibraryCallback |
| 539 EXPECT_EQ(2, sample.end() - end_frame) | 539 EXPECT_EQ(2, sample.frames.end() - end_frame) |
| 540 << "Stack:\n" | 540 << "Stack:\n" |
| 541 << FormatSampleForDiagnosticOutput(sample, profile.modules); | 541 << FormatSampleForDiagnosticOutput(sample, profile.modules); |
| 542 } else { | 542 } else { |
| 543 // We didn't wait for the asynchonous unloading to complete, so the results | 543 // We didn't wait for the asynchonous unloading to complete, so the results |
| 544 // are non-deterministic: if the library finished unloading we should have | 544 // are non-deterministic: if the library finished unloading we should have |
| 545 // the same stack as |wait_until_unloaded|, if not we should have the full | 545 // the same stack as |wait_until_unloaded|, if not we should have the full |
| 546 // stack. The important thing is that we should not crash. | 546 // stack. The important thing is that we should not crash. |
| 547 | 547 |
| 548 if ((sample.end() - 1) - end_frame == 2) { | 548 if ((sample.frames.end() - 1) - end_frame == 2) { |
| 549 // This is the same case as |wait_until_unloaded|. | 549 // This is the same case as |wait_until_unloaded|. |
| 550 return; | 550 return; |
| 551 } | 551 } |
| 552 | 552 |
| 553 // Check that the stack contains a frame for | 553 // Check that the stack contains a frame for |
| 554 // TargetThread::CallThroughOtherLibrary(). | 554 // TargetThread::CallThroughOtherLibrary(). |
| 555 Sample::const_iterator other_library_frame = FindFirstFrameWithinFunction( | 555 Frames::const_iterator other_library_frame = FindFirstFrameWithinFunction( |
| 556 sample, | 556 sample, &TargetThread::CallThroughOtherLibrary); |
| 557 &TargetThread::CallThroughOtherLibrary); | 557 ASSERT_TRUE(other_library_frame != sample.frames.end()) |
| 558 ASSERT_TRUE(other_library_frame != sample.end()) | |
| 559 << "Function at " | 558 << "Function at " |
| 560 << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>( | 559 << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>( |
| 561 &TargetThread::CallThroughOtherLibrary)) | 560 &TargetThread::CallThroughOtherLibrary)) |
| 562 << " was not found in stack:\n" | 561 << " was not found in stack:\n" |
| 563 << FormatSampleForDiagnosticOutput(sample, profile.modules); | 562 << FormatSampleForDiagnosticOutput(sample, profile.modules); |
| 564 | 563 |
| 565 // The stack should look like this, resulting in three frames between | 564 // The stack should look like this, resulting in three frames between |
| 566 // SignalAndWaitUntilSignaled and CallThroughOtherLibrary: | 565 // SignalAndWaitUntilSignaled and CallThroughOtherLibrary: |
| 567 // | 566 // |
| 568 // ... WaitableEvent and system frames ... | 567 // ... WaitableEvent and system frames ... |
| 569 // TargetThread::SignalAndWaitUntilSignaled | 568 // TargetThread::SignalAndWaitUntilSignaled |
| 570 // TargetThread::OtherLibraryCallback | 569 // TargetThread::OtherLibraryCallback |
| 571 // InvokeCallbackFunction (in other library) | 570 // InvokeCallbackFunction (in other library) |
| 572 // TargetThread::CallThroughOtherLibrary | 571 // TargetThread::CallThroughOtherLibrary |
| 573 EXPECT_EQ(3, other_library_frame - end_frame) | 572 EXPECT_EQ(3, other_library_frame - end_frame) |
| 574 << "Stack:\n" | 573 << "Stack:\n" |
| 575 << FormatSampleForDiagnosticOutput(sample, profile.modules); | 574 << FormatSampleForDiagnosticOutput(sample, profile.modules); |
| 576 } | 575 } |
| 577 } | 576 } |
| 578 | 577 |
| 579 } // namespace | 578 } // namespace |
| 580 | 579 |
| 581 // Checks that the basic expected information is present in a sampled call stack | 580 // Checks that the basic expected information is present in a sampled call stack |
| 582 // profile. | 581 // profile. |
| 583 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED) | 582 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED) |
| 584 #define MAYBE_Basic Basic | 583 #define MAYBE_Basic Basic |
| 585 #else | 584 #else |
| 586 #define MAYBE_Basic DISABLED_Basic | 585 #define MAYBE_Basic DISABLED_Basic |
| 587 #endif | 586 #endif |
| 588 TEST(StackSamplingProfilerTest, MAYBE_Basic) { | 587 TEST(StackSamplingProfilerTest, MAYBE_Basic) { |
| 588 StackSamplingProfiler::ResetAnnotationsForTesting(); |
| 589 |
| 589 SamplingParams params; | 590 SamplingParams params; |
| 590 params.sampling_interval = TimeDelta::FromMilliseconds(0); | 591 params.sampling_interval = TimeDelta::FromMilliseconds(0); |
| 591 params.samples_per_burst = 1; | 592 params.samples_per_burst = 1; |
| 592 | 593 |
| 593 std::vector<CallStackProfile> profiles; | 594 std::vector<CallStackProfile> profiles; |
| 594 CaptureProfiles(params, AVeryLongTimeDelta(), &profiles); | 595 CaptureProfiles(params, AVeryLongTimeDelta(), &profiles); |
| 595 | 596 |
| 596 // Check that the profile and samples sizes are correct, and the module | 597 // Check that the profile and samples sizes are correct, and the module |
| 597 // indices are in range. | 598 // indices are in range. |
| 598 ASSERT_EQ(1u, profiles.size()); | 599 ASSERT_EQ(1u, profiles.size()); |
| 599 const CallStackProfile& profile = profiles[0]; | 600 const CallStackProfile& profile = profiles[0]; |
| 600 ASSERT_EQ(1u, profile.samples.size()); | 601 ASSERT_EQ(1u, profile.samples.size()); |
| 601 EXPECT_EQ(params.sampling_interval, profile.sampling_period); | 602 EXPECT_EQ(params.sampling_interval, profile.sampling_period); |
| 602 const Sample& sample = profile.samples[0]; | 603 const Sample& sample = profile.samples[0]; |
| 603 for (const auto& frame : sample) { | 604 EXPECT_EQ(0u, sample.process_phases); |
| 605 for (const auto& frame : sample.frames) { |
| 604 ASSERT_GE(frame.module_index, 0u); | 606 ASSERT_GE(frame.module_index, 0u); |
| 605 ASSERT_LT(frame.module_index, profile.modules.size()); | 607 ASSERT_LT(frame.module_index, profile.modules.size()); |
| 606 } | 608 } |
| 607 | 609 |
| 608 // Check that the stack contains a frame for | 610 // Check that the stack contains a frame for |
| 609 // TargetThread::SignalAndWaitUntilSignaled() and that the frame has this | 611 // TargetThread::SignalAndWaitUntilSignaled() and that the frame has this |
| 610 // executable's module. | 612 // executable's module. |
| 611 Sample::const_iterator loc = FindFirstFrameWithinFunction( | 613 Frames::const_iterator loc = FindFirstFrameWithinFunction( |
| 612 sample, | 614 sample, &TargetThread::SignalAndWaitUntilSignaled); |
| 613 &TargetThread::SignalAndWaitUntilSignaled); | 615 ASSERT_TRUE(loc != sample.frames.end()) |
| 614 ASSERT_TRUE(loc != sample.end()) | |
| 615 << "Function at " | 616 << "Function at " |
| 616 << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>( | 617 << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>( |
| 617 &TargetThread::SignalAndWaitUntilSignaled)) | 618 &TargetThread::SignalAndWaitUntilSignaled)) |
| 618 << " was not found in stack:\n" | 619 << " was not found in stack:\n" |
| 619 << FormatSampleForDiagnosticOutput(sample, profile.modules); | 620 << FormatSampleForDiagnosticOutput(sample, profile.modules); |
| 620 FilePath executable_path; | 621 FilePath executable_path; |
| 621 EXPECT_TRUE(PathService::Get(FILE_EXE, &executable_path)); | 622 EXPECT_TRUE(PathService::Get(FILE_EXE, &executable_path)); |
| 622 EXPECT_EQ(executable_path, profile.modules[loc->module_index].filename); | 623 EXPECT_EQ(executable_path, profile.modules[loc->module_index].filename); |
| 623 } | 624 } |
| 624 | 625 |
| 626 // Checks that annotations are recorded in samples. |
| 627 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED) |
| 628 #define MAYBE_Annotations Annotations |
| 629 #else |
| 630 #define MAYBE_Annotations DISABLED_Annotations |
| 631 #endif |
| 632 TEST(StackSamplingProfilerTest, MAYBE_Annotations) { |
| 633 StackSamplingProfiler::ResetAnnotationsForTesting(); |
| 634 |
| 635 SamplingParams params; |
| 636 params.sampling_interval = TimeDelta::FromMilliseconds(0); |
| 637 params.samples_per_burst = 1; |
| 638 |
| 639 // Check that a run picks up annotations. |
| 640 StackSamplingProfiler::SetProcessPhase(1); |
| 641 std::vector<CallStackProfile> profiles1; |
| 642 CaptureProfiles(params, AVeryLongTimeDelta(), &profiles1); |
| 643 ASSERT_EQ(1u, profiles1.size()); |
| 644 const CallStackProfile& profile1 = profiles1[0]; |
| 645 ASSERT_EQ(1u, profile1.samples.size()); |
| 646 const Sample& sample1 = profile1.samples[0]; |
| 647 EXPECT_EQ(1u << 1, sample1.process_phases); |
| 648 |
| 649 // Run it a second time but with changed annotations. These annotations |
| 650 // should appear in the first acquired sample. |
| 651 StackSamplingProfiler::SetProcessPhase(2); |
| 652 std::vector<CallStackProfile> profiles2; |
| 653 CaptureProfiles(params, AVeryLongTimeDelta(), &profiles2); |
| 654 ASSERT_EQ(1u, profiles2.size()); |
| 655 const CallStackProfile& profile2 = profiles2[0]; |
| 656 ASSERT_EQ(1u, profile2.samples.size()); |
| 657 const Sample& sample2 = profile2.samples[0]; |
| 658 EXPECT_EQ(sample1.process_phases | (1u << 2), sample2.process_phases); |
| 659 } |
| 660 |
| 625 // Checks that the profiler handles stacks containing dynamically-allocated | 661 // Checks that the profiler handles stacks containing dynamically-allocated |
| 626 // stack memory. | 662 // stack memory. |
| 627 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED) | 663 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED) |
| 628 #define MAYBE_Alloca Alloca | 664 #define MAYBE_Alloca Alloca |
| 629 #else | 665 #else |
| 630 #define MAYBE_Alloca DISABLED_Alloca | 666 #define MAYBE_Alloca DISABLED_Alloca |
| 631 #endif | 667 #endif |
| 632 TEST(StackSamplingProfilerTest, MAYBE_Alloca) { | 668 TEST(StackSamplingProfilerTest, MAYBE_Alloca) { |
| 633 SamplingParams params; | 669 SamplingParams params; |
| 634 params.sampling_interval = TimeDelta::FromMilliseconds(0); | 670 params.sampling_interval = TimeDelta::FromMilliseconds(0); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 650 StackConfiguration(StackConfiguration::WITH_ALLOCA)); | 686 StackConfiguration(StackConfiguration::WITH_ALLOCA)); |
| 651 | 687 |
| 652 // Look up the sample. | 688 // Look up the sample. |
| 653 ASSERT_EQ(1u, profiles.size()); | 689 ASSERT_EQ(1u, profiles.size()); |
| 654 const CallStackProfile& profile = profiles[0]; | 690 const CallStackProfile& profile = profiles[0]; |
| 655 ASSERT_EQ(1u, profile.samples.size()); | 691 ASSERT_EQ(1u, profile.samples.size()); |
| 656 const Sample& sample = profile.samples[0]; | 692 const Sample& sample = profile.samples[0]; |
| 657 | 693 |
| 658 // Check that the stack contains a frame for | 694 // Check that the stack contains a frame for |
| 659 // TargetThread::SignalAndWaitUntilSignaled(). | 695 // TargetThread::SignalAndWaitUntilSignaled(). |
| 660 Sample::const_iterator end_frame = FindFirstFrameWithinFunction( | 696 Frames::const_iterator end_frame = FindFirstFrameWithinFunction( |
| 661 sample, | 697 sample, &TargetThread::SignalAndWaitUntilSignaled); |
| 662 &TargetThread::SignalAndWaitUntilSignaled); | 698 ASSERT_TRUE(end_frame != sample.frames.end()) |
| 663 ASSERT_TRUE(end_frame != sample.end()) | |
| 664 << "Function at " | 699 << "Function at " |
| 665 << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>( | 700 << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>( |
| 666 &TargetThread::SignalAndWaitUntilSignaled)) | 701 &TargetThread::SignalAndWaitUntilSignaled)) |
| 667 << " was not found in stack:\n" | 702 << " was not found in stack:\n" |
| 668 << FormatSampleForDiagnosticOutput(sample, profile.modules); | 703 << FormatSampleForDiagnosticOutput(sample, profile.modules); |
| 669 | 704 |
| 670 // Check that the stack contains a frame for TargetThread::CallWithAlloca(). | 705 // Check that the stack contains a frame for TargetThread::CallWithAlloca(). |
| 671 Sample::const_iterator alloca_frame = FindFirstFrameWithinFunction( | 706 Frames::const_iterator alloca_frame = |
| 672 sample, | 707 FindFirstFrameWithinFunction(sample, &TargetThread::CallWithAlloca); |
| 673 &TargetThread::CallWithAlloca); | 708 ASSERT_TRUE(alloca_frame != sample.frames.end()) |
| 674 ASSERT_TRUE(alloca_frame != sample.end()) | |
| 675 << "Function at " | 709 << "Function at " |
| 676 << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>( | 710 << MaybeFixupFunctionAddressForILT( |
| 677 &TargetThread::CallWithAlloca)) | 711 reinterpret_cast<const void*>(&TargetThread::CallWithAlloca)) |
| 678 << " was not found in stack:\n" | 712 << " was not found in stack:\n" |
| 679 << FormatSampleForDiagnosticOutput(sample, profile.modules); | 713 << FormatSampleForDiagnosticOutput(sample, profile.modules); |
| 680 | 714 |
| 681 // These frames should be adjacent on the stack. | 715 // These frames should be adjacent on the stack. |
| 682 EXPECT_EQ(1, alloca_frame - end_frame) | 716 EXPECT_EQ(1, alloca_frame - end_frame) |
| 683 << "Stack:\n" | 717 << "Stack:\n" |
| 684 << FormatSampleForDiagnosticOutput(sample, profile.modules); | 718 << FormatSampleForDiagnosticOutput(sample, profile.modules); |
| 685 } | 719 } |
| 686 | 720 |
| 687 // Checks that the fire-and-forget interface works. | 721 // Checks that the fire-and-forget interface works. |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 920 } | 954 } |
| 921 | 955 |
| 922 // Look up the sample. | 956 // Look up the sample. |
| 923 ASSERT_EQ(1u, profiles.size()); | 957 ASSERT_EQ(1u, profiles.size()); |
| 924 const CallStackProfile& profile = profiles[0]; | 958 const CallStackProfile& profile = profiles[0]; |
| 925 ASSERT_EQ(1u, profile.samples.size()); | 959 ASSERT_EQ(1u, profile.samples.size()); |
| 926 const Sample& sample = profile.samples[0]; | 960 const Sample& sample = profile.samples[0]; |
| 927 | 961 |
| 928 // Check that the stack contains a frame for | 962 // Check that the stack contains a frame for |
| 929 // TargetThread::CallThroughOtherLibrary(). | 963 // TargetThread::CallThroughOtherLibrary(). |
| 930 Sample::const_iterator other_library_frame = FindFirstFrameWithinFunction( | 964 Frames::const_iterator other_library_frame = FindFirstFrameWithinFunction( |
| 931 sample, | 965 sample, &TargetThread::CallThroughOtherLibrary); |
| 932 &TargetThread::CallThroughOtherLibrary); | 966 ASSERT_TRUE(other_library_frame != sample.frames.end()) |
| 933 ASSERT_TRUE(other_library_frame != sample.end()) | |
| 934 << "Function at " | 967 << "Function at " |
| 935 << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>( | 968 << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>( |
| 936 &TargetThread::CallThroughOtherLibrary)) | 969 &TargetThread::CallThroughOtherLibrary)) |
| 937 << " was not found in stack:\n" | 970 << " was not found in stack:\n" |
| 938 << FormatSampleForDiagnosticOutput(sample, profile.modules); | 971 << FormatSampleForDiagnosticOutput(sample, profile.modules); |
| 939 | 972 |
| 940 // Check that the stack contains a frame for | 973 // Check that the stack contains a frame for |
| 941 // TargetThread::SignalAndWaitUntilSignaled(). | 974 // TargetThread::SignalAndWaitUntilSignaled(). |
| 942 Sample::const_iterator end_frame = FindFirstFrameWithinFunction( | 975 Frames::const_iterator end_frame = FindFirstFrameWithinFunction( |
| 943 sample, | 976 sample, &TargetThread::SignalAndWaitUntilSignaled); |
| 944 &TargetThread::SignalAndWaitUntilSignaled); | 977 ASSERT_TRUE(end_frame != sample.frames.end()) |
| 945 ASSERT_TRUE(end_frame != sample.end()) | |
| 946 << "Function at " | 978 << "Function at " |
| 947 << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>( | 979 << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>( |
| 948 &TargetThread::SignalAndWaitUntilSignaled)) | 980 &TargetThread::SignalAndWaitUntilSignaled)) |
| 949 << " was not found in stack:\n" | 981 << " was not found in stack:\n" |
| 950 << FormatSampleForDiagnosticOutput(sample, profile.modules); | 982 << FormatSampleForDiagnosticOutput(sample, profile.modules); |
| 951 | 983 |
| 952 // The stack should look like this, resulting in three frames between | 984 // The stack should look like this, resulting in three frames between |
| 953 // SignalAndWaitUntilSignaled and CallThroughOtherLibrary: | 985 // SignalAndWaitUntilSignaled and CallThroughOtherLibrary: |
| 954 // | 986 // |
| 955 // ... WaitableEvent and system frames ... | 987 // ... WaitableEvent and system frames ... |
| 956 // TargetThread::SignalAndWaitUntilSignaled | 988 // TargetThread::SignalAndWaitUntilSignaled |
| 957 // TargetThread::OtherLibraryCallback | 989 // TargetThread::OtherLibraryCallback |
| 958 // InvokeCallbackFunction (in other library) | 990 // InvokeCallbackFunction (in other library) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 977 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED) | 1009 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED) |
| 978 #define MAYBE_UnloadedLibrary UnloadedLibrary | 1010 #define MAYBE_UnloadedLibrary UnloadedLibrary |
| 979 #else | 1011 #else |
| 980 #define MAYBE_UnloadedLibrary DISABLED_UnloadedLibrary | 1012 #define MAYBE_UnloadedLibrary DISABLED_UnloadedLibrary |
| 981 #endif | 1013 #endif |
| 982 TEST(StackSamplingProfilerTest, MAYBE_UnloadedLibrary) { | 1014 TEST(StackSamplingProfilerTest, MAYBE_UnloadedLibrary) { |
| 983 TestLibraryUnload(true); | 1015 TestLibraryUnload(true); |
| 984 } | 1016 } |
| 985 | 1017 |
| 986 } // namespace base | 1018 } // namespace base |
| OLD | NEW |