// REQUIRES: rdar64809498 // RUN: %target-build-swift -Xfrontend -disable-access-control -module-name a %s -o %t.out // RUN: %target-run %t.out | %FileCheck %s // REQUIRES: stress_test // UNSUPPORTED: threading_none import SwiftPrivate import StdlibUnittest #if canImport(Darwin) import Darwin #elseif canImport(Glibc) import Glibc #elseif os(Windows) import MSVCRT #else #error("Unsupported platform") #endif _setTestSuiteFailedCallback() { print("abort()") } struct RaceTest1 : RaceTestWithPerTrialData { static var shouldPass: Bool = true static var iterationCountdown: _stdlib_AtomicInt = _stdlib_AtomicInt(8) class RaceData { init() {} } typealias ThreadLocalData = Void typealias Observation = Observation1UInt func makeRaceData() -> RaceData { return RaceData() } func makeThreadLocalData() -> Void { return Void() } func thread1( _ raceData: RaceData, _ threadLocalData: inout ThreadLocalData ) -> Observation { switch RaceTest1.iterationCountdown.fetchAndAdd(-1) { case 0: return Observation(0x1) case 1: return Observation(RaceTest1.shouldPass ? 0x1 : 0xffff) case 1, 2: return Observation(0x2) case 3, 4, 5: return Observation(RaceTest1.shouldPass ? 0x2 : 0xfffe) default: return Observation(0x1) } } func evaluateObservations( _ observations: [Observation], _ sink: (RaceTestObservationEvaluation) -> Void ) { for observation in observations { switch observation { case Observation(0x1): sink(.pass) case Observation(0x2): sink(.passInteresting(String(describing: observation))) case Observation(0xffff): sink(.failure) case Observation(0xfffe): sink(.failureInteresting(String(describing: observation))) default: fatalError("should not happen") } } } } var RaceTestSuite = TestSuite("Race") RaceTestSuite.test("passes") { RaceTest1.shouldPass = true RaceTest1.iterationCountdown = _stdlib_AtomicInt(8) runRaceTest(RaceTest1.self, trials: 10) } // CHECK: [ RUN ] Race.passes // CHECK: stdout>>> Pass: {{.*}} times // CHECK: stdout>>> Pass (2): 4 times // CHECK: stdout>>> Failure: 0 times // CHECK: [ OK ] Race.passes RaceTestSuite.test("fails") { RaceTest1.shouldPass = false RaceTest1.iterationCountdown = _stdlib_AtomicInt(8) runRaceTest(RaceTest1.self, trials: 10) } // CHECK: [ RUN ] Race.fails // REQUIRES: executable_test // CHECK: stdout>>> Pass: {{.*}} times // CHECK: stdout>>> Pass (2): 1 times // CHECK: stdout>>> Failure: 1 times // CHECK: stdout>>> Failure (65534): 3 times // CHECK: [ FAIL ] Race.fails RaceTestSuite.test("closure") { let count = _stdlib_AtomicInt(0) runRaceTest(trials: 10) { _ = count.fetchAndAdd(1) } expectNotEqual(0, count.load()) } // CHECK: [ RUN ] Race.closure // CHECK: [ OK ] Race.closure RaceTestSuite.test("timeout-zero") { // Zero timeout is still expected to run at least one trial. let count = _stdlib_AtomicInt(0) runRaceTest(trials: 2000000000, timeoutInSeconds: 0) { _ = count.fetchAndAdd(1) } expectGT(count.load(), 0) } // CHECK: [ RUN ] Race.timeout-zero // CHECK: [ OK ] Race.timeout-zero func -(_ lhs: timeval, _ rhs: timeval) -> timeval { var result = timeval(tv_sec: 0, tv_usec: 0) result.tv_sec = lhs.tv_sec - rhs.tv_sec result.tv_usec = lhs.tv_usec - rhs.tv_usec if result.tv_usec < 0 { result.tv_usec += 1000000 result.tv_sec -= 1 } return result } func gettimeofday() -> timeval { var result = timeval(tv_sec: 0, tv_usec: 0) gettimeofday(&result, nil) return result } RaceTestSuite.test("timeout-small") { // Verify that the timeout fires after the correct number of seconds. // If the timeout fails to fire then this test will run for a very long time. var startTime: timeval var endTime: timeval let timeout = 5 let count = _stdlib_AtomicInt(0) startTime = gettimeofday() runRaceTest(trials: 2000000000, timeoutInSeconds: timeout) { _ = count.fetchAndAdd(1) } endTime = gettimeofday() expectGT(count.load(), 0) // Test should have run to the timeout. // Test should not have run too long after the timeout. let duration = endTime - startTime expectGE(duration.tv_sec, timeout) expectLT(duration.tv_sec, timeout*100) // large to avoid spurious failures } // CHECK: [ RUN ] Race.timeout-small // CHECK: [ OK ] Race.timeout-small RaceTestSuite.test("timeout-big") { // Verify that a short test with a long timeout completes before the timeout. var startTime: timeval var endTime: timeval let timeout = 10000 let count = _stdlib_AtomicInt(0) startTime = gettimeofday() runRaceTest(trials: 10, timeoutInSeconds: timeout) { _ = count.fetchAndAdd(1) } endTime = gettimeofday() expectGT(count.load(), 0) // Test should have stopped long before the timeout. let duration = endTime - startTime expectLT(duration.tv_sec, timeout / 2) } // CHECK: [ RUN ] Race.timeout-big // CHECK: [ OK ] Race.timeout-big runAllTests() // CHECK: Race: Some tests failed, aborting