|
1 |
| -/* |
2 |
| - This source file is part of the Swift.org open source project |
| 1 | +//===----------------------------------------------------------------------===// |
| 2 | +// |
| 3 | +// This source file is part of the example package dealer open source project |
| 4 | +// |
| 5 | +// Copyright (c) 2021-2025 Apple Inc. and the Swift project authors |
| 6 | +// Licensed under Apache License v2.0 with Runtime Library Exception |
| 7 | +// |
| 8 | +// See https://swift.org/LICENSE.txt for license information |
| 9 | +// |
| 10 | +//===----------------------------------------------------------------------===// |
| 11 | + |
| 12 | +import Foundation |
| 13 | +import Testing |
3 | 14 |
|
4 |
| - Copyright 2021 Apple Inc. and the Swift project authors |
5 |
| - Licensed under Apache License v2.0 with Runtime Library Exception |
| 15 | +import class Foundation.Bundle |
6 | 16 |
|
7 |
| - See http://swift.org/LICENSE.txt for license information |
8 |
| - See http://swift.org/CONTRIBUTORS.txt for Swift project authors |
9 |
| -*/ |
| 17 | +@testable import dealer |
10 | 18 |
|
11 |
| -import XCTest |
12 |
| -import class Foundation.Bundle |
| 19 | +struct DealerTests { |
| 20 | + @Test |
| 21 | + func testUsage() throws { |
| 22 | + let (status, output, error) = try execute(with: ["--help"]) |
| 23 | + #expect(status == EXIT_SUCCESS) |
| 24 | + #expect( |
| 25 | + output?.starts( |
| 26 | + with: "OVERVIEW: Shuffles a deck of playing cards and deals a number of cards.") ?? false) |
| 27 | + #expect(error?.isEmpty == true) |
| 28 | + } |
13 | 29 |
|
14 |
| -final class DealerTests: XCTestCase { |
15 |
| - func testUsage() throws { |
16 |
| - let (status, output, error) = try execute(with: ["--help"]) |
17 |
| - XCTAssertEqual(status, EXIT_SUCCESS) |
18 |
| - XCTAssert(output?.starts(with: "OVERVIEW: Shuffles a deck of playing cards and deals a number of cards.") ?? false) |
19 |
| - XCTAssertEqual(error, "") |
20 |
| - } |
| 30 | + @Test |
| 31 | + func testDealOneCard() throws { |
| 32 | + let (status, output, error) = try execute(with: ["1"]) |
| 33 | + #expect(status == EXIT_SUCCESS) |
| 34 | + #expect(output?.filter(\.isPlayingCardSuit).count == 1) |
21 | 35 |
|
22 |
| - func testDealOneCard() throws { |
23 |
| - let (status, output, error) = try execute(with: ["1"]) |
24 |
| - XCTAssertEqual(status, EXIT_SUCCESS) |
25 |
| - XCTAssertEqual(output?.filter(\.isPlayingCardSuit).count, 1) |
| 36 | + #expect(error?.isEmpty == true) |
26 | 37 |
|
27 |
| - XCTAssertEqual(error, "") |
28 |
| - } |
| 38 | + } |
29 | 39 |
|
30 |
| - func testDealTenCards() throws { |
31 |
| - let (status, output, error) = try execute(with: ["10"]) |
32 |
| - XCTAssertEqual(status, EXIT_SUCCESS) |
33 |
| - XCTAssertEqual(output?.filter(\.isPlayingCardSuit).count, 10) |
| 40 | + @Test |
| 41 | + func testDealTenCards() throws { |
| 42 | + let (status, output, error) = try execute(with: ["10"]) |
| 43 | + #expect(status == EXIT_SUCCESS) |
| 44 | + #expect(output?.filter(\.isPlayingCardSuit).count == 10) |
34 | 45 |
|
35 |
| - XCTAssertEqual(error, "") |
36 |
| - } |
| 46 | + #expect(error?.isEmpty == true) |
37 | 47 |
|
38 |
| - func testDealThirteenCardsFourTimes() throws { |
39 |
| - let (status, output, error) = try execute(with: ["13", "13", "13", "13"]) |
40 |
| - XCTAssertEqual(status, EXIT_SUCCESS) |
41 |
| - XCTAssertEqual(output?.filter(\.isPlayingCardSuit).count, 52) |
42 |
| - XCTAssertEqual(output?.filter(\.isNewline).count, 4) |
| 48 | + } |
43 | 49 |
|
44 |
| - XCTAssertEqual(error, "") |
45 |
| - } |
| 50 | + @Test |
| 51 | + func testDealThirteenCardsFourTimes() throws { |
| 52 | + let (status, output, error) = try execute(with: ["13", "13", "13", "13"]) |
| 53 | + #expect(status == EXIT_SUCCESS) |
| 54 | + #expect(output?.filter(\.isPlayingCardSuit).count == 52) |
| 55 | + #expect(output?.filter(\.isNewline).count == 4) |
46 | 56 |
|
47 |
| - func testDealOneHundredCards() throws { |
48 |
| - let (status, output, error) = try execute(with: ["100"]) |
49 |
| - XCTAssertNotEqual(status, EXIT_SUCCESS) |
50 |
| - XCTAssertEqual(output, "") |
51 |
| - XCTAssertEqual(error, "Error: Not enough cards\n") |
52 |
| - } |
| 57 | + #expect(error?.isEmpty == true) |
53 | 58 |
|
54 |
| - /// Returns path to the built products directory. |
55 |
| - var productsDirectory: URL { |
56 |
| - #if os(macOS) |
57 |
| - for bundle in Bundle.allBundles where bundle.bundlePath.hasSuffix(".xctest") { |
58 |
| - return bundle.bundleURL.deletingLastPathComponent() |
59 |
| - } |
60 |
| - fatalError("couldn't find the products directory") |
61 |
| - #else |
62 |
| - return Bundle.main.bundleURL |
63 |
| - #endif |
64 |
| - } |
| 59 | + } |
65 | 60 |
|
66 |
| - private func execute(with arguments: [String] = []) throws -> (status: Int32, output: String?, error: String?) { |
67 |
| - let process = Process() |
68 |
| - process.executableURL = productsDirectory.appendingPathComponent("dealer") |
69 |
| - process.arguments = arguments |
| 61 | + @Test |
| 62 | + func testDealOneHundredCards() throws { |
| 63 | + let (status, output, error) = try execute(with: ["100"]) |
| 64 | + #expect(status != EXIT_SUCCESS) |
| 65 | + #expect(output?.isEmpty == true) |
70 | 66 |
|
71 |
| - let outputPipe = Pipe() |
72 |
| - process.standardOutput = outputPipe |
| 67 | + #expect(error == "Error: Not enough cards\n") |
| 68 | + } |
73 | 69 |
|
74 |
| - let errorPipe = Pipe() |
75 |
| - process.standardError = errorPipe |
| 70 | + /// Returns path to the built products directory. |
| 71 | + var productsDirectory: URL { |
| 72 | + #if os(macOS) |
| 73 | + return Bundle(for: BundleMarker.self).bundleURL.deletingLastPathComponent() |
| 74 | + #else |
| 75 | + return Bundle.main.bundleURL |
| 76 | + #endif |
| 77 | + } |
76 | 78 |
|
77 |
| - try process.run() |
78 |
| - process.waitUntilExit() |
| 79 | + private func execute(with arguments: [String] = []) throws -> ( |
| 80 | + status: Int32, output: String?, error: String? |
| 81 | + ) { |
| 82 | + let process = Process() |
| 83 | + process.executableURL = productsDirectory.appendingPathComponent("dealer") |
| 84 | + process.arguments = arguments |
79 | 85 |
|
80 |
| - let status = process.terminationStatus |
| 86 | + let outputPipe = Pipe() |
| 87 | + process.standardOutput = outputPipe |
81 | 88 |
|
82 |
| - let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile() |
83 |
| - let output = String(data: outputData, encoding: .utf8) |
| 89 | + let errorPipe = Pipe() |
| 90 | + process.standardError = errorPipe |
84 | 91 |
|
85 |
| - let errorData = errorPipe.fileHandleForReading.readDataToEndOfFile() |
86 |
| - let error = String(data: errorData, encoding: .utf8) |
| 92 | + try process.run() |
| 93 | + process.waitUntilExit() |
87 | 94 |
|
88 |
| - return (status, output, error) |
89 |
| - } |
| 95 | + let status = process.terminationStatus |
| 96 | + |
| 97 | + let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile() |
| 98 | + let output = String(data: outputData, encoding: .utf8) |
| 99 | + |
| 100 | + let errorData = errorPipe.fileHandleForReading.readDataToEndOfFile() |
| 101 | + let error = String(data: errorData, encoding: .utf8) |
| 102 | + |
| 103 | + return (status, output, error) |
| 104 | + } |
90 | 105 | }
|
91 | 106 |
|
92 | 107 | // MARK: -
|
93 | 108 |
|
94 |
| -private extension Character { |
95 |
| - var isPlayingCardSuit: Bool { |
96 |
| - switch self { |
97 |
| - case "♠︎", "♡", "♢", "♣︎": |
98 |
| - return true |
99 |
| - default: |
100 |
| - return false |
101 |
| - } |
| 109 | +extension Character { |
| 110 | + fileprivate var isPlayingCardSuit: Bool { |
| 111 | + switch self { |
| 112 | + case "♠︎", "♡", "♢", "♣︎": |
| 113 | + return true |
| 114 | + default: |
| 115 | + return false |
102 | 116 | }
|
| 117 | + } |
103 | 118 | }
|
0 commit comments