Skip to content

Commit

Permalink
untangle a number of unittests from libtcmalloc_minimal.so
Browse files Browse the repository at this point in the history
  • Loading branch information
alk committed Feb 8, 2024
1 parent cad457a commit 8a147b4
Show file tree
Hide file tree
Showing 19 changed files with 336 additions and 327 deletions.
151 changes: 81 additions & 70 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,23 @@ WINDOWS_EXTRA = src/windows/preamble_patcher_test.cc \

### Unittests

# Note, we skip this test on mingw (and windows in general). It uses
# unsetenv, which is not available on win32.
if !MINGW
TESTS += unique_path_unittest
unique_path_unittest_SOURCES = src/tests/unique_path_unittest.cc
unique_path_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(AM_LDFLAGS)
unique_path_unittest_LDADD = libcommon.la
endif !MINGW

TESTS += generic_writer_test
generic_writer_test_SOURCES = src/tests/generic_writer_test.cc
generic_writer_test_LDADD = libcommon.la

TESTS += proc_maps_iterator_test
proc_maps_iterator_test_SOURCES = src/tests/proc_maps_iterator_test.cc
proc_maps_iterator_test_LDADD = libcommon.la

if WITH_HEAP_PROFILER_OR_CHECKER
TESTS += low_level_alloc_unittest
low_level_alloc_unittest_SOURCES = src/base/low_level_alloc.cc \
Expand Down Expand Up @@ -256,7 +273,70 @@ libtcmalloc_minimal_la_CXXFLAGS = -DNO_TCMALLOC_SAMPLES \
libtcmalloc_minimal_la_LDFLAGS = -version-info @TCMALLOC_SO_VERSION@ $(AM_LDFLAGS)
libtcmalloc_minimal_la_LIBADD = libcommon.la

### Unittests
### ------- unit tests for various internal modules of tcmalloc

TESTS += addressmap_unittest
addressmap_unittest_SOURCES = src/tests/addressmap_unittest.cc
addressmap_unittest_LDADD = libcommon.la

TESTS += packed_cache_test
packed_cache_test_SOURCES = src/tests/packed-cache_test.cc
packed_cache_test_LDADD = libcommon.la

TESTS += safe_strerror_test
safe_strerror_test_SOURCES = src/tests/safe_strerror_test.cc \
src/safe_strerror.cc
safe_strerror_test_LDADD = libcommon.la

TESTS += pagemap_unittest
pagemap_unittest_SOURCES = src/tests/pagemap_unittest.cc \
src/internal_logging.cc
pagemap_unittest_LDADD = libcommon.la

# note, it is not so great that page heap testing requires bringing
# almost entirety of tcmalloc (short of tcmalloc.cc), but it is what
# we have.
TESTS += page_heap_test
page_heap_test_SOURCES = src/tests/page_heap_test.cc \
$(MINIMAL_MALLOC_SRC)
page_heap_test_CXXFLAGS = -DNO_HEAP_CHECK -DNO_TCMALLOC_SAMPLES $(AM_CXXFLAGS)
page_heap_test_LDADD = libcommon.la

# note, it is not so great that stack_trace_table testing requires
# bringing almost entirety of tcmalloc (short of tcmalloc.cc), but it
# is what we have.
TESTS += stack_trace_table_test
stack_trace_table_test_SOURCES = src/tests/stack_trace_table_test.cc \
src/stack_trace_table.cc src/internal_logging.cc
stack_trace_table_test_CXXFLAGS = -DSTACK_TRACE_TABLE_IS_TESTED $(AM_CXXFLAGS)
stack_trace_table_test_LDADD = libcommon.la

TESTS += malloc_hook_test
malloc_hook_test_SOURCES = src/tests/malloc_hook_test.cc \
src/tests/testutil.cc \
src/malloc_hook.cc
malloc_hook_test_CXXFLAGS = -DNO_TCMALLOC_SAMPLES $(AM_CXXFLAGS)
malloc_hook_test_LDADD = libcommon.la

if WITH_HEAP_PROFILER_OR_CHECKER
if !MINGW
TESTS += mmap_hook_test
mmap_hook_test_SOURCES = src/tests/mmap_hook_test.cc \
src/mmap_hook.cc
mmap_hook_test_LDADD = libcommon.la
endif !MINGW
endif WITH_HEAP_PROFILER_OR_CHECKER

# sampler_test and sampling_test both require sampling to be turned
# on, which it's not by default. Use the "standard" value of 2^19.
TESTS_ENVIRONMENT += TCMALLOC_SAMPLE_PARAMETER=524288

TESTS += sampler_test
sampler_test_SOURCES = src/tests/sampler_test.cc \
src/sampler.cc
sampler_test_LDADD = libcommon.la

### Unittests for libtcmalloc_minimal.la

TESTS += tcmalloc_minimal_unittest
tcmalloc_minimal_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \
Expand Down Expand Up @@ -285,30 +365,13 @@ tcmalloc_minimal_large_heap_fragmentation_unittest_SOURCES = src/tests/large_hea
tcmalloc_minimal_large_heap_fragmentation_unittest_LDFLAGS = $(TCMALLOC_FLAGS) $(AM_LDFLAGS)
tcmalloc_minimal_large_heap_fragmentation_unittest_LDADD = libtcmalloc_minimal.la

