Home | History | Annotate | Download | only in unittest
      1 /*
      2   This file is part of Valgrind, a dynamic binary instrumentation
      3   framework.
      4 
      5   Copyright (C) 2008-2008 Google Inc
      6      opensource (at) google.com
      7 
      8   This program is free software; you can redistribute it and/or
      9   modify it under the terms of the GNU General Public License as
     10   published by the Free Software Foundation; either version 2 of the
     11   License, or (at your option) any later version.
     12 
     13   This program is distributed in the hope that it will be useful, but
     14   WITHOUT ANY WARRANTY; without even the implied warranty of
     15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16   General Public License for more details.
     17 
     18   You should have received a copy of the GNU General Public License
     19   along with this program; if not, write to the Free Software
     20   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     21   02111-1307, USA.
     22 
     23   The GNU General Public License is contained in the file COPYING.
     24 */
     25 
     26 /* Author: Konstantin Serebryany <opensource (at) google.com>
     27    Author: Timur Iskhodzhanov <opensource (at) google.com>
     28 
     29  This file contains a set of demonstration tests for ThreadSanitizer.
     30 */
     31 
     32 #include <gtest/gtest.h>
     33 
     34 #include "test_utils.h"
     35 
     36 int main(int argc, char** argv) {
     37   testing::InitGoogleTest(&argc, argv);
     38   return RUN_ALL_TESTS();
     39 }
     40 
     41 namespace RaceReportDemoTest {  // {{{1
     42 Mutex mu1;  // This Mutex guards var.
     43 Mutex mu2;  // This Mutex is not related to var.
     44 int   var;  // GUARDED_BY(mu1)
     45 
     46 void Thread1() {  // Runs in thread named 'test-thread-1'.
     47   MutexLock lock(&mu1);  // Correct Mutex.
     48   var = 1;
     49 }
     50 
     51 void Thread2() {  // Runs in thread named 'test-thread-2'.
     52   MutexLock lock(&mu2);  // Wrong Mutex.
     53   var = 2;
     54 }
     55 
     56 TEST(DemoTests, RaceReportDemoTest) {
     57   ANNOTATE_TRACE_MEMORY(&var);
     58   var = 0;
     59   MyThread t1(Thread1, NULL, "test-thread-1");
     60   MyThread t2(Thread2, NULL, "test-thread-2");
     61   t1.Start();
     62   t2.Start();
     63   t1.Join();
     64   t2.Join();
     65 }
     66 }  // namespace RaceReportDemoTest
     67 
     68 // test302: Complex race which happens at least twice.  {{{1
     69 namespace test302 {
     70 // In this test we have many different accesses to GLOB and only one access
     71 // is not synchronized properly.
     72 int     GLOB = 0;
     73 
     74 Mutex MU1;
     75 Mutex MU2;
     76 void Worker() {
     77   for(int i = 0; i < 100; i++) {
     78     switch(i % 4) {
     79       case 0:
     80         // This read is protected correctly.
     81         MU1.Lock(); CHECK(GLOB >= 0); MU1.Unlock();
     82         break;
     83       case 1:
     84         // Here we used the wrong lock! The reason of the race is here.
     85         MU2.Lock(); CHECK(GLOB >= 0); MU2.Unlock();
     86         break;
     87       case 2:
     88         // This read is protected correctly.
     89         MU1.Lock(); CHECK(GLOB >= 0); MU1.Unlock();
     90         break;
     91       case 3:
     92         // This write is protected correctly.
     93         MU1.Lock(); GLOB++; MU1.Unlock();
     94         break;
     95     }
     96     // sleep a bit so that the threads interleave
     97     // and the race happens at least twice.
     98     usleep(100);
     99   }
    100 }
    101 
    102 TEST(DemoTests, test302) {
    103   printf("test302: Complex race that happens twice.\n");
    104   MyThread t1(Worker), t2(Worker);
    105   t1.Start();
    106   t2.Start();
    107   t1.Join();   t2.Join();
    108 }
    109 }  // namespace test302
    110 
    111 
    112 // test303: Need to trace the memory to understand the report. {{{1
    113 namespace test303 {
    114 int     GLOB = 0;
    115 
    116 Mutex MU;
    117 void Worker1() { CHECK(GLOB >= 0); }
    118 void Worker2() { MU.Lock(); GLOB=1;  MU.Unlock();}
    119 
    120 TEST(DemoTests, test303) {
    121   printf("test303: a race that needs annotations.\n");
    122   ANNOTATE_TRACE_MEMORY(&GLOB);
    123   MyThreadArray t(Worker1, Worker2);
    124   t.Start();
    125   t.Join();
    126 }
    127 }  // namespace test303
    128 
    129 
    130 
    131 // test304: Can not trace the memory, since it is a library object. {{{1
    132 namespace test304 {
    133 string *STR;
    134 Mutex   MU;
    135 
    136 void Worker1() {
    137   sleep(0);
    138   ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
    139   MU.Lock(); CHECK(STR->length() >= 4); MU.Unlock();
    140 }
    141 void Worker2() {
    142   sleep(1);
    143   ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
    144   CHECK(STR->length() >= 4); // Unprotected!
    145 }
    146 void Worker3() {
    147   sleep(2);
    148   ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
    149   MU.Lock(); CHECK(STR->length() >= 4); MU.Unlock();
    150 }
    151 void Worker4() {
    152   sleep(3);
    153   ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
    154   MU.Lock(); *STR += " + a very very long string"; MU.Unlock();
    155 }
    156 
    157 TEST(DemoTests, test304) {
    158   STR = new string ("The String");
    159   printf("test304: a race where memory tracing does not work.\n");
    160   MyThreadArray t(Worker1, Worker2, Worker3, Worker4);
    161   t.Start();
    162   t.Join();
    163 
    164   printf("%s\n", STR->c_str());
    165   delete STR;
    166 }
    167 }  // namespace test304
    168 
    169 
    170 
    171 // test305: A bit more tricky: two locks used inconsistenly. {{{1
    172 namespace test305 {
    173 int     GLOB = 0;
    174 
    175 // In this test GLOB is protected by MU1 and MU2, but inconsistently.
    176 // The TRACES observed by helgrind are:
    177 // TRACE[1]: Access{T2/S2 wr} -> new State{Mod; #LS=2; #SS=1; T2/S2}
    178 // TRACE[2]: Access{T4/S9 wr} -> new State{Mod; #LS=1; #SS=2; T2/S2, T4/S9}
    179 // TRACE[3]: Access{T5/S13 wr} -> new State{Mod; #LS=1; #SS=3; T2/S2, T4/S9, T5/S13}
    180 // TRACE[4]: Access{T6/S19 wr} -> new State{Mod; #LS=0; #SS=4; T2/S2, T4/S9, T5/S13, T6/S19}
    181 //
    182 // The guilty access is either Worker2() or Worker4(), depending on
    183 // which mutex is supposed to protect GLOB.
    184 Mutex MU1;
    185 Mutex MU2;
    186 void Worker1() { MU1.Lock(); MU2.Lock(); GLOB=1; MU2.Unlock(); MU1.Unlock(); }
    187 void Worker2() { MU1.Lock();             GLOB=2;               MU1.Unlock(); }
    188 void Worker3() { MU1.Lock(); MU2.Lock(); GLOB=3; MU2.Unlock(); MU1.Unlock(); }
    189 void Worker4() {             MU2.Lock(); GLOB=4; MU2.Unlock();               }
    190 
    191 TEST(DemoTests, test305) {
    192   ANNOTATE_TRACE_MEMORY(&GLOB);
    193   printf("test305: simple race.\n");
    194   MyThread t1(Worker1), t2(Worker2), t3(Worker3), t4(Worker4);
    195   t1.Start(); usleep(100);
    196   t2.Start(); usleep(100);
    197   t3.Start(); usleep(100);
    198   t4.Start(); usleep(100);
    199   t1.Join(); t2.Join(); t3.Join(); t4.Join();
    200 }
    201 }  // namespace test305
    202 
    203 // test306: Two locks are used to protect a var.  {{{1
    204 namespace test306 {
    205 int     GLOB = 0;
    206 // Thread1 and Thread2 access the var under two locks.
    207 // Thread3 uses no locks.
    208 
    209 Mutex MU1;
    210 Mutex MU2;
    211 void Worker1() { MU1.Lock(); MU2.Lock(); GLOB=1; MU2.Unlock(); MU1.Unlock(); }
    212 void Worker2() { MU1.Lock(); MU2.Lock(); GLOB=3; MU2.Unlock(); MU1.Unlock(); }
    213 void Worker3() {                         GLOB=4;               }
    214 
    215 TEST(DemoTests, test306) {
    216   ANNOTATE_TRACE_MEMORY(&GLOB);
    217   printf("test306: simple race.\n");
    218   MyThread t1(Worker1), t2(Worker2), t3(Worker3);
    219   t1.Start(); usleep(100);
    220   t2.Start(); usleep(100);
    221   t3.Start(); usleep(100);
    222   t1.Join(); t2.Join(); t3.Join();
    223 }
    224 }  // namespace test306
    225 
    226 // test307: Simple race, code with control flow  {{{1
    227 namespace test307 {
    228 int     *GLOB = 0;
    229 volatile /*to fake the compiler*/ bool some_condition = true;
    230 
    231 
    232 void SomeFunc() { }
    233 
    234 int FunctionWithControlFlow() {
    235   int unrelated_stuff = 0;
    236   unrelated_stuff++;
    237   SomeFunc();                // "--keep-history=1" will point somewhere here.
    238   if (some_condition) {      // Or here
    239     if (some_condition) {
    240       unrelated_stuff++;     // Or here.
    241       unrelated_stuff++;
    242       (*GLOB)++;             // "--keep-history=2" will point here (experimental).
    243     }
    244   }
    245   usleep(100000);
    246   return unrelated_stuff;
    247 }
    248 
    249 void Worker1() { FunctionWithControlFlow(); }
    250 void Worker2() { Worker1(); }
    251 void Worker3() { Worker2(); }
    252 void Worker4() { Worker3(); }
    253 
    254 TEST(DemoTests, test307) {
    255   GLOB = new int;
    256   *GLOB = 1;
    257   printf("test307: simple race, code with control flow\n");
    258   MyThreadArray t1(Worker1, Worker2, Worker3, Worker4);
    259   t1.Start();
    260   t1.Join();
    261 }
    262 }  // namespace test307
    263 
    264 // test308: Example of double-checked-locking  {{{1
    265 namespace test308 {
    266 struct Foo {
    267   int a;
    268 };
    269 
    270 static int   is_inited = 0;
    271 static Mutex lock;
    272 static Foo  *foo;
    273 
    274 void InitMe() {
    275   if (!is_inited) {
    276     lock.Lock();
    277       if (!is_inited) {
    278         foo = new Foo;
    279         foo->a = 42;
    280         is_inited = 1;
    281       }
    282     lock.Unlock();
    283   }
    284 }
    285 
    286 void UseMe() {
    287   InitMe();
    288   CHECK(foo && foo->a == 42);
    289 }
    290 
    291 void Worker1() { UseMe(); }
    292 void Worker2() { UseMe(); }
    293 void Worker3() { UseMe(); }
    294 
    295 
    296 TEST(DemoTests, test308) {
    297   ANNOTATE_TRACE_MEMORY(&is_inited);
    298   printf("test308: Example of double-checked-locking\n");
    299   MyThreadArray t1(Worker1, Worker2, Worker3);
    300   t1.Start();
    301   t1.Join();
    302 }
    303 }  // namespace test308
    304 
    305 // test309: Simple race on an STL object.  {{{1
    306 namespace test309 {
    307 string  GLOB;
    308 
    309 void Worker1() {
    310   GLOB="Thread1";
    311 }
    312 void Worker2() {
    313   usleep(100000);
    314   GLOB="Booooooooooo";
    315 }
    316 
    317 TEST(DemoTests, test309) {
    318   printf("test309: simple race on an STL object.\n");
    319   MyThread t1(Worker1), t2(Worker2);
    320   t1.Start();
    321   t2.Start();
    322   t1.Join();   t2.Join();
    323 }
    324 }  // namespace test309
    325 
    326 // test310: One more simple race.  {{{1
    327 namespace test310 {
    328 int     *PTR = NULL;  // GUARDED_BY(mu1)
    329 
    330 Mutex mu1;  // Protects PTR.
    331 Mutex mu2;  // Unrelated to PTR.
    332 Mutex mu3;  // Unrelated to PTR.
    333 
    334 void Writer1() {
    335   MutexLock lock3(&mu3);  // This lock is unrelated to PTR.
    336   MutexLock lock1(&mu1);  // Protect PTR.
    337   *PTR = 1;
    338 }
    339 
    340 void Writer2() {
    341   MutexLock lock2(&mu2);  // This lock is unrelated to PTR.
    342   MutexLock lock1(&mu1);  // Protect PTR.
    343   int some_unrelated_stuff = 0;
    344   if (some_unrelated_stuff == 0)
    345     some_unrelated_stuff++;
    346   *PTR = 2;
    347 }
    348 
    349 
    350 void Reader() {
    351   MutexLock lock2(&mu2);  // Oh, gosh, this is a wrong mutex!
    352   CHECK(*PTR <= 2);
    353 }
    354 
    355 // Some functions to make the stack trace non-trivial.
    356 void DoWrite1() { Writer1();  }
    357 void Thread1()  { DoWrite1(); }
    358 
    359 void DoWrite2() { Writer2();  }
    360 void Thread2()  { DoWrite2(); }
    361 
    362 void DoRead()  { Reader();  }
    363 void Thread3() { DoRead();  }
    364 
    365 TEST(DemoTests, test310) {
    366   printf("test310: simple race.\n");
    367   PTR = new int;
    368   ANNOTATE_TRACE_MEMORY(PTR);
    369   *PTR = 0;
    370   MyThread t1(Thread1, NULL, "writer1"),
    371            t2(Thread2, NULL, "writer2"),
    372            t3(Thread3, NULL, "buggy reader");
    373   t1.Start();
    374   t2.Start();
    375   usleep(100000);  // Let the writers go first.
    376   t3.Start();
    377 
    378   t1.Join();
    379   t2.Join();
    380   t3.Join();
    381 }
    382 }  // namespace test310
    383 
    384 // test311: Yet another simple race.  {{{1
    385 namespace test311 {
    386 int     *PTR = NULL;  // GUARDED_BY(mu1)
    387 
    388 Mutex mu1;  // Protects PTR.
    389 Mutex mu2;  // Unrelated to PTR.
    390 Mutex mu3;  // Unrelated to PTR.
    391 
    392 void GoodWriter1() {      // Runs in Thread1
    393   MutexLock lock3(&mu3);  // This lock is unrelated to PTR.
    394   MutexLock lock1(&mu1);  // Protect PTR.
    395   *PTR = 1;
    396 }
    397 
    398 void GoodWriter2() {      // Runs in Thread2
    399   MutexLock lock2(&mu2);  // This lock is unrelated to PTR.
    400   MutexLock lock1(&mu1);  // Protect PTR.
    401   *PTR = 2;
    402 }
    403 
    404 void GoodReader() {      // Runs in Thread3
    405   MutexLock lock1(&mu1);  // Protect PTR.
    406   CHECK(*PTR >= 0);
    407 }
    408 
    409 void BuggyWriter() {      // Runs in Thread4
    410   MutexLock lock2(&mu2);  // Wrong mutex!
    411   *PTR = 3;
    412 }
    413 
    414 // Some functions to make the stack trace non-trivial.
    415 void DoWrite1() { GoodWriter1();  }
    416 void Thread1()  { DoWrite1(); }
    417 
    418 void DoWrite2() { GoodWriter2();  }
    419 void Thread2()  { DoWrite2(); }
    420 
    421 void DoGoodRead()  { GoodReader();  }
    422 void Thread3()     { DoGoodRead();  }
    423 
    424 void DoBadWrite()  { BuggyWriter(); }
    425 void Thread4()     { DoBadWrite(); }
    426 
    427 TEST(DemoTests, test311) {
    428   printf("test311: simple race.\n");
    429   PTR = new int;
    430   ANNOTATE_TRACE_MEMORY(PTR);
    431   *PTR = 0;
    432   MyThread t1(Thread1, NULL, "good writer1"),
    433            t2(Thread2, NULL, "good writer2"),
    434            t3(Thread3, NULL, "good reader"),
    435            t4(Thread4, NULL, "buggy writer");
    436   t1.Start();
    437   t3.Start();
    438   // t2 goes after t3. This way a pure happens-before detector has no chance.
    439   usleep(10000);
    440   t2.Start();
    441   usleep(100000);  // Let the good folks go first.
    442   t4.Start();
    443 
    444   t1.Join();
    445   t2.Join();
    446   t3.Join();
    447   t4.Join();
    448 }
    449 }  // namespace test311
    450 
    451 // test312: A test with a very deep stack. {{{1
    452 namespace test312 {
    453 int     GLOB = 0;
    454 void RaceyWrite() { GLOB++; }
    455 void Func1() { RaceyWrite(); }
    456 void Func2() { Func1(); }
    457 void Func3() { Func2(); }
    458 void Func4() { Func3(); }
    459 void Func5() { Func4(); }
    460 void Func6() { Func5(); }
    461 void Func7() { Func6(); }
    462 void Func8() { Func7(); }
    463 void Func9() { Func8(); }
    464 void Func10() { Func9(); }
    465 void Func11() { Func10(); }
    466 void Func12() { Func11(); }
    467 void Func13() { Func12(); }
    468 void Func14() { Func13(); }
    469 void Func15() { Func14(); }
    470 void Func16() { Func15(); }
    471 void Func17() { Func16(); }
    472 void Func18() { Func17(); }
    473 void Func19() { Func18(); }
    474 void Worker() { Func19(); }
    475 TEST(DemoTests, test312) {
    476   printf("test312: simple race with deep stack.\n");
    477   MyThreadArray t(Worker, Worker, Worker);
    478   t.Start();
    479   t.Join();
    480 }
    481 }  // namespace test312
    482 
    483 // test313 TP: test for thread graph output {{{1
    484 namespace  test313 {
    485 BlockingCounter *blocking_counter;
    486 int     GLOB = 0;
    487 
    488 // Worker(N) will do 2^N increments of GLOB, each increment in a separate thread
    489 void Worker(int depth) {
    490   CHECK(depth >= 0);
    491   if (depth > 0) {
    492     ThreadPool pool(2);
    493     pool.StartWorkers();
    494     pool.Add(NewCallback(Worker, depth-1));
    495     pool.Add(NewCallback(Worker, depth-1));
    496   } else {
    497     GLOB++; // Race here
    498   }
    499 }
    500 TEST(DemoTests, test313) {
    501   printf("test313: positive\n");
    502   Worker(4);
    503   printf("\tGLOB=%d\n", GLOB);
    504 }
    505 }  // namespace test313
    506 
    507 // test314: minimalistic test for race in vptr. {{{1
    508 namespace test314 {
    509 // Race on vptr. Will run A::F() or B::F() depending on the timing.
    510 class A {
    511  public:
    512   A() : done_(false) { }
    513   virtual void F() {
    514     printf ("A::F()\n");
    515   }
    516   void Done() {
    517     MutexLock lock(&mu_);
    518     done_ = true;
    519   }
    520   virtual ~A() {
    521     while (true) {
    522       MutexLock lock(&mu_);
    523       if (done_) break;
    524     }
    525   }
    526  private:
    527   Mutex mu_;
    528   bool  done_;
    529 };
    530 
    531 class B : public A {
    532  public:
    533   virtual void F() {
    534     printf ("B::F()\n");
    535   }
    536 };
    537 
    538 static A *a;
    539 
    540 void Thread1() {
    541   a->F();
    542   a->Done();
    543 };
    544 
    545 void Thread2() {
    546   delete a;
    547 }
    548 TEST(DemoTests, test314) {
    549   printf("test314: race on vptr; May print A::F() or B::F().\n");
    550   { // Will print B::F()
    551     a = new B;
    552     MyThreadArray t(Thread1, Thread2);
    553     t.Start();
    554     t.Join();
    555   }
    556   { // Will print A::F()
    557     a = new B;
    558     MyThreadArray t(Thread2, Thread1);
    559     t.Start();
    560     t.Join();
    561   }
    562 }
    563 }  // namespace test314
    564 
    565 // test315: demo for hybrid's false positive. {{{1
    566 namespace test315 {
    567 int GLOB;
    568 Mutex mu;
    569 int flag;
    570 
    571 void Thread1() {
    572   sleep(1);
    573   mu.Lock();
    574   bool f = flag;
    575   mu.Unlock();
    576   if (f) {
    577     GLOB++;
    578   }
    579 }
    580 
    581 void Thread2() {
    582   GLOB++;
    583   mu.Lock();
    584   flag = true;
    585   mu.Unlock();
    586 }
    587 
    588 TEST(DemoTests, test315) {
    589   GLOB = 0;
    590   printf("test315: false positive of the hybrid state machine\n");
    591   MyThreadArray t(Thread1, Thread2);
    592   t.Start();
    593   t.Join();
    594 }
    595 }  // namespace test315
    596