From df0e9dbe9772d7327481ec95ad4dd33a12c1d470 Mon Sep 17 00:00:00 2001 From: why Date: Fri, 3 Oct 2003 19:51:25 +0000 Subject: * ext/syck/rubyext.c: default keys handled. * ext/syck/syck.h: lowered default buffer size to 16k for increased performance. * test/yaml: checkin of basic unit tests. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4667 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/yaml/test_yaml.rb | 1155 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1155 insertions(+) create mode 100644 test/yaml/test_yaml.rb (limited to 'test/yaml/test_yaml.rb') diff --git a/test/yaml/test_yaml.rb b/test/yaml/test_yaml.rb new file mode 100644 index 0000000000..8baad11e5f --- /dev/null +++ b/test/yaml/test_yaml.rb @@ -0,0 +1,1155 @@ +# vim:sw=4:ts=4 +# $Id$ +# +require 'test/unit/testsuite' +require 'test/unit/testcase' +require 'yaml' + +class YAML_Unit_Tests < Test::Unit::TestCase + # + # Convert between YAML and the object to verify correct parsing and + # emitting + # + def assert_to_yaml( obj, yaml ) + assert_equal( obj, YAML::load( yaml ) ) + assert_equal( obj, YAML::parse( yaml ).transform ) + assert_equal( obj, YAML::load( obj.to_yaml ) ) + assert_equal( obj, YAML::parse( obj.to_yaml ).transform ) + assert_equal( obj, YAML::load( + obj.to_yaml( :UseVersion => true, :UseHeader => true, :SortKeys => true ) + ) ) + end + + # + # Test parser only + # + def assert_parse_only( obj, yaml ) + assert_equal( obj, YAML::load( yaml ) ) + assert_equal( obj, YAML::parse( yaml ).transform ) + end + + def assert_path_segments( path, segments ) + YAML::YPath.each_path( path ) { |choice| + assert_equal( choice.segments, segments.shift ) + } + assert_equal( segments.length, 0, "Some segments leftover: #{ segments.inspect }" ) + end + + # + # Make a time with the time zone + # + def mktime( year, mon, day, hour, min, sec, usec, zone = "Z" ) + usec = usec.to_s.to_f * 1000000 + val = Time::utc( year.to_i, mon.to_i, day.to_i, hour.to_i, min.to_i, sec.to_i, usec ) + if zone != "Z" + hour = zone[0,3].to_i * 3600 + min = zone[3,2].to_i * 60 + ofs = (hour + min) + val = Time.at( val.to_f - ofs ) + end + return val + end + + # + # Tests modified from 00basic.t in YAML.pm + # + def test_basic_map + # Simple map + assert_parse_only( + { 'one' => 'foo', 'three' => 'baz', 'two' => 'bar' }, < 'simple string', 2 => 42, 3 => '1 Single Quoted String', + 4 => 'YAML\'s Double "Quoted" String', 5 => "A block\n with several\n lines.\n", + 6 => "A \"chomped\" block", 7 => "A folded\n string\n" }, < + A + folded + string +EOY + ) + end + + # + # Test the specification examples + # - Many examples have been changes because of whitespace problems that + # caused the two to be inequivalent, or keys to be sorted wrong + # + + def test_spec_simple_implicit_sequence + # Simple implicit sequence + assert_to_yaml( + [ 'Mark McGwire', 'Sammy Sosa', 'Ken Griffey' ], < 65, 'avg' => 0.278, 'rbi' => 147 }, < + [ 'Boston Red Sox', 'Detroit Tigers', 'New York Yankees' ], + 'national' => + [ 'New York Mets', 'Chicago Cubs', 'Atlanta Braves' ] }, < 'Mark McGwire', 'hr' => 65, 'avg' => 0.278}, + {'name' => 'Sammy Sosa', 'hr' => 63, 'avg' => 0.288} + ], < + { 'hr' => 65, 'avg' => 0.278 }, + 'Sammy Sosa' => + { 'hr' => 63, 'avg' => 0.288 } + }, < [ 'Mark McGwire', 'Sammy Sosa' ], + 'rbi' => [ 'Sammy Sosa', 'Ken Griffey' ] }, < + [ 'Mark McGwire', 'Sammy Sosa' ], + 'rbi' => + [ 'Sammy Sosa', 'Ken Griffey' ] }, <"EDI", "departure"=>"LAX", "fareref"=>"DOGMA", "currency"=>"GBP"}, {"arrival"=>"MEL", "departure"=>"SYD", "fareref"=>"MADF", "currency"=>"AUD"}, {"arrival"=>"MCO", "departure"=>"JFK", "fareref"=>"DFSF", "currency"=>"USD"}], <["fareref", "currency", "departure", "arrival"], "FARES"=>[{"arrival"=>"EDI", "departure"=>"LAX", "fareref"=>"DOGMA", "currency"=>"GBP"}, {"arrival"=>"MEL", "departure"=>"SYD", "fareref"=>"MADF", "currency"=>"AUD"}, {"arrival"=>"MCO", "departure"=>"JFK", "fareref"=>"DFSF", "currency"=>"USD"}]}, < [ Date.new( 2001, 7, 23 ) ], + [ 'New York Yankees', 'Atlanta Braves' ] => [ Date.new( 2001, 7, 2 ), Date.new( 2001, 8, 12 ), Date.new( 2001, 8, 14 ) ] }, < + [ Date.new( 2001, 7, 2 ), Date.new( 2001, 8, 12 ), + Date.new( 2001, 8, 14 ) ], + [ 'Detroit Tigers', 'Chicago Cubs' ] => + [ Date.new( 2001, 7, 23 ) ] + }, < 34843, 'date' => Date.new( 2001, 1, 23 ), + 'bill-to' => 'Chris Dumars', 'product' => + [ { 'item' => 'Super Hoop', 'quantity' => 1 }, + { 'item' => 'Basketball', 'quantity' => 4 }, + { 'item' => 'Big Shoes', 'quantity' => 1 } ] }, < nil }, + [ { 'five' => [ 'six' ] } ], + [ 'seven' ] + ], + [ 'eight', 'nine' ] +], < + Mark McGwire's + year was crippled + by a knee injury. +EOY + ) + end + + def test_spec_preserve_indent + # Preserve indented spaces + assert_parse_only( + "Sammy Sosa completed another fine season with great stats.\n\n 63 Home Runs\n 0.288 Batting Average\n\nWhat a year!\n", < + Sammy Sosa completed another + fine season with great stats. + + 63 Home Runs + 0.288 Batting Average + + What a year! +EOY + ) + end + + def test_spec_indentation_determines_scope + assert_parse_only( + { 'name' => 'Mark McGwire', 'accomplishment' => "Mark set a major league home run record in 1998.\n", + 'stats' => "65 Home Runs\n0.278 Batting Average\n" }, < + Mark set a major league + home run record in 1998. +stats: | + 65 Home Runs + 0.278 Batting Average +EOY + ) + end + + def test_spec_multiline_scalars + # Multiline flow scalars + assert_parse_only( + { 'plain' => 'This unquoted scalar spans many lines.', + 'quoted' => "So does this quoted scalar.\n" }, < 12345, 'decimal' => 12345, 'octal' => '014'.oct, 'hexadecimal' => '0xC'.hex }, < 1230.15, 'exponential' => 1230.15, 'fixed' => 1230.15, + 'negative infinity' => -1.0/0.0 }, < nil, true => true, false => false, 'string' => '12345' }, < 'Chris', 'family' => 'Dumars', 'address' => + { 'lines' => "458 Walkman Dr.\nSuite #292\n", 'city' => 'Royal Oak', + 'state' => 'MI', 'postal' => 48046 } } + assert_parse_only( + { 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ), + 'bill-to' => id001, 'ship-to' => id001, 'product' => + [ { 'sku' => 'BL394D', 'quantity' => 4, + 'description' => 'Basketball', 'price' => 450.00 }, + { 'sku' => 'BL4438H', 'quantity' => 1, + 'description' => 'Super Hoop', 'price' => 2392.00 } ], + 'tax' => 251.42, 'total' => 4443.52, + 'comments' => "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.\n" }, < + Late afternoon is best. + Backup contact is Nancy + Billsmer @ 338-4338. +EOY + ) + end + + def test_spec_log_file + doc_ct = 0 + YAML::load_documents( < + This is an error message + for the log file +--- +Time: 2001-11-23 15:02:31 -05:00 +User: ed +Warning: > + A slightly different error + message. +--- +Date: 2001-11-23 15:03:17 -05:00 +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 +EOY + ) { |doc| + case doc_ct + when 0 + assert_equal( doc, { 'Time' => mktime( 2001, 11, 23, 15, 01, 42, 00, "-05:00" ), + 'User' => 'ed', 'Warning' => "This is an error message for the log file\n" } ) + when 1 + assert_equal( doc, { 'Time' => mktime( 2001, 11, 23, 15, 02, 31, 00, "-05:00" ), + 'User' => 'ed', 'Warning' => "A slightly different error message.\n" } ) + when 2 + assert_equal( doc, { 'Date' => mktime( 2001, 11, 23, 15, 03, 17, 00, "-05:00" ), + 'User' => 'ed', 'Fatal' => "Unknown variable \"bar\"\n", + 'Stack' => [ + { 'file' => 'TopClass.py', 'line' => 23, 'code' => "x = MoreObject(\"345\\n\")\n" }, + { 'file' => 'MoreClass.py', 'line' => 58, 'code' => "foo = bar" } ] } ) + end + doc_ct += 1 + } + assert_equal( doc_ct, 3 ) + end + + def test_spec_root_fold + y = YAML::load( < +This YAML stream contains a single text value. +The next stream is a log file - a sequence of +log entries. Adding an entry to the log is a +simple matter of appending it at the end. +EOY + ) + assert_equal( y, "This YAML stream contains a single text value. The next stream is a log file - a sequence of log entries. Adding an entry to the log is a simple matter of appending it at the end.\n" ) + end + + def test_spec_root_mapping + y = YAML::load( < 34843, 'date' => Date.new( 2001, 1, 23 ), 'total' => 4443.52 } ) + end + + def test_spec_oneline_docs + doc_ct = 0 + YAML::load_documents( < { "customers"=> [ { "given"=>"Chris", "type"=>"domain customer", "family"=>"Dumars" } ], "type"=>"domain invoice" } }, <"contains three lines of text.\nThe third one starts with a\n# character. This isn't a comment.\n"}, < 12, 'also int' => 12, 'string' => '12' }, < 8, 'color' => 'black' } ) + when 1 + assert_equal( doc['bearing'].type_id, 'x-private:ball' ) + assert_equal( doc['bearing'].transform.value, { 'material' => 'steel' } ) + end + doc_ct += 1 + } + assert_equal( doc_ct, 2 ) + end + + def test_spec_url_escaping + YAML.add_domain_type( "domain.tld,2002", "type0" ) { |type, val| + "ONE: #{val}" + } + YAML.add_domain_type( "domain.tld,2002", "type%30" ) { |type, val| + "TWO: #{val}" + } + assert_parse_only( + { 'same' => [ 'ONE: value', 'ONE: value' ], 'different' => [ 'TWO: value' ] }, < 'This scalar has an anchor.', 'override' => a001, 'alias' => a001 }, < + The alias node below is a + repeated use of this value. +alias : *A001 +EOY + ) + end + + def test_spec_explicit_families + YAML.add_domain_type( "somewhere.com,2002", /^type$/ ) { |type, val| + "SOMEWHERE: #{val}" + } + assert_parse_only( + { 'not-date' => '2002-04-28', 'picture' => "GIF89a\f\000\f\000\204\000\000\377\377\367\365\365\356\351\351\345fff\000\000\000\347\347\347^^^\363\363\355\216\216\216\340\340\340\237\237\237\223\223\223\247\247\247\236\236\236i^\020' \202\n\001\000;", 'hmm' => "SOMEWHERE: family above is short for\nhttp://somewhere.com/type\n" }, <7, "center"=>{"x"=>73, "y"=>129}, "TYPE"=>"Shape: graph/circle"}, {"finish"=>{"x"=>89, "y"=>102}, "TYPE"=>"Shape: graph/line", "start"=>{"x"=>73, "y"=>129}}, {"TYPE"=>"Shape: graph/text", "value"=>"Pretty vector drawing.", "start"=>{"x"=>73, "y"=>129}, "color"=>16772795}, "Shape Container"]], < [], 'in-line' => [ 'one', 'two', 'three', 'four', 'five' ], + 'nested' => [ 'First item in top sequence', [ 'Subordinate sequence entry' ], + "A multi-line sequence entry\n", 'Sixth item in top sequence' ] }, < + A multi-line + sequence entry + - Sixth item in top sequence +EOY + ) + end + + def test_spec_builtin_map + # Assortment of mappings + assert_parse_only( + { 'empty' => {}, 'in-line' => { 'one' => 1, 'two' => 2 }, + 'spanning' => { 'one' => 1, 'two' => 2 }, + 'nested' => { 'first' => 'First entry', 'second' => + { 'key' => 'Subordinate mapping' }, 'third' => + [ 'Subordinate sequence', {}, 'Previous mapping is empty.', + { 'A key' => 'value pair in a sequence.', 'A second' => 'key:value pair.' }, + 'The previous entry is equal to the following one.', + { 'A key' => 'value pair in a sequence.', 'A second' => 'key:value pair.' } ], + 12.0 => 'This key is a float.', "?\n" => 'This key had to be protected.', + "\a" => 'This key had to be escaped.', + "This is a multi-line folded key\n" => "Whose value is also multi-line.\n", + [ 'This key', 'is a sequence' ] => [ 'With a sequence value.' ] } }, < + ? + : This key had to be protected. + "\\a" : This key had to be escaped. + ? > + This is a + multi-line + folded key + : > + Whose value is + also multi-line. + ? + - This key + - is a sequence + : + - With a sequence value. +# The following parses correctly, +# but Ruby 1.6.* fails the comparison! +# ? +# This: key +# is a: mapping +# : +# with a: mapping value. +EOY + ) + end + + def test_spec_builtin_literal_blocks + # Assortment of literal scalar blocks + assert_parse_only( + {"both are equal to"=>" This has no newline.", "is equal to"=>"The \\ ' \" characters may be\nfreely used. Leading white\n space is significant.\n\nLine breaks are significant.\nThus this value contains one\nempty line and ends with a\nsingle line break, but does\nnot start with one.\n", "also written as"=>" This has no newline.", "indented and chomped"=>" This has no newline.", "empty"=>"", "literal"=>"The \\ ' \" characters may be\nfreely used. Leading white\n space is significant.\n\nLine breaks are significant.\nThus this value contains one\nempty line and ends with a\nsingle line break, but does\nnot start with one.\n"}, < str1, 'same as "clipped" above' => str1, + 'stripped' => str2, 'same as "stripped" above' => str2, + 'kept' => str3, 'same as "kept" above' => str3 }, <"a single quote ' must be escaped.", "second"=>"! : \\ etc. can be used freely.", "is same as"=>"this contains six spaces\nand one line break", "empty"=>"", "span"=>"this contains six spaces\nand one line break"}, <"this contains four spaces", "third"=>"a \" or a \\ must be escaped.", "second"=>"! : etc. can be used freely.", "empty"=>"", "fourth"=>"this value ends with an LF.\n", "span"=>"this contains four spaces"}, < mktime( 2001, 12, 14, 21, 59, 43, ".10", "-05:00" ), + "canonical" => mktime( 2001, 12, 15, 2, 59, 43, ".10" ), + "date (noon UTC)" => Date.new( 2002, 12, 14), + "valid iso8601" => mktime( 2001, 12, 14, 21, 59, 43, ".10", "-05:00" ) }, < arrow_gif, 'base64' => arrow_gif, + 'description' => "The binary value above is a tiny arrow encoded as a gif image.\n" }, < /George McFly/i }, < 2, :UseVersion => 0 ) + y.add( + { 'hi' => 'hello', 'map' => + { 'good' => 'two' }, + 'time' => Time.now, + 'try' => /^po(.*)$/, + 'bye' => 'goodbye' + } + ) + y.add( { 'po' => 'nil', 'oper' => 90 } ) + y.add( { 'hi' => 'wow!', 'bye' => 'wow!' } ) + y.add( { [ 'Red Socks', 'Boston' ] => [ 'One', 'Two', 'Three' ] } ) + y.add( [ true, false, false ] ) + end + + # + # Test YPath choices parsing + # + def test_ypath_parsing + assert_path_segments( "/*/((one|three)/name|place)|//place", + [ ["*", "one", "name"], + ["*", "three", "name"], + ["*", "place"], + ["/", "place"] ] + ) + end + + # + # Tests from Tanaka Akira on [ruby-core] + # + def test_akira + + # Commas in plain scalars [ruby-core:1066] + assert_to_yaml( + {"A"=>"A,","B"=>"B"}, <2, "2"=>3}, <"b"}] * 2, <"b", "c"=>"d"} } + # YAML::load( a.to_yaml ) + + end + + # + # Circular references + # + def test_circular_references + a = []; a[0] = a; a[1] = a + inspect_str = "[[...], [...]]" + assert_equal( inspect_str, YAML::load( a.to_yaml ).inspect ) + end +end + +if $0 == __FILE__ + suite = Test::Unit::TestSuite.new('YAML') + ObjectSpace.each_object(Class) do |klass| + suite << klass.suite if (Test::Unit::TestCase > klass) + end + require 'test/unit/ui/console/testrunner' + Test::Unit::UI::Console::TestRunner.run(suite).passed? +end -- cgit v1.2.3