Skip to content

Commit 3447a34

Browse files
authored
Get nearly everything up and rolling for linux (#85)
* Get nearly everything up and rolling for linux * Alter validation diagrams for an internal function to expect failures
1 parent 5ac8bb4 commit 3447a34

File tree

9 files changed

+103
-90
lines changed

9 files changed

+103
-90
lines changed

Sources/AsyncSequenceValidation/SourceLocation.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ public struct SourceLocation: Sendable, CustomStringConvertible {
1313
public var file: StaticString
1414
public var line: UInt
1515

16+
public init(file: StaticString, line: UInt) {
17+
self.file = file
18+
self.line = line
19+
}
20+
1621
public var description: String {
1722
return "\(file):\(line)"
1823
}

Sources/AsyncSequenceValidation/TaskDriver.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,32 @@ import _CAsyncSequenceValidationSupport
1919
#error("TODO: Port TaskDriver threading to windows")
2020
#endif
2121

22+
#if canImport(Darwin)
2223
@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
2324
func start_thread(_ raw: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? {
2425
Unmanaged<TaskDriver>.fromOpaque(raw).takeRetainedValue().run()
2526
return nil
2627
}
28+
#elseif canImport(Glibc)
29+
func start_thread(_ raw: UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer? {
30+
Unmanaged<TaskDriver>.fromOpaque(raw!).takeRetainedValue().run()
31+
return nil
32+
}
33+
#elseif canImport(WinSDK)
34+
#error("TODO: Port TaskDriver threading to windows")
35+
#endif
2736

2837
@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
2938
final class TaskDriver {
3039
let work: (TaskDriver) -> Void
3140
let queue: WorkQueue
41+
#if canImport(Darwin)
3242
var thread: pthread_t?
43+
#elseif canImport(Glibc)
44+
var thread = pthread_t()
45+
#elseif canImport(WinSDK)
46+
#error("TODO: Port TaskDriver threading to windows")
47+
#endif
3348

3449
init(queue: WorkQueue, _ work: @escaping (TaskDriver) -> Void) {
3550
self.queue = queue
@@ -42,12 +57,20 @@ final class TaskDriver {
4257
}
4358

4459
func run() {
60+
#if canImport(Darwin)
4561
pthread_setname_np("Validation Diagram Clock Driver")
62+
#endif
4663
work(self)
4764
}
4865

4966
func join() {
67+
#if canImport(Darwin)
5068
pthread_join(thread!, nil)
69+
#elseif canImport(Glibc)
70+
pthread_join(thread, nil)
71+
#elseif canImport(WinSDK)
72+
#error("TODO: Port TaskDriver threading to windows")
73+
#endif
5174
}
5275

5376
func enqueue(_ job: JobRef) {

Tests/AsyncAlgorithmsTests/Performance/TestThroughput.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import XCTest
1313
import AsyncAlgorithms
1414

15+
#if canImport(Darwin)
1516
final class TestThroughput: XCTestCase {
1617
func test_chain2() async {
1718
await measureSequenceThroughput(output: 1) {
@@ -64,3 +65,4 @@ final class TestThroughput: XCTestCase {
6465
}
6566
}
6667
}
68+
#endif

Tests/AsyncAlgorithmsTests/Performance/ThroughputMeasurement.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import AsyncAlgorithms
1313
import Foundation
1414
@preconcurrency import XCTest
1515

16+
#if canImport(Darwin)
1617
public struct InfiniteAsyncSequence<Value: Sendable>: AsyncSequence, Sendable {
1718
public typealias Element = Value
1819
let value: Value
@@ -138,3 +139,4 @@ final class TestMeasurements: XCTestCase {
138139
}
139140
}
140141
}
142+
#endif

Tests/AsyncAlgorithmsTests/Support/Asserts.swift

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -150,13 +150,3 @@ fileprivate func ==<A: Equatable, B: Equatable, C: Equatable>(_ lhs: [(A, B, C)]
150150
public func XCTAssertEqual<A: Equatable, B: Equatable, C: Equatable>(_ expression1: @autoclosure () throws -> [(A, B, C)], _ expression2: @autoclosure () throws -> [(A, B, C)], _ message: @autoclosure () -> String = "", file: StaticString = #filePath, line: UInt = #line) {
151151
_XCTAssertEqual(expression1, expression2, { $0 == $1 }, message, file: file, line: line)
152152
}
153-
154-
extension XCTestCase {
155-
func expectFailures(_ failures: Set<String>) {
156-
let options = XCTExpectedFailure.Options()
157-
options.issueMatcher = { issue in
158-
return failures.contains(issue.compactDescription)
159-
}
160-
XCTExpectFailure(nil, options: options)
161-
}
162-
}

Tests/AsyncAlgorithmsTests/Support/ValidationTest.swift

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,19 @@ import AsyncAlgorithms
1414
import AsyncSequenceValidation
1515

1616
extension XCTestCase {
17-
public func validate<Test: AsyncSequenceValidationTest, Theme: AsyncSequenceValidationTheme>(theme: Theme, @AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #file, line: UInt = #line) {
18-
let baseLocation = XCTSourceCodeLocation(filePath: file.description, lineNumber: Int(line))
19-
let baseContext = XCTSourceCodeContext(location: baseLocation)
17+
func recordFailure(_ description: String, detail: String? = nil, system: Bool = false, at location: AsyncSequenceValidation.SourceLocation) {
18+
#if canImport(Darwin)
19+
let context = XCTSourceCodeContext(location: XCTSourceCodeLocation(filePath: location.file.description, lineNumber: Int(location.line)))
20+
let issue = XCTIssue(type: system ? .system : .assertionFailure, compactDescription: description, detailedDescription: detail, sourceCodeContext: context, associatedError: nil, attachments: [])
21+
record(issue)
22+
#else
23+
XCTFail(description, file: location.file, line: location.line)
24+
#endif
25+
}
26+
27+
func validate<Test: AsyncSequenceValidationTest, Theme: AsyncSequenceValidationTheme>(theme: Theme, expectedFailures: Set<String>, @AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #file, line: UInt = #line) {
28+
var expectations = expectedFailures
29+
let baseLoc = AsyncSequenceValidation.SourceLocation(file: file, line: line)
2030
do {
2131
let (result, failures) = try AsyncSequenceValidationDiagram.test(theme: theme, build)
2232
var detail: String?
@@ -33,30 +43,30 @@ extension XCTestCase {
3343
print(result.reconstituteActual(theme: theme))
3444
}
3545
for failure in failures {
36-
if let specification = failure.specification {
37-
let location = XCTSourceCodeLocation(filePath: specification.location.file.description, lineNumber: Int(specification.location.line))
38-
let context = XCTSourceCodeContext(location: location)
39-
let issue = XCTIssue(type: .assertionFailure, compactDescription: failure.description, detailedDescription: detail, sourceCodeContext: context, associatedError: nil, attachments: [])
40-
record(issue)
41-
} else {
42-
let issue = XCTIssue(type: .assertionFailure, compactDescription: failure.description, detailedDescription: detail, sourceCodeContext: baseContext, associatedError: nil, attachments: [])
43-
record(issue)
46+
if expectations.remove(failure.description) == nil {
47+
recordFailure(failure.description, detail: detail, at: failure.specification?.location ?? baseLoc)
4448
}
4549
}
4650
} catch {
47-
if let sourceFailure = error as? SourceFailure {
48-
let location = XCTSourceCodeLocation(filePath: sourceFailure.location.file.description, lineNumber: Int(sourceFailure.location.line))
49-
let context = XCTSourceCodeContext(location: location)
50-
let issue = XCTIssue(type: .system, compactDescription: "\(error)", detailedDescription: nil, sourceCodeContext: context, associatedError: nil, attachments: [])
51-
record(issue)
52-
} else {
53-
let issue = XCTIssue(type: .system, compactDescription: "\(error)", detailedDescription: nil, sourceCodeContext: baseContext, associatedError: nil, attachments: [])
54-
record(issue)
51+
if expectations.remove("\(error)") == nil {
52+
recordFailure("\(error)", system: true, at: (error as? SourceFailure)?.location ?? baseLoc)
5553
}
5654
}
55+
// any remaining expectations are failures that were expected but did not happen
56+
for expectation in expectations {
57+
XCTFail("Expected failure: \(expectation) did not occur.", file: file, line: line)
58+
}
59+
}
60+
61+
func validate<Test: AsyncSequenceValidationTest>(expectedFailures: Set<String>, @AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #file, line: UInt = #line) {
62+
validate(theme: .ascii, expectedFailures: expectedFailures, build, file: file, line: line)
63+
}
64+
65+
public func validate<Test: AsyncSequenceValidationTest, Theme: AsyncSequenceValidationTheme>(theme: Theme, @AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #file, line: UInt = #line) {
66+
validate(theme: theme, expectedFailures: [], build, file: file, line: line)
5767
}
5868

5969
public func validate<Test: AsyncSequenceValidationTest>(@AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #file, line: UInt = #line) {
60-
validate(theme: .ascii, build, file: file, line: line)
70+
validate(theme: .ascii, expectedFailures: [], build, file: file, line: line)
6171
}
6272
}

Tests/AsyncAlgorithmsTests/TestBuffer.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -254,17 +254,17 @@ final class TestBuffer: XCTestCase {
254254
return result
255255
}
256256

257-
try? await Task.sleep(nanoseconds: NSEC_PER_SEC / 10)
257+
try? await Task.sleep(nanoseconds: 100_000_000)
258258
values.advance()
259259
values.advance()
260260
values.advance()
261261

262-
try? await Task.sleep(nanoseconds: NSEC_PER_SEC / 10)
262+
try? await Task.sleep(nanoseconds: 100_000_000)
263263
values.advance()
264264
values.advance()
265265
values.advance()
266266

267-
try? await Task.sleep(nanoseconds: NSEC_PER_SEC / 10)
267+
try? await Task.sleep(nanoseconds: 100_000_000)
268268
values.advance()
269269
values.advance()
270270
values.advance()
@@ -320,17 +320,17 @@ final class TestBuffer: XCTestCase {
320320
return (result, err)
321321
}
322322

323-
try? await Task.sleep(nanoseconds: NSEC_PER_SEC / 10)
323+
try? await Task.sleep(nanoseconds: 100_000_000)
324324
values.advance()
325325
values.advance()
326326
values.advance()
327327

328-
try? await Task.sleep(nanoseconds: NSEC_PER_SEC / 10)
328+
try? await Task.sleep(nanoseconds: 100_000_000)
329329
values.advance()
330330
values.advance()
331331
values.advance()
332332

333-
try? await Task.sleep(nanoseconds: NSEC_PER_SEC / 10)
333+
try? await Task.sleep(nanoseconds: 100_000_000)
334334
values.advance()
335335

336336
let task1Results = await task1.value
@@ -406,17 +406,17 @@ final class TestBuffer: XCTestCase {
406406
return (result, err)
407407
}
408408

409-
try? await Task.sleep(nanoseconds: NSEC_PER_SEC / 10)
409+
try? await Task.sleep(nanoseconds: 100_000_000)
410410
values.advance()
411411
values.advance()
412412
values.advance()
413413

414-
try? await Task.sleep(nanoseconds: NSEC_PER_SEC / 10)
414+
try? await Task.sleep(nanoseconds: 100_000_000)
415415
values.advance()
416416
values.advance()
417417
values.advance()
418418

419-
try? await Task.sleep(nanoseconds: NSEC_PER_SEC / 10)
419+
try? await Task.sleep(nanoseconds: 100_000_000)
420420
values.advance()
421421

422422
let task1Results = await task1.value

Tests/AsyncAlgorithmsTests/TestTaskSelect.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,23 @@
1010
//===----------------------------------------------------------------------===//
1111

1212
@preconcurrency import XCTest
13+
import Dispatch
1314
import AsyncAlgorithms
1415

1516
final class TestTaskSelect: XCTestCase {
1617
func test_first() async {
1718
let firstValue = await Task.select(Task {
1819
return 1
1920
}, Task {
20-
try! await Task.sleep(nanoseconds: NSEC_PER_SEC * 2)
21+
try! await Task.sleep(until: .now + .seconds(2), clock: .continuous)
2122
return 2
2223
}).value
2324
XCTAssertEqual(firstValue, 1)
2425
}
2526

2627
func test_second() async {
2728
let firstValue = await Task.select(Task {
28-
try! await Task.sleep(nanoseconds: NSEC_PER_SEC * 2)
29+
try! await Task.sleep(until: .now + .seconds(2), clock: .continuous)
2930
return 1
3031
}, Task {
3132
return 2
@@ -36,7 +37,7 @@ final class TestTaskSelect: XCTestCase {
3637
func test_throwing() async {
3738
do {
3839
_ = try await Task.select(Task { () async throws -> Int in
39-
try await Task.sleep(nanoseconds: NSEC_PER_SEC * 2)
40+
try await Task.sleep(until: .now + .seconds(2), clock: .continuous)
4041
return 1
4142
}, Task { () async throws -> Int in
4243
throw NSError(domain: NSCocoaErrorDomain, code: -1, userInfo: nil)
@@ -58,15 +59,15 @@ final class TestTaskSelect: XCTestCase {
5859
firstCancelled.fulfill()
5960
} operation: { () -> Int in
6061
firstReady.fulfill()
61-
try? await Task.sleep(nanoseconds: NSEC_PER_SEC * 2)
62+
try? await Task.sleep(until: .now + .seconds(2), clock: .continuous)
6263
return 1
6364
}
6465
}, Task {
6566
await withTaskCancellationHandler {
6667
secondCancelled.fulfill()
6768
} operation: { () -> Int in
6869
secondReady.fulfill()
69-
try? await Task.sleep(nanoseconds: NSEC_PER_SEC * 2)
70+
try? await Task.sleep(until: .now + .seconds(2), clock: .continuous)
7071
return 1
7172
}
7273
})

0 commit comments

Comments
 (0)