@testable import PureYAML import Testing /// The reader-level control-character check (`Reader.recordFirstInvalidControlCharacter`, /// `fetchNextToken()`'s check in `LibYAML.Scanner.Fetch.swift`) added to close a real gap /// found comparing PureYAML against Yams on a real-world OpenAPI corpus: Yams's underlying /// libyaml rejects raw control characters (`c-printable` violations) anywhere in the input, /// while `PureYAML.parse()` previously accepted them silently (the only existing check, /// `PreflightScanner.invalidControlCharacterColumn`, is opt-in via `validate()`, not part of /// the core scanner `parse()` uses). @Suite("Invalid control character rejection") struct InvalidControlCharacterTests { @Test("A raw control character in scalar content is rejected with the correct position") func test_rawControlCharacterRejected() { expectParseError( "key: value\u{01}with control\n", .invalidControlCharacter(line: 1, column: 11), ) } @Test("A tab in scalar content, not indentation, is still legal") func test_tabInContentStillAccepted() throws { let value = try PureYAML.parse("key: value\twith tab\n") let mapping = requireMapping(value) #expect(mapping?["key"] == .string("value\twith tab")) } @Test("CR and LF are still legal") func test_crAndLFStillAccepted() throws { let value = try PureYAML.parse("key: |\n line one\n line two\n") let mapping = requireMapping(value) #expect(mapping?["key"] == .string("line one\nline two\n")) } @Test("A control character deep inside a large document is still caught") func test_controlCharacterFarIntoDocumentIsCaught() { let padding = String(repeating: "line: value\n", count: 5000) expectParseError( padding + "bad: value\u{02}here\n", .invalidControlCharacter(line: 5001, column: 11), ) } @Test("An earlier real syntax error is not hidden behind a later control character") func test_earlierSyntaxErrorNotHiddenByLaterControlCharacter() { do { _ = try PureYAML.parse("key: \"unterminated\nbad: value\u{02}here\n") recordIssue("expected parse to throw") } catch let error as PureYAML.Parsing.ParseError { #expect(error.diagnosticCode != "invalidControlCharacter") } catch { recordIssue("expected a ParseError, got \(error)") } } }