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