tools_sanity_unittest.cc revision dc0f95d653279beabeb9817299e2902918ba123e
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  WriteValueOutOfArrayBoundsLeft(ptr);
65  WriteValueOutOfArrayBoundsRight(ptr, size);
66}
67
68}  // namespace
69
70// A memory leak detector should report an error in this test.
71TEST(ToolsSanityTest, MemoryLeak) {
72  int *leak = new int[256];  // Leak some memory intentionally.
73  leak[4] = 1;  // Make sure the allocated memory is used.
74}
75
76TEST(ToolsSanityTest, AccessesToNewMemory) {
77  // This test may corrupt memory if not run under Valgrind.
78  if (!RunningOnValgrind())
79    return;
80
81  char *foo = new char[10];
82  MakeSomeErrors(foo, 10);
83  delete [] foo;
84  foo[5] = 0;  // Use after delete. This won't break anything under Valgrind.
85}
86
87TEST(ToolsSanityTest, AccessesToMallocMemory) {
88  // This test may corrupt memory if not run under Valgrind.
89  if (!RunningOnValgrind())
90    return;
91  char *foo = reinterpret_cast<char*>(malloc(10));
92  MakeSomeErrors(foo, 10);
93  free(foo);
94  foo[5] = 0;  // Use after free. This won't break anything under Valgrind.
95}
96
97TEST(ToolsSanityTest, ArrayDeletedWithoutBraces) {
98  // This test may corrupt memory if not run under Valgrind.
99  if (!RunningOnValgrind())
100    return;
101
102  int *foo = new int[10];
103  delete foo;
104}
105
106TEST(ToolsSanityTest, SingleElementDeletedWithBraces) {
107  // This test may corrupt memory if not run under Valgrind.
108  if (!RunningOnValgrind())
109    return;
110
111  int *foo = new int;
112  delete [] foo;
113}
114
115// A data race detector should report an error in this test.
116TEST(ToolsSanityTest, DataRace) {
117  bool shared = false;
118  PlatformThreadHandle a;
119  PlatformThreadHandle b;
120  PlatformThread::Delegate *thread1 =
121      new TOOLS_SANITY_TEST_CONCURRENT_THREAD(&shared);
122  PlatformThread::Delegate *thread2 =
123      new TOOLS_SANITY_TEST_CONCURRENT_THREAD(&shared);
124
125  PlatformThread::Create(0, thread1, &a);
126  PlatformThread::Create(0, thread2, &b);
127  PlatformThread::Join(a);
128  PlatformThread::Join(b);
129  EXPECT_TRUE(shared);
130  delete thread1;
131  delete thread2;
132}
133
134}  // namespace base
135