PureYAML/Tests/EventStreamingParserTests.swift
Mihaela Mihaljevic bf2dc4ece7 refactor(validation): rename framework to match the validation idiom
The validation module already implemented the composable-rule idiom under
its own names (Check/Issue/SubjectContext) and a value-type Validator with
duplicated traversal machinery per layer. Renamed the core types to the
canonical names (Validation/ValidationError/ValidationErrorCollection/
ValidationContext/BuiltinValidation/AnyValidation), converted Validator to
a reference-type class with the two-tier default-rule split, and genericized
it over both Subject and Document via a new Traversable protocol so the
model and tagged layers share one walk engine instead of two copies. Wired
the JSON-representability rule set into the same shape and closed the two
missing pieces (unwrap combinator, JSON coverage/config-pin tests).
2026-07-12 18:10:00 +02:00

146 lines
4.2 KiB
Swift

@testable import PureYAML
import Testing
@Suite("Event Streaming Parser")
struct EventStreamingParserTests {
@Test(
"Streaming composer matches full event composer for single documents",
arguments: EventStreamingFixtures.singleDocuments,
)
func test_streamingComposerMatchesFullEventComposer(testCase: EventStreamingFixtures.DocumentCase) throws {
let parser = PureYAML.Parsing.Parser()
let streaming = try parser.parse(testCase.yaml)
let fullEvents = try composeSingleDocumentWithFullEvents(testCase.yaml)
#expect(streaming == fullEvents)
}
@Test(
"Streaming composer matches full event composer for streams",
arguments: EventStreamingFixtures.streams,
)
func test_streamingComposerMatchesFullEventComposerForStreams(testCase: EventStreamingFixtures.DocumentCase) throws {
let parser = PureYAML.Parsing.Parser()
let streaming = try parser.parseStream(testCase.yaml)
let fullEvents = try composeStreamWithFullEvents(testCase.yaml)
#expect(streaming == fullEvents)
}
@Test("Streaming parser preserves duplicate keys for validation")
func test_streamingParserPreservesDuplicateKeysForValidation() throws {
let value = try PureYAML.parse("""
root:
title: First
title: Second
flow: {id: one, id: two}
""")
let issues = PureYAML.Validation.Validator<PureYAML.Model.Value, PureYAML.Model.Value>().collect(value).values
#expect(issues.map(\.description) == [
"Duplicate mapping key 'title' at path: $.root.title",
"Duplicate mapping key 'id' at path: $.flow.id",
])
}
}
enum EventStreamingFixtures {
struct DocumentCase: CustomTestStringConvertible {
var name: String
var yaml: String
var testDescription: String {
name
}
}
static let singleDocuments = [
DocumentCase(
name: "block mappings and sequences",
yaml: """
servers:
- url: /
description: Default
""",
),
DocumentCase(
name: "anchors aliases and merge keys",
yaml: """
defaults: &defaults
enabled: true
retries: 3
service:
<<: *defaults
name: API
""",
),
DocumentCase(
name: "flow collections and tags",
yaml: """
flow: [!Thing &item "value", *item, {tagged: !<tag:example.com,2026:thing> 'it''s'}]
""",
),
DocumentCase(
name: "block scalars",
yaml: """
text: |
one
two
folded: >
three
four
""",
),
DocumentCase(
name: "JSON style input",
yaml: #"{"openapi":"3.0.0","info":{"title":"JSON API"},"items":["a:b","c"],"enabled":true}"#,
),
DocumentCase(
name: "complex mapping key",
yaml: """
? {name: service, version: 1}
: active
""",
),
]
static let streams = [
DocumentCase(
name: "multi document sequence stream",
yaml: """
---
- one
- two
---
name: three
...
---
null
""",
),
DocumentCase(
name: "empty explicit documents",
yaml: """
---
...
---
""",
),
]
}
private func composeSingleDocumentWithFullEvents(_ yaml: String) throws -> PureYAML.Model.Value {
let parser = PureYAML.Parsing.Parser()
let events = try parser.parseEvents(yaml)
var composer = PureYAML.Parsing.EventComposer(events: events, scalarParser: parser)
return try composer.compose()
}
private func composeStreamWithFullEvents(_ yaml: String) throws -> [PureYAML.Stream.Document] {
let parser = PureYAML.Parsing.Parser()
let events = try parser.parseEvents(yaml)
var composer = PureYAML.Parsing.EventComposer(events: events, scalarParser: parser)
return try composer.composeStream()
}