Skip to content

Commit

Permalink
Merge pull request #2 from trill-lang/end-of-the-line
Browse files Browse the repository at this point in the history
Allow custom CheckString file buffers
  • Loading branch information
CodaFi authored Oct 20, 2017
2 parents c8ce838 + be03720 commit e047d6b
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 7 deletions.
8 changes: 7 additions & 1 deletion Sources/FileCheck/CheckString.swift
Original file line number Diff line number Diff line change
Expand Up @@ -307,12 +307,18 @@ private func diagnoseFailedCheck(
_ buffer: String
) {
if let rtm = pattern.computeRegexToMatch(variableTable) {
if !pattern.fixedString.isEmpty {
if !pattern.fixedString.isEmpty && !rtm.isEmpty {
diagnose(.error,
at: loc,
with: prefix + ": could not find '\(pattern.fixedString)' (with regex '\(rtm)') in input",
options: options
)
} else if !pattern.fixedString.isEmpty {
diagnose(.error,
at: loc,
with: prefix + ": could not find '\(pattern.fixedString)' in input",
options: options
)
} else {
diagnose(.error,
at: loc,
Expand Down
40 changes: 35 additions & 5 deletions Sources/FileCheck/FileCheck.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,25 @@ public enum FileCheckFD {
}
}

/// `FileCheckSource` enumerates possible sources of Check Strings that act as
/// the model against which output is checked.
public enum FileCheckSource {
/// A path to a file that will be opened and parsed for check strings. If the
/// file path is invalid, checking will abort.
case filePath(String)
/// A buffer of check strings.
case buffer(String)
}

/// - Bug: (SR-3258) Expansion of magic literals like #file does not behave
/// correctly when in argument position. Making it convertible from String
/// does do the expansion for some reason.
extension FileCheckSource: ExpressibleByStringLiteral {
public init(stringLiteral value: String) {
self = .filePath(value)
}
}

/// Reads from the given output stream and runs a file verification procedure
/// by comparing the output to a specified result.
///
Expand All @@ -92,7 +111,7 @@ public enum FileCheckFD {
/// file descriptor.
///
/// - returns: Whether or not FileCheck succeeded in verifying the file.
public func fileCheckOutput(of FD : FileCheckFD = .stdout, withPrefixes prefixes : [String] = ["CHECK"], checkNot : [String] = [], against file : String = #file, options: FileCheckOptions = [], block : () -> ()) -> Bool {
public func fileCheckOutput(of FD : FileCheckFD = .stdout, withPrefixes prefixes : [String] = ["CHECK"], checkNot : [String] = [], against source : FileCheckSource = #file, options: FileCheckOptions = [], block : () -> ()) -> Bool {
guard let validPrefixes = validateCheckPrefixes(prefixes) else {
print("Supplied check-prefix is invalid! Prefixes must be unique and",
"start with a letter and contain only alphanumeric characters,",
Expand All @@ -109,16 +128,25 @@ public func fileCheckOutput(of FD : FileCheckFD = .stdout, withPrefixes prefixes
let input = overrideFDAndCollectOutput(file: FD, of: block)
if input.isEmpty {
guard options.contains(.allowEmptyInput) else {
print("FileCheck error: input from file descriptor \(FD) is empty.\n")
print("FileCheck error: input from file descriptor \(FD) is empty.")
return false
}

return true
}

guard let contents = try? String(contentsOfFile: file, encoding: .utf8) else {
return false
let contents : String
switch source {
case .filePath(let file):
guard let openFile = try? String(contentsOfFile: file, encoding: .utf8) else {
print("FileCheck error: unable to open check file at path \(file).")
return false
}
contents = openFile
case .buffer(let buf):
contents = buf
}

let buf = contents.cString(using: .utf8)?.withUnsafeBufferPointer { buffer in
return readCheckStrings(in: buffer, withPrefixes: validPrefixes, checkNot: checkNot, options: options, prefixRE)
}
Expand Down Expand Up @@ -407,7 +435,9 @@ private func readCheckStrings(in buf : UnsafeBufferPointer<CChar>, withPrefixes
}

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

// Remember the location of the start of the pattern, for diagnostics.
let patternLoc = CheckLocation.inBuffer(buffer.baseAddress!, buf)
Expand Down
23 changes: 22 additions & 1 deletion Tests/FileCheckTests/FileCheckSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,26 @@ import XCTest
import Foundation

class FileCheckSpec : XCTestCase {
func testCustomInputBuffer() {
XCTAssert(fileCheckOutput(of: .stdout, withPrefixes: ["CUSTOMEMPTYBUF-ERR"]) {
// CUSTOMEMPTYBUF-ERR: error: no check strings found with prefixes
// CUSTOMEMPTYBUF-ERR-NEXT: CUSTOMEMPTYBUF:
XCTAssertFalse(fileCheckOutput(of: .stdout, withPrefixes: ["CUSTOMEMPTYBUF"], against: .buffer(""), options: [.disableColors]) {
print("asdf")
})
})

XCTAssert(fileCheckOutput(of: .stdout, withPrefixes: ["CUSTOMBUF"], against: .buffer("""
// CUSTOMBUF: shi shi shi shi shi
// CUSTOMBUF-NEXT: asdf
""")) {
print("""
shi shi shi shi shi
asdf
""")
})
}

func testWhitespace() {
// Check that CHECK-NEXT without a space after the colon works.
// Check that CHECK-NOT without a space after the colon works.
Expand Down Expand Up @@ -129,7 +149,7 @@ class FileCheckSpec : XCTestCase {

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

#if !os(macOS)
static var allTests = testCase([
("testCustomInputBuffer", testCustomInputBuffer),
("testWhitespace", testWhitespace),
("testSame", testSame),
("testCheckDAG", testCheckDAG),
Expand Down

0 comments on commit e047d6b

Please sign in to comment.