Index: runtime/vm/malloc_hooks_test.cc |
diff --git a/runtime/vm/malloc_hooks_test.cc b/runtime/vm/malloc_hooks_test.cc |
index 791e2694aa9deff839b4454d2137c52575820a64..26a56478ae90d85fe7f9eaca17566e9d6bafdfaf 100644 |
--- a/runtime/vm/malloc_hooks_test.cc |
+++ b/runtime/vm/malloc_hooks_test.cc |
@@ -4,13 +4,15 @@ |
#include "platform/globals.h" |
-#if defined(DART_USE_TCMALLOC) && !defined(PRODUCT) |
+#if defined(DART_USE_TCMALLOC) && !defined(PRODUCT) && \ |
+ !defined(TARGET_ARCH_DBC) && !defined(TARGET_OS_FUCHSIA) |
#include "platform/assert.h" |
-#include "vm/class_finalizer.h" |
#include "vm/globals.h" |
#include "vm/malloc_hooks.h" |
-#include "vm/symbols.h" |
+#include "vm/os.h" |
+#include "vm/profiler.h" |
+#include "vm/profiler_service.h" |
#include "vm/unit_test.h" |
namespace dart { |
@@ -64,7 +66,7 @@ UNIT_TEST_CASE(FreeUnseenMemoryMallocHookTest) { |
EXPECT_EQ(0L, MallocHooks::heap_allocated_memory_in_bytes()); |
const intptr_t buffer_size = 10; |
- volatile char* buffer = new char[buffer_size]; |
+ char* buffer = new char[buffer_size]; |
MallocHookTestBufferInitializer(buffer, buffer_size); |
EXPECT_EQ(1L, MallocHooks::allocation_count()); |
@@ -85,6 +87,123 @@ UNIT_TEST_CASE(FreeUnseenMemoryMallocHookTest) { |
FLAG_enable_malloc_hooks = enable_malloc_hooks_saved; |
} |
+ |
+VM_UNIT_TEST_CASE(StackTraceMallocHookSimpleTest) { |
+ bool enable_malloc_hooks_saved = FLAG_enable_malloc_hooks; |
+ FLAG_enable_malloc_hooks = true; |
+ |
+ MallocHooks::InitOnce(); |
+ MallocHooks::ResetStats(); |
+ |
+ bool enable_stack_traces_saved = |
+ MallocHooks::stack_trace_collection_enabled(); |
+ MallocHooks::set_stack_trace_collection_enabled(true); |
+ |
+ char* var = static_cast<char*>(malloc(16 * sizeof(char))); |
+ Sample* sample = MallocHooks::GetSample(var); |
+ EXPECT(sample != NULL); |
+ |
+ free(var); |
+ sample = MallocHooks::GetSample(var); |
+ EXPECT(sample == NULL); |
+ MallocHooks::TearDown(); |
+ MallocHooks::set_stack_trace_collection_enabled(enable_stack_traces_saved); |
+ FLAG_enable_malloc_hooks = enable_malloc_hooks_saved; |
+} |
+ |
+ |
+static char* DART_NOINLINE StackTraceLengthHelper(uintptr_t* end_address) { |
+ char* var = static_cast<char*>(malloc(16 * sizeof(char))); |
+ *end_address = OS::GetProgramCounter(); |
+ return var; |
+} |
+ |
+ |
+VM_UNIT_TEST_CASE(StackTraceMallocHookLengthTest) { |
+ bool enable_malloc_hooks_saved = FLAG_enable_malloc_hooks; |
+ FLAG_enable_malloc_hooks = true; |
+ |
+ uintptr_t test_start_address = |
+ reinterpret_cast<uintptr_t>(Dart_TestStackTraceMallocHookLengthTest); |
+ uintptr_t helper_start_address = |
+ reinterpret_cast<uintptr_t>(StackTraceLengthHelper); |
+ uintptr_t helper_end_address = 0; |
+ |
+ MallocHooks::InitOnce(); |
+ MallocHooks::ResetStats(); |
+ |
+ bool enable_stack_traces_saved = |
+ MallocHooks::stack_trace_collection_enabled(); |
+ MallocHooks::set_stack_trace_collection_enabled(true); |
+ |
+ char* var = StackTraceLengthHelper(&helper_end_address); |
+ Sample* sample = MallocHooks::GetSample(var); |
+ EXPECT(sample != NULL); |
+ uintptr_t test_end_address = OS::GetProgramCounter(); |
+ |
+ // Ensure that all stack frames are where we expect them to be in the sample. |
+ // If they aren't, the kSkipCount constant in malloc_hooks.cc is likely |
+ // incorrect. |
+ uword address = sample->At(0); |
+ bool first_result = |
+ (helper_start_address <= address) && (helper_end_address >= address); |
+ EXPECT(first_result); |
+ address = sample->At(1); |
+ bool second_result = |
+ (test_start_address <= address) && (test_end_address >= address); |
+ EXPECT(second_result); |
+ |
+ if (!(first_result && second_result)) { |
+ OS::PrintErr( |
+ "If this test is failing, it's likely that the value set for" |
+ "the number of frames to skip in malloc_hooks.cc is " |
+ "incorrect for this configuration/platform. This value can be" |
+ " found in malloc_hooks.cc in the AllocationInfo class, and " |
+ "is stored in the kSkipCount constant."); |
+ } |
+ |
+ free(var); |
+ MallocHooks::TearDown(); |
+ MallocHooks::set_stack_trace_collection_enabled(enable_stack_traces_saved); |
+ FLAG_enable_malloc_hooks = enable_malloc_hooks_saved; |
+} |
+ |
+ |
+ISOLATE_UNIT_TEST_CASE(StackTraceMallocHookSimpleJSONTest) { |
+ bool enable_malloc_hooks_saved = FLAG_enable_malloc_hooks; |
+ FLAG_enable_malloc_hooks = true; |
+ |
+ MallocHooks::InitOnce(); |
+ MallocHooks::ResetStats(); |
+ |
+ bool enable_stack_traces_saved = |
+ MallocHooks::stack_trace_collection_enabled(); |
+ MallocHooks::set_stack_trace_collection_enabled(true); |
+ |
+ ClearProfileVisitor cpv(Isolate::Current()); |
+ Profiler::sample_buffer()->VisitSamples(&cpv); |
+ |
+ char* var = static_cast<char*>(malloc(16 * sizeof(char))); |
+ JSONStream js; |
+ ProfilerService::PrintNativeAllocationJSON(&js, Profile::kNoTags, -1, -1); |
+ const char* json = js.ToCString(); |
+ |
+ // Check that all the stack frames from the current down to main are actually |
+ // present in the profile. This is just a simple sanity check to make sure |
+ // that the ProfileTrie has a representation of the stack trace collected when |
+ // var is allocated. More intense testing is already done in profiler_test.cc. |
+ EXPECT_SUBSTRING("\"dart::Dart_TestStackTraceMallocHookSimpleJSONTest()\"", |
+ json); |
+ EXPECT_SUBSTRING("\"dart::TestCase::Run()\"", json); |
+ EXPECT_SUBSTRING("\"dart::TestCaseBase::RunTest()\"", json); |
+ EXPECT_SUBSTRING("\"main\"", json); |
+ |
+ free(var); |
+ MallocHooks::TearDown(); |
+ MallocHooks::set_stack_trace_collection_enabled(enable_stack_traces_saved); |
+ FLAG_enable_malloc_hooks = enable_malloc_hooks_saved; |
+} |
+ |
}; // namespace dart |
#endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT) |