Skip to content

Commit d41f2bb

Browse files
Raise TLE, RE error when run fail test case
1 parent fd14f09 commit d41f2bb

File tree

3 files changed

+51
-19
lines changed

3 files changed

+51
-19
lines changed

Sources/AtCoderLibrary/Command/New/Generator/Test.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ struct Test: Generator {
88
import XCTest
99
import TestLibrary
1010
11-
final class \(className): XCTestCase {
11+
final class \(className): XCTestCase, TimeLimit {
12+
let timeLimit: TimeInterval = \(Double(problem.timeLimit)/1000)
13+
1214
func testExample() throws {
1315
let cases: [TestCase] = [
1416
\(problem.tests.map { """

Sources/AtCoderLibrary/Command/New/Generator/TestLibrary.swift

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,44 +6,72 @@ struct TestLibrary: Generator {
66
import XCTest
77
import class Foundation.Bundle
88
9+
public protocol TimeLimit {
10+
var timeLimit: TimeInterval { get }
11+
}
12+
913
public typealias TestCase = (file: StaticString, line: UInt, input: String, expected: String)
1014
11-
public extension XCTestCase {
15+
public extension TimeLimit where Self: XCTestCase {
1216
func solve(file: StaticString, line: UInt, input: String, expected: String) throws {
1317
// Some of the APIs that we use below are available in macOS 10.13 and above.
1418
guard #available(macOS 10.13, *) else {
1519
return
1620
}
17-
18-
let testTarget = String(describing: type(of: self)).replacingOccurrences(of: \"Tests\", with: \"\")
21+
var error = ""
22+
let exp = expectation(description: "")
23+
let testTarget = String(describing: type(of: self)).replacingOccurrences(of: "Tests", with: "")
1924
let binary = productsDirectory.appendingPathComponent(testTarget)
2025
let process = Process()
26+
27+
addTeardownBlock {
28+
if process.isRunning {
29+
process.terminate()
30+
}
31+
}
32+
2133
process.executableURL = binary
2234
let pipeInput = Pipe()
2335
process.standardInput = pipeInput
2436
let pipeOutput = Pipe()
2537
process.standardOutput = pipeOutput
2638
let pipeError = Pipe()
2739
process.standardError = pipeError
28-
try process.run()
29-
pipeInput.fileHandleForWriting.write(input.data(using: .utf8)!)
30-
pipeInput.fileHandleForWriting.closeFile()
31-
process.waitUntilExit()
32-
let error = String(data: pipeError.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8)!
33-
if !error.isEmpty {
34-
XCTFail(error, file: file, line: line)
35-
return
40+
41+
DispatchQueue.global().async {
42+
do {
43+
try process.run()
44+
pipeInput.fileHandleForWriting.write(input.data(using: .utf8)!)
45+
pipeInput.fileHandleForWriting.closeFile()
46+
process.waitUntilExit()
47+
exp.fulfill()
48+
error = String(data: pipeError.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8)!
49+
} catch (let e) {
50+
error = e.localizedDescription
51+
}
52+
}
53+
let result = XCTWaiter.wait(for: [exp], timeout: timeLimit)
54+
switch result {
55+
case .completed:
56+
if error.isEmpty {
57+
let data = pipeOutput.fileHandleForReading.readDataToEndOfFile()
58+
let output = String(data: data, encoding: .utf8)!
59+
XCTAssertEqual(output, expected, file: file, line: line)
60+
} else {
61+
XCTFail("RE: \\(error)", file: file, line: line)
62+
}
63+
case .timedOut:
64+
XCTFail("TLE: Exceeded timeout of \\(timeLimit) seconds", file: file, line: line)
65+
default:
66+
XCTFail("Unrecognized error.", file: file, line: line)
3667
}
37-
let data = pipeOutput.fileHandleForReading.readDataToEndOfFile()
38-
let output = String(data: data, encoding: .utf8)!
39-
XCTAssertEqual(output, expected, file: file, line: line)
4068
}
4169
4270
private var productsDirectory: URL {
43-
for bundle in Bundle.allBundles where bundle.bundlePath.hasSuffix(\".xctest\") {
71+
for bundle in Bundle.allBundles where bundle.bundlePath.hasSuffix(".xctest") {
4472
return bundle.bundleURL.deletingLastPathComponent()
4573
}
46-
fatalError(\"couldn't find the products directory\")
74+
fatalError("couldn't find the products directory")
4775
}
4876
}
4977
"""

Tests/AtCoderLibraryTests/Command/New/Generator/TestTests.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@ final class TestTests: XCTestCase {
1414
name: "",
1515
context: .init(contest: .empty, alphabet: "A"),
1616
memoryLimit: 1000,
17-
timeLimit: 1000
17+
timeLimit: 2000
1818
)
1919
let test = Test(problem: problem)
2020
let expected = """
2121
import XCTest
2222
import TestLibrary
2323
24-
final class ATests: XCTestCase {
24+
final class ATests: XCTestCase, TimeLimit {
25+
let timeLimit: TimeInterval = 2.0
26+
2527
func testExample() throws {
2628
let cases: [TestCase] = [
2729
(#filePath, #line, "input1", "output1"),

0 commit comments

Comments
 (0)