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