21
21
import Foundation
22
22
import XCTest
23
23
24
+ @testable import Surge
25
+
26
+ private struct ValueError : Swift . Error , CustomStringConvertible {
27
+ let message : String
28
+
29
+ var description : String {
30
+ return self . message
31
+ }
32
+ }
33
+
34
+ private enum ArrayError : Swift . Error , CustomStringConvertible {
35
+ case size( message: String )
36
+ case content( index: Int , content: ValueError )
37
+
38
+ var description : String {
39
+ switch self {
40
+ case let . size( message) :
41
+ return message
42
+ case let . content( index, error) :
43
+ return " Failure at index [ \( index) ]: \( error) "
44
+ }
45
+ }
46
+ }
47
+
48
+ private enum GridError : Swift . Error , CustomStringConvertible {
49
+ case size( message: String )
50
+ case content( index: Int , content: ArrayError )
51
+
52
+ var description : String {
53
+ switch self {
54
+ case let . size( message) :
55
+ return message
56
+ case let . content( gridIndex, arrayError) :
57
+ switch arrayError {
58
+ case let . size( message) :
59
+ return " Failure at index [ \( gridIndex) , ..]: \( message) "
60
+ case let . content( arrayIndex, valueError) :
61
+ return " Failure at index [ \( gridIndex) , \( arrayIndex) ]: \( valueError) "
62
+ }
63
+ }
64
+ }
65
+ }
66
+
67
+ private func checkValue< T> (
68
+ _ actualValue: T ,
69
+ _ expectedValue: T ,
70
+ accuracy: T
71
+ ) -> Result < ( ) , ValueError > where T: FloatingPoint {
72
+ guard abs ( actualValue - expectedValue) <= abs ( accuracy) else {
73
+ let ( actual, expected) = ( actualValue, expectedValue)
74
+ let message = " ( \( actual) ) is not equal to ( \( expected) ) +/- ( \( accuracy) ) "
75
+ return . failure( ValueError ( message: message) )
76
+ }
77
+
78
+ return . success( ( ) )
79
+ }
80
+
81
+ private func checkArray< T, U> (
82
+ _ actualArray: T ,
83
+ _ expectedArray: T ,
84
+ accuracy: U
85
+ ) -> Result < ( ) , ArrayError > where T: Collection , T. Element == U , U: FloatingPoint {
86
+ guard actualArray. count == expectedArray. count else {
87
+ let ( actual, expected) = ( actualArray. count, expectedArray. count)
88
+ let message = " Values have different size: ( \( actual) ) is not equal to ( \( expected) ) "
89
+ return . failure( . size( message: message) )
90
+ }
91
+
92
+ for (index, ( actualValue, expectedValue) ) in Swift . zip ( actualArray, expectedArray) . enumerated ( ) {
93
+ switch checkValue ( actualValue, expectedValue, accuracy: accuracy) {
94
+ case . success:
95
+ continue
96
+ case . failure( let error) :
97
+ return . failure( . content( index: index, content: error) )
98
+ }
99
+ }
100
+
101
+ return . success( ( ) )
102
+ }
103
+
104
+ private func checkGrid< T, U, V> (
105
+ _ actualGrid: T ,
106
+ _ expectedGrid: T ,
107
+ accuracy: V
108
+ ) -> Result < ( ) , GridError > where T: Collection , U: Collection , T. Element == U , U. Element == V , V: FloatingPoint {
109
+ guard actualGrid. count == expectedGrid. count else {
110
+ let ( actual, expected) = ( actualGrid. count, expectedGrid. count)
111
+ let message = " Values have different size: ( \( actual) × _) is not equal to ( \( expected) × _) "
112
+ return . failure( . size( message: message) )
113
+ }
114
+
115
+ for (index, ( actualArray, expectedArray) ) in Swift . zip ( actualGrid, expectedGrid) . enumerated ( ) {
116
+ switch checkArray ( actualArray, expectedArray, accuracy: accuracy) {
117
+ case . success:
118
+ continue
119
+ case . failure( let error) :
120
+ return . failure( . content( index: index, content: error) )
121
+ }
122
+ }
123
+
124
+ return . success( ( ) )
125
+ }
126
+
127
+ private enum Prefix : String {
128
+ case assertEqual = " XCTAssertEqual "
129
+ case assertEqualWithAccuracy = " XCTAssertEqualWithAccuracy "
130
+ }
131
+
132
+ private func fail(
133
+ prefix: Prefix ,
134
+ failureMessage: String ,
135
+ userMessage: String ? = nil ,
136
+ file: StaticString ,
137
+ line: UInt
138
+ ) {
139
+ let prefix = " \( prefix. rawValue) failed: "
140
+ let suffix = userMessage. map { " - \( $0) " } ?? " "
141
+ let message = " \( prefix) \( failureMessage) \( suffix) "
142
+ XCTFail ( message, file: file, line: line)
143
+ }
144
+
24
145
/// Allows comparing:
25
146
///
26
147
/// ```
@@ -33,41 +154,50 @@ import XCTest
33
154
/// Useful for comparing:
34
155
/// - `[Float]`
35
156
/// - `[Double]`
36
- @discardableResult
37
157
func XCTAssertEqual< T, U> (
38
158
_ expression1: @autoclosure ( ) throws -> T ,
39
159
_ expression2: @autoclosure ( ) throws -> T ,
40
- accuracy: U ,
160
+ accuracy: U ? = nil ,
161
+ _ message: @autoclosure ( ) -> String = " " ,
162
+ file: StaticString = #file,
163
+ line: UInt = #line
164
+ ) where T: Collection , T. Element == U , U: FloatingPoint & ExpressibleByFloatLiteral {
165
+ XCTAssertEqual1D (
166
+ try expression1 ( ) ,
167
+ try expression2 ( ) ,
168
+ accuracy: accuracy,
169
+ message ( ) ,
170
+ file: file,
171
+ line: line
172
+ )
173
+ }
174
+
175
+ func XCTAssertEqual1D< T, U> (
176
+ _ expression1: @autoclosure ( ) throws -> T ,
177
+ _ expression2: @autoclosure ( ) throws -> T ,
178
+ accuracy: U ? = nil ,
41
179
_ message: @autoclosure ( ) -> String = " " ,
42
180
file: StaticString = #file,
43
181
line: UInt = #line
44
- ) -> Bool
45
- where T: Collection , T. Element == U , U: FloatingPoint {
46
- let ( actualValues, expectedValues) : ( T , T )
182
+ ) where T: Collection , T. Element == U , U: FloatingPoint & ExpressibleByFloatLiteral {
183
+ let prefix : Prefix = ( accuracy == nil ) ? . assertEqual : . assertEqualWithAccuracy
184
+
185
+ let ( actual, expected) : ( T , T )
47
186
48
187
do {
49
- ( actualValues , expectedValues ) = ( try expression1 ( ) , try expression2 ( ) )
188
+ ( actual , expected ) = ( try expression1 ( ) , try expression2 ( ) )
50
189
} catch let error {
51
- XCTFail ( " Error: \( error ) " , file : file , line : line )
52
- return false
190
+ let message = String ( describing : error )
191
+ return fail ( prefix : prefix , failureMessage : message , file : file , line : line )
53
192
}
54
193
55
- XCTAssertEqual ( actualValues. count, expectedValues. count, file: file, line: line)
56
-
57
- for (actual, expected) in Swift . zip ( actualValues, expectedValues) {
58
- guard abs ( actual - expected) > abs ( accuracy) else {
59
- continue
60
- }
61
-
62
- let failureMessage = " XCTAssertEqualWithAccuracy failed: ( \( actual) ) is not equal to ( \( expected) ) +/- ( \( accuracy) ) "
63
- let userMessage = message ( )
64
- let message = " \( failureMessage) - \( userMessage) "
65
- XCTFail ( message, file: file, line: line)
194
+ let result = checkArray ( actual, expected, accuracy: accuracy ?? 0.0 )
66
195
67
- return false
196
+ guard case . failure( let error) = result else {
197
+ return
68
198
}
69
199
70
- return true
200
+ return fail ( prefix : prefix , failureMessage : error . description , file : file , line : line )
71
201
}
72
202
73
203
/// Allows comparing:
@@ -86,31 +216,48 @@ func XCTAssertEqual<T, U>(
86
216
/// - `[[Double]]`
87
217
/// - `Matrix<Float>`
88
218
/// - `Matrix<Double>`
89
- @discardableResult
90
219
func XCTAssertEqual< T, U, V> (
91
220
_ expression1: @autoclosure ( ) throws -> T ,
92
221
_ expression2: @autoclosure ( ) throws -> T ,
93
- accuracy: V ,
222
+ accuracy: V ? = nil ,
94
223
_ message: @autoclosure ( ) -> String = " " ,
95
224
file: StaticString = #file,
96
225
line: UInt = #line
97
- ) -> Bool
98
- where T: Collection , U: Collection , T. Element == U , U. Element == V , V: FloatingPoint {
99
- let ( actualValues, expectedValues) : ( T , T )
226
+ ) where T: Collection , U: Collection , T. Element == U , U. Element == V , V: FloatingPoint & ExpressibleByFloatLiteral {
227
+ XCTAssertEqual2D (
228
+ try expression1 ( ) ,
229
+ try expression2 ( ) ,
230
+ accuracy: accuracy,
231
+ message ( ) ,
232
+ file: file,
233
+ line: line
234
+ )
235
+ }
236
+
237
+ func XCTAssertEqual2D< T, U, V> (
238
+ _ expression1: @autoclosure ( ) throws -> T ,
239
+ _ expression2: @autoclosure ( ) throws -> T ,
240
+ accuracy: V ? = nil ,
241
+ _ message: @autoclosure ( ) -> String = " " ,
242
+ file: StaticString = #file,
243
+ line: UInt = #line
244
+ ) where T: Collection , U: Collection , T. Element == U , U. Element == V , V: FloatingPoint & ExpressibleByFloatLiteral {
245
+ let prefix : Prefix = ( accuracy == nil ) ? . assertEqual : . assertEqualWithAccuracy
246
+
247
+ let ( actual, expected) : ( T , T )
100
248
101
249
do {
102
- ( actualValues , expectedValues ) = ( try expression1 ( ) , try expression2 ( ) )
250
+ ( actual , expected ) = ( try expression1 ( ) , try expression2 ( ) )
103
251
} catch let error {
104
- XCTFail ( " Error: \( error ) " , file : file , line : line )
105
- return false
252
+ let message = String ( describing : error )
253
+ return fail ( prefix : prefix , failureMessage : message , file : file , line : line )
106
254
}
107
255
108
- XCTAssertEqual ( actualValues . count , expectedValues . count , file : file , line : line )
256
+ let result = checkGrid ( actual , expected , accuracy : accuracy ?? 0.0 )
109
257
110
- for (actual, expected) in Swift . zip ( actualValues, expectedValues) {
111
- guard XCTAssertEqual ( actual, expected, accuracy: accuracy) else {
112
- return false
113
- }
258
+ guard case . failure( let error) = result else {
259
+ return
114
260
}
115
- return true
261
+
262
+ return fail ( prefix: prefix, failureMessage: error. description, file: file, line: line)
116
263
}
0 commit comments