tools_sanity_unittest.cc revision 3f50c38dc070f4bb515c1b64450dae14f316474e
1// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/message_loop.h"
6#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
7#include "base/threading/thread.h"
8#include "testing/gtest/include/gtest/gtest.h"
9
10namespace base {
11
12namespace {
13
14// We use caps here just to ensure that the method name doesn't interfere with
15// the wildcarded suppressions.
16class TOOLS_SANITY_TEST_CONCURRENT_THREAD : public PlatformThread::Delegate {
17 public:
18  explicit TOOLS_SANITY_TEST_CONCURRENT_THREAD(bool *value) : value_(value) {}
19  ~TOOLS_SANITY_TEST_CONCURRENT_THREAD() {}
20  void ThreadMain() {
21    *value_ = true;
22
23    // Sleep for a few milliseconds so the two threads are more likely to live
24    // simultaneously. Otherwise we may miss the report due to mutex
25    // lock/unlock's inside thread creation code in pure-happens-before mode...
26    PlatformThread::Sleep(100);
27  }
28 private:
29  bool *value_;
30};
31
32void ReadUninitializedValue(char *ptr) {
33  if (*ptr == '\0') {
34    (*ptr)++;
35  } else {
36    (*ptr)--;
37  }
38}
39
40void ReadValueOutOfArrayBoundsLeft(char *ptr) {
41  char c = ptr[-2];
42  VLOG(1) << "Reading a byte out of bounds: " << c;
43}
44
45void ReadValueOutOfArrayBoundsRight(char *ptr, size_t size) {
46  char c = ptr[size + 1];
47  VLOG(1) << "Reading a byte out of bounds: " << c;
48}
49
50// This is harmless if you run it under Valgrind thanks to redzones.
51void WriteValueOutOfArrayBoundsLeft(char *ptr) {
52  ptr[-1] = 42;
53}
54
55// This is harmless if you run it under Valgrind thanks to redzones.
56void WriteValueOutOfArrayBoundsRight(char *ptr, size_t size) {
57  ptr[size] = 42;
58}
59
60void MakeSomeErrors(char *ptr, size_t size) {
61  ReadUninitializedValue(ptr);
62  ReadValueOutOfArrayBoundsLeft(ptr);
63  ReadValueOutOfArrayBoundsRight(ptr, size);
64
65  // We execute this function only under memory checking tools -
66  // Valgrind on Linux and Mac, Dr. Memory on Windows.
67  // Currently writing values out-of-bounds makes Dr. Memory a bit crazy when
68  // this code is linked with /MTd, so skip these writes on Windows.
69  // See http://code.google.com/p/drmemory/issues/detail?id=51
70#if !defined(OS_WIN)
71  WriteValueOutOfArrayBoundsLeft(ptr);
72  WriteValueOutOfArrayBoundsRight(ptr, size);
73#endif
74}
75
76}  // namespace
77
78// A memory leak detector should report an error in this test.
79TEST(ToolsSanityTest, MemoryLeak) {
80  int *leak = new int[256];  // Leak some memory intentionally.
81  leak[4] = 1;  // Make sure the allocated memory is used.
82}
83
84TEST(ToolsSanityTest, AccessesToNewMemory) {
85  // This test may corrupt memory if not run under Valgrind.
86  if (!RunningOnValgrind())
87    return;
88
89  char *foo = new char[10];
90  MakeSomeErrors(foo, 10);
91  delete [] foo;
92  foo[5] = 0;  // Use after delete. This won't break anything under Valgrind.
93}
94
95TEST(ToolsSanityTest, AccessesToMallocMemory) {
96  // This test may corrupt memory if not run under Valgrind.
97  if (!RunningOnValgrind())
98    return;
99  char *foo = reinterpret_cast<char*>(malloc(10));
100  MakeSomeErrors(foo, 10);
101  free(foo);
102  foo[5] = 0;  // Use after free. This won't break anything under Valgrind.
103}
104
105TEST(ToolsSanityTest, ArrayDeletedWithoutBraces) {
106  // This test may corrupt memory if not run under Valgrind.
107  if (!RunningOnValgrind())
108    return;
109
110  int *foo = new int[10];
111  delete foo;
112}
113
114TEST(ToolsSanityTest, SingleElementDeletedWithBraces) {
115  // This test may corrupt memory if not run under Valgrind.
116  if (!RunningOnValgrind())
117    return;
118
119  int *foo = new int;
120  delete [] foo;
121}
122
123// A data race detector should report an error in this test.
124TEST(ToolsSanityTest, DataRace) {
125  bool shared = false;
126  PlatformThreadHandle a;
127  PlatformThreadHandle b;
128  PlatformThread::Delegate *thread1 =
129      new TOOLS_SANITY_TEST_CONCURRENT_THREAD(&shared);
130  PlatformThread::Delegate *thread2 =
131      new TOOLS_SANITY_TEST_CONCURRENT_THREAD(&shared);
132
133  PlatformThread::Create(0, thread1, &a);
134  PlatformThread::Create(0, thread2, &b);
135  PlatformThread::Join(a);
136  PlatformThread::Join(b);
137  EXPECT_TRUE(shared);
138  delete thread1;
139  delete thread2;
140}
141
142}  // namespace base
143