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