# -*- tcl -*- # yaml.test: tests for the yaml library. # # Copyright (c) 2008 by KATO Kanryu # All rights reserved. # if {[lsearch [namespace children] ::tcltest] == -1} { # single test set selfrun 1 package require tcltest namespace import ::tcltest::* puts [source huddle.tcl] puts [source yaml.tcl] } else { # all.tcl source [file join \ [file dirname [file dirname [file join [pwd] [info script]]]] \ devtools testutilities.tcl] testsNeedTcl 8.3 testsNeedTcltest 1.0 if {$::tcl_version < 8.5} { if {[catch {package require dict}]} { puts " Aborting the tests found in \"[file tail [info script]]\"" puts " Requiring dict package, not found." return } } testing { useLocal huddle.tcl huddle useLocal yaml.tcl yaml } } proc dictsort2 {dict {pattern d}} { set cur [lindex $pattern 0] set subs [lrange $pattern 1 end] foreach {tag sw} $cur break set out {} if {$sw ne ""} {array set msubs $sw} if {$tag eq "l"} { ; # list set i 0 foreach {node} $dict { set subs1 $subs if {$sw ne "" && [info exists msubs($i)]} { set subs1 $msubs($i) } if {$subs1 ne ""} { set node [dictsort2 $node $subs1] } lappend out $node incr i } return $out } if {$tag eq "d"} { ; # dict array set map $dict foreach key [lsort [array names map]] { set node $map($key) set subs1 $subs if {$sw ne "" && [info exists msubs($key)]} { set subs1 $msubs($key) } if {$subs1 ne ""} { set node [dictsort2 $node $subs1] } lappend out $key $node } return $out } error } # ------------ # error ..... test yaml-1.1 "error" -body { set error1 { --- - [name , \{hr: avg \[\hr: avg\} \] ] } set code [catch {yaml::yaml2dict $error1} msg] concat $code $msg } -result [concat 1 line(3): $yaml::errors(MAPEND_NOT_IN_MAP)] test yaml-1.2 "error" -body { set error2 { --- - [name , \[hr: avg \{\hr: avg\] \} ] } set code [catch {yaml::yaml2dict $error2} msg] concat $code $msg } -result [concat 1 line(3): $yaml::errors(SEQEND_NOT_IN_SEQ)] test yaml-1.3 "error" -body { set error3 { --- - Clark - @Brian } set code [catch {yaml::yaml2dict $error3} msg] concat $code $msg } -result [concat 1 line(4): $yaml::errors(AT_IN_PLAIN)] test yaml-1.4 "error" -body { set error4 { --- - Clark - `Brian } set code [catch {yaml::yaml2dict $error4} msg] concat $code $msg } -result [concat 1 line(4): $yaml::errors(BT_IN_PLAIN)] test yaml-1.5 "error" -body { set error5 { --- - Clark - Brian } set code [catch {yaml::yaml2dict $error5} msg] concat $code $msg } -result [concat 1 line(4): $yaml::errors(TAB_IN_PLAIN)] test yaml-1.6 "error" -body { set error6 { --- - *a - Brian - @a Geoge } set code [catch {yaml::yaml2dict $error6} msg] concat $code $msg } -result [concat 1 line(4): $yaml::errors(ANCHOR_NOT_FOUND)] test yaml-1.7 "error" -body { set error7 { --- - "Clark - Brian } set code [catch {yaml::yaml2dict $error7} msg] concat $code $msg } -result [concat 1 line(3): $yaml::errors(MALFORM_D_QUOTE)] test yaml-1.8 "error" -body { set error8 { --- - 'Clark - Brian } set code [catch {yaml::yaml2dict $error8} msg] concat $code $msg } -result [concat 1 line(3): $yaml::errors(MALFORM_S_QUOTE)] test yaml-1.9 "error" -body { set error9 { --- - !!invalidtag Clark - Brian } set code [catch {yaml::yaml2dict $error9} msg] concat $code $msg } -result [concat 1 {line(4): The "!!invalidtag" handle wasn't declared.}] test yaml-1.10 "error" -body { set error10 { --- - Clark << - Brian } set code [catch {yaml::yaml2dict $error10} msg] concat $code $msg } -result [concat 1 line(5): $yaml::errors(INVALID_MERGE_KEY)] # ----------- # flow ..... test yaml-2.1 "flow sequence" -body { set inline_seq_seqs { --- - [name , hr, avg ] - [Mark McGwire, 65, 0.278] - [Sammy Sosa , 63, 0.288] ... - [Sammy Sosa2 , 64, 0.388] } yaml::yaml2dict $inline_seq_seqs } -result {{name hr avg} {{Mark McGwire} 65 0.278} {{Sammy Sosa} 63 0.288}} test yaml-2.2 "flow mappings" -body { set inline_map_maps { --- Mark McGwire: {hr: 65, avg: 0.278} Sammy Sosa: { hr: 63, avg: 0.288} } dictsort2 [yaml::yaml2dict $inline_map_maps] {d d} } -result [dictsort2 {{Mark McGwire} {hr 65 avg 0.278} {Sammy Sosa} {hr 63 avg 0.288}} {d d}] test yaml-2.3 "flow mappings" -body { set inline_map_maps { --- ? Mark McGwire: {? hr: 65, ? avg: 0.278} ? Sammy Sosa : {? hr: 63, ? avg: 0.288} } dictsort2 [yaml::yaml2dict $inline_map_maps] {d d} } -result [dictsort2 {{Mark McGwire} {hr 65 avg 0.278} {Sammy Sosa} {hr 63 avg 0.288}} {d d}] # ------------------ # block nodes ..... test yaml-3.2 "Literal Block Scalar" -body { set literal { --- clipped: | # comment This has one newline. # comment same as "clipped" above: "This has one newline.\n" # comment stripped: |- # comment This has no newline. same as "stripped" above: "This has no newline." # comment kept: |+ This has four newlines. same as "kept" above: "This has four newlines.\n\n\n\n" } dictsort2 [yaml::yaml2dict $literal] } -result [dictsort2 {clipped {This has one newline. } {same as "clipped" above} {This has one newline. } stripped {This has no newline.} {same as "stripped" above} {This has no newline.} kept {This has four newlines. } {same as "kept" above} {This has four newlines. }}] test yaml-3.3 "Folding Block Scalar" -body { set folding { --- clipped: > This has one newline. same as "clipped" above: "This has one newline.\n" stripped: >- This has no newline. same as "stripped" above: "This has no newline." kept: >+ This has no newline. same as "kept" above: "This has four newlines.\n\n\n\n"} dictsort2 [yaml::yaml2dict $folding] } -result [dictsort2 {clipped {This has one newline. } {same as "clipped" above} {This has one newline. } stripped {This has no newline.} {same as "stripped" above} {This has no newline.} kept {This has no newline. } {same as "kept" above} {This has four newlines. }}] test yaml-3.4 "Folded Block as a Mapping Value" -body { set foldedmap { --- quote: > Mark McGwire's year was crippled by a knee injury. source: espn } yaml::yaml2dict $foldedmap } -result [dict create quote {Mark McGwire's year was crippled by a knee injury. } source espn] # ----------------------- # Anchor - Aliaces ..... test yaml-4.1 "Alias Node" -body { set alias { --- - &showell Steve - Clark - Brian - Oren - *showell } yaml::yaml2dict $alias } -result {Steve Clark Brian Oren Steve} test yaml-4.2 "Alias Node" -body { set alias2 { --- - &hello Meat: pork Starch: potato - banana - *hello } yaml::yaml2dict $alias2 } -result [list [dict create Meat pork Starch potato] banana [dict create Meat pork Starch potato]] test yaml-4.3 "Flow Alias Node" -body { set alias3 { --- - &hello { Meat: &meat pork, Starch: potato } - banana - *hello - &bye [ The last man, children, *meat ] - habana - *bye } dictsort2 [yaml::yaml2dict $alias3] {{l {0 d 2 d}}} } -result [dictsort2 {{Meat pork Starch potato} banana {Meat pork Starch potato} {{The last man} children pork} habana {{The last man} children pork}} \ {{l {0 d 2 d}}} ] # ----------------------- # Plane Characters ..... test yaml-5.1 "Plane Characters" -body { set plane_characters { --- # Outside flow collection: - ::std::vector - Up, up and away! - -123 # Inside flow collection: - [ ::std::vector, "Up, up and away!", -123 ] } yaml::yaml2dict $plane_characters } -result {::std::vector {Up, up and away!} -123 {::std::vector {Up, up and away!} -123}} test yaml-5.2 "boolean" -body { set boolean { --- india: pork : yes beef : n oil : off polytheism : true arabia: pork : no beef : y oil : on polytheism : false } dictsort2 [yaml::yaml2dict $boolean] {d d} } -result [dictsort2 {india {pork 1 beef 0 oil 0 polytheism 1} arabia {pork 0 beef 1 oil 1 polytheism 0}} {d d}] if {$::tcl_version < 8.5} { test yaml-5.3 "Timestamps" -body { set timestamps { - 2001-12-15T02:59:43.1Z - 2001-12-14t21:59:43.10-05:00 - 2001-12-14 21:59:43.10 -5 - 2001-12-15 2:59:43.10 - 2002-12-14 } yaml::yaml2dict $timestamps } -result [list \ [clock scan "2001-12-15 02:59:43" -gmt 1] \ [clock scan "+5 hours" -base [clock scan "2001-12-14 21:59:43" -gmt 1]] \ [clock scan "+5 hours" -base [clock scan "2001-12-14 21:59:43" -gmt 1]] \ [clock scan "2001-12-15 02:59:43"] \ [clock scan "2002-12-14"] ] } else { test yaml-5.3 "Timestamps" -body { set timestamps { - 2001-12-15T02:59:43.1Z - 2001-12-14t21:59:43.10-05:00 - 2001-12-14 21:59:43.10 -5 - 2001-12-15 2:59:43.10 - 2002-12-14 } yaml::yaml2dict $timestamps } -result [list \ [clock scan "2001-12-15 02:59:43 Z" -format {%Y-%m-%d %k:%M:%S %Z}] \ [clock scan "2001-12-14 21:59:43 -05:00" -format {%Y-%m-%d %k:%M:%S %Z}] \ [clock scan "2001-12-14 21:59:43 -05:00" -format {%Y-%m-%d %k:%M:%S %Z}] \ [clock scan "2001-12-15 02:59:43" -format {%Y-%m-%d %k:%M:%S}] \ [clock scan "2002-12-14" -format {%Y-%m-%d}] ] } # {1008385183 1008385183 1008385183 1008352783 1039791600} <- JST test yaml-5.4 "integer" -body { set integers { - 1 - 1000 - 100,000,000 } yaml::yaml2dict $integers } -result {1 1000 100000000} # ----------- # block ..... test yaml-6.1 "block sequences" -body { set sequences { --- - - Mark McGwire^--- - Sammy Sosa - - Sammy Sosa - Ken Griffey } yaml::yaml2dict $sequences } -result {{{Mark McGwire^---} {Sammy Sosa}} {{Sammy Sosa} {Ken Griffey}}} test yaml-6.2 "block mapping" -body { set mappings { --- bill-to: given : Chris family : Dumars hello-to: given : Arnold Berry family : Son } yaml::yaml2dict $mappings } -result [dict create bill-to [dict create given Chris family Dumars] hello-to [dict create given {Arnold Berry} family Son]] test yaml-6.3 "block mapping, sequence" -body { set map_seqs { --- hr: # 1998 hr ranking - Mark McGwire - Sammy Sosa rbi: # 1998 rbi ranking - Sammy Sosa - Ken Griffey } yaml::yaml2dict $map_seqs } -result [dict create hr {{Mark McGwire} {Sammy Sosa}} rbi {{Sammy Sosa} {Ken Griffey}}] test yaml-6.4 "block sequence, mapping" -body { set seq_maps { --- - name: Mark McGwire hr: 65 avg: 0.278 - name: Sammy Sosa hr: 63 avg: 0.288 } yaml::yaml2dict $seq_maps } -result [list [dict create name {Mark McGwire} hr 65 avg 0.278] [dict create name {Sammy Sosa} hr 63 avg 0.288]] test yaml-6.5 "block mapping, noheader" -body { set maps {bar: fruit: apple name: steve sport: baseball } dictsort2 [yaml::yaml2dict $maps] {d d} } -result [dictsort2 {bar {sport baseball name steve fruit apple}} {d d}] # -------------- # options ..... test yaml-7.1 "load from file" -body { set data [yaml::yaml2dict -file [file join [file dirname [info script]] CHANGES]] dict get $data title } -result {YAML parser for Tcl.} test yaml-7.2 "load from file" -body { yaml::setOptions -file set data [yaml::yaml2dict [file join [file dirname [info script]] CHANGES]] yaml::setOptions -stream dict get $data title } -result {YAML parser for Tcl.} # ----------------- # flow nodes ..... test yaml-8.1 "double quote" -body { set dquote { - "1st non-empty, 2nd non-empty, 3rd non-empty" } yaml::yaml2dict $dquote } -result {{1st non-empty, 2nd non-empty, 3rd non-empty}} test yaml-8.2 "single quote" -body { set squote { - '1st non-empty, 2nd ''non-empty'', 3rd non-empty' } yaml::yaml2dict $squote } -result {{1st non-empty, 2nd 'non-empty', 3rd non-empty}} package require base64 test yaml-9.1 "explicit_tags binary" -body { set explicit_tags { --- not-date: !!str 2002-04-28 picture: !!binary | R0lGODlhDAAMAIQAAP//9/X 17unp5WZmZgAAAOfn515eXv Pz7Y6OjuDg4J+fn5OTk6enp 56enmleECcgggoBADs= } yaml::yaml2dict $explicit_tags } -result [dict create not-date 2002-04-28 picture [::base64::decode { R0lGODlhDAAMAIQAAP//9/X 17unp5WZmZgAAAOfn515eXv Pz7Y6OjuDg4J+fn5OTk6enp 56enmleECcgggoBADs= }]] test yaml-9.2 "explicit_tags(inline)" -body { set explicit_tags { --- {not-date: !!str 2002-04-28, picture: !!binary "R0lGODlhDAAMAIQAAP//9/X 17unp5WZmZgAAAOfn515eXv Pz7Y6OjuDg4J+fn5OTk6enp 56enmleECcgggoBADs=" } } dictsort2 [yaml::yaml2dict $explicit_tags] } -result [dictsort2 [list not-date 2002-04-28 picture [::base64::decode { R0lGODlhDAAMAIQAAP//9/X 17unp5WZmZgAAAOfn515eXv Pz7Y6OjuDg4J+fn5OTk6enp 56enmleECcgggoBADs= } ]] ] test yaml-10.1 "Merge key" -body { set merge1 { --- mapping: name: Joe job: Accountant <<: age: 38 } dictsort2 [yaml::yaml2dict $merge1] {d d} } -result [dictsort2 {mapping {name Joe job Accountant age 38}} {d d}] test yaml-10.2 "Merge key 2" -body { set merge2 { --- - &CENTER { x: 1, y: 2 } - &LEFT { x: 0, y: 2 } - &BIG { r: "spaced string" } - &SMALL { r: 1 } # All the following maps are equal: - # Explicit keys x: 1 y: 2 r: 10 label: base - # Merge one map << : *CENTER r: 10 label: center - # Merge multiple maps << : [ *CENTER, *BIG ] label: center/big - # Override << : [ *BIG, *LEFT, *SMALL ] x: 1 label: big/left/small } yaml::yaml2dict $merge2 } -result [list {x 1 y 2} {x 0 y 2} {r {spaced string}} {r 1} \ [dict create x 1 y 2 r 10 label base] \ [dict create x 1 y 2 r 10 label center] \ [dict create x 1 y 2 r {spaced string} label center/big] \ [dict create r 1 x 1 y 2 label big/left/small]] test yaml-11.1 "Invoice" -body { set Invoice { --- # ! invoice: 34843 date : 2001-01-23 bill-to: &id001 given : Chris family : Dumars address: lines: | 458 Walkman Dr. Suite #292 city : Royal Oak state : MI postal : 48046 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. } dictsort2 [yaml::yaml2dict $Invoice] {{d {bill-to {{d {address d}}} ship-to {{d {address d}}} product {l d}}}} } -result [dictsort2 [string map [list TIMESTAMP [clock scan "2001-01-23"]] \ [dict create invoice 34843 date TIMESTAMP bill-to [dict create given Chris family Dumars address [dict create lines {458 Walkman Dr. Suite #292 } city {Royal Oak} state MI postal 48046]] ship-to [dict create given Chris family Dumars address [dict create lines {458 Walkman Dr. Suite #292 } city {Royal Oak} state MI postal 48046]] product [list [dict create sku BL394D quantity 4 description Basketball price 450.00] [dict create 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.}] ] \ {{d {bill-to {{d {address d}}} ship-to {{d {address d}}} product {l d}}}}] # -------------- # dumping ..... test yaml-20.1 "list2yaml" -body { set dump1 { {Mark McGwire} {Sammy Sosa} } yaml::list2yaml $dump1 } -result {--- - Mark McGwire - Sammy Sosa } test yaml-20.2 "dict2yaml" -body { set dump2 { name {Sammy Sosa} hr 63 avg 0.288 } set _before [eval huddle create $dump2] set yaml2 [yaml::dict2yaml $dump2] set _after [yaml::yaml2dict $yaml2] set _after [eval huddle create $_after] huddle equal $_before $_after } -result {1} test yaml-20.3 "dict2yaml block/flow scalars" -body { set dump_scalars [list \ {http://www.activestate.com/Products/activetcl/} \ {This is the core development home for the tcllib standardized Tcl library. This is a set of pure-Tcl extensions that you can use to become even more productive with Tcl. See also the Tcl Foundry that collects information about many Tcl-related SourceForge projects.} \ {tklib: A library of all-Tcl routines for Tk tclapps: A set of little apps for Tcl or Tk, to be used as examples, or just for fun tclbench: A benchmarking suite for Tcl and Tk} ] yaml::list2yaml $dump_scalars } -result {--- - > http://www.activestate.com/Products/activetcl/ - > This is the core development home for the tcllib standardized Tcl library. This is a set of pure-Tcl extensions that you can use to become even more productive with Tcl. See also the Tcl Foundry that collects information about many Tcl-related SourceForge projects. - |- tklib: A library of all-Tcl routines for Tk tclapps: A set of little apps for Tcl or Tk, to be used as examples, or just for fun tclbench: A benchmarking suite for Tcl and Tk } # ... Tests of addStrings ... # (Requires introspection of parser state) if [info exists selfrun] { tcltest::cleanupTests } else { testsuiteCleanup }