aboutsummaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/tests
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-18 20:11:54 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-18 20:11:54 +0000
commitcdf4f3055e964bb585f294cf77cb549ead82783f (patch)
tree7bceeca766b3fbe491245bc926a083f78c35d1de /lib/sanitizer_common/tests
parent625108084a3ec7c19c7745004c5af0ed7aa417a9 (diff)
downloadsrc-cdf4f3055e964bb585f294cf77cb549ead82783f.tar.gz
src-cdf4f3055e964bb585f294cf77cb549ead82783f.zip
Vendor import of compiler-rt trunk r321017:vendor/compiler-rt/compiler-rt-trunk-r321017
Notes
Notes: svn path=/vendor/compiler-rt/dist/; revision=326943 svn path=/vendor/compiler-rt/compiler-rt-trunk-r321017/; revision=326944; tag=vendor/compiler-rt/compiler-rt-trunk-r321017
Diffstat (limited to 'lib/sanitizer_common/tests')
-rw-r--r--lib/sanitizer_common/tests/CMakeLists.txt64
-rw-r--r--lib/sanitizer_common/tests/sanitizer_allocator_test.cc294
-rw-r--r--lib/sanitizer_common/tests/sanitizer_common_test.cc86
-rw-r--r--lib/sanitizer_common/tests/sanitizer_libc_test.cc1
-rw-r--r--lib/sanitizer_common/tests/sanitizer_linux_test.cc1
-rw-r--r--lib/sanitizer_common/tests/sanitizer_test_utils.h6
-rw-r--r--lib/sanitizer_common/tests/sanitizer_vector_test.cc42
7 files changed, 434 insertions, 60 deletions
diff --git a/lib/sanitizer_common/tests/CMakeLists.txt b/lib/sanitizer_common/tests/CMakeLists.txt
index 2acedd0ef56a..1bccaa78f39b 100644
--- a/lib/sanitizer_common/tests/CMakeLists.txt
+++ b/lib/sanitizer_common/tests/CMakeLists.txt
@@ -34,7 +34,8 @@ set(SANITIZER_UNITTESTS
sanitizer_suppressions_test.cc
sanitizer_symbolizer_test.cc
sanitizer_test_main.cc
- sanitizer_thread_registry_test.cc)
+ sanitizer_thread_registry_test.cc
+ sanitizer_vector_test.cc)
set(SANITIZER_TEST_HEADERS
sanitizer_pthread_wrappers.h
@@ -120,23 +121,13 @@ macro(add_sanitizer_common_lib library)
FOLDER "Compiler-RT Runtime tests")
endmacro()
-function(get_sanitizer_common_lib_for_arch arch lib lib_name)
+function(get_sanitizer_common_lib_for_arch arch lib)
if(APPLE)
set(tgt_name "RTSanitizerCommon.test.osx")
else()
set(tgt_name "RTSanitizerCommon.test.${arch}")
endif()
set(${lib} "${tgt_name}" PARENT_SCOPE)
- if(CMAKE_CONFIGURATION_TYPES)
- set(configuration_path "${CMAKE_CFG_INTDIR}/")
- else()
- set(configuration_path "")
- endif()
- if(NOT MSVC)
- set(${lib_name} "${configuration_path}lib${tgt_name}.a" PARENT_SCOPE)
- else()
- set(${lib_name} "${configuration_path}${tgt_name}.lib" PARENT_SCOPE)
- endif()
endfunction()
# Sanitizer_common unit tests testsuite.
@@ -145,45 +136,22 @@ set_target_properties(SanitizerUnitTests PROPERTIES FOLDER "Compiler-RT Tests")
# Adds sanitizer tests for architecture.
macro(add_sanitizer_tests_for_arch arch)
- get_target_flags_for_arch(${arch} TARGET_FLAGS)
-
- # If the sanitizer library was built with _FILE_OFFSET_BITS=64 we need
- # to ensure that the library and tests agree on the layout of certain
- # structures such as 'struct stat'.
+ set(extra_flags)
if( CMAKE_SIZEOF_VOID_P EQUAL 4 )
- list(APPEND TARGET_FLAGS "-D_LARGEFILE_SOURCE")
- list(APPEND TARGET_FLAGS "-D_FILE_OFFSET_BITS=64")
+ list(APPEND extra_flags "-D_LARGEFILE_SOURCE")
+ list(APPEND extra_flags "-D_FILE_OFFSET_BITS=64")
endif()
+ get_sanitizer_common_lib_for_arch(${arch} SANITIZER_COMMON_LIB)
- set(SANITIZER_TEST_SOURCES ${SANITIZER_UNITTESTS}
- ${COMPILER_RT_GTEST_SOURCE})
- set(SANITIZER_TEST_COMPILE_DEPS ${SANITIZER_TEST_HEADERS})
- if(NOT COMPILER_RT_STANDALONE_BUILD)
- list(APPEND SANITIZER_TEST_COMPILE_DEPS gtest)
- endif()
set(SANITIZER_TEST_OBJECTS)
- foreach(source ${SANITIZER_TEST_SOURCES})
- get_filename_component(basename ${source} NAME)
- if(CMAKE_CONFIGURATION_TYPES)
- set(output_obj "${CMAKE_CFG_INTDIR}/${basename}.${arch}.o")
- else()
- set(output_obj "${basename}.${arch}.o")
- endif()
- clang_compile(${output_obj} ${source}
- CFLAGS ${SANITIZER_TEST_CFLAGS_COMMON} ${TARGET_FLAGS}
- DEPS ${SANITIZER_TEST_COMPILE_DEPS})
- list(APPEND SANITIZER_TEST_OBJECTS ${output_obj})
- endforeach()
- get_sanitizer_common_lib_for_arch(${arch} SANITIZER_COMMON_LIB
- SANITIZER_COMMON_LIB_NAME)
- # Add unittest target.
- set(SANITIZER_TEST_NAME "Sanitizer-${arch}-Test")
- add_compiler_rt_test(SanitizerUnitTests ${SANITIZER_TEST_NAME}
- OBJECTS ${SANITIZER_TEST_OBJECTS}
- ${SANITIZER_COMMON_LIB_NAME}
- DEPS ${SANITIZER_TEST_OBJECTS} ${SANITIZER_COMMON_LIB}
- LINK_FLAGS ${SANITIZER_TEST_LINK_FLAGS_COMMON}
- ${TARGET_FLAGS})
+ generate_compiler_rt_tests(SANITIZER_TEST_OBJECTS SanitizerUnitTests
+ "Sanitizer-${arch}-Test" ${arch}
+ RUNTIME "${SANITIZER_COMMON_LIB}"
+ SOURCES ${SANITIZER_UNITTESTS} ${COMPILER_RT_GTEST_SOURCE}
+ COMPILE_DEPS ${SANITIZER_TEST_HEADERS}
+ DEPS gtest
+ CFLAGS ${SANITIZER_TEST_CFLAGS_COMMON} ${extra_flags}
+ LINK_FLAGS ${SANITIZER_TEST_LINK_FLAGS_COMMON} ${extra_flags})
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" AND "${arch}" STREQUAL "x86_64")
# Test that the libc-independent part of sanitizer_common is indeed
@@ -193,7 +161,7 @@ macro(add_sanitizer_tests_for_arch arch)
sanitizer_nolibc_test_main.cc
CFLAGS ${SANITIZER_TEST_CFLAGS_COMMON} ${TARGET_FLAGS}
DEPS ${SANITIZER_TEST_COMPILE_DEPS})
- add_compiler_rt_test(SanitizerUnitTests "Sanitizer-${arch}-Test-Nolibc"
+ add_compiler_rt_test(SanitizerUnitTests "Sanitizer-${arch}-Test-Nolibc" ${arch}
OBJECTS sanitizer_nolibc_test_main.${arch}.o
-Wl,-whole-archive
libRTSanitizerCommon.test.nolibc.${arch}.a
diff --git a/lib/sanitizer_common/tests/sanitizer_allocator_test.cc b/lib/sanitizer_common/tests/sanitizer_allocator_test.cc
index 0def8ee0fd70..7b5e3e21f1ee 100644
--- a/lib/sanitizer_common/tests/sanitizer_allocator_test.cc
+++ b/lib/sanitizer_common/tests/sanitizer_allocator_test.cc
@@ -20,6 +20,7 @@
#include "gtest/gtest.h"
+#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <vector>
@@ -240,6 +241,23 @@ TEST(SanitizerCommon, SizeClassAllocator32Compact) {
TestSizeClassAllocator<Allocator32Compact>();
}
+struct AP32SeparateBatches {
+ static const uptr kSpaceBeg = 0;
+ static const u64 kSpaceSize = kAddressSpaceSize;
+ static const uptr kMetadataSize = 16;
+ typedef DefaultSizeClassMap SizeClassMap;
+ static const uptr kRegionSizeLog = ::kRegionSizeLog;
+ typedef FlatByteMap<kFlatByteMapSize> ByteMap;
+ typedef NoOpMapUnmapCallback MapUnmapCallback;
+ static const uptr kFlags =
+ SizeClassAllocator32FlagMasks::kUseSeparateSizeClassForBatch;
+};
+typedef SizeClassAllocator32<AP32SeparateBatches> Allocator32SeparateBatches;
+
+TEST(SanitizerCommon, SizeClassAllocator32SeparateBatches) {
+ TestSizeClassAllocator<Allocator32SeparateBatches>();
+}
+
template <class Allocator>
void SizeClassAllocatorMetadataStress() {
Allocator *a = new Allocator;
@@ -996,6 +1014,282 @@ TEST(SanitizerCommon, SizeClassAllocator64PopulateFreeListOOM) {
#endif
+#if SANITIZER_CAN_USE_ALLOCATOR64
+
+class NoMemoryMapper {
+ public:
+ uptr last_request_buffer_size;
+
+ NoMemoryMapper() : last_request_buffer_size(0) {}
+
+ uptr MapPackedCounterArrayBuffer(uptr buffer_size) {
+ last_request_buffer_size = buffer_size;
+ return 0;
+ }
+ void UnmapPackedCounterArrayBuffer(uptr buffer, uptr buffer_size) {}
+};
+
+class RedZoneMemoryMapper {
+ public:
+ RedZoneMemoryMapper() {
+ const auto page_size = GetPageSize();
+ buffer = MmapOrDie(3ULL * page_size, "");
+ MprotectNoAccess(reinterpret_cast<uptr>(buffer), page_size);
+ MprotectNoAccess(reinterpret_cast<uptr>(buffer) + page_size * 2, page_size);
+ }
+ ~RedZoneMemoryMapper() {
+ UnmapOrDie(buffer, 3 * GetPageSize());
+ }
+
+ uptr MapPackedCounterArrayBuffer(uptr buffer_size) {
+ const auto page_size = GetPageSize();
+ CHECK_EQ(buffer_size, page_size);
+ memset(reinterpret_cast<void*>(reinterpret_cast<uptr>(buffer) + page_size),
+ 0, page_size);
+ return reinterpret_cast<uptr>(buffer) + page_size;
+ }
+ void UnmapPackedCounterArrayBuffer(uptr buffer, uptr buffer_size) {}
+
+ private:
+ void *buffer;
+};
+
+TEST(SanitizerCommon, SizeClassAllocator64PackedCounterArray) {
+ NoMemoryMapper no_memory_mapper;
+ typedef Allocator64::PackedCounterArray<NoMemoryMapper>
+ NoMemoryPackedCounterArray;
+
+ for (int i = 0; i < 64; i++) {
+ // Various valid counter's max values packed into one word.
+ NoMemoryPackedCounterArray counters_2n(1, 1ULL << i, &no_memory_mapper);
+ EXPECT_EQ(8ULL, no_memory_mapper.last_request_buffer_size);
+
+ // Check the "all bit set" values too.
+ NoMemoryPackedCounterArray counters_2n1_1(1, ~0ULL >> i, &no_memory_mapper);
+ EXPECT_EQ(8ULL, no_memory_mapper.last_request_buffer_size);
+
+ // Verify the packing ratio, the counter is expected to be packed into the
+ // closest power of 2 bits.
+ NoMemoryPackedCounterArray counters(64, 1ULL << i, &no_memory_mapper);
+ EXPECT_EQ(8ULL * RoundUpToPowerOfTwo(i + 1),
+ no_memory_mapper.last_request_buffer_size);
+ }
+
+ RedZoneMemoryMapper memory_mapper;
+ typedef Allocator64::PackedCounterArray<RedZoneMemoryMapper>
+ RedZonePackedCounterArray;
+ // Go through 1, 2, 4, 8, .. 64 bits per counter.
+ for (int i = 0; i < 7; i++) {
+ // Make sure counters request one memory page for the buffer.
+ const u64 kNumCounters = (GetPageSize() / 8) * (64 >> i);
+ RedZonePackedCounterArray counters(kNumCounters,
+ 1ULL << ((1 << i) - 1),
+ &memory_mapper);
+ counters.Inc(0);
+ for (u64 c = 1; c < kNumCounters - 1; c++) {
+ ASSERT_EQ(0ULL, counters.Get(c));
+ counters.Inc(c);
+ ASSERT_EQ(1ULL, counters.Get(c - 1));
+ }
+ ASSERT_EQ(0ULL, counters.Get(kNumCounters - 1));
+ counters.Inc(kNumCounters - 1);
+
+ if (i > 0) {
+ counters.IncRange(0, kNumCounters - 1);
+ for (u64 c = 0; c < kNumCounters; c++)
+ ASSERT_EQ(2ULL, counters.Get(c));
+ }
+ }
+}
+
+class RangeRecorder {
+ public:
+ std::string reported_pages;
+
+ RangeRecorder()
+ : page_size_scaled_log(
+ Log2(GetPageSizeCached() >> Allocator64::kCompactPtrScale)),
+ last_page_reported(0) {}
+
+ void ReleasePageRangeToOS(u32 from, u32 to) {
+ from >>= page_size_scaled_log;
+ to >>= page_size_scaled_log;
+ ASSERT_LT(from, to);
+ if (!reported_pages.empty())
+ ASSERT_LT(last_page_reported, from);
+ reported_pages.append(from - last_page_reported, '.');
+ reported_pages.append(to - from, 'x');
+ last_page_reported = to;
+ }
+ private:
+ const uptr page_size_scaled_log;
+ u32 last_page_reported;
+};
+
+TEST(SanitizerCommon, SizeClassAllocator64FreePagesRangeTracker) {
+ typedef Allocator64::FreePagesRangeTracker<RangeRecorder> RangeTracker;
+
+ // 'x' denotes a page to be released, '.' denotes a page to be kept around.
+ const char* test_cases[] = {
+ "",
+ ".",
+ "x",
+ "........",
+ "xxxxxxxxxxx",
+ "..............xxxxx",
+ "xxxxxxxxxxxxxxxxxx.....",
+ "......xxxxxxxx........",
+ "xxx..........xxxxxxxxxxxxxxx",
+ "......xxxx....xxxx........",
+ "xxx..........xxxxxxxx....xxxxxxx",
+ "x.x.x.x.x.x.x.x.x.x.x.x.",
+ ".x.x.x.x.x.x.x.x.x.x.x.x",
+ ".x.x.x.x.x.x.x.x.x.x.x.x.",
+ "x.x.x.x.x.x.x.x.x.x.x.x.x",
+ };
+
+ for (auto test_case : test_cases) {
+ RangeRecorder range_recorder;
+ RangeTracker tracker(&range_recorder);
+ for (int i = 0; test_case[i] != 0; i++)
+ tracker.NextPage(test_case[i] == 'x');
+ tracker.Done();
+ // Strip trailing '.'-pages before comparing the results as they are not
+ // going to be reported to range_recorder anyway.
+ const char* last_x = strrchr(test_case, 'x');
+ std::string expected(
+ test_case,
+ last_x == nullptr ? 0 : (last_x - test_case + 1));
+ EXPECT_STREQ(expected.c_str(), range_recorder.reported_pages.c_str());
+ }
+}
+
+class ReleasedPagesTrackingMemoryMapper {
+ public:
+ std::set<u32> reported_pages;
+
+ uptr MapPackedCounterArrayBuffer(uptr buffer_size) {
+ reported_pages.clear();
+ return reinterpret_cast<uptr>(calloc(1, buffer_size));
+ }
+ void UnmapPackedCounterArrayBuffer(uptr buffer, uptr buffer_size) {
+ free(reinterpret_cast<void*>(buffer));
+ }
+
+ void ReleasePageRangeToOS(u32 from, u32 to) {
+ uptr page_size_scaled =
+ GetPageSizeCached() >> Allocator64::kCompactPtrScale;
+ for (u32 i = from; i < to; i += page_size_scaled)
+ reported_pages.insert(i);
+ }
+};
+
+template <class Allocator>
+void TestReleaseFreeMemoryToOS() {
+ ReleasedPagesTrackingMemoryMapper memory_mapper;
+ const uptr kAllocatedPagesCount = 1024;
+ const uptr page_size = GetPageSizeCached();
+ const uptr page_size_scaled = page_size >> Allocator::kCompactPtrScale;
+ std::mt19937 r;
+ uint32_t rnd_state = 42;
+
+ for (uptr class_id = 1; class_id <= Allocator::SizeClassMapT::kLargestClassID;
+ class_id++) {
+ const uptr chunk_size = Allocator::SizeClassMapT::Size(class_id);
+ const uptr chunk_size_scaled = chunk_size >> Allocator::kCompactPtrScale;
+ const uptr max_chunks =
+ kAllocatedPagesCount * GetPageSizeCached() / chunk_size;
+
+ // Generate the random free list.
+ std::vector<u32> free_array;
+ bool in_free_range = false;
+ uptr current_range_end = 0;
+ for (uptr i = 0; i < max_chunks; i++) {
+ if (i == current_range_end) {
+ in_free_range = (my_rand_r(&rnd_state) & 1U) == 1;
+ current_range_end += my_rand_r(&rnd_state) % 100 + 1;
+ }
+ if (in_free_range)
+ free_array.push_back(i * chunk_size_scaled);
+ }
+ if (free_array.empty())
+ continue;
+ // Shuffle free_list to verify that ReleaseFreeMemoryToOS does not depend on
+ // the list ordering.
+ std::shuffle(free_array.begin(), free_array.end(), r);
+
+ Allocator::ReleaseFreeMemoryToOS(&free_array[0], free_array.size(),
+ chunk_size, kAllocatedPagesCount,
+ &memory_mapper);
+
+ // Verify that there are no released pages touched by used chunks and all
+ // ranges of free chunks big enough to contain the entire memory pages had
+ // these pages released.
+ uptr verified_released_pages = 0;
+ std::set<u32> free_chunks(free_array.begin(), free_array.end());
+
+ u32 current_chunk = 0;
+ in_free_range = false;
+ u32 current_free_range_start = 0;
+ for (uptr i = 0; i <= max_chunks; i++) {
+ bool is_free_chunk = free_chunks.find(current_chunk) != free_chunks.end();
+
+ if (is_free_chunk) {
+ if (!in_free_range) {
+ in_free_range = true;
+ current_free_range_start = current_chunk;
+ }
+ } else {
+ // Verify that this used chunk does not touch any released page.
+ for (uptr i_page = current_chunk / page_size_scaled;
+ i_page <= (current_chunk + chunk_size_scaled - 1) /
+ page_size_scaled;
+ i_page++) {
+ bool page_released =
+ memory_mapper.reported_pages.find(i_page * page_size_scaled) !=
+ memory_mapper.reported_pages.end();
+ ASSERT_EQ(false, page_released);
+ }
+
+ if (in_free_range) {
+ in_free_range = false;
+ // Verify that all entire memory pages covered by this range of free
+ // chunks were released.
+ u32 page = RoundUpTo(current_free_range_start, page_size_scaled);
+ while (page + page_size_scaled <= current_chunk) {
+ bool page_released =
+ memory_mapper.reported_pages.find(page) !=
+ memory_mapper.reported_pages.end();
+ ASSERT_EQ(true, page_released);
+ verified_released_pages++;
+ page += page_size_scaled;
+ }
+ }
+ }
+
+ current_chunk += chunk_size_scaled;
+ }
+
+ ASSERT_EQ(memory_mapper.reported_pages.size(), verified_released_pages);
+ }
+}
+
+TEST(SanitizerCommon, SizeClassAllocator64ReleaseFreeMemoryToOS) {
+ TestReleaseFreeMemoryToOS<Allocator64>();
+}
+
+#if !SANITIZER_ANDROID
+TEST(SanitizerCommon, SizeClassAllocator64CompactReleaseFreeMemoryToOS) {
+ TestReleaseFreeMemoryToOS<Allocator64Compact>();
+}
+
+TEST(SanitizerCommon, SizeClassAllocator64VeryCompactReleaseFreeMemoryToOS) {
+ TestReleaseFreeMemoryToOS<Allocator64VeryCompact>();
+}
+#endif // !SANITIZER_ANDROID
+
+#endif // SANITIZER_CAN_USE_ALLOCATOR64
+
TEST(SanitizerCommon, TwoLevelByteMap) {
const u64 kSize1 = 1 << 6, kSize2 = 1 << 12;
const u64 n = kSize1 * kSize2;
diff --git a/lib/sanitizer_common/tests/sanitizer_common_test.cc b/lib/sanitizer_common/tests/sanitizer_common_test.cc
index 93a8794eeb8f..576649cea359 100644
--- a/lib/sanitizer_common/tests/sanitizer_common_test.cc
+++ b/lib/sanitizer_common/tests/sanitizer_common_test.cc
@@ -14,6 +14,7 @@
#include "sanitizer_common/sanitizer_allocator_internal.h"
#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_file.h"
#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_platform.h"
@@ -303,18 +304,85 @@ TEST(SanitizerCommon, InternalScopedString) {
#if SANITIZER_LINUX
TEST(SanitizerCommon, GetRandom) {
u8 buffer_1[32], buffer_2[32];
- EXPECT_FALSE(GetRandom(nullptr, 32));
- EXPECT_FALSE(GetRandom(buffer_1, 0));
- EXPECT_FALSE(GetRandom(buffer_1, 512));
- EXPECT_EQ(ARRAY_SIZE(buffer_1), ARRAY_SIZE(buffer_2));
- for (uptr size = 4; size <= ARRAY_SIZE(buffer_1); size += 4) {
- for (uptr i = 0; i < 100; i++) {
- EXPECT_TRUE(GetRandom(buffer_1, size));
- EXPECT_TRUE(GetRandom(buffer_2, size));
- EXPECT_NE(internal_memcmp(buffer_1, buffer_2, size), 0);
+ for (bool blocking : { false, true }) {
+ EXPECT_FALSE(GetRandom(nullptr, 32, blocking));
+ EXPECT_FALSE(GetRandom(buffer_1, 0, blocking));
+ EXPECT_FALSE(GetRandom(buffer_1, 512, blocking));
+ EXPECT_EQ(ARRAY_SIZE(buffer_1), ARRAY_SIZE(buffer_2));
+ for (uptr size = 4; size <= ARRAY_SIZE(buffer_1); size += 4) {
+ for (uptr i = 0; i < 100; i++) {
+ EXPECT_TRUE(GetRandom(buffer_1, size, blocking));
+ EXPECT_TRUE(GetRandom(buffer_2, size, blocking));
+ EXPECT_NE(internal_memcmp(buffer_1, buffer_2, size), 0);
+ }
}
}
}
#endif
+TEST(SanitizerCommon, ReservedAddressRangeInit) {
+ uptr init_size = 0xffff;
+ ReservedAddressRange address_range;
+ uptr res = address_range.Init(init_size);
+ CHECK_NE(res, (void*)-1);
+ UnmapOrDie((void*)res, init_size);
+ // Should be able to map into the same space now.
+ ReservedAddressRange address_range2;
+ uptr res2 = address_range2.Init(init_size, nullptr, res);
+ CHECK_EQ(res, res2);
+
+ // TODO(flowerhack): Once this is switched to the "real" implementation
+ // (rather than passing through to MmapNoAccess*), enforce and test "no
+ // double initializations allowed"
+}
+
+TEST(SanitizerCommon, ReservedAddressRangeMap) {
+ constexpr uptr init_size = 0xffff;
+ ReservedAddressRange address_range;
+ uptr res = address_range.Init(init_size);
+ CHECK_NE(res, (void*) -1);
+
+ // Valid mappings should succeed.
+ CHECK_EQ(res, address_range.Map(res, init_size));
+
+ // Valid mappings should be readable.
+ unsigned char buffer[init_size];
+ memcpy(buffer, reinterpret_cast<void *>(res), init_size);
+
+ // TODO(flowerhack): Once this is switched to the "real" implementation, make
+ // sure you can only mmap into offsets in the Init range.
+}
+
+TEST(SanitizerCommon, ReservedAddressRangeUnmap) {
+ uptr PageSize = GetPageSizeCached();
+ uptr init_size = PageSize * 8;
+ ReservedAddressRange address_range;
+ uptr base_addr = address_range.Init(init_size);
+ CHECK_NE(base_addr, (void*)-1);
+ CHECK_EQ(base_addr, address_range.Map(base_addr, init_size));
+
+ // Unmapping the entire range should succeed.
+ address_range.Unmap(base_addr, init_size);
+
+ // Map a new range.
+ base_addr = address_range.Init(init_size);
+ CHECK_EQ(base_addr, address_range.Map(base_addr, init_size));
+
+ // Windows doesn't allow partial unmappings.
+ #if !SANITIZER_WINDOWS
+
+ // Unmapping at the beginning should succeed.
+ address_range.Unmap(base_addr, PageSize);
+
+ // Unmapping at the end should succeed.
+ uptr new_start = reinterpret_cast<uptr>(address_range.base()) +
+ address_range.size() - PageSize;
+ address_range.Unmap(new_start, PageSize);
+
+ #endif
+
+ // Unmapping in the middle of the ReservedAddressRange should fail.
+ EXPECT_DEATH(address_range.Unmap(base_addr + (PageSize * 2), PageSize), ".*");
+}
+
} // namespace __sanitizer
diff --git a/lib/sanitizer_common/tests/sanitizer_libc_test.cc b/lib/sanitizer_common/tests/sanitizer_libc_test.cc
index 625257622bf2..a73c65a510c2 100644
--- a/lib/sanitizer_common/tests/sanitizer_libc_test.cc
+++ b/lib/sanitizer_common/tests/sanitizer_libc_test.cc
@@ -11,6 +11,7 @@
#include <algorithm>
#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_file.h"
#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_platform.h"
#include "gtest/gtest.h"
diff --git a/lib/sanitizer_common/tests/sanitizer_linux_test.cc b/lib/sanitizer_common/tests/sanitizer_linux_test.cc
index fb6b109ee23b..8a6afab65adb 100644
--- a/lib/sanitizer_common/tests/sanitizer_linux_test.cc
+++ b/lib/sanitizer_common/tests/sanitizer_linux_test.cc
@@ -17,6 +17,7 @@
#include "sanitizer_common/sanitizer_linux.h"
#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_file.h"
#include "gtest/gtest.h"
#include <pthread.h>
diff --git a/lib/sanitizer_common/tests/sanitizer_test_utils.h b/lib/sanitizer_common/tests/sanitizer_test_utils.h
index b7728d9ea25e..f8821a15d9b9 100644
--- a/lib/sanitizer_common/tests/sanitizer_test_utils.h
+++ b/lib/sanitizer_common/tests/sanitizer_test_utils.h
@@ -101,8 +101,8 @@ static inline uint32_t my_rand() {
# define SANITIZER_TEST_HAS_POSIX_MEMALIGN 0
#endif
-#if !defined(__APPLE__) && !defined(__FreeBSD__) && \
- !defined(__ANDROID__) && !defined(_WIN32)
+#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__ANDROID__) && \
+ !defined(__NetBSD__) && !defined(_WIN32)
# define SANITIZER_TEST_HAS_MEMALIGN 1
# define SANITIZER_TEST_HAS_PVALLOC 1
# define SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE 1
@@ -118,7 +118,7 @@ static inline uint32_t my_rand() {
# define SANITIZER_TEST_HAS_STRNLEN 0
#endif
-#if defined(__FreeBSD__)
+#if defined(__FreeBSD__) || defined(__NetBSD__)
# define SANITIZER_TEST_HAS_PRINTF_L 1
#else
# define SANITIZER_TEST_HAS_PRINTF_L 0
diff --git a/lib/sanitizer_common/tests/sanitizer_vector_test.cc b/lib/sanitizer_common/tests/sanitizer_vector_test.cc
new file mode 100644
index 000000000000..33ed14e190c5
--- /dev/null
+++ b/lib/sanitizer_common/tests/sanitizer_vector_test.cc
@@ -0,0 +1,42 @@
+//===-- sanitizer_vector_test.cc ------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of *Sanitizer runtime.
+//
+//===----------------------------------------------------------------------===//
+#include "sanitizer_common/sanitizer_vector.h"
+#include "gtest/gtest.h"
+
+namespace __sanitizer {
+
+TEST(Vector, Basic) {
+ Vector<int> v;
+ EXPECT_EQ(v.Size(), (uptr)0);
+ v.PushBack(42);
+ EXPECT_EQ(v.Size(), (uptr)1);
+ EXPECT_EQ(v[0], 42);
+ v.PushBack(43);
+ EXPECT_EQ(v.Size(), (uptr)2);
+ EXPECT_EQ(v[0], 42);
+ EXPECT_EQ(v[1], 43);
+}
+
+TEST(Vector, Stride) {
+ Vector<int> v;
+ for (int i = 0; i < 1000; i++) {
+ v.PushBack(i);
+ EXPECT_EQ(v.Size(), (uptr)(i + 1));
+ EXPECT_EQ(v[i], i);
+ }
+ for (int i = 0; i < 1000; i++) {
+ EXPECT_EQ(v[i], i);
+ }
+}
+
+} // namespace __sanitizer