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