1 #ifdef OS_darwin_10 2 #include <dispatch/dispatch.h> 3 #endif 4 5 #include <gtest/gtest.h> 6 #include <sys/types.h> 7 #include <sys/mman.h> 8 #import <Foundation/Foundation.h> 9 10 #include "test_utils.h" 11 #include "gtest_fixture_injection.h" 12 13 #ifndef OS_darwin 14 #error "This file should be built on Darwin only." 15 #endif 16 17 class Task { 18 public: 19 Task() {}; 20 void Run() { printf("Inside Task::Run()\n"); } 21 }; 22 23 @interface TaskOperation : NSOperation { 24 @private 25 Task *task_; 26 } 27 28 + (id)taskOperationWithTask:(Task*)task; 29 30 - (id)initWithTask:(Task*)task; 31 32 @end // @interface TaskOperation 33 34 @implementation TaskOperation 35 36 + (id)taskOperationWithTask:(Task*)task { 37 return [[TaskOperation alloc] initWithTask:task]; 38 } 39 40 - (id)init { 41 return [self initWithTask:NULL]; 42 } 43 44 - (id)initWithTask:(Task*)task { 45 if ((self = [super init])) { 46 task_ = task; 47 } 48 return self; 49 } 50 51 - (void)main { 52 if (!task_) { 53 return; 54 } 55 56 task_->Run(); 57 delete task_; 58 task_ = NULL; 59 } 60 61 - (void)dealloc { 62 if (task_) delete task_; 63 [super dealloc]; 64 } 65 66 @end // @implementation TaskOperation 67 68 namespace MacTests { 69 // Regression test for https://bugs.kde.org/show_bug.cgi?id=216837. 70 TEST(MacTests, WqthreadRegressionTest) { 71 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 72 Task *task = new Task(); 73 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 74 [queue addOperation:[TaskOperation taskOperationWithTask:task]]; 75 76 sleep(1); // wait for the worker thread to start. 77 // If the bug is still there, ThreadSanitizer should crash after starting 78 // the worker thread. 79 [pool release]; 80 } 81 82 // Regression test for a bug with passing a 32-bit value instead of a 64-bit 83 // as the last parameter to mmap(). 84 TEST(MacTests, ShmMmapRegressionTest) { 85 #ifdef OS_darwin_9 86 int md; 87 void *virt_addr; 88 shm_unlink("apple.shm.notification_center"); 89 md = shm_open("apple.shm.notification_center", 0, 0); 90 if (md != -1) { 91 virt_addr = mmap(0, 4096, 1, 1, md, 0); 92 if (virt_addr == (void*)-1) { 93 shm_unlink("apple.shm.notification_center"); 94 FAIL() << "mmap returned -1"; 95 } else { 96 munmap(virt_addr, 4096); 97 shm_unlink("apple.shm.notification_center"); 98 } 99 } else { 100 printf("shm_open() returned -1\n"); 101 } 102 #endif 103 } 104 105 } // namespace MacTests 106 107 #ifdef OS_darwin_10 108 namespace SnowLeopardTests { 109 110 int GLOB = 0; 111 StealthNotification sn1, sn2; 112 113 void worker_do_add(int *var, int val, 114 StealthNotification *notify, 115 StealthNotification *waitfor) { 116 (*var) += val; 117 fprintf(stderr, "var=%d\n", *var); 118 notify->signal(); 119 // Make sure that the callbacks are ran on different threads. 120 if (waitfor) { 121 waitfor->wait(); 122 } 123 } 124 125 TEST(SnowLeopardTests, GCD_GlobalQueueRace) { 126 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "SnowLeopardTests.GCD_GlobalQueueRace TP."); 127 dispatch_queue_t queue = dispatch_get_global_queue(0,0); 128 dispatch_block_t block_plus = ^{ worker_do_add(&GLOB, 1, &sn1, &sn2); }; 129 dispatch_block_t block_minus = ^{ worker_do_add(&GLOB, -1, &sn2, NULL); }; 130 dispatch_async(queue, block_plus); 131 dispatch_async(queue, block_minus); 132 sn1.wait(); 133 sn2.wait(); 134 } 135 136 } // namespace SnowLeopardTests 137 #endif 138