1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
|
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
import StdlibUnittest
import Swift
let ResultTests = TestSuite("Result")
fileprivate enum Err: Error, Equatable {
case err
case derr
}
fileprivate let string = "string"
fileprivate extension Result {
var success: Success? {
switch self {
case let .success(success):
return success
case .failure:
return nil
}
}
var failure: Failure? {
switch self {
case .success:
return nil
case let .failure(failure):
return failure
}
}
}
ResultTests.test("Construction") {
let result1: Result<String, Err> = .success(string)
let result2: Result<String, Err> = .failure(.err)
let string1: String? = {
switch result1 {
case let .success(string):
return string
case .failure:
expectUnreachable()
return nil
}
}()
let error: Err? = {
switch result2 {
case let .failure(failure):
return failure
case .success:
expectUnreachable()
return nil
}
}()
expectEqual(string, string1)
expectEqual(.err, error)
}
ResultTests.test("Throwing Initialization and Unwrapping") {
func notThrowing() throws -> String {
return string
}
func throwing() throws -> String {
throw Err.err
}
func throwingTyped() throws(Err) -> String {
throw .err
}
func knownNotThrowing() -> String { return string }
let result1 = Result { try throwing() }
let result2 = Result { try notThrowing() }
expectEqual(result1.failure as? Err, Err.err)
expectEqual(result2.success, string)
do {
_ = try result1.get()
} catch let error as Err {
expectEqual(error, Err.err)
} catch {
expectUnreachable()
}
do {
let unwrapped = try result2.get()
expectEqual(unwrapped, string)
} catch {
expectUnreachable()
}
// Test unwrapping strongly typed error.
let result3 = Result<String, Err>.failure(Err.err)
do {
_ = try result3.get()
} catch let error as Err {
expectEqual(error, Err.err)
} catch {
expectUnreachable()
}
// Test strongly typed error via closure.
// FIXME: Type inference should eliminate the need for the throws(Err)
// annotations below.
let result4 = Result { () throws(Err) in try throwingTyped() }
let _: Result<String, Err> = result4 // check the type
expectEqual(result4.failure, .err)
do throws(Err) {
_ = try result4.get()
} catch let error {
expectEqual(error, .err)
}
let result5 = Result { knownNotThrowing() }
let _: Result<String, Never> = result5 // check the type
_ = result5.get() // no need for 'try'
}
ResultTests.test("Functional Transforms") {
func transformDouble(_ int: Int) -> Int {
return 2 * int
}
func transformTriple(_ int: Int) -> Int {
return 3 * int
}
func transformError(_ err: Err) -> Err {
if err == .err {
return .derr
} else {
return .err
}
}
func resultValueTransform(_ int: Int) -> Result<Int, Err> {
return .success(transformDouble(int))
}
func resultErrorTransform(_ err: Err) -> Result<Int, Err> {
return .failure(transformError(err))
}
let result1: Result<Int, Err> = .success(1)
let newResult1 = result1.map(transformDouble)
expectEqual(newResult1, .success(2))
let result2: Result<Int, Err> = .failure(.err)
let newResult2 = result2.mapError(transformError)
expectEqual(newResult2, .failure(.derr))
let result3: Result<Int, Err> = .success(1)
let newResult3 = result3.flatMap(resultValueTransform)
expectEqual(newResult3, .success(2))
let result4: Result<Int, Err> = .failure(.derr)
let newResult4 = result4.flatMapError(resultErrorTransform)
expectEqual(newResult4, .failure(.err))
}
ResultTests.test("Equatable") {
let result1: Result<Int, Err> = .success(1)
let result2: Result<Int, Err> = .failure(.err)
expectEqual(result1, .success(1))
expectNotEqual(result1, .success(2))
expectNotEqual(result1, .failure(.err))
expectNotEqual(result1, .failure(.derr))
expectNotEqual(result2, .success(1))
expectNotEqual(result2, .success(2))
expectEqual(result2, .failure(.err))
expectNotEqual(result2, .failure(.derr))
let confusables: [Result<Err, Err>] = [
.success(.err),
.success(.derr),
.failure(.err),
.failure(.derr)
]
checkEquatable(confusables, oracle: { $0 == $1 })
}
ResultTests.test("Hashable") {
let result1: Result<Int, Err> = .success(1)
let result2: Result<Int, Err> = .success(2)
let result3: Result<Int, Err> = .failure(.err)
checkHashable([result1, result2, result3], equalityOracle: { $0 == $1 })
let confusables: [Result<Err, Err>] = [
.success(.err),
.success(.derr),
.failure(.err),
.failure(.derr)
]
checkHashable(confusables, equalityOracle: { $0 == $1 })
}
runAllTests()
|