A flow-sequence single-pair implicit key is single-line
(c-s-implicit-json-key uses s-separate-in-line), so its ':' may not cross
a line break: '[ "key"\n :value ]' is malformed. A flow MAPPING adjacent
value may still span lines ('{ "foo"\n :bar }' stays valid), which is why
the check is scoped to flow levels that are sequences.
Track per-flow-level whether it is a sequence ('[' vs '{') in a
flowIsSequence stack pushed/popped with the flow level, and in fetchValue
reject a pending simple key whose ':' crossed a line break when the
current flow level is a sequence.
Surpasses libyaml on ZXT5 (5MUD, the flow-mapping analogue, stays valid);
whole-suite conformance 397/402, canonical events 308/308.
68 lines
2.9 KiB
Swift
68 lines
2.9 KiB
Swift
@testable import PureYAML
|
|
import Testing
|
|
|
|
/// Verifies the ported simple-key mechanism (`save_simple_key`,
|
|
/// `remove_simple_key`, `stale_simple_keys`, flow-level push/pop) reproduces
|
|
/// libyaml's behavior.
|
|
@Suite("LibYAML Simple Key")
|
|
struct LibYAMLSimpleKeyTests {
|
|
private func mark(line: Int, column: Int, index: Int) -> PureYAML.Parsing.Mark {
|
|
PureYAML.Parsing.Mark(line: line, column: column, index: index)
|
|
}
|
|
|
|
@Test("saves a possible key, required when it sits at the block indent")
|
|
func test_saveSimpleKeyRequiredAtIndent() throws {
|
|
var scanner = PureYAML.Parsing.LibYAML.Scanner()
|
|
scanner.indentEngine.rollIndent(column: 0, number: -1, type: .blockMappingStart, mark: .start)
|
|
scanner.mark = mark(line: 1, column: 0, index: 0)
|
|
try scanner.saveSimpleKey()
|
|
#expect(scanner.simpleKeys.last?.possible == true)
|
|
#expect(scanner.simpleKeys.last?.required == true)
|
|
}
|
|
|
|
@Test("a key not at the block indent is possible but not required")
|
|
func test_saveSimpleKeyNotRequired() throws {
|
|
var scanner = PureYAML.Parsing.LibYAML.Scanner()
|
|
scanner.indentEngine.rollIndent(column: 0, number: -1, type: .blockMappingStart, mark: .start)
|
|
scanner.mark = mark(line: 1, column: 4, index: 4)
|
|
try scanner.saveSimpleKey()
|
|
#expect(scanner.simpleKeys.last?.possible == true)
|
|
#expect(scanner.simpleKeys.last?.required == false)
|
|
}
|
|
|
|
@Test("removing a required possible key is an error")
|
|
func test_removeRequiredKeyThrows() throws {
|
|
var scanner = PureYAML.Parsing.LibYAML.Scanner()
|
|
scanner.indentEngine.rollIndent(column: 0, number: -1, type: .blockMappingStart, mark: .start)
|
|
scanner.mark = mark(line: 1, column: 0, index: 0)
|
|
try scanner.saveSimpleKey()
|
|
#expect(throws: PureYAML.Parsing.LibYAML.ScannerError.self) {
|
|
try scanner.removeSimpleKey()
|
|
}
|
|
}
|
|
|
|
@Test("a non-required key on an earlier line goes stale without error")
|
|
func test_staleNonRequiredKey() throws {
|
|
var scanner = PureYAML.Parsing.LibYAML.Scanner()
|
|
scanner.indentEngine.rollIndent(column: 0, number: -1, type: .blockMappingStart, mark: .start)
|
|
scanner.mark = mark(line: 1, column: 4, index: 4)
|
|
try scanner.saveSimpleKey()
|
|
scanner.mark = mark(line: 2, column: 0, index: 10)
|
|
try scanner.staleSimpleKeys()
|
|
#expect(scanner.simpleKeys.last?.possible == false)
|
|
}
|
|
|
|
@Test("flow level pushes and pops a simple-key slot")
|
|
func test_flowLevelStack() {
|
|
var scanner = PureYAML.Parsing.LibYAML.Scanner()
|
|
#expect(scanner.simpleKeys.count == 1)
|
|
scanner.increaseFlowLevel(isSequence: true)
|
|
#expect(scanner.flowLevel == 1)
|
|
#expect(scanner.simpleKeys.count == 2)
|
|
#expect(scanner.flowIsSequence == [true])
|
|
scanner.decreaseFlowLevel()
|
|
#expect(scanner.flowLevel == 0)
|
|
#expect(scanner.simpleKeys.count == 1)
|
|
}
|
|
}
|