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 10 namespace base { 11 12 namespace { 13 14 // We use caps here just to ensure that the method name doesn't interfere with 15 // the wildcarded suppressions. 16 class 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 32 void ReadUninitializedValue(char *ptr) { 33 if (*ptr == '\0') { 34 (*ptr)++; 35 } else { 36 (*ptr)--; 37 } 38 } 39 40 void ReadValueOutOfArrayBoundsLeft(char *ptr) { 41 char c = ptr[-2]; 42 VLOG(1) << "Reading a byte out of bounds: " << c; 43 } 44 45 void 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. 51 void WriteValueOutOfArrayBoundsLeft(char *ptr) { 52 ptr[-1] = 42; 53 } 54 55 // This is harmless if you run it under Valgrind thanks to redzones. 56 void WriteValueOutOfArrayBoundsRight(char *ptr, size_t size) { 57 ptr[size] = 42; 58 } 59 60 void 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. 71 TEST(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 76 TEST(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 87 TEST(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 97 TEST(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 106 TEST(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. 116 TEST(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