Skip to content

Commit e047d6b

Browse files
authored
Merge pull request #2 from trill-lang/end-of-the-line
Allow custom CheckString file buffers
2 parents c8ce838 + be03720 commit e047d6b

File tree

3 files changed

+64
-7
lines changed

3 files changed

+64
-7
lines changed

Sources/FileCheck/CheckString.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,12 +307,18 @@ private func diagnoseFailedCheck(
307307
_ buffer: String
308308
) {
309309
if let rtm = pattern.computeRegexToMatch(variableTable) {
310-
if !pattern.fixedString.isEmpty {
310+
if !pattern.fixedString.isEmpty && !rtm.isEmpty {
311311
diagnose(.error,
312312
at: loc,
313313
with: prefix + ": could not find '\(pattern.fixedString)' (with regex '\(rtm)') in input",
314314
options: options
315315
)
316+
} else if !pattern.fixedString.isEmpty {
317+
diagnose(.error,
318+
at: loc,
319+
with: prefix + ": could not find '\(pattern.fixedString)' in input",
320+
options: options
321+
)
316322
} else {
317323
diagnose(.error,
318324
at: loc,

Sources/FileCheck/FileCheck.swift

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,25 @@ public enum FileCheckFD {
7272
}
7373
}
7474

75+
/// `FileCheckSource` enumerates possible sources of Check Strings that act as
76+
/// the model against which output is checked.
77+
public enum FileCheckSource {
78+
/// A path to a file that will be opened and parsed for check strings. If the
79+
/// file path is invalid, checking will abort.
80+
case filePath(String)
81+
/// A buffer of check strings.
82+
case buffer(String)
83+
}
84+
85+
/// - Bug: (SR-3258) Expansion of magic literals like #file does not behave
86+
/// correctly when in argument position. Making it convertible from String
87+
/// does do the expansion for some reason.
88+
extension FileCheckSource: ExpressibleByStringLiteral {
89+
public init(stringLiteral value: String) {
90+
self = .filePath(value)
91+
}
92+
}
93+
7594
/// Reads from the given output stream and runs a file verification procedure
7695
/// by comparing the output to a specified result.
7796
///
@@ -92,7 +111,7 @@ public enum FileCheckFD {
92111
/// file descriptor.
93112
///
94113
/// - returns: Whether or not FileCheck succeeded in verifying the file.
95-
public func fileCheckOutput(of FD : FileCheckFD = .stdout, withPrefixes prefixes : [String] = ["CHECK"], checkNot : [String] = [], against file : String = #file, options: FileCheckOptions = [], block : () -> ()) -> Bool {
114+
public func fileCheckOutput(of FD : FileCheckFD = .stdout, withPrefixes prefixes : [String] = ["CHECK"], checkNot : [String] = [], against source : FileCheckSource = #file, options: FileCheckOptions = [], block : () -> ()) -> Bool {
96115
guard let validPrefixes = validateCheckPrefixes(prefixes) else {
97116
print("Supplied check-prefix is invalid! Prefixes must be unique and",
98117
"start with a letter and contain only alphanumeric characters,",
@@ -109,16 +128,25 @@ public func fileCheckOutput(of FD : FileCheckFD = .stdout, withPrefixes prefixes
109128
let input = overrideFDAndCollectOutput(file: FD, of: block)
110129
if input.isEmpty {
111130
guard options.contains(.allowEmptyInput) else {
112-
print("FileCheck error: input from file descriptor \(FD) is empty.\n")
131+
print("FileCheck error: input from file descriptor \(FD) is empty.")
113132
return false
114133
}
115134

116135
return true
117136
}
118137

119-
guard let contents = try? String(contentsOfFile: file, encoding: .utf8) else {
120-
return false
138+
let contents : String
139+
switch source {
140+
case .filePath(let file):
141+
guard let openFile = try? String(contentsOfFile: file, encoding: .utf8) else {
142+
print("FileCheck error: unable to open check file at path \(file).")
143+
return false
144+
}
145+
contents = openFile
146+
case .buffer(let buf):
147+
contents = buf
121148
}
149+
122150
let buf = contents.cString(using: .utf8)?.withUnsafeBufferPointer { buffer in
123151
return readCheckStrings(in: buffer, withPrefixes: validPrefixes, checkNot: checkNot, options: options, prefixRE)
124152
}
@@ -407,7 +435,9 @@ private func readCheckStrings(in buf : UnsafeBufferPointer<CChar>, withPrefixes
407435
}
408436

409437
// Scan ahead to the end of line.
410-
let EOL : Int = buffer.index(of: ("\n" as Character).utf8CodePoint) ?? buffer.index(of: ("\r" as Character).utf8CodePoint)!
438+
let EOL : Int = buffer.index(of: ("\n" as Character).utf8CodePoint)
439+
?? buffer.index(of: ("\r" as Character).utf8CodePoint)
440+
?? buffer.count - 1
411441

412442
// Remember the location of the start of the pattern, for diagnostics.
413443
let patternLoc = CheckLocation.inBuffer(buffer.baseAddress!, buf)

Tests/FileCheckTests/FileCheckSpec.swift

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,26 @@ import XCTest
33
import Foundation
44

55
class FileCheckSpec : XCTestCase {
6+
func testCustomInputBuffer() {
7+
XCTAssert(fileCheckOutput(of: .stdout, withPrefixes: ["CUSTOMEMPTYBUF-ERR"]) {
8+
// CUSTOMEMPTYBUF-ERR: error: no check strings found with prefixes
9+
// CUSTOMEMPTYBUF-ERR-NEXT: CUSTOMEMPTYBUF:
10+
XCTAssertFalse(fileCheckOutput(of: .stdout, withPrefixes: ["CUSTOMEMPTYBUF"], against: .buffer(""), options: [.disableColors]) {
11+
print("asdf")
12+
})
13+
})
14+
15+
XCTAssert(fileCheckOutput(of: .stdout, withPrefixes: ["CUSTOMBUF"], against: .buffer("""
16+
// CUSTOMBUF: shi shi shi shi shi
17+
// CUSTOMBUF-NEXT: asdf
18+
""")) {
19+
print("""
20+
shi shi shi shi shi
21+
asdf
22+
""")
23+
})
24+
}
25+
626
func testWhitespace() {
727
// Check that CHECK-NEXT without a space after the colon works.
828
// Check that CHECK-NOT without a space after the colon works.
@@ -129,7 +149,7 @@ class FileCheckSpec : XCTestCase {
129149

130150
func testNearestPattern() {
131151
XCTAssert(fileCheckOutput(of: .stdout, withPrefixes: ["CHECK-NEAREST-PATTERN-MSG"]) {
132-
// CHECK-NEAREST-PATTERN-MSG: error: {{.*}}: could not find 'Once more into the beach' (with regex '') in input
152+
// CHECK-NEAREST-PATTERN-MSG: error: {{.*}}: could not find 'Once more into the beach' in input
133153
// CHECK-NEAREST-PATTERN-MSG-NEXT: // {{.*}}: Once more into the beach
134154
// CHECK-NEAREST-PATTERN-MSG-NEXT: note: possible intended match here
135155
// CHECK-NEAREST-PATTERN-MSG-NEXT: Once more into the breach
@@ -189,6 +209,7 @@ class FileCheckSpec : XCTestCase {
189209

190210
#if !os(macOS)
191211
static var allTests = testCase([
212+
("testCustomInputBuffer", testCustomInputBuffer),
192213
("testWhitespace", testWhitespace),
193214
("testSame", testSame),
194215
("testCheckDAG", testCheckDAG),

0 commit comments

Comments
 (0)