blob: 64a9ca68f1878431713960c7a2a41a95abacbfa2 [file] [log] [blame]
[email protected]f49ecd8f2011-05-10 18:03:341// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]0716cba2009-12-17 12:37:582// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]f49ecd8f2011-05-10 18:03:345#include "base/atomicops.h"
[email protected]0716cba2009-12-17 12:37:586#include "base/message_loop.h"
[email protected]ee857512010-05-14 08:24:427#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
[email protected]34b99632011-01-01 01:01:068#include "base/threading/thread.h"
[email protected]0716cba2009-12-17 12:37:589#include "testing/gtest/include/gtest/gtest.h"
10
[email protected]ce072a72010-12-31 20:02:1611namespace base {
12
[email protected]0716cba2009-12-17 12:37:5813namespace {
14
[email protected]f49ecd8f2011-05-10 18:03:3415const base::subtle::Atomic32 kMagicValue = 42;
[email protected]0716cba2009-12-17 12:37:5816
[email protected]adf7d802010-09-23 09:12:3717void ReadUninitializedValue(char *ptr) {
[email protected]d0d0152e2010-09-23 09:50:4718 if (*ptr == '\0') {
[email protected]adf7d802010-09-23 09:12:3719 (*ptr)++;
20 } else {
21 (*ptr)--;
22 }
23}
24
[email protected]9ded9912010-03-26 12:54:4425void ReadValueOutOfArrayBoundsLeft(char *ptr) {
[email protected]45b9eba2010-10-18 23:57:4926 char c = ptr[-2];
27 VLOG(1) << "Reading a byte out of bounds: " << c;
[email protected]9ded9912010-03-26 12:54:4428}
29
30void ReadValueOutOfArrayBoundsRight(char *ptr, size_t size) {
[email protected]45b9eba2010-10-18 23:57:4931 char c = ptr[size + 1];
32 VLOG(1) << "Reading a byte out of bounds: " << c;
[email protected]9ded9912010-03-26 12:54:4433}
34
35// This is harmless if you run it under Valgrind thanks to redzones.
36void WriteValueOutOfArrayBoundsLeft(char *ptr) {
[email protected]f49ecd8f2011-05-10 18:03:3437 ptr[-1] = kMagicValue;
[email protected]9ded9912010-03-26 12:54:4438}
39
40// This is harmless if you run it under Valgrind thanks to redzones.
41void WriteValueOutOfArrayBoundsRight(char *ptr, size_t size) {
[email protected]f49ecd8f2011-05-10 18:03:3442 ptr[size] = kMagicValue;
[email protected]9ded9912010-03-26 12:54:4443}
44
45void MakeSomeErrors(char *ptr, size_t size) {
[email protected]adf7d802010-09-23 09:12:3746 ReadUninitializedValue(ptr);
[email protected]9ded9912010-03-26 12:54:4447 ReadValueOutOfArrayBoundsLeft(ptr);
48 ReadValueOutOfArrayBoundsRight(ptr, size);
49 WriteValueOutOfArrayBoundsLeft(ptr);
50 WriteValueOutOfArrayBoundsRight(ptr, size);
51}
52
[email protected]66d051bb2010-10-14 08:25:5453} // namespace
54
55// A memory leak detector should report an error in this test.
56TEST(ToolsSanityTest, MemoryLeak) {
57 int *leak = new int[256]; // Leak some memory intentionally.
58 leak[4] = 1; // Make sure the allocated memory is used.
59}
60
[email protected]9ded9912010-03-26 12:54:4461TEST(ToolsSanityTest, AccessesToNewMemory) {
62 // This test may corrupt memory if not run under Valgrind.
63 if (!RunningOnValgrind())
64 return;
65
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.
70}
71
72TEST(ToolsSanityTest, AccessesToMallocMemory) {
73 // This test may corrupt memory if not run under Valgrind.
74 if (!RunningOnValgrind())
75 return;
[email protected]9ded9912010-03-26 12:54:4476 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.
80}
81
82TEST(ToolsSanityTest, ArrayDeletedWithoutBraces) {
83 // This test may corrupt memory if not run under Valgrind.
84 if (!RunningOnValgrind())
85 return;
86
87 int *foo = new int[10];
88 delete foo;
89}
90
91TEST(ToolsSanityTest, SingleElementDeletedWithBraces) {
92 // This test may corrupt memory if not run under Valgrind.
93 if (!RunningOnValgrind())
94 return;
95
96 int *foo = new int;
97 delete [] foo;
98}
99
[email protected]f49ecd8f2011-05-10 18:03:34100
101namespace {
102
103// We use caps here just to ensure that the method name doesn't interfere with
104// the wildcarded suppressions.
105class 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;
111
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);
116 }
117 private:
118 bool *value_;
119};
120
121class 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);
127
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);
132 }
133 private:
134 base::subtle::Atomic32 *value_;
135};
136
137class 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_);
145 }
146 private:
147 base::subtle::Atomic32 *value_;
148};
149
150void 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);
157}
158
159} // namespace
160
[email protected]0716cba2009-12-17 12:37:58161// A data race detector should report an error in this test.
[email protected]456a3c5e2010-06-11 12:50:22162TEST(ToolsSanityTest, DataRace) {
[email protected]0716cba2009-12-17 12:37:58163 bool shared = false;
[email protected]f49ecd8f2011-05-10 18:03:34164 TOOLS_SANITY_TEST_CONCURRENT_THREAD thread1(&shared), thread2(&shared);
165 RunInParallel(&thread1, &thread2);
[email protected]0716cba2009-12-17 12:37:58166 EXPECT_TRUE(shared);
[email protected]f49ecd8f2011-05-10 18:03:34167}
168
169TEST(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);
175}
176
177TEST(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);
[email protected]0716cba2009-12-17 12:37:58183}
[email protected]ce072a72010-12-31 20:02:16184
185} // namespace base