-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathExamplesTests.swift
124 lines (103 loc) · 4.19 KB
/
ExamplesTests.swift
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
//
// ExamplesTests.swift
// CGTCalcCoreTests
//
// Created by Matt Galloway on 10/06/2020.
//
@testable import CGTCalcCore
import Foundation
import XCTest
class ExamplesTests: XCTestCase {
let logger = StubLogger()
private func runTests(inDirectory directory: URL, record: Bool) throws {
let inputsDirectory = directory.appendingPathComponent("Inputs")
let outputsDirectory = directory.appendingPathComponent("Outputs")
let fileManager = FileManager()
let inputs = try fileManager.contentsOfDirectory(at: inputsDirectory, includingPropertiesForKeys: nil, options: [])
for inputFile in inputs {
guard inputFile.pathExtension == "txt" else { continue }
let testName = inputFile.deletingPathExtension().lastPathComponent
guard let inputData = try? String(contentsOf: inputFile) else {
XCTFail("Failed to read input for test: \(testName)")
return
}
let outputFile = outputsDirectory.appendingPathComponent(inputFile.lastPathComponent)
let outputFileExists = fileManager.fileExists(atPath: outputFile.path)
let allowRecord = record || !outputFileExists
guard allowRecord || outputFileExists else {
XCTFail("Failed to find output for test: \(testName)")
return
}
do {
let parser = DefaultParser()
let input = try parser.calculatorInput(fromData: inputData)
let calculator = try Calculator(input: input, logger: self.logger)
let result = try calculator.process()
let presenter = TextPresenter(result: result)
let output = try presenter.process()
let outputString: String
switch output {
case .data:
XCTFail("Shouldn't return data")
return
case .string(let string):
outputString = string
}
if allowRecord {
do {
try outputString.write(to: outputFile, atomically: true, encoding: .utf8)
} catch {
XCTFail("Failed to write output data: \(error)")
}
} else {
let compareOutputData = try String(contentsOf: outputFile)
if outputString != compareOutputData {
let diffURL = URL(fileURLWithPath: "/usr/bin/diff")
if fileManager.fileExists(atPath: diffURL.path) {
let tempDirectory = URL(fileURLWithPath: NSTemporaryDirectory())
let fileA = tempDirectory.appendingPathComponent(UUID().uuidString)
let fileB = tempDirectory.appendingPathComponent(UUID().uuidString)
try compareOutputData.write(to: fileA, atomically: true, encoding: .utf8)
try outputString.write(to: fileB, atomically: true, encoding: .utf8)
let stdout = Pipe()
let diffProcess = Process()
diffProcess.executableURL = diffURL
diffProcess.standardOutput = stdout
diffProcess.arguments = ["-u", fileA.path, fileB.path]
try diffProcess.run()
diffProcess.waitUntilExit()
let output = stdout.fileHandleForReading.readDataToEndOfFile()
if let string = String(data: output, encoding: .utf8) {
print(string)
}
try fileManager.removeItem(at: fileA)
try fileManager.removeItem(at: fileB)
}
XCTFail("\(testName) failed")
}
}
} catch {
XCTFail("Failed to process \(testName): \(error)")
}
}
if record {
XCTFail("Record mode")
}
}
func testExamples() throws {
let thisFile = URL(fileURLWithPath: #file)
let examplesDirectory = thisFile.deletingLastPathComponent().appendingPathComponent("Examples")
try self.runTests(inDirectory: examplesDirectory, record: false)
}
func testPrivateExamples() throws {
let thisFile = URL(fileURLWithPath: #file)
let examplesDirectory = thisFile.deletingLastPathComponent().appendingPathComponent("PrivateExamples")
if FileManager.default.fileExists(atPath: examplesDirectory.path) {
try self.runTests(inDirectory: examplesDirectory, record: false)
}
}
static let allTests = [
("testExamples", testExamples),
("testPrivateExamples", testPrivateExamples)
]
}