Index: packages/yaml/test/yaml_test.dart |
diff --git a/packages/yaml/test/yaml_test.dart b/packages/yaml/test/yaml_test.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c4601d50d23d6693d974880ccb99511532145815 |
--- /dev/null |
+++ b/packages/yaml/test/yaml_test.dart |
@@ -0,0 +1,1885 @@ |
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
+library yaml.test; |
+ |
+import 'package:test/test.dart'; |
+import 'package:yaml/yaml.dart'; |
+ |
+import 'utils.dart'; |
+ |
+main() { |
+ var infinity = double.parse("Infinity"); |
+ var nan = double.parse("NaN"); |
+ |
+ group('has a friendly error message for', () { |
+ var tabError = predicate((e) => |
+ e.toString().contains('Tab characters are not allowed as indentation')); |
+ |
+ test('using a tab as indentation', () { |
+ expect(() => loadYaml('foo:\n\tbar'), |
+ throwsA(tabError)); |
+ }); |
+ |
+ test('using a tab not as indentation', () { |
+ expect(() => loadYaml(''' |
+ "foo |
+ \tbar" |
+ error'''), |
+ throwsA(isNot(tabError))); |
+ }); |
+ }); |
+ |
+ group("refuses documents that declare version", () { |
+ test("1.0", () { |
+ expectYamlFails(""" |
+ %YAML 1.0 |
+ --- text |
+ """); |
+ }); |
+ |
+ test("1.3", () { |
+ expectYamlFails(""" |
+ %YAML 1.3 |
+ --- text |
+ """); |
+ }); |
+ |
+ test("2.0", () { |
+ expectYamlFails(""" |
+ %YAML 2.0 |
+ --- text |
+ """); |
+ }); |
+ }); |
+ |
+ test("includes source span information", () { |
+ var yaml = loadYamlNode(r""" |
+- foo: |
+ bar |
+- 123 |
+"""); |
+ |
+ expect(yaml.span.start.line, equals(0)); |
+ expect(yaml.span.start.column, equals(0)); |
+ expect(yaml.span.end.line, equals(3)); |
+ expect(yaml.span.end.column, equals(0)); |
+ |
+ var map = yaml.nodes.first; |
+ expect(map.span.start.line, equals(0)); |
+ expect(map.span.start.column, equals(2)); |
+ expect(map.span.end.line, equals(2)); |
+ expect(map.span.end.column, equals(0)); |
+ |
+ var key = map.nodes.keys.first; |
+ expect(key.span.start.line, equals(0)); |
+ expect(key.span.start.column, equals(2)); |
+ expect(key.span.end.line, equals(0)); |
+ expect(key.span.end.column, equals(5)); |
+ |
+ var value = map.nodes.values.first; |
+ expect(value.span.start.line, equals(1)); |
+ expect(value.span.start.column, equals(4)); |
+ expect(value.span.end.line, equals(1)); |
+ expect(value.span.end.column, equals(7)); |
+ |
+ var scalar = yaml.nodes.last; |
+ expect(scalar.span.start.line, equals(2)); |
+ expect(scalar.span.start.column, equals(2)); |
+ expect(scalar.span.end.line, equals(2)); |
+ expect(scalar.span.end.column, equals(5)); |
+ }); |
+ |
+ // The following tests are all taken directly from the YAML spec |
+ // (http://www.yaml.org/spec/1.2/spec.html). Most of them are code examples |
+ // that are directly included in the spec, but additional tests are derived |
+ // from the prose. |
+ |
+ // A few examples from the spec are deliberately excluded, because they test |
+ // features that this implementation doesn't intend to support (character |
+ // encoding detection and user-defined tags). More tests are commented out, |
+ // because they're intended to be supported but not yet implemented. |
+ |
+ // Chapter 2 is just a preview of various Yaml documents. It's probably not |
+ // necessary to test its examples, but it would be nice to test everything in |
+ // the spec. |
+ group('2.1: Collections', () { |
+ test('[Example 2.1]', () { |
+ expectYamlLoads(["Mark McGwire", "Sammy Sosa", "Ken Griffey"], |
+ """ |
+ - Mark McGwire |
+ - Sammy Sosa |
+ - Ken Griffey"""); |
+ }); |
+ |
+ test('[Example 2.2]', () { |
+ expectYamlLoads({"hr": 65, "avg": 0.278, "rbi": 147}, |
+ """ |
+ hr: 65 # Home runs |
+ avg: 0.278 # Batting average |
+ rbi: 147 # Runs Batted In"""); |
+ }); |
+ |
+ test('[Example 2.3]', () { |
+ expectYamlLoads({ |
+ "american": ["Boston Red Sox", "Detroit Tigers", "New York Yankees"], |
+ "national": ["New York Mets", "Chicago Cubs", "Atlanta Braves"], |
+ }, |
+ """ |
+ american: |
+ - Boston Red Sox |
+ - Detroit Tigers |
+ - New York Yankees |
+ national: |
+ - New York Mets |
+ - Chicago Cubs |
+ - Atlanta Braves"""); |
+ }); |
+ |
+ test('[Example 2.4]', () { |
+ expectYamlLoads([ |
+ {"name": "Mark McGwire", "hr": 65, "avg": 0.278}, |
+ {"name": "Sammy Sosa", "hr": 63, "avg": 0.288}, |
+ ], |
+ """ |
+ - |
+ name: Mark McGwire |
+ hr: 65 |
+ avg: 0.278 |
+ - |
+ name: Sammy Sosa |
+ hr: 63 |
+ avg: 0.288"""); |
+ }); |
+ |
+ test('[Example 2.5]', () { |
+ expectYamlLoads([ |
+ ["name", "hr", "avg"], |
+ ["Mark McGwire", 65, 0.278], |
+ ["Sammy Sosa", 63, 0.288] |
+ ], |
+ """ |
+ - [name , hr, avg ] |
+ - [Mark McGwire, 65, 0.278] |
+ - [Sammy Sosa , 63, 0.288]"""); |
+ }); |
+ |
+ test('[Example 2.6]', () { |
+ expectYamlLoads({ |
+ "Mark McGwire": {"hr": 65, "avg": 0.278}, |
+ "Sammy Sosa": {"hr": 63, "avg": 0.288} |
+ }, |
+ """ |
+ Mark McGwire: {hr: 65, avg: 0.278} |
+ Sammy Sosa: { |
+ hr: 63, |
+ avg: 0.288 |
+ }"""); |
+ }); |
+ }); |
+ |
+ group('2.2: Structures', () { |
+ test('[Example 2.7]', () { |
+ expectYamlStreamLoads([ |
+ ["Mark McGwire", "Sammy Sosa", "Ken Griffey"], |
+ ["Chicago Cubs", "St Louis Cardinals"] |
+ ], |
+ """ |
+ # Ranking of 1998 home runs |
+ --- |
+ - Mark McGwire |
+ - Sammy Sosa |
+ - Ken Griffey |
+ |
+ # Team ranking |
+ --- |
+ - Chicago Cubs |
+ - St Louis Cardinals"""); |
+ }); |
+ |
+ test('[Example 2.8]', () { |
+ expectYamlStreamLoads([ |
+ {"time": "20:03:20", "player": "Sammy Sosa", "action": "strike (miss)"}, |
+ {"time": "20:03:47", "player": "Sammy Sosa", "action": "grand slam"}, |
+ ], |
+ """ |
+ --- |
+ time: 20:03:20 |
+ player: Sammy Sosa |
+ action: strike (miss) |
+ ... |
+ --- |
+ time: 20:03:47 |
+ player: Sammy Sosa |
+ action: grand slam |
+ ..."""); |
+ }); |
+ |
+ test('[Example 2.9]', () { |
+ expectYamlLoads({ |
+ "hr": ["Mark McGwire", "Sammy Sosa"], |
+ "rbi": ["Sammy Sosa", "Ken Griffey"] |
+ }, |
+ """ |
+ --- |
+ hr: # 1998 hr ranking |
+ - Mark McGwire |
+ - Sammy Sosa |
+ rbi: |
+ # 1998 rbi ranking |
+ - Sammy Sosa |
+ - Ken Griffey"""); |
+ }); |
+ |
+ test('[Example 2.10]', () { |
+ expectYamlLoads({ |
+ "hr": ["Mark McGwire", "Sammy Sosa"], |
+ "rbi": ["Sammy Sosa", "Ken Griffey"] |
+ }, |
+ """ |
+ --- |
+ hr: |
+ - Mark McGwire |
+ # Following node labeled SS |
+ - &SS Sammy Sosa |
+ rbi: |
+ - *SS # Subsequent occurrence |
+ - Ken Griffey"""); |
+ }); |
+ |
+ test('[Example 2.11]', () { |
+ var doc = deepEqualsMap(); |
+ doc[["Detroit Tigers", "Chicago cubs"]] = ["2001-07-23"]; |
+ doc[["New York Yankees", "Atlanta Braves"]] = |
+ ["2001-07-02", "2001-08-12", "2001-08-14"]; |
+ expectYamlLoads(doc, |
+ """ |
+ ? - Detroit Tigers |
+ - Chicago cubs |
+ : |
+ - 2001-07-23 |
+ |
+ ? [ New York Yankees, |
+ Atlanta Braves ] |
+ : [ 2001-07-02, 2001-08-12, |
+ 2001-08-14 ]"""); |
+ }); |
+ |
+ test('[Example 2.12]', () { |
+ expectYamlLoads([ |
+ {"item": "Super Hoop", "quantity": 1}, |
+ {"item": "Basketball", "quantity": 4}, |
+ {"item": "Big Shoes", "quantity": 1}, |
+ ], |
+ """ |
+ --- |
+ # Products purchased |
+ - item : Super Hoop |
+ quantity: 1 |
+ - item : Basketball |
+ quantity: 4 |
+ - item : Big Shoes |
+ quantity: 1"""); |
+ }); |
+ }); |
+ |
+ group('2.3: Scalars', () { |
+ test('[Example 2.13]', () { |
+ expectYamlLoads( |
+ cleanUpLiteral( |
+ """ |
+ \\//||\\/|| |
+ // || ||__"""), |
+ """ |
+ # ASCII Art |
+ --- | |
+ \\//||\\/|| |
+ // || ||__"""); |
+ }); |
+ |
+ test('[Example 2.14]', () { |
+ expectYamlLoads("Mark McGwire's year was crippled by a knee injury.", |
+ """ |
+ --- > |
+ Mark McGwire's |
+ year was crippled |
+ by a knee injury."""); |
+ }); |
+ |
+ test('[Example 2.15]', () { |
+ expectYamlLoads( |
+ cleanUpLiteral( |
+ """ |
+ Sammy Sosa completed another fine season with great stats. |
+ |
+ 63 Home Runs |
+ 0.288 Batting Average |
+ |
+ What a year!"""), |
+ """ |
+ > |
+ Sammy Sosa completed another |
+ fine season with great stats. |
+ |
+ 63 Home Runs |
+ 0.288 Batting Average |
+ |
+ What a year!"""); |
+ }); |
+ |
+ test('[Example 2.16]', () { |
+ expectYamlLoads({ |
+ "name": "Mark McGwire", |
+ "accomplishment": "Mark set a major league home run record in 1998.\n", |
+ "stats": "65 Home Runs\n0.278 Batting Average" |
+ }, |
+ """ |
+ name: Mark McGwire |
+ accomplishment: > |
+ Mark set a major league |
+ home run record in 1998. |
+ stats: | |
+ 65 Home Runs |
+ 0.278 Batting Average"""); |
+ }); |
+ |
+ test('[Example 2.17]', () { |
+ expectYamlLoads({ |
+ "unicode": "Sosa did fine.\u263A", |
+ "control": "\b1998\t1999\t2000\n", |
+ "hex esc": "\r\n is \r\n", |
+ "single": '"Howdy!" he cried.', |
+ "quoted": " # Not a 'comment'.", |
+ "tie-fighter": "|\\-*-/|" |
+ }, |
+ """ |
+ unicode: "Sosa did fine.\\u263A" |
+ control: "\\b1998\\t1999\\t2000\\n" |
+ hex esc: "\\x0d\\x0a is \\r\\n" |
+ |
+ single: '"Howdy!" he cried.' |
+ quoted: ' # Not a ''comment''.' |
+ tie-fighter: '|\\-*-/|'"""); |
+ }); |
+ |
+ test('[Example 2.18]', () { |
+ expectYamlLoads({ |
+ "plain": "This unquoted scalar spans many lines.", |
+ "quoted": "So does this quoted scalar.\n" |
+ }, |
+ ''' |
+ plain: |
+ This unquoted scalar |
+ spans many lines. |
+ |
+ quoted: "So does this |
+ quoted scalar.\\n"'''); |
+ }); |
+ }); |
+ |
+ group('2.4: Tags', () { |
+ test('[Example 2.19]', () { |
+ expectYamlLoads({ |
+ "canonical": 12345, |
+ "decimal": 12345, |
+ "octal": 12, |
+ "hexadecimal": 12 |
+ }, |
+ """ |
+ canonical: 12345 |
+ decimal: +12345 |
+ octal: 0o14 |
+ hexadecimal: 0xC"""); |
+ }); |
+ |
+ test('[Example 2.20]', () { |
+ expectYamlLoads({ |
+ "canonical": 1230.15, |
+ "exponential": 1230.15, |
+ "fixed": 1230.15, |
+ "negative infinity": -infinity, |
+ "not a number": nan |
+ }, |
+ """ |
+ canonical: 1.23015e+3 |
+ exponential: 12.3015e+02 |
+ fixed: 1230.15 |
+ negative infinity: -.inf |
+ not a number: .NaN"""); |
+ }); |
+ |
+ test('[Example 2.21]', () { |
+ var doc = deepEqualsMap({ |
+ "booleans": [true, false], |
+ "string": "012345" |
+ }); |
+ doc[null] = null; |
+ expectYamlLoads(doc, |
+ """ |
+ null: |
+ booleans: [ true, false ] |
+ string: '012345'"""); |
+ }); |
+ |
+ // Examples 2.22 through 2.26 test custom tag URIs, which this |
+ // implementation currently doesn't plan to support. |
+ }); |
+ |
+ group('2.5 Full Length Example', () { |
+ // Example 2.27 tests custom tag URIs, which this implementation currently |
+ // doesn't plan to support. |
+ |
+ test('[Example 2.28]', () { |
+ expectYamlStreamLoads([ |
+ { |
+ "Time": "2001-11-23 15:01:42 -5", |
+ "User": "ed", |
+ "Warning": "This is an error message for the log file" |
+ }, |
+ { |
+ "Time": "2001-11-23 15:02:31 -5", |
+ "User": "ed", |
+ "Warning": "A slightly different error message." |
+ }, |
+ { |
+ "DateTime": "2001-11-23 15:03:17 -5", |
+ "User": "ed", |
+ "Fatal": 'Unknown variable "bar"', |
+ "Stack": [ |
+ { |
+ "file": "TopClass.py", |
+ "line": 23, |
+ "code": 'x = MoreObject("345\\n")\n' |
+ }, |
+ {"file": "MoreClass.py", "line": 58, "code": "foo = bar"} |
+ ] |
+ } |
+ ], |
+ """ |
+ --- |
+ Time: 2001-11-23 15:01:42 -5 |
+ User: ed |
+ Warning: |
+ This is an error message |
+ for the log file |
+ --- |
+ Time: 2001-11-23 15:02:31 -5 |
+ User: ed |
+ Warning: |
+ A slightly different error |
+ message. |
+ --- |
+ DateTime: 2001-11-23 15:03:17 -5 |
+ User: ed |
+ Fatal: |
+ Unknown variable "bar" |
+ Stack: |
+ - file: TopClass.py |
+ line: 23 |
+ code: | |
+ x = MoreObject("345\\n") |
+ - file: MoreClass.py |
+ line: 58 |
+ code: |- |
+ foo = bar"""); |
+ }); |
+ }); |
+ |
+ // Chapter 3 just talks about the structure of loading and dumping Yaml. |
+ // Chapter 4 explains conventions used in the spec. |
+ |
+ // Chapter 5: Characters |
+ group('5.1: Character Set', () { |
+ expectAllowsCharacter(int charCode) { |
+ var char = new String.fromCharCodes([charCode]); |
+ expectYamlLoads('The character "$char" is allowed', |
+ 'The character "$char" is allowed'); |
+ } |
+ |
+ expectAllowsQuotedCharacter(int charCode) { |
+ var char = new String.fromCharCodes([charCode]); |
+ expectYamlLoads("The character '$char' is allowed", |
+ '"The character \'$char\' is allowed"'); |
+ } |
+ |
+ expectDisallowsCharacter(int charCode) { |
+ var char = new String.fromCharCodes([charCode]); |
+ expectYamlFails('The character "$char" is disallowed'); |
+ } |
+ |
+ test("doesn't include C0 control characters", () { |
+ expectDisallowsCharacter(0x0); |
+ expectDisallowsCharacter(0x8); |
+ expectDisallowsCharacter(0x1F); |
+ }); |
+ |
+ test("includes TAB", () => expectAllowsCharacter(0x9)); |
+ test("doesn't include DEL", () => expectDisallowsCharacter(0x7F)); |
+ |
+ test("doesn't include C1 control characters", () { |
+ expectDisallowsCharacter(0x80); |
+ expectDisallowsCharacter(0x8A); |
+ expectDisallowsCharacter(0x9F); |
+ }); |
+ |
+ test("includes NEL", () => expectAllowsCharacter(0x85)); |
+ |
+ group("within quoted strings", () { |
+ test("includes DEL", () => expectAllowsQuotedCharacter(0x7F)); |
+ test("includes C1 control characters", () { |
+ expectAllowsQuotedCharacter(0x80); |
+ expectAllowsQuotedCharacter(0x8A); |
+ expectAllowsQuotedCharacter(0x9F); |
+ }); |
+ }); |
+ }); |
+ |
+ // Skipping section 5.2 (Character Encodings), since at the moment the module |
+ // assumes that the client code is providing it with a string of the proper |
+ // encoding. |
+ |
+ group('5.3: Indicator Characters', () { |
+ test('[Example 5.3]', () { |
+ expectYamlLoads({ |
+ 'sequence': ['one', 'two'], |
+ 'mapping': {'sky': 'blue', 'sea': 'green'} |
+ }, |
+ """ |
+ sequence: |
+ - one |
+ - two |
+ mapping: |
+ ? sky |
+ : blue |
+ sea : green"""); |
+ }); |
+ |
+ test('[Example 5.4]', () { |
+ expectYamlLoads({ |
+ 'sequence': ['one', 'two'], |
+ 'mapping': {'sky': 'blue', 'sea': 'green'} |
+ }, |
+ """ |
+ sequence: [ one, two, ] |
+ mapping: { sky: blue, sea: green }"""); |
+ }); |
+ |
+ test('[Example 5.5]', () => expectYamlLoads(null, "# Comment only.")); |
+ |
+ // Skipping 5.6 because it uses an undefined tag. |
+ |
+ test('[Example 5.7]', () { |
+ expectYamlLoads({ |
+ 'literal': "some\ntext\n", |
+ 'folded': "some text\n" |
+ }, |
+ """ |
+ literal: | |
+ some |
+ text |
+ folded: > |
+ some |
+ text |
+ """); |
+ }); |
+ |
+ test('[Example 5.8]', () { |
+ expectYamlLoads({ |
+ 'single': "text", |
+ 'double': "text" |
+ }, |
+ """ |
+ single: 'text' |
+ double: "text" |
+ """); |
+ }); |
+ |
+ test('[Example 5.9]', () { |
+ expectYamlLoads("text", |
+ """ |
+ %YAML 1.2 |
+ --- text"""); |
+ }); |
+ |
+ test('[Example 5.10]', () { |
+ expectYamlFails("commercial-at: @text"); |
+ expectYamlFails("commercial-at: `text"); |
+ }); |
+ }); |
+ |
+ group('5.4: Line Break Characters', () { |
+ group('include', () { |
+ test('\\n', () => expectYamlLoads([1, 2], indentLiteral("- 1\n- 2"))); |
+ test('\\r', () => expectYamlLoads([1, 2], "- 1\r- 2")); |
+ }); |
+ |
+ group('do not include', () { |
+ test('form feed', () => expectYamlFails("- 1\x0C- 2")); |
+ test('NEL', () => expectYamlLoads(["1\x85- 2"], "- 1\x85- 2")); |
+ test('0x2028', () => expectYamlLoads(["1\u2028- 2"], "- 1\u2028- 2")); |
+ test('0x2029', () => expectYamlLoads(["1\u2029- 2"], "- 1\u2029- 2")); |
+ }); |
+ |
+ group('in a scalar context must be normalized', () { |
+ test("from \\r to \\n", () => |
+ expectYamlLoads(["foo\nbar"], indentLiteral('- |\n foo\r bar'))); |
+ test("from \\r\\n to \\n", () => |
+ expectYamlLoads(["foo\nbar"], indentLiteral('- |\n foo\r\n bar'))); |
+ }); |
+ |
+ test('[Example 5.11]', () { |
+ expectYamlLoads( |
+ cleanUpLiteral(""" |
+ Line break (no glyph) |
+ Line break (glyphed)"""), |
+ """ |
+ | |
+ Line break (no glyph) |
+ Line break (glyphed)"""); |
+ }); |
+ }); |
+ |
+ group('5.5: White Space Characters', () { |
+ test('[Example 5.12]', () { |
+ expectYamlLoads({ |
+ "quoted": "Quoted \t", |
+ "block": 'void main() {\n\tprintf("Hello, world!\\n");\n}\n' |
+ }, |
+ """ |
+ # Tabs and spaces |
+ quoted: "Quoted \t" |
+ block:\t| |
+ void main() { |
+ \tprintf("Hello, world!\\n"); |
+ } |
+ """); |
+ }); |
+ }); |
+ |
+ group('5.7: Escaped Characters', () { |
+ test('[Example 5.13]', () { |
+ expectYamlLoads( |
+ "Fun with \x5C " |
+ "\x22 \x07 \x08 \x1B \x0C " |
+ "\x0A \x0D \x09 \x0B \x00 " |
+ "\x20 \xA0 \x85 \u2028 \u2029 " |
+ "A A A", |
+ ''' |
+ "Fun with \\\\ |
+ \\" \\a \\b \\e \\f \\ |
+ \\n \\r \\t \\v \\0 \\ |
+ \\ \\_ \\N \\L \\P \\ |
+ \\x41 \\u0041 \\U00000041"'''); |
+ }); |
+ |
+ test('[Example 5.14]', () { |
+ expectYamlFails('Bad escape: "\\c"'); |
+ expectYamlFails('Bad escape: "\\xq-"'); |
+ }); |
+ }); |
+ |
+ // Chapter 6: Basic Structures |
+ group('6.1: Indentation Spaces', () { |
+ test('may not include TAB characters', () { |
+ expectYamlFails( |
+ """ |
+ - |
+ \t- foo |
+ \t- bar"""); |
+ }); |
+ |
+ test('must be the same for all sibling nodes', () { |
+ expectYamlFails( |
+ """ |
+ - |
+ - foo |
+ - bar"""); |
+ }); |
+ |
+ test('may be different for the children of sibling nodes', () { |
+ expectYamlLoads([["foo"], ["bar"]], |
+ """ |
+ - |
+ - foo |
+ - |
+ - bar"""); |
+ }); |
+ |
+ test('[Example 6.1]', () { |
+ expectYamlLoads({ |
+ "Not indented": { |
+ "By one space": "By four\n spaces\n", |
+ "Flow style": [ |
+ "By two", |
+ "Also by two", |
+ "Still by two" |
+ ] |
+ } |
+ }, |
+ """ |
+ # Leading comment line spaces are |
+ # neither content nor indentation. |
+ |
+ Not indented: |
+ By one space: | |
+ By four |
+ spaces |
+ Flow style: [ # Leading spaces |
+ By two, # in flow style |
+ Also by two, # are neither |
+ \tStill by two # content nor |
+ ] # indentation."""); |
+ }); |
+ |
+ test('[Example 6.2]', () { |
+ expectYamlLoads({'a': ['b', ['c', 'd']]}, |
+ """ |
+ ? a |
+ : -\tb |
+ - -\tc |
+ - d"""); |
+ }); |
+ }); |
+ |
+ group('6.2: Separation Spaces', () { |
+ test('[Example 6.3]', () { |
+ expectYamlLoads([{'foo': 'bar'}, ['baz', 'baz']], |
+ """ |
+ - foo:\t bar |
+ - - baz |
+ -\tbaz"""); |
+ }); |
+ }); |
+ |
+ group('6.3: Line Prefixes', () { |
+ test('[Example 6.4]', () { |
+ expectYamlLoads({ |
+ "plain": "text lines", |
+ "quoted": "text lines", |
+ "block": "text\n \tlines\n" |
+ }, |
+ """ |
+ plain: text |
+ lines |
+ quoted: "text |
+ \tlines" |
+ block: | |
+ text |
+ \tlines |
+ """); |
+ }); |
+ }); |
+ |
+ group('6.4: Empty Lines', () { |
+ test('[Example 6.5]', () { |
+ expectYamlLoads({ |
+ "Folding": "Empty line\nas a line feed", |
+ "Chomping": "Clipped empty lines\n", |
+ }, |
+ """ |
+ Folding: |
+ "Empty line |
+ \t |
+ as a line feed" |
+ Chomping: | |
+ Clipped empty lines |
+ """); |
+ }); |
+ }); |
+ |
+ group('6.5: Line Folding', () { |
+ test('[Example 6.6]', () { |
+ expectYamlLoads("trimmed\n\n\nas space", |
+ """ |
+ >- |
+ trimmed |
+ |
+ |
+ |
+ as |
+ space |
+ """); |
+ }); |
+ |
+ test('[Example 6.7]', () { |
+ expectYamlLoads("foo \n\n\t bar\n\nbaz\n", |
+ """ |
+ > |
+ foo |
+ |
+ \t bar |
+ |
+ baz |
+ """); |
+ }); |
+ |
+ test('[Example 6.8]', () { |
+ expectYamlLoads(" foo\nbar\nbaz ", |
+ ''' |
+ " |
+ foo |
+ |
+ \t bar |
+ |
+ baz |
+ "'''); |
+ }); |
+ }); |
+ |
+ group('6.6: Comments', () { |
+ test('must be separated from other tokens by white space characters', () { |
+ expectYamlLoads("foo#bar", "foo#bar"); |
+ expectYamlLoads("foo:#bar", "foo:#bar"); |
+ expectYamlLoads("-#bar", "-#bar"); |
+ }); |
+ |
+ test('[Example 6.9]', () { |
+ expectYamlLoads({'key': 'value'}, |
+ """ |
+ key: # Comment |
+ value"""); |
+ }); |
+ |
+ group('outside of scalar content', () { |
+ test('may appear on a line of their own', () { |
+ expectYamlLoads([1, 2], |
+ """ |
+ - 1 |
+ # Comment |
+ - 2"""); |
+ }); |
+ |
+ test('are independent of indentation level', () { |
+ expectYamlLoads([[1, 2]], |
+ """ |
+ - |
+ - 1 |
+ # Comment |
+ - 2"""); |
+ }); |
+ |
+ test('include lines containing only white space characters', () { |
+ expectYamlLoads([1, 2], |
+ """ |
+ - 1 |
+ \t |
+ - 2"""); |
+ }); |
+ }); |
+ |
+ group('within scalar content', () { |
+ test('may not appear on a line of their own', () { |
+ expectYamlLoads(["foo\n# not comment\nbar\n"], |
+ """ |
+ - | |
+ foo |
+ # not comment |
+ bar |
+ """); |
+ }); |
+ |
+ test("don't include lines containing only white space characters", () { |
+ expectYamlLoads(["foo\n \t \nbar\n"], |
+ """ |
+ - | |
+ foo |
+ \t |
+ bar |
+ """); |
+ }); |
+ }); |
+ |
+ test('[Example 6.10]', () { |
+ expectYamlLoads(null, |
+ """ |
+ # Comment |
+ |
+ """); |
+ }); |
+ |
+ test('[Example 6.11]', () { |
+ expectYamlLoads({'key': 'value'}, |
+ """ |
+ key: # Comment |
+ # lines |
+ value |
+ """); |
+ }); |
+ |
+ group('ending a block scalar header', () { |
+ test('may not be followed by additional comment lines', () { |
+ expectYamlLoads(["# not comment\nfoo\n"], |
+ """ |
+ - | # comment |
+ # not comment |
+ foo |
+ """); |
+ }); |
+ }); |
+ }); |
+ |
+ group('6.7: Separation Lines', () { |
+ test('may not be used within implicit keys', () { |
+ expectYamlFails( |
+ """ |
+ [1, |
+ 2]: 3"""); |
+ }); |
+ |
+ test('[Example 6.12]', () { |
+ var doc = deepEqualsMap(); |
+ doc[{'first': 'Sammy', 'last': 'Sosa'}] = { |
+ 'hr': 65, |
+ 'avg': 0.278 |
+ }; |
+ expectYamlLoads(doc, |
+ """ |
+ { first: Sammy, last: Sosa }: |
+ # Statistics: |
+ hr: # Home runs |
+ 65 |
+ avg: # Average |
+ 0.278"""); |
+ }); |
+ }); |
+ |
+ group('6.8: Directives', () { |
+ // TODO(nweiz): assert that this produces a warning |
+ test('[Example 6.13]', () { |
+ expectYamlLoads("foo", |
+ ''' |
+ %FOO bar baz # Should be ignored |
+ # with a warning. |
+ --- "foo"'''); |
+ }); |
+ |
+ // TODO(nweiz): assert that this produces a warning. |
+ test('[Example 6.14]', () { |
+ expectYamlLoads("foo", |
+ ''' |
+ %YAML 1.3 # Attempt parsing |
+ # with a warning |
+ --- |
+ "foo"'''); |
+ }); |
+ |
+ test('[Example 6.15]', () { |
+ expectYamlFails( |
+ """ |
+ %YAML 1.2 |
+ %YAML 1.1 |
+ foo"""); |
+ }); |
+ |
+ test('[Example 6.16]', () { |
+ expectYamlLoads("foo", |
+ ''' |
+ %TAG !yaml! tag:yaml.org,2002: |
+ --- |
+ !yaml!str "foo"'''); |
+ }); |
+ |
+ test('[Example 6.17]', () { |
+ expectYamlFails( |
+ """ |
+ %TAG ! !foo |
+ %TAG ! !foo |
+ bar"""); |
+ }); |
+ |
+ // Examples 6.18 through 6.22 test custom tag URIs, which this |
+ // implementation currently doesn't plan to support. |
+ }); |
+ |
+ group('6.9: Node Properties', () { |
+ test('may be specified in any order', () { |
+ expectYamlLoads(["foo", "bar"], |
+ """ |
+ - !!str &a1 foo |
+ - &a2 !!str bar"""); |
+ }); |
+ |
+ test('[Example 6.23]', () { |
+ expectYamlLoads({ |
+ "foo": "bar", |
+ "baz": "foo" |
+ }, |
+ ''' |
+ !!str &a1 "foo": |
+ !!str bar |
+ &a2 baz : *a1'''); |
+ }); |
+ |
+ // Example 6.24 tests custom tag URIs, which this implementation currently |
+ // doesn't plan to support. |
+ |
+ test('[Example 6.25]', () { |
+ expectYamlFails("- !<!> foo"); |
+ expectYamlFails("- !<\$:?> foo"); |
+ }); |
+ |
+ // Examples 6.26 and 6.27 test custom tag URIs, which this implementation |
+ // currently doesn't plan to support. |
+ |
+ test('[Example 6.28]', () { |
+ expectYamlLoads(["12", 12, "12"], |
+ ''' |
+ # Assuming conventional resolution: |
+ - "12" |
+ - 12 |
+ - ! 12'''); |
+ }); |
+ |
+ test('[Example 6.29]', () { |
+ expectYamlLoads({ |
+ "First occurrence": "Value", |
+ "Second occurrence": "Value" |
+ }, |
+ """ |
+ First occurrence: &anchor Value |
+ Second occurrence: *anchor"""); |
+ }); |
+ }); |
+ |
+ // Chapter 7: Flow Styles |
+ group('7.1: Alias Nodes', () { |
+ test("must not use an anchor that doesn't previously occur", () { |
+ expectYamlFails( |
+ """ |
+ - *anchor |
+ - &anchor foo"""); |
+ }); |
+ |
+ test("don't have to exist for a given anchor node", () { |
+ expectYamlLoads(["foo"], "- &anchor foo"); |
+ }); |
+ |
+ group('must not specify', () { |
+ test('tag properties', () => expectYamlFails( |
+ """ |
+ - &anchor foo |
+ - !str *anchor""")); |
+ |
+ test('anchor properties', () => expectYamlFails( |
+ """ |
+ - &anchor foo |
+ - &anchor2 *anchor""")); |
+ |
+ test('content', () => expectYamlFails( |
+ """ |
+ - &anchor foo |
+ - *anchor bar""")); |
+ }); |
+ |
+ test('must preserve structural equality', () { |
+ var doc = loadYaml(cleanUpLiteral( |
+ """ |
+ anchor: &anchor [a, b, c] |
+ alias: *anchor""")); |
+ var anchorList = doc['anchor']; |
+ var aliasList = doc['alias']; |
+ expect(anchorList, same(aliasList)); |
+ |
+ doc = loadYaml(cleanUpLiteral( |
+ """ |
+ ? &anchor [a, b, c] |
+ : ? *anchor |
+ : bar""")); |
+ anchorList = doc.keys.first; |
+ aliasList = doc[['a', 'b', 'c']].keys.first; |
+ expect(anchorList, same(aliasList)); |
+ }); |
+ |
+ test('[Example 7.1]', () { |
+ expectYamlLoads({ |
+ "First occurrence": "Foo", |
+ "Second occurrence": "Foo", |
+ "Override anchor": "Bar", |
+ "Reuse anchor": "Bar", |
+ }, |
+ """ |
+ First occurrence: &anchor Foo |
+ Second occurrence: *anchor |
+ Override anchor: &anchor Bar |
+ Reuse anchor: *anchor"""); |
+ }); |
+ }); |
+ |
+ group('7.2: Empty Nodes', () { |
+ test('[Example 7.2]', () { |
+ expectYamlLoads({ |
+ "foo": "", |
+ "": "bar" |
+ }, |
+ """ |
+ { |
+ foo : !!str, |
+ !!str : bar, |
+ }"""); |
+ }); |
+ |
+ test('[Example 7.3]', () { |
+ var doc = deepEqualsMap({"foo": null}); |
+ doc[null] = "bar"; |
+ expectYamlLoads(doc, |
+ """ |
+ { |
+ ? foo :, |
+ : bar, |
+ }"""); |
+ }); |
+ }); |
+ |
+ group('7.3: Flow Scalar Styles', () { |
+ test('[Example 7.4]', () { |
+ expectYamlLoads({ |
+ "implicit block key": [{"implicit flow key": "value"}] |
+ }, |
+ ''' |
+ "implicit block key" : [ |
+ "implicit flow key" : value, |
+ ]'''); |
+ }); |
+ |
+ test('[Example 7.5]', () { |
+ expectYamlLoads( |
+ "folded to a space,\nto a line feed, or \t \tnon-content", |
+ ''' |
+ "folded |
+ to a space,\t |
+ |
+ to a line feed, or \t\\ |
+ \\ \tnon-content"'''); |
+ }); |
+ |
+ test('[Example 7.6]', () { |
+ expectYamlLoads(" 1st non-empty\n2nd non-empty 3rd non-empty ", |
+ ''' |
+ " 1st non-empty |
+ |
+ 2nd non-empty |
+ \t3rd non-empty "'''); |
+ }); |
+ |
+ test('[Example 7.7]', () { |
+ expectYamlLoads("here's to \"quotes\"", "'here''s to \"quotes\"'"); |
+ }); |
+ |
+ test('[Example 7.8]', () { |
+ expectYamlLoads({ |
+ "implicit block key": [{"implicit flow key": "value"}] |
+ }, |
+ """ |
+ 'implicit block key' : [ |
+ 'implicit flow key' : value, |
+ ]"""); |
+ }); |
+ |
+ test('[Example 7.9]', () { |
+ expectYamlLoads(" 1st non-empty\n2nd non-empty 3rd non-empty ", |
+ """ |
+ ' 1st non-empty |
+ |
+ 2nd non-empty |
+ \t3rd non-empty '"""); |
+ }); |
+ |
+ test('[Example 7.10]', () { |
+ expectYamlLoads([ |
+ "::vector", ": - ()", "Up, up, and away!", -123, |
+ "http://example.com/foo#bar", |
+ [ |
+ "::vector", ": - ()", "Up, up, and away!", -123, |
+ "http://example.com/foo#bar" |
+ ] |
+ ], |
+ ''' |
+ # Outside flow collection: |
+ - ::vector |
+ - ": - ()" |
+ - Up, up, and away! |
+ - -123 |
+ - http://example.com/foo#bar |
+ # Inside flow collection: |
+ - [ ::vector, |
+ ": - ()", |
+ "Up, up, and away!", |
+ -123, |
+ http://example.com/foo#bar ]'''); |
+ }); |
+ |
+ test('[Example 7.11]', () { |
+ expectYamlLoads({ |
+ "implicit block key": [{"implicit flow key": "value"}] |
+ }, |
+ """ |
+ implicit block key : [ |
+ implicit flow key : value, |
+ ]"""); |
+ }); |
+ |
+ test('[Example 7.12]', () { |
+ expectYamlLoads("1st non-empty\n2nd non-empty 3rd non-empty", |
+ """ |
+ 1st non-empty |
+ |
+ 2nd non-empty |
+ \t3rd non-empty"""); |
+ }); |
+ }); |
+ |
+ group('7.4: Flow Collection Styles', () { |
+ test('[Example 7.13]', () { |
+ expectYamlLoads([ |
+ ['one', 'two'], |
+ ['three', 'four'] |
+ ], |
+ """ |
+ - [ one, two, ] |
+ - [three ,four]"""); |
+ }); |
+ |
+ test('[Example 7.14]', () { |
+ expectYamlLoads([ |
+ "double quoted", "single quoted", "plain text", ["nested"], |
+ {"single": "pair"} |
+ ], |
+ """ |
+ [ |
+ "double |
+ quoted", 'single |
+ quoted', |
+ plain |
+ text, [ nested ], |
+ single: pair, |
+ ]"""); |
+ }); |
+ |
+ test('[Example 7.15]', () { |
+ expectYamlLoads([ |
+ {"one": "two", "three": "four"}, |
+ {"five": "six", "seven": "eight"}, |
+ ], |
+ """ |
+ - { one : two , three: four , } |
+ - {five: six,seven : eight}"""); |
+ }); |
+ |
+ test('[Example 7.16]', () { |
+ var doc = deepEqualsMap({ |
+ "explicit": "entry", |
+ "implicit": "entry" |
+ }); |
+ doc[null] = null; |
+ expectYamlLoads(doc, |
+ """ |
+ { |
+ ? explicit: entry, |
+ implicit: entry, |
+ ? |
+ }"""); |
+ }); |
+ |
+ test('[Example 7.17]', () { |
+ var doc = deepEqualsMap({ |
+ "unquoted": "separate", |
+ "http://foo.com": null, |
+ "omitted value": null |
+ }); |
+ doc[null] = "omitted key"; |
+ expectYamlLoads(doc, |
+ ''' |
+ { |
+ unquoted : "separate", |
+ http://foo.com, |
+ omitted value:, |
+ : omitted key, |
+ }'''); |
+ }); |
+ |
+ test('[Example 7.18]', () { |
+ expectYamlLoads({ |
+ "adjacent": "value", |
+ "readable": "value", |
+ "empty": null |
+ }, |
+ ''' |
+ { |
+ "adjacent":value, |
+ "readable": value, |
+ "empty": |
+ }'''); |
+ }); |
+ |
+ test('[Example 7.19]', () { |
+ expectYamlLoads([{"foo": "bar"}], |
+ """ |
+ [ |
+ foo: bar |
+ ]"""); |
+ }); |
+ |
+ test('[Example 7.20]', () { |
+ expectYamlLoads([{"foo bar": "baz"}], |
+ """ |
+ [ |
+ ? foo |
+ bar : baz |
+ ]"""); |
+ }); |
+ |
+ test('[Example 7.21]', () { |
+ var el1 = deepEqualsMap(); |
+ el1[null] = "empty key entry"; |
+ |
+ var el2 = deepEqualsMap(); |
+ el2[{"JSON": "like"}] = "adjacent"; |
+ |
+ expectYamlLoads([[{"YAML": "separate"}], [el1], [el2]], |
+ """ |
+ - [ YAML : separate ] |
+ - [ : empty key entry ] |
+ - [ {JSON: like}:adjacent ]"""); |
+ }); |
+ |
+ // TODO(nweiz): enable this when we throw an error for long or multiline |
+ // keys. |
+ // test('[Example 7.22]', () { |
+ // expectYamlFails( |
+ // """ |
+ // [ foo |
+ // bar: invalid ]"""); |
+ // |
+ // var dotList = new List.filled(1024, ' '); |
+ // var dots = dotList.join(); |
+ // expectYamlFails('[ "foo...$dots...bar": invalid ]'); |
+ // }); |
+ }); |
+ |
+ group('7.5: Flow Nodes', () { |
+ test('[Example 7.23]', () { |
+ expectYamlLoads([["a", "b"], {"a": "b"}, "a", "b", "c"], |
+ """ |
+ - [ a, b ] |
+ - { a: b } |
+ - "a" |
+ - 'b' |
+ - c"""); |
+ }); |
+ |
+ test('[Example 7.24]', () { |
+ expectYamlLoads(["a", "b", "c", "c", ""], |
+ """ |
+ - !!str "a" |
+ - 'b' |
+ - &anchor "c" |
+ - *anchor |
+ - !!str"""); |
+ }); |
+ }); |
+ |
+ // Chapter 8: Block Styles |
+ group('8.1: Block Scalar Styles', () { |
+ test('[Example 8.1]', () { |
+ expectYamlLoads(["literal\n", " folded\n", "keep\n\n", " strip"], |
+ """ |
+ - | # Empty header |
+ literal |
+ - >1 # Indentation indicator |
+ folded |
+ - |+ # Chomping indicator |
+ keep |
+ |
+ - >1- # Both indicators |
+ strip"""); |
+ }); |
+ |
+ test('[Example 8.2]', () { |
+ // Note: in the spec, the fourth element in this array is listed as |
+ // "\t detected\n", not "\t\ndetected\n". However, I'm reasonably |
+ // confident that "\t\ndetected\n" is correct when parsed according to the |
+ // rest of the spec. |
+ expectYamlLoads([ |
+ "detected\n", |
+ "\n\n# detected\n", |
+ " explicit\n", |
+ "\t\ndetected\n" |
+ ], |
+ """ |
+ - | |
+ detected |
+ - > |
+ |
+ |
+ # detected |
+ - |1 |
+ explicit |
+ - > |
+ \t |
+ detected |
+ """); |
+ }); |
+ |
+ test('[Example 8.3]', () { |
+ expectYamlFails( |
+ """ |
+ - | |
+ |
+ text"""); |
+ |
+ expectYamlFails( |
+ """ |
+ - > |
+ text |
+ text"""); |
+ |
+ expectYamlFails( |
+ """ |
+ - |2 |
+ text"""); |
+ }); |
+ |
+ test('[Example 8.4]', () { |
+ expectYamlLoads({"strip": "text", "clip": "text\n", "keep": "text\n"}, |
+ """ |
+ strip: |- |
+ text |
+ clip: | |
+ text |
+ keep: |+ |
+ text |
+ """); |
+ }); |
+ |
+ test('[Example 8.5]', () { |
+ // This example in the spec only includes a single newline in the "keep" |
+ // value, but as far as I can tell that's not how it's supposed to be |
+ // parsed according to the rest of the spec. |
+ expectYamlLoads({ |
+ "strip": "# text", |
+ "clip": "# text\n", |
+ "keep": "# text\n\n" |
+ }, |
+ """ |
+ # Strip |
+ # Comments: |
+ strip: |- |
+ # text |
+ |
+ # Clip |
+ # comments: |
+ |
+ clip: | |
+ # text |
+ |
+ # Keep |
+ # comments: |
+ |
+ keep: |+ |
+ # text |
+ |
+ # Trail |
+ # comments. |
+ """); |
+ }); |
+ |
+ test('[Example 8.6]', () { |
+ expectYamlLoads({"strip": "", "clip": "", "keep": "\n"}, |
+ """ |
+ strip: >- |
+ |
+ clip: > |
+ |
+ keep: |+ |
+ |
+ """); |
+ }); |
+ |
+ test('[Example 8.7]', () { |
+ expectYamlLoads("literal\n\ttext\n", |
+ """ |
+ | |
+ literal |
+ \ttext |
+ """); |
+ }); |
+ |
+ test('[Example 8.8]', () { |
+ expectYamlLoads("\n\nliteral\n \n\ntext\n", |
+ """ |
+ | |
+ |
+ |
+ literal |
+ |
+ |
+ text |
+ |
+ # Comment"""); |
+ }); |
+ |
+ test('[Example 8.9]', () { |
+ expectYamlLoads("folded text\n", |
+ """ |
+ > |
+ folded |
+ text |
+ """); |
+ }); |
+ |
+ test('[Example 8.10]', () { |
+ expectYamlLoads( |
+ cleanUpLiteral(""" |
+ |
+ folded line |
+ next line |
+ * bullet |
+ |
+ * list |
+ * lines |
+ |
+ last line |
+ """), |
+ """ |
+ > |
+ |
+ folded |
+ line |
+ |
+ next |
+ line |
+ * bullet |
+ |
+ * list |
+ * lines |
+ |
+ last |
+ line |
+ |
+ # Comment"""); |
+ }); |
+ |
+ // Examples 8.11 through 8.13 are duplicates of 8.10. |
+ }); |
+ |
+ group('8.2: Block Collection Styles', () { |
+ test('[Example 8.14]', () { |
+ expectYamlLoads({"block sequence": ["one", {"two": "three"}]}, |
+ """ |
+ block sequence: |
+ - one |
+ - two : three"""); |
+ }); |
+ |
+ test('[Example 8.15]', () { |
+ expectYamlLoads([ |
+ null, "block node\n", ["one", "two"], {"one": "two"} |
+ ], |
+ """ |
+ - # Empty |
+ - | |
+ block node |
+ - - one # Compact |
+ - two # sequence |
+ - one: two # Compact mapping"""); |
+ }); |
+ |
+ test('[Example 8.16]', () { |
+ expectYamlLoads({"block mapping": {"key": "value"}}, |
+ """ |
+ block mapping: |
+ key: value"""); |
+ }); |
+ |
+ test('[Example 8.17]', () { |
+ expectYamlLoads({ |
+ "explicit key": null, |
+ "block key\n": ["one", "two"] |
+ }, |
+ """ |
+ ? explicit key # Empty value |
+ ? | |
+ block key |
+ : - one # Explicit compact |
+ - two # block value"""); |
+ }); |
+ |
+ test('[Example 8.18]', () { |
+ var doc = deepEqualsMap({ |
+ 'plain key': 'in-line value', |
+ "quoted key": ["entry"] |
+ }); |
+ doc[null] = null; |
+ expectYamlLoads(doc, |
+ ''' |
+ plain key: in-line value |
+ : # Both empty |
+ "quoted key": |
+ - entry'''); |
+ }); |
+ |
+ test('[Example 8.19]', () { |
+ var el = deepEqualsMap(); |
+ el[{'earth': 'blue'}] = {'moon': 'white'}; |
+ expectYamlLoads([{'sun': 'yellow'}, el], |
+ """ |
+ - sun: yellow |
+ - ? earth: blue |
+ : moon: white"""); |
+ }); |
+ |
+ test('[Example 8.20]', () { |
+ expectYamlLoads(["flow in block", "Block scalar\n", {"foo": "bar"}], |
+ ''' |
+ - |
+ "flow in block" |
+ - > |
+ Block scalar |
+ - !!map # Block collection |
+ foo : bar'''); |
+ }); |
+ |
+ test('[Example 8.21]', () { |
+ // The spec doesn't include a newline after "value" in the parsed map, but |
+ // the block scalar is clipped so it should be retained. |
+ expectYamlLoads({"literal": "value\n", "folded": "value"}, |
+ """ |
+ literal: |2 |
+ value |
+ folded: |
+ !!str |
+ >1 |
+ value"""); |
+ }); |
+ |
+ test('[Example 8.22]', () { |
+ expectYamlLoads({ |
+ "sequence": ["entry", ["nested"]], |
+ "mapping": {"foo": "bar"} |
+ }, |
+ """ |
+ sequence: !!seq |
+ - entry |
+ - !!seq |
+ - nested |
+ mapping: !!map |
+ foo: bar"""); |
+ }); |
+ }); |
+ |
+ // Chapter 9: YAML Character Stream |
+ group('9.1: Documents', () { |
+ // Example 9.1 tests the use of a BOM, which this implementation currently |
+ // doesn't plan to support. |
+ |
+ test('[Example 9.2]', () { |
+ expectYamlLoads("Document", |
+ """ |
+ %YAML 1.2 |
+ --- |
+ Document |
+ ... # Suffix"""); |
+ }); |
+ |
+ test('[Example 9.3]', () { |
+ // The spec example indicates that the comment after "%!PS-Adobe-2.0" |
+ // should be stripped, which would imply that that line is not part of the |
+ // literal defined by the "|". The rest of the spec is ambiguous on this |
+ // point; the allowable indentation for non-indented literal content is |
+ // not clearly explained. However, if both the "|" and the text were |
+ // indented the same amount, the text would be part of the literal, which |
+ // implies that the spec's parse of this document is incorrect. |
+ expectYamlStreamLoads( |
+ ["Bare document", "%!PS-Adobe-2.0 # Not the first line\n"], |
+ """ |
+ Bare |
+ document |
+ ... |
+ # No document |
+ ... |
+ | |
+ %!PS-Adobe-2.0 # Not the first line |
+ """); |
+ }); |
+ |
+ test('[Example 9.4]', () { |
+ expectYamlStreamLoads([{"matches %": 20}, null], |
+ """ |
+ --- |
+ { matches |
+ % : 20 } |
+ ... |
+ --- |
+ # Empty |
+ ..."""); |
+ }); |
+ |
+ test('[Example 9.5]', () { |
+ // The spec doesn't have a space between the second |
+ // "YAML" and "1.2", but this seems to be a typo. |
+ expectYamlStreamLoads(["%!PS-Adobe-2.0\n", null], |
+ """ |
+ %YAML 1.2 |
+ --- | |
+ %!PS-Adobe-2.0 |
+ ... |
+ %YAML 1.2 |
+ --- |
+ # Empty |
+ ..."""); |
+ }); |
+ |
+ test('[Example 9.6]', () { |
+ expectYamlStreamLoads(["Document", null, {"matches %": 20}], |
+ """ |
+ Document |
+ --- |
+ # Empty |
+ ... |
+ %YAML 1.2 |
+ --- |
+ matches %: 20"""); |
+ }); |
+ }); |
+ |
+ // Chapter 10: Recommended Schemas |
+ group('10.1: Failsafe Schema', () { |
+ test('[Example 10.1]', () { |
+ expectYamlLoads({ |
+ "Block style": { |
+ "Clark": "Evans", |
+ "Ingy": "döt Net", |
+ "Oren": "Ben-Kiki" |
+ }, |
+ "Flow style": { |
+ "Clark": "Evans", |
+ "Ingy": "döt Net", |
+ "Oren": "Ben-Kiki" |
+ } |
+ }, |
+ """ |
+ Block style: !!map |
+ Clark : Evans |
+ Ingy : döt Net |
+ Oren : Ben-Kiki |
+ |
+ Flow style: !!map { Clark: Evans, Ingy: döt Net, Oren: Ben-Kiki }"""); |
+ }); |
+ |
+ test('[Example 10.2]', () { |
+ expectYamlLoads({ |
+ "Block style": ["Clark Evans", "Ingy döt Net", "Oren Ben-Kiki"], |
+ "Flow style": ["Clark Evans", "Ingy döt Net", "Oren Ben-Kiki"] |
+ }, |
+ """ |
+ Block style: !!seq |
+ - Clark Evans |
+ - Ingy döt Net |
+ - Oren Ben-Kiki |
+ |
+ Flow style: !!seq [ Clark Evans, Ingy döt Net, Oren Ben-Kiki ]"""); |
+ }); |
+ |
+ test('[Example 10.3]', () { |
+ expectYamlLoads({ |
+ "Block style": "String: just a theory.", |
+ "Flow style": "String: just a theory." |
+ }, |
+ ''' |
+ Block style: !!str |- |
+ String: just a theory. |
+ |
+ Flow style: !!str "String: just a theory."'''); |
+ }); |
+ }); |
+ |
+ group('10.2: JSON Schema', () { |
+ // test('[Example 10.4]', () { |
+ // var doc = deepEqualsMap({"key with null value": null}); |
+ // doc[null] = "value for null key"; |
+ // expectYamlStreamLoads(doc, |
+ // """ |
+ // !!null null: value for null key |
+ // key with null value: !!null null"""); |
+ // }); |
+ |
+ // test('[Example 10.5]', () { |
+ // expectYamlStreamLoads({ |
+ // "YAML is a superset of JSON": true, |
+ // "Pluto is a planet": false |
+ // }, |
+ // """ |
+ // YAML is a superset of JSON: !!bool true |
+ // Pluto is a planet: !!bool false"""); |
+ // }); |
+ |
+ // test('[Example 10.6]', () { |
+ // expectYamlStreamLoads({ |
+ // "negative": -12, |
+ // "zero": 0, |
+ // "positive": 34 |
+ // }, |
+ // """ |
+ // negative: !!int -12 |
+ // zero: !!int 0 |
+ // positive: !!int 34"""); |
+ // }); |
+ |
+ // test('[Example 10.7]', () { |
+ // expectYamlStreamLoads({ |
+ // "negative": -1, |
+ // "zero": 0, |
+ // "positive": 23000, |
+ // "infinity": infinity, |
+ // "not a number": nan |
+ // }, |
+ // """ |
+ // negative: !!float -1 |
+ // zero: !!float 0 |
+ // positive: !!float 2.3e4 |
+ // infinity: !!float .inf |
+ // not a number: !!float .nan"""); |
+ // }); |
+ |
+ // test('[Example 10.8]', () { |
+ // expectYamlStreamLoads({ |
+ // "A null": null, |
+ // "Booleans": [true, false], |
+ // "Integers": [0, -0, 3, -19], |
+ // "Floats": [0, 0, 12000, -200000], |
+ // // Despite being invalid in the JSON schema, these values are valid in |
+ // // the core schema which this implementation supports. |
+ // "Invalid": [ true, null, 7, 0x3A, 12.3] |
+ // }, |
+ // """ |
+ // A null: null |
+ // Booleans: [ true, false ] |
+ // Integers: [ 0, -0, 3, -19 ] |
+ // Floats: [ 0., -0.0, 12e03, -2E+05 ] |
+ // Invalid: [ True, Null, 0o7, 0x3A, +12.3 ]"""); |
+ // }); |
+ }); |
+ |
+ group('10.3: Core Schema', () { |
+ test('[Example 10.9]', () { |
+ expectYamlLoads({ |
+ "A null": null, |
+ "Also a null": null, |
+ "Not a null": "", |
+ "Booleans": [true, true, false, false], |
+ "Integers": [0, 7, 0x3A, -19], |
+ "Floats": [0, 0, 0.5, 12000, -200000], |
+ "Also floats": [infinity, -infinity, infinity, nan] |
+ }, |
+ ''' |
+ A null: null |
+ Also a null: # Empty |
+ Not a null: "" |
+ Booleans: [ true, True, false, FALSE ] |
+ Integers: [ 0, 0o7, 0x3A, -19 ] |
+ Floats: [ 0., -0.0, .5, +12e03, -2E+05 ] |
+ Also floats: [ .inf, -.Inf, +.INF, .NAN ]'''); |
+ }); |
+ }); |
+} |