require "spec" require "yaml" require "spec/helpers/string" private def assert_built(expected, expect_document_end = false, *, file = __FILE__, line = __LINE__, &) if expect_document_end expected = append_stream_end_indicator(expected) end assert_prints YAML.build { |yaml| with yaml yield yaml }, expected, file: file, line: line end private def append_stream_end_indicator(yaml) # libyaml 0.2.1 removed the erroneously written document end marker (`...`) after some scalars in root context (see https://github.com/yaml/libyaml/pull/18). # Earlier libyaml releases still write the document end marker and this is hard to fix on Crystal's side. # So we just ignore it and adopt the specs accordingly to coincide with the used libyaml version. if YAML.libyaml_version < SemanticVersion.new(0, 2, 1) yaml + "...\n" else yaml end end private def build_stream(&) String.build do |io| YAML::Builder.build(io) do |yaml| yaml.stream do yield yaml end end end end describe YAML::Builder do describe "#document" do describe "implicit_start_indicator" do it "explicit" do build_stream do |yaml| yaml.document(implicit_start_indicator: false) do yaml.scalar(1) end end.should eq append_stream_end_indicator("--- 1\n") build_stream do |yaml| yaml.document(implicit_start_indicator: false) do yaml.scalar(1) end yaml.document(implicit_start_indicator: false) do yaml.scalar(2) end end.should eq append_stream_end_indicator("--- 1\n--- 2\n") end it "implicit" do build_stream do |yaml| yaml.document(implicit_start_indicator: true) do yaml.scalar(1) end end.should eq append_stream_end_indicator("1\n") build_stream do |yaml| yaml.document(implicit_start_indicator: true) do yaml.scalar(1) end yaml.document(implicit_start_indicator: true) do yaml.scalar(2) end end.should eq append_stream_end_indicator("1\n--- 2\n") end end end it "writes scalar" do assert_built("--- 1\n", expect_document_end: true) do scalar(1) end end it "writes alias" do assert_built("--- *key\n") do itself.alias "key" end end it "writes scalar with style" do assert_built(%(--- "1"\n)) do scalar(1, style: YAML::ScalarStyle::DOUBLE_QUOTED) end end it "writes scalar with tag" do assert_built(%(--- !foo 1\n), expect_document_end: true) do scalar(1, tag: "!foo") end end it "writes scalar with anchor" do assert_built(%(--- &foo 1\n), expect_document_end: true) do scalar(1, anchor: "foo") end end it "writes sequence" do assert_built("---\n- 1\n- 2\n- 3\n") do sequence do scalar(1) scalar(2) scalar(3) end end end it "writes sequence with tag" do assert_built("--- !foo\n- 1\n- 2\n- 3\n") do sequence(tag: "!foo") do scalar(1) scalar(2) scalar(3) end end end it "writes sequence with anchor" do assert_built("--- &foo\n- 1\n- 2\n- 3\n") do sequence(anchor: "foo") do scalar(1) scalar(2) scalar(3) end end end it "writes sequence with style" do assert_built("--- [1, 2, 3]\n") do sequence(style: YAML::SequenceStyle::FLOW) do scalar(1) scalar(2) scalar(3) end end end it "writes mapping" do assert_built("---\nfoo: 1\nbar: 2\n") do mapping do scalar("foo") scalar(1) scalar("bar") scalar(2) end end end it "writes mapping with tag" do assert_built("--- !foo\nfoo: 1\nbar: 2\n") do mapping(tag: "!foo") do scalar("foo") scalar(1) scalar("bar") scalar(2) end end end it "writes mapping with anchor" do assert_built("--- &foo\nfoo: 1\nbar: 2\n") do mapping(anchor: "foo") do scalar("foo") scalar(1) scalar("bar") scalar(2) end end end it "writes mapping with alias" do assert_built("---\nfoo: *bar\n") do mapping do scalar "foo" itself.alias "bar" end end end it "writes mapping with merge" do assert_built("---\n<<: *key\n") do mapping do merge "key" end end end it "writes mapping with style" do assert_built("--- {foo: 1, bar: 2}\n") do mapping(style: YAML::MappingStyle::FLOW) do scalar("foo") scalar(1) scalar("bar") scalar(2) end end end it "errors on max nesting (sequence)" do io = IO::Memory.new builder = YAML::Builder.new(io) builder.max_nesting = 3 builder.start_stream builder.start_document 3.times do builder.start_sequence end expect_raises(YAML::Error, "Nesting of 4 is too deep") do builder.start_sequence end end it "errors on max nesting (mapping)" do io = IO::Memory.new builder = YAML::Builder.new(io) builder.max_nesting = 3 builder.start_stream builder.start_document 3.times do builder.start_mapping end expect_raises(YAML::Error, "Nesting of 4 is too deep") do builder.start_mapping end end it ".build (with block)" do String.build do |io| YAML::Builder.build(io) do |builder| builder.stream do builder.document do builder.scalar(1) end end end end.should eq 1.to_yaml end it "errors on invalid state" do String.build do |io| YAML::Builder.build(io) do |builder| expect_raises YAML::Error, "Error emitting document_end: expected STREAM-START" do builder.end_document end end end end end