| #ifdef OS_darwin_10 |
| #include <dispatch/dispatch.h> |
| #endif |
| |
| #include <gtest/gtest.h> |
| #include <sys/types.h> |
| #include <sys/mman.h> |
| #import <Foundation/Foundation.h> |
| |
| #include "test_utils.h" |
| #include "gtest_fixture_injection.h" |
| |
| #ifndef OS_darwin |
| #error "This file should be built on Darwin only." |
| #endif |
| |
| class Task { |
| public: |
| Task() {}; |
| void Run() { printf("Inside Task::Run()\n"); } |
| }; |
| |
| @interface TaskOperation : NSOperation { |
| @private |
| Task *task_; |
| } |
| |
| + (id)taskOperationWithTask:(Task*)task; |
| |
| - (id)initWithTask:(Task*)task; |
| |
| @end // @interface TaskOperation |
| |
| @implementation TaskOperation |
| |
| + (id)taskOperationWithTask:(Task*)task { |
| return [[TaskOperation alloc] initWithTask:task]; |
| } |
| |
| - (id)init { |
| return [self initWithTask:NULL]; |
| } |
| |
| - (id)initWithTask:(Task*)task { |
| if ((self = [super init])) { |
| task_ = task; |
| } |
| return self; |
| } |
| |
| - (void)main { |
| if (!task_) { |
| return; |
| } |
| |
| task_->Run(); |
| delete task_; |
| task_ = NULL; |
| } |
| |
| - (void)dealloc { |
| if (task_) delete task_; |
| [super dealloc]; |
| } |
| |
| @end // @implementation TaskOperation |
| |
| namespace MacTests { |
| // Regression test for https://bugs.kde.org/show_bug.cgi?id=216837. |
| TEST(MacTests, WqthreadRegressionTest) { |
| NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
| Task *task = new Task(); |
| NSOperationQueue *queue = [[NSOperationQueue alloc] init]; |
| [queue addOperation:[TaskOperation taskOperationWithTask:task]]; |
| |
| sleep(1); // wait for the worker thread to start. |
| // If the bug is still there, ThreadSanitizer should crash after starting |
| // the worker thread. |
| [pool release]; |
| } |
| |
| // Regression test for a bug with passing a 32-bit value instead of a 64-bit |
| // as the last parameter to mmap(). |
| TEST(MacTests, ShmMmapRegressionTest) { |
| #ifdef OS_darwin_9 |
| int md; |
| void *virt_addr; |
| shm_unlink("apple.shm.notification_center"); |
| md = shm_open("apple.shm.notification_center", 0, 0); |
| if (md != -1) { |
| virt_addr = mmap(0, 4096, 1, 1, md, 0); |
| if (virt_addr == (void*)-1) { |
| shm_unlink("apple.shm.notification_center"); |
| FAIL() << "mmap returned -1"; |
| } else { |
| munmap(virt_addr, 4096); |
| shm_unlink("apple.shm.notification_center"); |
| } |
| } else { |
| printf("shm_open() returned -1\n"); |
| } |
| #endif |
| } |
| |
| } // namespace MacTests |
| |
| #ifdef OS_darwin_10 |
| namespace SnowLeopardTests { |
| |
| int GLOB = 0; |
| StealthNotification sn1, sn2; |
| |
| void worker_do_add(int *var, int val, |
| StealthNotification *notify, |
| StealthNotification *waitfor) { |
| (*var) += val; |
| fprintf(stderr, "var=%d\n", *var); |
| notify->signal(); |
| // Make sure that the callbacks are ran on different threads. |
| if (waitfor) { |
| waitfor->wait(); |
| } |
| } |
| |
| TEST(SnowLeopardTests, GCD_GlobalQueueRace) { |
| ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "SnowLeopardTests.GCD_GlobalQueueRace TP."); |
| dispatch_queue_t queue = dispatch_get_global_queue(0,0); |
| dispatch_block_t block_plus = ^{ worker_do_add(&GLOB, 1, &sn1, &sn2); }; |
| dispatch_block_t block_minus = ^{ worker_do_add(&GLOB, -1, &sn2, NULL); }; |
| dispatch_async(queue, block_plus); |
| dispatch_async(queue, block_minus); |
| sn1.wait(); |
| sn2.wait(); |
| } |
| |
| } // namespace SnowLeopardTests |
| #endif |