1 //===-- sanitizer_stack_store_test.cpp --------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 #include "sanitizer_common/sanitizer_stack_store.h" 9 10 #include <algorithm> 11 #include <numeric> 12 #include <vector> 13 14 #include "gtest/gtest.h" 15 #include "sanitizer_hash.h" 16 #include "sanitizer_stacktrace.h" 17 18 namespace __sanitizer { 19 20 class StackStoreTest : public testing::Test { 21 protected: 22 void SetUp() override {} 23 void TearDown() override { store_.TestOnlyUnmap(); } 24 25 template <typename Fn> 26 void ForEachTrace(Fn fn, uptr n = 1000000) { 27 std::vector<uptr> frames(kStackTraceMax); 28 std::iota(frames.begin(), frames.end(), 1); 29 MurMur2HashBuilder h(0); 30 for (uptr i = 0; i < n; ++i) { 31 h.add(i); 32 u32 size = h.get() % kStackTraceMax; 33 h.add(i); 34 uptr tag = h.get() % 256; 35 StackTrace s(frames.data(), size, tag); 36 if (!s.size && !s.tag) 37 continue; 38 fn(s); 39 std::next_permutation(frames.begin(), frames.end()); 40 }; 41 } 42 43 StackStore store_ = {}; 44 }; 45 46 TEST_F(StackStoreTest, Empty) { 47 uptr before = store_.Allocated(); 48 EXPECT_EQ(0u, store_.Store({})); 49 uptr after = store_.Allocated(); 50 EXPECT_EQ(before, after); 51 } 52 53 TEST_F(StackStoreTest, Basic) { 54 std::vector<StackStore::Id> ids; 55 ForEachTrace([&](const StackTrace& s) { ids.push_back(store_.Store(s)); }); 56 57 auto id = ids.begin(); 58 ForEachTrace([&](const StackTrace& s) { 59 StackTrace trace = store_.Load(*(id++)); 60 EXPECT_EQ(s.size, trace.size); 61 EXPECT_EQ(s.tag, trace.tag); 62 EXPECT_EQ(std::vector<uptr>(s.trace, s.trace + s.size), 63 std::vector<uptr>(trace.trace, trace.trace + trace.size)); 64 }); 65 } 66 67 TEST_F(StackStoreTest, Allocated) { 68 EXPECT_LE(store_.Allocated(), 0x100000u); 69 std::vector<StackStore::Id> ids; 70 ForEachTrace([&](const StackTrace& s) { ids.push_back(store_.Store(s)); }); 71 EXPECT_NEAR(store_.Allocated(), FIRST_32_SECOND_64(500000000u, 1000000000u), 72 FIRST_32_SECOND_64(50000000u, 100000000u)); 73 store_.TestOnlyUnmap(); 74 EXPECT_LE(store_.Allocated(), 0x100000u); 75 } 76 77 } // namespace __sanitizer 78