# These all tests components of tcmalloc_minimal

TESTS += addressmap_unittest
addressmap_unittest_SOURCES = src/tests/addressmap_unittest.cc
addressmap_unittest_LDADD = libcommon.la

if !MINGW
TESTS += system_alloc_unittest
system_alloc_unittest_SOURCES = src/tests/system-alloc_unittest.cc
system_alloc_unittest_LDFLAGS = $(TCMALLOC_FLAGS) $(AM_LDFLAGS)
system_alloc_unittest_LDADD = libtcmalloc_minimal.la

# Note, we skip this test on mingw (and windows in general). It uses
# unsetenv, which is not available on win32.
TESTS += unique_path_unittest
unique_path_unittest_SOURCES = src/tests/unique_path_unittest.cc
unique_path_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(AM_LDFLAGS)
unique_path_unittest_LDADD = libcommon.la
endif !MINGW

TESTS += packed_cache_test
packed_cache_test_SOURCES = src/tests/packed-cache_test.cc
packed_cache_test_LDADD = libcommon.la

TESTS += frag_unittest
frag_unittest_SOURCES = src/tests/frag_unittest.cc
frag_unittest_LDFLAGS = $(TCMALLOC_FLAGS) $(AM_LDFLAGS)
Expand All @@ -325,21 +388,6 @@ current_allocated_bytes_test_SOURCES = src/tests/current_allocated_bytes_test.cc
current_allocated_bytes_test_LDFLAGS = $(TCMALLOC_FLAGS) $(AM_LDFLAGS)
current_allocated_bytes_test_LDADD = libtcmalloc_minimal.la

TESTS += malloc_hook_test
malloc_hook_test_SOURCES = src/tests/malloc_hook_test.cc \
src/tests/testutil.cc
malloc_hook_test_LDFLAGS = $(TCMALLOC_FLAGS) $(AM_LDFLAGS)
malloc_hook_test_LDADD = libtcmalloc_minimal.la

if WITH_HEAP_PROFILER_OR_CHECKER
if !MINGW
TESTS += mmap_hook_test
mmap_hook_test_SOURCES = src/tests/mmap_hook_test.cc \
src/mmap_hook.cc
mmap_hook_test_LDADD = libcommon.la
endif !MINGW
endif WITH_HEAP_PROFILER_OR_CHECKER

TESTS += malloc_extension_test
malloc_extension_test_SOURCES = src/tests/malloc_extension_test.cc
malloc_extension_test_LDFLAGS = $(TCMALLOC_FLAGS) $(AM_LDFLAGS)
Expand All @@ -360,39 +408,11 @@ memalign_unittest_LDADD = libtcmalloc_minimal.la
endif !OSX
endif !MINGW

TESTS += page_heap_test
page_heap_test_SOURCES = src/tests/page_heap_test.cc
page_heap_test_LDFLAGS = $(TCMALLOC_FLAGS) $(AM_LDFLAGS)
page_heap_test_LDADD = libtcmalloc_minimal.la

TESTS += pagemap_unittest
pagemap_unittest_SOURCES = src/tests/pagemap_unittest.cc
pagemap_unittest_LDFLAGS = $(TCMALLOC_FLAGS) $(AM_LDFLAGS)
pagemap_unittest_LDADD = libtcmalloc_minimal.la

TESTS += safe_strerror_test
safe_strerror_test_SOURCES = src/tests/safe_strerror_test.cc \
src/safe_strerror.cc
safe_strerror_test_LDADD = libcommon.la

TESTS += generic_writer_test
generic_writer_test_SOURCES = src/tests/generic_writer_test.cc
generic_writer_test_LDADD = libcommon.la

TESTS += proc_maps_iterator_test
proc_maps_iterator_test_SOURCES = src/tests/proc_maps_iterator_test.cc
proc_maps_iterator_test_LDADD = libcommon.la

TESTS += realloc_unittest
realloc_unittest_SOURCES = src/tests/realloc_unittest.cc
realloc_unittest_LDFLAGS = $(TCMALLOC_FLAGS) $(AM_LDFLAGS)
realloc_unittest_LDADD = libtcmalloc_minimal.la

TESTS += stack_trace_table_test
stack_trace_table_test_SOURCES = src/tests/stack_trace_table_test.cc
stack_trace_table_test_LDFLAGS = $(TCMALLOC_FLAGS) $(AM_LDFLAGS)
stack_trace_table_test_LDADD = libtcmalloc_minimal.la

TESTS += thread_dealloc_unittest
thread_dealloc_unittest_SOURCES = src/tests/thread_dealloc_unittest.cc \
src/tests/testutil.cc
Expand Down Expand Up @@ -647,15 +667,6 @@ tcmalloc_large_heap_fragmentation_unittest_SOURCES = src/tests/large_heap_fragme
tcmalloc_large_heap_fragmentation_unittest_LDFLAGS = $(TCMALLOC_FLAGS) $(AM_LDFLAGS)
tcmalloc_large_heap_fragmentation_unittest_LDADD = libtcmalloc.la

