Skip to content

Commit 7ad1d05

Browse files
authored
Merge pull request #8 from mattt/swift-5.5
Update to Swift 5.5
2 parents ff985f5 + 0c38745 commit 7ad1d05

File tree

4 files changed

+193
-37
lines changed

4 files changed

+193
-37
lines changed

Package.swift

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
// swift-tools-version:4.0
1+
// swift-tools-version:5.5
22
// The swift-tools-version declares the minimum version of Swift required to build this package.
33

44
/*
55
This source file is part of the Swift.org open source project
66

7-
Copyright 2015 Apple Inc. and the Swift project authors
7+
Copyright 2015 – 2021 Apple Inc. and the Swift project authors
88
Licensed under Apache License v2.0 with Runtime Library Exception
99

1010
See http://swift.org/LICENSE.txt for license information
@@ -15,18 +15,34 @@ import PackageDescription
1515

1616
let package = Package(
1717
name: "dealer",
18+
platforms: [
19+
.macOS(.v11)
20+
],
1821
products: [
19-
.executable(name: "Dealer", targets: ["Dealer"]),
22+
.executable(name: "dealer", targets: ["dealer"]),
2023
],
2124
dependencies: [
2225
// Dependencies declare other packages that this package depends on.
23-
.package(url: "https://github.com/apple/example-package-deckofplayingcards.git", from: "3.0.0"),
26+
.package(url: "https://github.com/apple/example-package-deckofplayingcards.git",
27+
from: "3.0.0"),
28+
.package(url: "https://github.com/apple/swift-argument-parser.git",
29+
from: "0.4.4"),
2430
],
2531
targets: [
2632
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
2733
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
28-
.target(
29-
name: "Dealer",
30-
dependencies: ["DeckOfPlayingCards"]),
34+
.executableTarget(
35+
name: "dealer",
36+
dependencies: [
37+
.product(name: "DeckOfPlayingCards",
38+
package: "example-package-deckofplayingcards"),
39+
.product(name: "ArgumentParser",
40+
package: "swift-argument-parser")
41+
]),
42+
.testTarget(
43+
name: "DealerTests",
44+
dependencies: [
45+
.byName(name: "dealer")
46+
]),
3147
]
3248
)

Sources/Dealer/main.swift

Lines changed: 0 additions & 30 deletions
This file was deleted.

Sources/dealer/Deal.swift

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright 2015 – 2021 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See http://swift.org/LICENSE.txt for license information
8+
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
*/
10+
11+
#if os(Linux)
12+
import Glibc
13+
#endif
14+
15+
import Foundation
16+
import DeckOfPlayingCards
17+
import PlayingCard
18+
import ArgumentParser
19+
20+
@main
21+
struct Deal: ParsableCommand {
22+
enum Error: Swift.Error, CustomStringConvertible {
23+
case notEnoughCards
24+
25+
var description: String {
26+
switch self {
27+
case .notEnoughCards:
28+
return "Not enough cards"
29+
}
30+
}
31+
}
32+
33+
static var configuration = CommandConfiguration(
34+
abstract: "Shuffles a deck of playing cards and deals a number of cards.",
35+
discussion: """
36+
For each count argument, prints a line of tab-delimited cards to stdout,
37+
or if there aren't enough cards remaining,
38+
prints "Not enough cards" to stderr and exits with a nonzero status.
39+
""")
40+
41+
@Argument(help: .init("The number of cards to deal at a time.",
42+
valueName: "count"))
43+
var counts: [UInt]
44+
45+
mutating func run() throws {
46+
#if os(Linux)
47+
srandom(UInt32(clock()))
48+
#endif
49+
50+
var deck = Deck.standard52CardDeck()
51+
deck.shuffle()
52+
53+
for count in counts {
54+
var cards: [PlayingCard] = []
55+
56+
for _ in 0..<count {
57+
guard let card = deck.deal() else {
58+
Self.exit(withError: Error.notEnoughCards)
59+
}
60+
61+
cards.append(card)
62+
}
63+
64+
print(cards.map(\.description).joined(separator: "\t"))
65+
}
66+
}
67+
}

Tests/DealerTests/DealerTests.swift

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright 2021 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See http://swift.org/LICENSE.txt for license information
8+
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
*/
10+
11+
import XCTest
12+
import class Foundation.Bundle
13+
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+
}
21+
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)
26+
27+
XCTAssertEqual(error, "")
28+
}
29+
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)
34+
35+
XCTAssertEqual(error, "")
36+
}
37+
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)
43+
44+
XCTAssertEqual(error, "")
45+
}
46+
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+
}
53+
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+
}
65+
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
70+
71+
let outputPipe = Pipe()
72+
process.standardOutput = outputPipe
73+
74+
let errorPipe = Pipe()
75+
process.standardError = errorPipe
76+
77+
try process.run()
78+
process.waitUntilExit()
79+
80+
let status = process.terminationStatus
81+
82+
let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile()
83+
let output = String(data: outputData, encoding: .utf8)
84+
85+
let errorData = errorPipe.fileHandleForReading.readDataToEndOfFile()
86+
let error = String(data: errorData, encoding: .utf8)
87+
88+
return (status, output, error)
89+
}
90+
}
91+
92+
// MARK: -
93+
94+
private extension Character {
95+
var isPlayingCardSuit: Bool {
96+
switch self {
97+
case "♠︎", "", "", "♣︎":
98+
return true
99+
default:
100+
return false
101+
}
102+
}
103+
}

0 commit comments

Comments
 (0)