mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
The feature was renamed in 0cf687aa2b but
validation tests were not updated at that time.
191 lines
5.0 KiB
Swift
191 lines
5.0 KiB
Swift
// 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
|
|
|