NimYAML/test/parsing.nim

232 lines
14 KiB
Nim

# NimYAML - YAML implementation in Nim
# (c) Copyright 2015 Felix Krause
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
import "../yaml"
import unittest, common
template ensure(input: string, expected: varargs[YamlStreamEvent]) {.dirty.} =
var
parser = newYamlParser(tagLib)
events = parser.parse(newStringStream(input))
try: ensure(events, expected)
except YamlParserError:
let e = cast[ref YamlParserError](getCurrentException())
echo "Parser error:", getCurrentExceptionMsg()
echo e.lineContent
fail()
suite "Parsing":
setup:
var tagLib = initCoreTagLibrary()
teardown:
discard
test "Parsing: Simple scalarEvent":
ensure("scalarEvent", startDocEvent(), scalarEvent("scalarEvent"), endDocEvent())
test "Parsing: Simple Sequence":
ensure("- off", startDocEvent(), startSeqEvent(),
scalarEvent("off"), endSeqEvent(), endDocEvent())
test "Parsing: Simple Map":
ensure("42: value\nkey2: -7.5", startDocEvent(), startMapEvent(),
scalarEvent("42"), scalarEvent("value"), scalarEvent("key2"),
scalarEvent("-7.5"), endMapEvent(), endDocEvent())
test "Parsing: Explicit Map":
ensure("? null\n: value\n? ON\n: value2", startDocEvent(), startMapEvent(),
scalarEvent("null"), scalarEvent("value"),
scalarEvent("ON"), scalarEvent("value2"),
endMapEvent(), endDocEvent())
test "Parsing: Mixed Map (explicit to implicit)":
ensure("? a\n: 13\n1.5: d", startDocEvent(), startMapEvent(), scalarEvent("a"),
scalarEvent("13"), scalarEvent("1.5"),
scalarEvent("d"), endMapEvent(), endDocEvent())
test "Parsing: Mixed Map (implicit to explicit)":
ensure("a: 4.2\n? 23\n: d", startDocEvent(), startMapEvent(), scalarEvent("a"),
scalarEvent("4.2"), scalarEvent("23"),
scalarEvent("d"), endMapEvent(), endDocEvent())
test "Parsing: Missing values in map":
ensure("? a\n? b\nc:", startDocEvent(), startMapEvent(), scalarEvent("a"), scalarEvent(""),
scalarEvent("b"), scalarEvent(""), scalarEvent("c"), scalarEvent(""), endMapEvent(),
endDocEvent())
test "Parsing: Missing keys in map":
ensure(": a\n: b", startDocEvent(), startMapEvent(), scalarEvent(""), scalarEvent("a"),
scalarEvent(""), scalarEvent("b"), endMapEvent(), endDocEvent())
test "Parsing: Multiline scalarEvents in explicit map":
ensure("? a\n true\n: null\n d\n? e\n 42", startDocEvent(), startMapEvent(),
scalarEvent("a true"), scalarEvent("null d"), scalarEvent("e 42"), scalarEvent(""),
endMapEvent(), endDocEvent())
test "Parsing: Map in Sequence":
ensure(" - key: value\n key2: value2\n -\n key3: value3",
startDocEvent(), startSeqEvent(), startMapEvent(), scalarEvent("key"),
scalarEvent("value"), scalarEvent("key2"), scalarEvent("value2"), endMapEvent(),
startMapEvent(), scalarEvent("key3"), scalarEvent("value3"), endMapEvent(),
endSeqEvent(), endDocEvent())
test "Parsing: Sequence in Map":
ensure("key:\n - item1\n - item2", startDocEvent(), startMapEvent(),
scalarEvent("key"), startSeqEvent(), scalarEvent("item1"), scalarEvent("item2"),
endSeqEvent(), endMapEvent(), endDocEvent())
test "Parsing: Sequence in Sequence":
ensure("- - l1_i1\n - l1_i2\n- l2_i1", startDocEvent(), startSeqEvent(),
startSeqEvent(), scalarEvent("l1_i1"), scalarEvent("l1_i2"), endSeqEvent(),
scalarEvent("l2_i1"), endSeqEvent(), endDocEvent())
test "Parsing: Flow Sequence":
ensure("[2, b]", startDocEvent(), startSeqEvent(), scalarEvent("2"),
scalarEvent("b"), endSeqEvent(), endDocEvent())
test "Parsing: Flow Map":
ensure("{a: Y, 1.337: d}", startDocEvent(), startMapEvent(), scalarEvent("a"),
scalarEvent("Y"), scalarEvent("1.337"),
scalarEvent("d"), endMapEvent(), endDocEvent())
test "Parsing: Flow Sequence in Flow Sequence":
ensure("[a, [b, c]]", startDocEvent(), startSeqEvent(), scalarEvent("a"),
startSeqEvent(), scalarEvent("b"), scalarEvent("c"), endSeqEvent(),
endSeqEvent(), endDocEvent())
test "Parsing: Flow Sequence in Flow Map":
ensure("{a: [b, c], [d, e]: f}", startDocEvent(), startMapEvent(), scalarEvent("a"),
startSeqEvent(), scalarEvent("b"), scalarEvent("c"), endSeqEvent(),
startSeqEvent(), scalarEvent("d"), scalarEvent("e"), endSeqEvent(),
scalarEvent("f"), endMapEvent(), endDocEvent())
test "Parsing: Flow Sequence in Map":
ensure("a: [b, c]", startDocEvent(), startMapEvent(), scalarEvent("a"),
startSeqEvent(), scalarEvent("b"), scalarEvent("c"), endSeqEvent(),
endMapEvent(), endDocEvent())
test "Parsing: Flow Map in Sequence":
ensure("- {a: b}", startDocEvent(), startSeqEvent(), startMapEvent(), scalarEvent("a"),
scalarEvent("b"), endMapEvent(), endSeqEvent(), endDocEvent())
test "Parsing: Multiline scalar (top level)":
ensure("a\nb \n c\nd", startDocEvent(), scalarEvent("a b c d"), endDocEvent())
test "Parsing: Multiline scalar (in map)":
ensure("a: b\n c\nd:\n e\n f", startDocEvent(), startMapEvent(), scalarEvent("a"),
scalarEvent("b c"), scalarEvent("d"), scalarEvent("e f"), endMapEvent(), endDocEvent())
test "Parsing: Block scalar (literal)":
ensure("a: |\x0A ab\x0A \x0A cd\x0A ef\x0A \x0A", startDocEvent(),
startMapEvent(), scalarEvent("a"), scalarEvent("ab\x0A\x0Acd\x0Aef\x0A", yTagExclamationmark),
endMapEvent(), endDocEvent())
test "Parsing: Block scalar (folded)":
ensure("a: >\x0A ab\x0A cd\x0A \x0A ef\x0A\x0A\x0A gh\x0A", startDocEvent(),
startMapEvent(), scalarEvent("a"), scalarEvent("ab cd\x0Aef\x0A\x0Agh\x0A", yTagExclamationmark),
endMapEvent(), endDocEvent())
test "Parsing: Block scalar (keep)":
ensure("a: |+\x0A ab\x0A \x0A \x0A", startDocEvent(), startMapEvent(),
scalarEvent("a"), scalarEvent("ab\x0A\x0A \x0A", yTagExclamationmark), endMapEvent(), endDocEvent())
test "Parsing: Block scalar (strip)":
ensure("a: |-\x0A ab\x0A \x0A \x0A", startDocEvent(), startMapEvent(),
scalarEvent("a"), scalarEvent("ab", yTagExclamationmark), endMapEvent(), endDocEvent())
test "Parsing: non-specific tags of quoted strings":
ensure("\"a\"", startDocEvent(),
scalarEvent("a", yTagExclamationMark), endDocEvent())
test "Parsing: explicit non-specific tag":
ensure("! a", startDocEvent(), scalarEvent("a", yTagExclamationMark), endDocEvent())
test "Parsing: secondary tag handle resolution":
ensure("!!str a", startDocEvent(), scalarEvent("a", yTagString), endDocEvent())
test "Parsing: resolving custom tag handles":
let fooId = tagLib.registerUri("tag:example.com,2015:foo")
ensure("%TAG !t! tag:example.com,2015:\n---\n!t!foo a", startDocEvent(),
scalarEvent("a", fooId), endDocEvent())
test "Parsing: tags in sequence":
ensure(" - !!str a\n - b\n - !!int c\n - d", startDocEvent(),
startSeqEvent(), scalarEvent("a", yTagString), scalarEvent("b"),
scalarEvent("c", yTagInteger), scalarEvent("d"), endSeqEvent(), endDocEvent())
test "Parsing: tags in implicit map":
ensure("!!str a: b\nc: !!int d\ne: !!str f\ng: h", startDocEvent(), startMapEvent(),
scalarEvent("a", yTagString), scalarEvent("b"), scalarEvent("c"),
scalarEvent("d", yTagInteger), scalarEvent("e"), scalarEvent("f", yTagString),
scalarEvent("g"), scalarEvent("h"), endMapEvent(), endDocEvent())
test "Parsing: tags in explicit map":
ensure("? !!str a\n: !!int b\n? c\n: !!str d", startDocEvent(), startMapEvent(),
scalarEvent("a", yTagString), scalarEvent("b", yTagInteger), scalarEvent("c"),
scalarEvent("d", yTagString), endMapEvent(), endDocEvent())
test "Parsing: tags for block objects":
ensure("--- !!map\nfoo: !!seq\n - a\n - !!str b\n!!str bar: !!str baz",
startDocEvent(), startMapEvent(yTagMap), scalarEvent("foo"),
startSeqEvent(yTagSequence), scalarEvent("a"), scalarEvent("b", yTagString),
endSeqEvent(), scalarEvent("bar", yTagString),
scalarEvent("baz", yTagString), endMapEvent(), endDocEvent())
test "Parsing: root tag for block sequence":
ensure("--- !!seq\n- a", startDocEvent(), startSeqEvent(yTagSequence),
scalarEvent("a"), endSeqEvent(), endDocEvent())
test "Parsing: root tag for explicit block map":
ensure("--- !!map\n? a\n: b", startDocEvent(), startMapEvent(yTagMap),
scalarEvent("a"), scalarEvent("b"), endMapEvent(), endDocEvent())
test "Parsing: tags for flow objects":
ensure("!!map { k: !!seq [ a, !!str b] }", startDocEvent(), startMapEvent(yTagMap),
scalarEvent("k"), startSeqEvent(yTagSequence), scalarEvent("a"),
scalarEvent("b", yTagString), endSeqEvent(), endMapEvent(), endDocEvent())
test "Parsing: Tag after directives end":
ensure("--- !!str\nfoo", startDocEvent(), scalarEvent("foo", yTagString), endDocEvent())
test "Parsing: Simple Anchor":
ensure("&a str", startDocEvent(), scalarEvent("str", yTagQuestionMark,
0.AnchorId), endDocEvent())
test "Parsing: Anchors in sequence":
ensure(" - &a a\n - b\n - &c c\n - &a d", startDocEvent(), startSeqEvent(),
scalarEvent("a", yTagQuestionMark, 0.AnchorId), scalarEvent("b"),
scalarEvent("c", yTagQuestionMark, 1.AnchorId),
scalarEvent("d", yTagQuestionMark, 2.AnchorId), endSeqEvent(),
endDocEvent())
test "Parsing: Anchors in map":
ensure("&a a: b\nc: &d d", startDocEvent(), startMapEvent(),
scalarEvent("a", yTagQuestionMark, 0.AnchorId),
scalarEvent("b"), scalarEvent("c"),
scalarEvent("d", yTagQuestionMark, 1.AnchorId),
endMapEvent(), endDocEvent())
test "Parsing: Anchors and tags":
ensure(" - &a !!str a\n - !!int b\n - &c !!int c\n - &d d", startDocEvent(),
startSeqEvent(), scalarEvent("a", yTagString, 0.AnchorId),
scalarEvent("b", yTagInteger), scalarEvent("c", yTagInteger, 1.AnchorId),
scalarEvent("d", yTagQuestionMark, 2.AnchorId), endSeqEvent(),
endDocEvent())
test "Parsing: Aliases in sequence":
ensure(" - &a a\n - &b b\n - *a\n - *b", startDocEvent(), startSeqEvent(),
scalarEvent("a", yTagQuestionMark, 0.AnchorId),
scalarEvent("b", yTagQuestionMark, 1.AnchorId), aliasEvent(0.AnchorId),
aliasEvent(1.AnchorId), endSeqEvent(), endDocEvent())
test "Parsing: Aliases in map":
ensure("&a a: &b b\n*a : *b", startDocEvent(), startMapEvent(),
scalarEvent("a", yTagQuestionMark, 0.AnchorId),
scalarEvent("b", yTagQuestionMark, 1.AnchorId), aliasEvent(0.AnchorId),
aliasEvent(1.AnchorId), endMapEvent(), endDocEvent())
test "Parsing: Aliases in flow":
ensure("{ &a [a, &b b]: *b, *a : [c, *b, d]}", startDocEvent(), startMapEvent(),
startSeqEvent(yTagQuestionMark, 0.AnchorId), scalarEvent("a"),
scalarEvent("b", yTagQuestionMark, 1.AnchorId), endSeqEvent(),
aliasEvent(1.AnchorId), aliasEvent(0.AnchorId), startSeqEvent(),
scalarEvent("c"), aliasEvent(1.AnchorId), scalarEvent("d"), endSeqEvent(),
endMapEvent(), endDocEvent())
test "Parsing: Tags on empty scalars":
ensure("!!str : a\nb: !!int\n!!str : !!str", startDocEvent(), startMapEvent(),
scalarEvent("", yTagString), scalarEvent("a"), scalarEvent("b"),
scalarEvent("", yTagInteger), scalarEvent("", yTagString),
scalarEvent("", yTagString), endMapEvent(), endDocEvent())
test "Parsing: Anchors on empty scalars":
ensure("&a : a\nb: &b\n&c : &a", startDocEvent(), startMapEvent(),
scalarEvent("", yTagQuestionMark, 0.AnchorId), scalarEvent("a"),
scalarEvent("b"), scalarEvent("", yTagQuestionMark, 1.AnchorId),
scalarEvent("", yTagQuestionMark, 2.AnchorId),
scalarEvent("", yTagQuestionMark, 3.AnchorId), endMapEvent(), endDocEvent())
test "Parsing: Whitespace before end of flow content":
ensure("- [a, b, c ]", startDocEvent(), startSeqEvent(),
startSeqEvent(), scalarEvent("a"), scalarEvent("b"),
scalarEvent("c"), endSeqEvent(), endSeqEvent(), endDocEvent())
test "Parsing: Empty lines after document":
ensure(":\n\n", startDocEvent(), startMapEvent(), scalarEvent(""),
scalarEvent(""), endMapEvent(), endDocEvent())
test "Parsing: Empty lines between map elements":
ensure("1: 2\n\n\n3: 4", startDocEvent(), startMapEvent(),
scalarEvent("1"), scalarEvent("2"), scalarEvent("3"),
scalarEvent("4"), endMapEvent(), endDocEvent())
test "Parsing: Sequence beginning at same line as map key":
ensure("1:\n- 2\n- 3\n4: 5", startDocEvent(), startMapEvent(),
scalarEvent("1"), startSeqEvent(), scalarEvent("2"),
scalarEvent("3"), endSeqEvent(), scalarEvent("4"),
scalarEvent("5"), endMapEvent(), endDocEvent())
test "Parsing: Sequence beginning at same line as map key with > 0 indent":
ensure(" foo:\n - bar\n baz:", startDocEvent(), startMapEvent(),
scalarEvent("foo"), startSeqEvent(), scalarEvent("bar"),
endSeqEvent(), scalarEvent("baz"), scalarEvent(""),
endMapEvent(), endDocEvent())
test "Parsing: Colon in double quoted string":
ensure("\"foo: bar\\\": baz\"", startDocEvent(),
scalarEvent("foo: bar\": baz", yTagExclamationMark),
endDocEvent())