stack_trace_table_test.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright 2009 Google Inc. All Rights Reserved.
2// Author: fikes@google.com (Andrew Fikes)
3
4#include "config_for_unittests.h"
5#include <stdio.h>   // for puts()
6#include "stack_trace_table.h"
7#include "base/logging.h"
8#include "base/spinlock.h"
9#include "static_vars.h"
10
11#undef ARRAYSIZE   // may be defined on, eg, windows
12#define ARRAYSIZE(a)  ( sizeof(a) / sizeof(*(a)) )
13
14static void CheckTracesAndReset(tcmalloc::StackTraceTable* table,
15                        const uintptr_t* expected, int len) {
16  void** entries = table->ReadStackTracesAndClear();
17  for (int i = 0; i < len; ++i) {
18    CHECK_EQ(reinterpret_cast<uintptr_t>(entries[i]), expected[i]);
19  }
20  delete[] entries;
21}
22
23static void AddTrace(tcmalloc::StackTraceTable* table,
24                     const tcmalloc::StackTrace& t) {
25  // Normally we'd need this lock, but since the test is single-threaded
26  // we don't.  I comment it out on windows because the DLL-decl thing
27  // is really annoying in this case.
28#ifndef _MSC_VER
29  SpinLockHolder h(tcmalloc::Static::pageheap_lock());
30#endif
31  table->AddTrace(t);
32}
33
34int main(int argc, char **argv) {
35  tcmalloc::StackTraceTable table;
36
37  // Empty table
38  CHECK_EQ(table.depth_total(), 0);
39  CHECK_EQ(table.bucket_total(), 0);
40  static const uintptr_t k1[] = {0};
41  CheckTracesAndReset(&table, k1, ARRAYSIZE(k1));
42
43  tcmalloc::StackTrace t1;
44  t1.size = static_cast<uintptr_t>(1024);
45  t1.depth = static_cast<uintptr_t>(2);
46  t1.stack[0] = reinterpret_cast<void*>(1);
47  t1.stack[1] = reinterpret_cast<void*>(2);
48
49
50  tcmalloc::StackTrace t2;
51  t2.size = static_cast<uintptr_t>(512);
52  t2.depth = static_cast<uintptr_t>(2);
53  t2.stack[0] = reinterpret_cast<void*>(2);
54  t2.stack[1] = reinterpret_cast<void*>(1);
55
56  // Table w/ just t1
57  AddTrace(&table, t1);
58  CHECK_EQ(table.depth_total(), 2);
59  CHECK_EQ(table.bucket_total(), 1);
60  static const uintptr_t k2[] = {1, 1024, 2, 1, 2, 0};
61  CheckTracesAndReset(&table, k2, ARRAYSIZE(k2));
62
63  // Table w/ t1, t2
64  AddTrace(&table, t1);
65  AddTrace(&table, t2);
66  CHECK_EQ(table.depth_total(), 4);
67  CHECK_EQ(table.bucket_total(), 2);
68  static const uintptr_t k3[] = {1, 1024, 2, 1, 2, 1,  512, 2, 2, 1, 0};
69  CheckTracesAndReset(&table, k3, ARRAYSIZE(k3));
70
71  // Table w/ 2 x t1, 1 x t2
72  AddTrace(&table, t1);
73  AddTrace(&table, t2);
74  AddTrace(&table, t1);
75  CHECK_EQ(table.depth_total(), 4);
76  CHECK_EQ(table.bucket_total(), 2);
77  static const uintptr_t k4[] = {2, 2048, 2, 1, 2, 1,  512, 2, 2, 1, 0};
78  CheckTracesAndReset(&table, k4, ARRAYSIZE(k4));
79
80  // Same stack as t1, but w/ different size
81  tcmalloc::StackTrace t3;
82  t3.size = static_cast<uintptr_t>(2);
83  t3.depth = static_cast<uintptr_t>(2);
84  t3.stack[0] = reinterpret_cast<void*>(1);
85  t3.stack[1] = reinterpret_cast<void*>(2);
86
87  // Table w/ t1, t3
88  AddTrace(&table, t1);
89  AddTrace(&table, t3);
90  CHECK_EQ(table.depth_total(), 2);
91  CHECK_EQ(table.bucket_total(), 1);
92  static const uintptr_t k5[] = {2, 1026, 2, 1, 2, 0};
93  CheckTracesAndReset(&table, k5, ARRAYSIZE(k5));
94
95  puts("PASS");
96  return 0;
97}
98