# sampler_test and sampling_test both require sampling to be turned
# on, which it's not by default. Use the "standard" value of 2^19.
TESTS_ENVIRONMENT += TCMALLOC_SAMPLE_PARAMETER=524288

TESTS += sampler_test
sampler_test_SOURCES = src/tests/sampler_test.cc \
src/sampler.cc
sampler_test_LDADD = libcommon.la

# These unittests often need to run binaries. They're in the current dir
TESTS_ENVIRONMENT += BINDIR=.

Expand Down
2 changes: 2 additions & 0 deletions src/pagemap.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
#include <stddef.h> // for NULL, size_t
#include <string.h> // for memset
#include <stdint.h>

#include "base/basictypes.h"
#include "internal_logging.h" // for ASSERT

// Single-level array
Expand Down
87 changes: 43 additions & 44 deletions src/stack_trace_table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@
// ---
// Author: Andrew Fikes

#include <config.h>
#include "config.h"

#include "stack_trace_table.h"
#include <string.h> // for NULL, memset

#include "base/spinlock.h" // for SpinLockHolder
#include "common.h" // for StackTrace
#include "internal_logging.h" // for ASSERT, Log
Expand All @@ -42,24 +43,45 @@

namespace tcmalloc {

StackTraceTable::StackTraceTable()
: error_(false),
depth_total_(0),
bucket_total_(0),
head_(nullptr) {
}
std::unique_ptr<void*[]> ProduceStackTracesDump(const StackTrace* (*next_fn)(const void** current_head),
const void* head) {
int depth_total = 0;
int bucket_total = 0;
for (const void* entry = head; entry != nullptr;) {
const StackTrace* trace = next_fn(&entry);
depth_total += trace->depth;
bucket_total++;
}

int out_len = bucket_total * 3 + depth_total + 1;
std::unique_ptr<void*[]> out{new void*[out_len]};

StackTraceTable::~StackTraceTable() {
ASSERT(head_ == nullptr);
int idx = 0;
for (const void* entry = head; entry != nullptr;) {
const StackTrace* trace = next_fn(&entry);
out[idx++] = reinterpret_cast<void*>(uintptr_t{1}); // count
out[idx++] = reinterpret_cast<void*>(trace->size); // cumulative size
out[idx++] = reinterpret_cast<void*>(trace->depth);
for (int d = 0; d < trace->depth; ++d) {
out[idx++] = trace->stack[d];
}
}
out[idx++] = nullptr;
ASSERT(idx == out_len);

return out;
}

// In order to avoid dependencies we're only unit-testing function
// above. Stuff below pulls too much and isn't worth own unit-test
// (already covered by sampling_test).
#ifndef STACK_TRACE_TABLE_IS_TESTED

void StackTraceTable::AddTrace(const StackTrace& t) {
if (error_) {
return;
}

depth_total_ += t.depth;
bucket_total_++;
Entry* entry = allocator_.allocate(1);
if (entry == nullptr) {
Log(kLog, __FILE__, __LINE__,
Expand All @@ -73,40 +95,15 @@ void StackTraceTable::AddTrace(const StackTrace& t) {
}

void** StackTraceTable::ReadStackTracesAndClear() {
void** out = nullptr;

const int out_len = bucket_total_ * 3 + depth_total_ + 1;
if (!error_) {
// Allocate output array
out = new (std::nothrow_t{}) void*[out_len];
if (out == nullptr) {
Log(kLog, __FILE__, __LINE__,
"tcmalloc: allocation failed for stack traces",
out_len * sizeof(*out));
}
}

if (out) {
// Fill output array
int idx = 0;
Entry* entry = head_;
while (entry != NULL) {
out[idx++] = reinterpret_cast<void*>(uintptr_t{1}); // count
out[idx++] = reinterpret_cast<void*>(entry->trace.size); // cumulative size
out[idx++] = reinterpret_cast<void*>(entry->trace.depth);
for (int d = 0; d < entry->trace.depth; ++d) {
out[idx++] = entry->trace.stack[d];
}
entry = entry->next;
}
out[idx++] = NULL;
ASSERT(idx == out_len);
}
std::unique_ptr<void*[]> out = ProduceStackTracesDump(
+[] (const void** current_head) -> const StackTrace* {
const Entry* head = static_cast<const Entry*>(*current_head);
*current_head = head->next;
return &head->trace;
}, head_);

// Clear state
error_ = false;
depth_total_ = 0;
bucket_total_ = 0;

SpinLockHolder h(Static::pageheap_lock());
Entry* entry = head_;
Expand All @@ -117,7 +114,9 @@ void** StackTraceTable::ReadStackTracesAndClear() {
}
head_ = nullptr;

return out;
return out.release();
}

#endif // STACK_TRACE_TABLE_IS_TESTED

} // namespace tcmalloc
Loading

0 comments on commit 8a147b4

Please sign in to comment.