Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can these sync methods be effectively unit tested?

Based on answers to this question, I feel happy with the simplicity and ease of use of the following two methods for synchronization:

func synchronized(lock: AnyObject, closure: () -> Void) {
    objc_sync_enter(lock)
    closure()
    objc_sync_exit(lock)
}

func synchronized<T>(lock: AnyObject, closure: () -> T) -> T {
    objc_sync_enter(lock)
    defer { objc_sync_exit(lock) }
    return closure()
}

But to be sure they're actually doing what I want, I want to wrap these in piles of unit tests. How can I write unit tests that will effectively test these methods (and show they are actually synchronizing the code)?

Ideally, I'd also like these unit tests to be as simple and as clear as possible. Presumably, this test should be code that, if run outside the synchronization block, would give one set of results, but give an entirely separate set of results inside these synchronized blocks.

like image 782
nhgrif Avatar asked Nov 08 '22 21:11

nhgrif


1 Answers

Here is a runnable XCTest that verifies the synchronization. If you synchronize delayedAddToArray, it will work, otherwise it will fail.

class DelayedArray:NSObject {
    func synchronized(lock: AnyObject, closure: () -> Void) {
        objc_sync_enter(lock)
        closure()
        objc_sync_exit(lock)
    }

    private var array = [String]()
    func delayedAddToArray(expectation:XCTestExpectation) {
        synchronized(self) {
            let arrayCount = self.array.count
            self.array.append("hi")
            sleep(5)
            XCTAssert(self.array.count == arrayCount + 1)
            expectation.fulfill()
        }
    }
}

func testExample() {
    let expectation = self.expectationWithDescription("desc")
    let expectation2 = self.expectationWithDescription("desc2")

    let delayedArray:DelayedArray = DelayedArray()
    // This is an example of a functional test case.
    let thread = NSThread(target: delayedArray, selector: "delayedAddToArray:", object: expectation)
    let secondThread = NSThread(target: delayedArray, selector: "delayedAddToArray:", object: expectation2)
    thread.start()
    sleep(1)
    secondThread.start()

    self.waitForExpectationsWithTimeout(15, handler: nil)
}
like image 134
Will M. Avatar answered Nov 15 '22 06:11

Will M.