Home | History | Annotate | Download | only in base
      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