Updating trunk VERSION from 833.0 to 834.0
[chromium-blink-merge.git] / base / tools_sanity_unittest.cc
blob64a9ca68f1878431713960c7a2a41a95abacbfa2
1 // Copyright (c) 2011 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.
5 #include "base/atomicops.h"
6 #include "base/message_loop.h"
7 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
8 #include "base/threading/thread.h"
9 #include "testing/gtest/include/gtest/gtest.h"
11 namespace base {
13 namespace {
15 const base::subtle::Atomic32 kMagicValue = 42;
17 void ReadUninitializedValue(char *ptr) {
18 if (*ptr == '\0') {
19 (*ptr)++;
20 } else {
21 (*ptr)--;
25 void ReadValueOutOfArrayBoundsLeft(char *ptr) {
26 char c = ptr[-2];
27 VLOG(1) << "Reading a byte out of bounds: " << c;
30 void ReadValueOutOfArrayBoundsRight(char *ptr, size_t size) {
31 char c = ptr[size + 1];
32 VLOG(1) << "Reading a byte out of bounds: " << c;
35 // This is harmless if you run it under Valgrind thanks to redzones.
36 void WriteValueOutOfArrayBoundsLeft(char *ptr) {
37 ptr[-1] = kMagicValue;
40 // This is harmless if you run it under Valgrind thanks to redzones.
41 void WriteValueOutOfArrayBoundsRight(char *ptr, size_t size) {
42 ptr[size] = kMagicValue;
45 void MakeSomeErrors(char *ptr, size_t size) {
46 ReadUninitializedValue(ptr);
47 ReadValueOutOfArrayBoundsLeft(ptr);
48 ReadValueOutOfArrayBoundsRight(ptr, size);
49 WriteValueOutOfArrayBoundsLeft(ptr);
50 WriteValueOutOfArrayBoundsRight(ptr, size);
53 } // namespace
55 // A memory leak detector should report an error in this test.
56 TEST(ToolsSanityTest, MemoryLeak) {
57 int *leak = new int[256]; // Leak some memory intentionally.
58 leak[4] = 1; // Make sure the allocated memory is used.
61 TEST(ToolsSanityTest, AccessesToNewMemory) {
62 // This test may corrupt memory if not run under Valgrind.
63 if (!RunningOnValgrind())
64 return;
66 char *foo = new char[10];
67 MakeSomeErrors(foo, 10);
68 delete [] foo;
69 foo[5] = 0; // Use after delete. This won't break anything under Valgrind.
72 TEST(ToolsSanityTest, AccessesToMallocMemory) {
73 // This test may corrupt memory if not run under Valgrind.
74 if (!RunningOnValgrind())
75 return;
76 char *foo = reinterpret_cast<char*>(malloc(10));
77 MakeSomeErrors(foo, 10);
78 free(foo);
79 foo[5] = 0; // Use after free. This won't break anything under Valgrind.
82 TEST(ToolsSanityTest, ArrayDeletedWithoutBraces) {
83 // This test may corrupt memory if not run under Valgrind.
84 if (!RunningOnValgrind())
85 return;
87 int *foo = new int[10];
88 delete foo;
91 TEST(ToolsSanityTest, SingleElementDeletedWithBraces) {
92 // This test may corrupt memory if not run under Valgrind.
93 if (!RunningOnValgrind())
94 return;
96 int *foo = new int;
97 delete [] foo;
101 namespace {
103 // We use caps here just to ensure that the method name doesn't interfere with
104 // the wildcarded suppressions.
105 class TOOLS_SANITY_TEST_CONCURRENT_THREAD : public PlatformThread::Delegate {
106 public:
107 explicit TOOLS_SANITY_TEST_CONCURRENT_THREAD(bool *value) : value_(value) {}
108 ~TOOLS_SANITY_TEST_CONCURRENT_THREAD() {}
109 void ThreadMain() {
110 *value_ = true;
112 // Sleep for a few milliseconds so the two threads are more likely to live
113 // simultaneously. Otherwise we may miss the report due to mutex
114 // lock/unlock's inside thread creation code in pure-happens-before mode...
115 PlatformThread::Sleep(100);
117 private:
118 bool *value_;
121 class ReleaseStoreThread : public PlatformThread::Delegate {
122 public:
123 explicit ReleaseStoreThread(base::subtle::Atomic32 *value) : value_(value) {}
124 ~ReleaseStoreThread() {}
125 void ThreadMain() {
126 base::subtle::Release_Store(value_, kMagicValue);
128 // Sleep for a few milliseconds so the two threads are more likely to live
129 // simultaneously. Otherwise we may miss the report due to mutex
130 // lock/unlock's inside thread creation code in pure-happens-before mode...
131 PlatformThread::Sleep(100);
133 private:
134 base::subtle::Atomic32 *value_;
137 class AcquireLoadThread : public PlatformThread::Delegate {
138 public:
139 explicit AcquireLoadThread(base::subtle::Atomic32 *value) : value_(value) {}
140 ~AcquireLoadThread() {}
141 void ThreadMain() {
142 // Wait for the other thread to make Release_Store
143 PlatformThread::Sleep(100);
144 base::subtle::Acquire_Load(value_);
146 private:
147 base::subtle::Atomic32 *value_;
150 void RunInParallel(PlatformThread::Delegate *d1, PlatformThread::Delegate *d2) {
151 PlatformThreadHandle a;
152 PlatformThreadHandle b;
153 PlatformThread::Create(0, d1, &a);
154 PlatformThread::Create(0, d2, &b);
155 PlatformThread::Join(a);
156 PlatformThread::Join(b);
159 } // namespace
161 // A data race detector should report an error in this test.
162 TEST(ToolsSanityTest, DataRace) {
163 bool shared = false;
164 TOOLS_SANITY_TEST_CONCURRENT_THREAD thread1(&shared), thread2(&shared);
165 RunInParallel(&thread1, &thread2);
166 EXPECT_TRUE(shared);
169 TEST(ToolsSanityTest, AnnotateBenignRace) {
170 bool shared = false;
171 ANNOTATE_BENIGN_RACE(&shared, "Intentional race - make sure doesn't show up");
172 TOOLS_SANITY_TEST_CONCURRENT_THREAD thread1(&shared), thread2(&shared);
173 RunInParallel(&thread1, &thread2);
174 EXPECT_TRUE(shared);
177 TEST(ToolsSanityTest, AtomicsAreIgnored) {
178 base::subtle::Atomic32 shared = 0;
179 ReleaseStoreThread thread1(&shared);
180 AcquireLoadThread thread2(&shared);
181 RunInParallel(&thread1, &thread2);
182 EXPECT_EQ(kMagicValue, shared);
185 } // namespace base