PageRenderTime 57ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/test/syck/test_yaml.rb

http://github.com/ruby/ruby
Ruby | 1414 lines | 1268 code | 68 blank | 78 comment | 2 complexity | b963c75833c47e1d26548dc24faf8297 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-3.0
  1. # -*- mode: ruby; ruby-indent-level: 4; tab-width: 4; indent-tabs-mode: t -*-
  2. # vim:sw=4:ts=4
  3. # $Id$
  4. #
  5. require 'test/unit'
  6. require 'syck'
  7. require 'yaml'
  8. require 'syck/ypath'
  9. # [ruby-core:01946]
  10. module YAML_Tests
  11. StructTest = Struct::new( :c )
  12. end
  13. module Syck
  14. class YAML_Unit_Tests < Test::Unit::TestCase
  15. def setup
  16. @current_engine = YAML::ENGINE.yamler
  17. YAML::ENGINE.yamler = 'syck'
  18. end
  19. def teardown
  20. YAML::ENGINE.yamler = @current_engine
  21. end
  22. # [ruby-core:34969]
  23. def test_regexp_with_n
  24. assert_cycle(Regexp.new('',0,'n'))
  25. end
  26. #
  27. # Convert between YAML and the object to verify correct parsing and
  28. # emitting
  29. #
  30. def assert_to_yaml( obj, yaml, msg = nil )
  31. assert_equal( obj, YAML::load( yaml ), msg )
  32. assert_equal( obj, YAML::parse( yaml ).transform, msg )
  33. assert_equal( obj, YAML::load( obj.to_yaml ), msg )
  34. assert_equal( obj, YAML::parse( obj.to_yaml ).transform, msg )
  35. assert_equal( obj, YAML::load(
  36. obj.to_yaml( :UseVersion => true, :UseHeader => true, :SortKeys => true )
  37. ), msg )
  38. end
  39. #
  40. # Test parser only
  41. #
  42. def assert_parse_only( obj, yaml, msg = nil )
  43. assert_equal( obj, YAML::load( yaml ), msg )
  44. assert_equal( obj, YAML::parse( yaml ).transform, msg )
  45. end
  46. def assert_cycle( obj, msg = nil )
  47. assert_equal( obj, YAML::load( obj.to_yaml ), msg )
  48. end
  49. def assert_path_segments( path, segments, msg = nil )
  50. YAML::YPath.each_path( path ) { |choice|
  51. assert_equal( choice.segments, segments.shift, msg )
  52. }
  53. assert_equal( segments.length, 0, "Some segments leftover: #{ segments.inspect }" )
  54. end
  55. #
  56. # Make a time with the time zone
  57. #
  58. def mktime( year, mon, day, hour, min, sec, usec, zone = "Z" )
  59. usec = Rational(usec.to_s) * 1000000
  60. val = Time::utc( year.to_i, mon.to_i, day.to_i, hour.to_i, min.to_i, sec.to_i, usec )
  61. if zone != "Z"
  62. hour = zone[0,3].to_i * 3600
  63. min = zone[3,2].to_i * 60
  64. ofs = (hour + min)
  65. val = Time.at( val.tv_sec - ofs, val.tv_nsec / 1000.0 )
  66. end
  67. return val
  68. end
  69. #
  70. # Tests modified from 00basic.t in YAML.pm
  71. #
  72. def test_basic_map
  73. # Simple map
  74. assert_parse_only(
  75. { 'one' => 'foo', 'three' => 'baz', 'two' => 'bar' }, <<EOY
  76. one: foo
  77. two: bar
  78. three: baz
  79. EOY
  80. )
  81. end
  82. def test_basic_strings
  83. # Common string types
  84. assert_cycle("x")
  85. assert_cycle(":x")
  86. assert_cycle(":")
  87. assert_parse_only(
  88. { 1 => 'simple string', 2 => 42, 3 => '1 Single Quoted String',
  89. 4 => 'YAML\'s Double "Quoted" String', 5 => "A block\n with several\n lines.\n",
  90. 6 => "A \"chomped\" block", 7 => "A folded\n string\n", 8 => ": started string" },
  91. <<EOY
  92. 1: simple string
  93. 2: 42
  94. 3: '1 Single Quoted String'
  95. 4: "YAML's Double \\\"Quoted\\\" String"
  96. 5: |
  97. A block
  98. with several
  99. lines.
  100. 6: |-
  101. A "chomped" block
  102. 7: >
  103. A
  104. folded
  105. string
  106. 8: ": started string"
  107. EOY
  108. )
  109. end
  110. #
  111. # Test the specification examples
  112. # - Many examples have been changes because of whitespace problems that
  113. # caused the two to be inequivalent, or keys to be sorted wrong
  114. #
  115. def test_spec_simple_implicit_sequence
  116. # Simple implicit sequence
  117. assert_to_yaml(
  118. [ 'Mark McGwire', 'Sammy Sosa', 'Ken Griffey' ], <<EOY
  119. - Mark McGwire
  120. - Sammy Sosa
  121. - Ken Griffey
  122. EOY
  123. )
  124. end
  125. def test_spec_simple_implicit_map
  126. # Simple implicit map
  127. assert_to_yaml(
  128. { 'hr' => 65, 'avg' => 0.278, 'rbi' => 147 }, <<EOY
  129. avg: 0.278
  130. hr: 65
  131. rbi: 147
  132. EOY
  133. )
  134. end
  135. def test_spec_simple_map_with_nested_sequences
  136. # Simple mapping with nested sequences
  137. assert_to_yaml(
  138. { 'american' =>
  139. [ 'Boston Red Sox', 'Detroit Tigers', 'New York Yankees' ],
  140. 'national' =>
  141. [ 'New York Mets', 'Chicago Cubs', 'Atlanta Braves' ] }, <<EOY
  142. american:
  143. - Boston Red Sox
  144. - Detroit Tigers
  145. - New York Yankees
  146. national:
  147. - New York Mets
  148. - Chicago Cubs
  149. - Atlanta Braves
  150. EOY
  151. )
  152. end
  153. def test_spec_simple_sequence_with_nested_map
  154. # Simple sequence with nested map
  155. assert_to_yaml(
  156. [
  157. {'name' => 'Mark McGwire', 'hr' => 65, 'avg' => 0.278},
  158. {'name' => 'Sammy Sosa', 'hr' => 63, 'avg' => 0.288}
  159. ], <<EOY
  160. -
  161. avg: 0.278
  162. hr: 65
  163. name: Mark McGwire
  164. -
  165. avg: 0.288
  166. hr: 63
  167. name: Sammy Sosa
  168. EOY
  169. )
  170. end
  171. def test_spec_sequence_of_sequences
  172. # Simple sequence with inline sequences
  173. assert_parse_only(
  174. [
  175. [ 'name', 'hr', 'avg' ],
  176. [ 'Mark McGwire', 65, 0.278 ],
  177. [ 'Sammy Sosa', 63, 0.288 ]
  178. ], <<EOY
  179. - [ name , hr , avg ]
  180. - [ Mark McGwire , 65 , 0.278 ]
  181. - [ Sammy Sosa , 63 , 0.288 ]
  182. EOY
  183. )
  184. end
  185. def test_spec_mapping_of_mappings
  186. # Simple map with inline maps
  187. assert_parse_only(
  188. { 'Mark McGwire' =>
  189. { 'hr' => 65, 'avg' => 0.278 },
  190. 'Sammy Sosa' =>
  191. { 'hr' => 63, 'avg' => 0.288 }
  192. }, <<EOY
  193. Mark McGwire: {hr: 65, avg: 0.278}
  194. Sammy Sosa: {hr: 63,
  195. avg: 0.288}
  196. EOY
  197. )
  198. end
  199. def test_ambiguous_comments
  200. # [ruby-talk:88012]
  201. assert_to_yaml( "Call the method #dave", <<EOY )
  202. --- "Call the method #dave"
  203. EOY
  204. end
  205. def test_spec_nested_comments
  206. # Map and sequences with comments
  207. assert_parse_only(
  208. { 'hr' => [ 'Mark McGwire', 'Sammy Sosa' ],
  209. 'rbi' => [ 'Sammy Sosa', 'Ken Griffey' ] }, <<EOY
  210. hr: # 1998 hr ranking
  211. - Mark McGwire
  212. - Sammy Sosa
  213. rbi:
  214. # 1998 rbi ranking
  215. - Sammy Sosa
  216. - Ken Griffey
  217. EOY
  218. )
  219. end
  220. def test_spec_anchors_and_aliases
  221. # Anchors and aliases
  222. assert_parse_only(
  223. { 'hr' =>
  224. [ 'Mark McGwire', 'Sammy Sosa' ],
  225. 'rbi' =>
  226. [ 'Sammy Sosa', 'Ken Griffey' ] }, <<EOY
  227. hr:
  228. - Mark McGwire
  229. # Name "Sammy Sosa" scalar SS
  230. - &SS Sammy Sosa
  231. rbi:
  232. # So it can be referenced later.
  233. - *SS
  234. - Ken Griffey
  235. EOY
  236. )
  237. assert_to_yaml(
  238. [{"arrival"=>"EDI", "departure"=>"LAX", "fareref"=>"DOGMA", "currency"=>"GBP"}, {"arrival"=>"MEL", "departure"=>"SYD", "fareref"=>"MADF", "currency"=>"AUD"}, {"arrival"=>"MCO", "departure"=>"JFK", "fareref"=>"DFSF", "currency"=>"USD"}], <<EOY
  239. -
  240. &F fareref: DOGMA
  241. &C currency: GBP
  242. &D departure: LAX
  243. &A arrival: EDI
  244. - { *F: MADF, *C: AUD, *D: SYD, *A: MEL }
  245. - { *F: DFSF, *C: USD, *D: JFK, *A: MCO }
  246. EOY
  247. )
  248. assert_to_yaml(
  249. {"ALIASES"=>["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"}]}, <<EOY
  250. ---
  251. ALIASES: [&f fareref, &c currency, &d departure, &a arrival]
  252. FARES:
  253. - *f: DOGMA
  254. *c: GBP
  255. *d: LAX
  256. *a: EDI
  257. - *f: MADF
  258. *c: AUD
  259. *d: SYD
  260. *a: MEL
  261. - *f: DFSF
  262. *c: USD
  263. *d: JFK
  264. *a: MCO
  265. EOY
  266. )
  267. end
  268. def test_spec_mapping_between_sequences
  269. # Complex key #1
  270. dj = Date.new( 2001, 7, 23 )
  271. assert_parse_only(
  272. { [ 'Detroit Tigers', 'Chicago Cubs' ] => [ Date.new( 2001, 7, 23 ) ],
  273. [ 'New York Yankees', 'Atlanta Braves' ] => [ Date.new( 2001, 7, 2 ), Date.new( 2001, 8, 12 ), Date.new( 2001, 8, 14 ) ] }, <<EOY
  274. ? # PLAY SCHEDULE
  275. - Detroit Tigers
  276. - Chicago Cubs
  277. :
  278. - 2001-07-23
  279. ? [ New York Yankees,
  280. Atlanta Braves ]
  281. : [ 2001-07-02, 2001-08-12,
  282. 2001-08-14 ]
  283. EOY
  284. )
  285. # Complex key #2
  286. assert_parse_only(
  287. { [ 'New York Yankees', 'Atlanta Braves' ] =>
  288. [ Date.new( 2001, 7, 2 ), Date.new( 2001, 8, 12 ),
  289. Date.new( 2001, 8, 14 ) ],
  290. [ 'Detroit Tigers', 'Chicago Cubs' ] =>
  291. [ Date.new( 2001, 7, 23 ) ]
  292. }, <<EOY
  293. ?
  294. - New York Yankees
  295. - Atlanta Braves
  296. :
  297. - 2001-07-02
  298. - 2001-08-12
  299. - 2001-08-14
  300. ?
  301. - Detroit Tigers
  302. - Chicago Cubs
  303. :
  304. - 2001-07-23
  305. EOY
  306. )
  307. end
  308. def test_spec_sequence_key_shortcut
  309. # Shortcut sequence map
  310. assert_parse_only(
  311. { 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ),
  312. 'bill-to' => 'Chris Dumars', 'product' =>
  313. [ { 'item' => 'Super Hoop', 'quantity' => 1 },
  314. { 'item' => 'Basketball', 'quantity' => 4 },
  315. { 'item' => 'Big Shoes', 'quantity' => 1 } ] }, <<EOY
  316. invoice: 34843
  317. date : 2001-01-23
  318. bill-to: Chris Dumars
  319. product:
  320. - item : Super Hoop
  321. quantity: 1
  322. - item : Basketball
  323. quantity: 4
  324. - item : Big Shoes
  325. quantity: 1
  326. EOY
  327. )
  328. end
  329. def test_spec_sequence_in_sequence_shortcut
  330. # Seq-in-seq
  331. assert_parse_only( [ [ [ 'one', 'two', 'three' ] ] ], <<EOY )
  332. - - - one
  333. - two
  334. - three
  335. EOY
  336. end
  337. def test_spec_sequence_shortcuts
  338. # Sequence shortcuts combined
  339. assert_parse_only(
  340. [
  341. [
  342. [ [ 'one' ] ],
  343. [ 'two', 'three' ],
  344. { 'four' => nil },
  345. [ { 'five' => [ 'six' ] } ],
  346. [ 'seven' ]
  347. ],
  348. [ 'eight', 'nine' ]
  349. ], <<EOY )
  350. - - - - one
  351. - - two
  352. - three
  353. - four:
  354. - - five:
  355. - six
  356. - - seven
  357. - - eight
  358. - nine
  359. EOY
  360. end
  361. def test_spec_single_literal
  362. # Literal scalar block
  363. assert_parse_only( [ "\\/|\\/|\n/ | |_\n" ], <<EOY )
  364. - |
  365. \\/|\\/|
  366. / | |_
  367. EOY
  368. end
  369. def test_spec_single_folded
  370. # Folded scalar block
  371. assert_parse_only(
  372. [ "Mark McGwire's year was crippled by a knee injury.\n" ], <<EOY
  373. - >
  374. Mark McGwire\'s
  375. year was crippled
  376. by a knee injury.
  377. EOY
  378. )
  379. end
  380. def test_spec_preserve_indent
  381. # Preserve indented spaces
  382. assert_parse_only(
  383. "Sammy Sosa completed another fine season with great stats.\n\n 63 Home Runs\n 0.288 Batting Average\n\nWhat a year!\n", <<EOY
  384. --- >
  385. Sammy Sosa completed another
  386. fine season with great stats.
  387. 63 Home Runs
  388. 0.288 Batting Average
  389. What a year!
  390. EOY
  391. )
  392. end
  393. def test_spec_indentation_determines_scope
  394. assert_parse_only(
  395. { 'name' => 'Mark McGwire', 'accomplishment' => "Mark set a major league home run record in 1998.\n",
  396. 'stats' => "65 Home Runs\n0.278 Batting Average\n" }, <<EOY
  397. name: Mark McGwire
  398. accomplishment: >
  399. Mark set a major league
  400. home run record in 1998.
  401. stats: |
  402. 65 Home Runs
  403. 0.278 Batting Average
  404. EOY
  405. )
  406. end
  407. #
  408. # Reports from N.Easterly & J.Trupiano : Tests with patch from daz
  409. # [ruby-core:23006] [Bug #1311] http://bugs.ruby-lang.org/issues/show/1311
  410. #
  411. def test_scan_scalar_nl
  412. bug1311 = '[ruby-core:23006]'
  413. assert_cycle(<<EoY, bug1311)
  414. a
  415. b
  416. EoY
  417. assert_cycle(<<EoY, bug1311)
  418. a
  419. b
  420. c
  421. EoY
  422. assert_cycle(<<EoY, bug1311)
  423. a
  424. b
  425. EoY
  426. assert_cycle(" Do I work?\nNo indent", bug1311)
  427. assert_cycle(" \n Do I work?\nNo indent", bug1311)
  428. assert_cycle("\n Do I work?\nNo indent", bug1311)
  429. assert_cycle("\n", bug1311)
  430. assert_cycle("\n\n", bug1311)
  431. assert_cycle("\r\n", bug1311)
  432. assert_cycle <<EoY, '[ruby-core:28777]'
  433. Domain name:
  434. ckgteam.co.uk
  435. Registrant:
  436. James Gregory
  437. Registrant type:
  438. UK Individual
  439. Registrant's address:
  440. The registrant is a non-trading individual who has opted to have their
  441. address omitted from the WHOIS service.
  442. Registrar:
  443. Webfusion Ltd t/a 123-Reg.co.uk [Tag = 123-REG]
  444. URL: http://www.123-reg.co.uk
  445. Relevant dates:
  446. Registered on: 16-Nov-2009
  447. Renewal date: 16-Nov-2011
  448. Last updated: 25-Nov-2009
  449. Registration status:
  450. Registered until renewal date.
  451. Name servers:
  452. ns1.slicehost.net
  453. ns2.slicehost.net
  454. ns3.slicehost.net
  455. WHOIS lookup made at 11:56:46 19-Mar-2010
  456. --
  457. This WHOIS information is provided for free by Nominet UK the central registry
  458. for .uk domain names. This information and the .uk WHOIS are:
  459. Copyright Nominet UK 1996 - 2010.
  460. You may not access the .uk WHOIS or use any data from it except as permitted
  461. by the terms of use available in full at http://www.nominet.org.uk/whois, which
  462. includes restrictions on: (A) use of the data for advertising, or its
  463. repackaging, recompilation, redistribution or reuse (B) obscuring, removing
  464. or hiding any or all of this notice and (C) exceeding query rate or volume
  465. limits. The data is provided on an 'as-is' basis and may lag behind the
  466. register. Access may be withdrawn or restricted at any time.
  467. EoY
  468. end
  469. def test_spec_multiline_scalars
  470. # Multiline flow scalars
  471. assert_parse_only(
  472. { 'plain' => 'This unquoted scalar spans many lines.',
  473. 'quoted' => "So does this quoted scalar.\n" }, <<EOY
  474. plain: This unquoted
  475. scalar spans
  476. many lines.
  477. quoted: "\\
  478. So does this quoted
  479. scalar.\\n"
  480. EOY
  481. )
  482. end
  483. def test_spec_type_int
  484. assert_parse_only(
  485. { 'canonical' => 12345, 'decimal' => 12345, 'octal' => '014'.oct, 'hexadecimal' => '0xC'.hex }, <<EOY
  486. canonical: 12345
  487. decimal: +12,345
  488. octal: 014
  489. hexadecimal: 0xC
  490. EOY
  491. )
  492. assert_parse_only(
  493. { 'canonical' => 685230, 'decimal' => 685230, 'octal' => 02472256, 'hexadecimal' => 0x0A74AE, 'sexagesimal' => 685230 }, <<EOY)
  494. canonical: 685230
  495. decimal: +685,230
  496. octal: 02472256
  497. hexadecimal: 0x0A,74,AE
  498. sexagesimal: 190:20:30
  499. EOY
  500. end
  501. def test_spec_type_float
  502. assert_parse_only(
  503. { 'canonical' => 1230.15, 'exponential' => 1230.15, 'fixed' => 1230.15,
  504. 'negative infinity' => -1.0/0.0 }, <<EOY)
  505. canonical: 1.23015e+3
  506. exponential: 12.3015e+02
  507. fixed: 1,230.15
  508. negative infinity: -.inf
  509. EOY
  510. nan = YAML::load( <<EOY )
  511. not a number: .NaN
  512. EOY
  513. assert( nan['not a number'].nan? )
  514. end
  515. def test_spec_type_misc
  516. assert_parse_only(
  517. { nil => nil, true => true, false => false, 'string' => '12345' }, <<EOY
  518. null: ~
  519. true: yes
  520. false: no
  521. string: '12345'
  522. EOY
  523. )
  524. end
  525. def test_spec_complex_invoice
  526. # Complex invoice type
  527. id001 = { 'given' => 'Chris', 'family' => 'Dumars', 'address' =>
  528. { 'lines' => "458 Walkman Dr.\nSuite #292\n", 'city' => 'Royal Oak',
  529. 'state' => 'MI', 'postal' => 48046 } }
  530. assert_parse_only(
  531. { 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ),
  532. 'bill-to' => id001, 'ship-to' => id001, 'product' =>
  533. [ { 'sku' => 'BL394D', 'quantity' => 4,
  534. 'description' => 'Basketball', 'price' => 450.00 },
  535. { 'sku' => 'BL4438H', 'quantity' => 1,
  536. 'description' => 'Super Hoop', 'price' => 2392.00 } ],
  537. 'tax' => 251.42, 'total' => 4443.52,
  538. 'comments' => "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.\n" }, <<EOY
  539. invoice: 34843
  540. date : 2001-01-23
  541. bill-to: &id001
  542. given : Chris
  543. family : !str Dumars
  544. address:
  545. lines: |
  546. 458 Walkman Dr.
  547. Suite #292
  548. city : Royal Oak
  549. state : MI
  550. postal : 48046
  551. ship-to: *id001
  552. product:
  553. - !map
  554. sku : BL394D
  555. quantity : 4
  556. description : Basketball
  557. price : 450.00
  558. - sku : BL4438H
  559. quantity : 1
  560. description : Super Hoop
  561. price : 2392.00
  562. tax : 251.42
  563. total: 4443.52
  564. comments: >
  565. Late afternoon is best.
  566. Backup contact is Nancy
  567. Billsmer @ 338-4338.
  568. EOY
  569. )
  570. end
  571. def test_spec_log_file
  572. doc_ct = 0
  573. YAML::load_documents( <<EOY
  574. ---
  575. Time: 2001-11-23 15:01:42 -05:00
  576. User: ed
  577. Warning: >
  578. This is an error message
  579. for the log file
  580. ---
  581. Time: 2001-11-23 15:02:31 -05:00
  582. User: ed
  583. Warning: >
  584. A slightly different error
  585. message.
  586. ---
  587. Date: 2001-11-23 15:03:17 -05:00
  588. User: ed
  589. Fatal: >
  590. Unknown variable "bar"
  591. Stack:
  592. - file: TopClass.py
  593. line: 23
  594. code: |
  595. x = MoreObject("345\\n")
  596. - file: MoreClass.py
  597. line: 58
  598. code: |-
  599. foo = bar
  600. EOY
  601. ) { |doc|
  602. case doc_ct
  603. when 0
  604. assert_equal( doc, { 'Time' => mktime( 2001, 11, 23, 15, 01, 42, 00, "-05:00" ),
  605. 'User' => 'ed', 'Warning' => "This is an error message for the log file\n" } )
  606. when 1
  607. assert_equal( doc, { 'Time' => mktime( 2001, 11, 23, 15, 02, 31, 00, "-05:00" ),
  608. 'User' => 'ed', 'Warning' => "A slightly different error message.\n" } )
  609. when 2
  610. assert_equal( doc, { 'Date' => mktime( 2001, 11, 23, 15, 03, 17, 00, "-05:00" ),
  611. 'User' => 'ed', 'Fatal' => "Unknown variable \"bar\"\n",
  612. 'Stack' => [
  613. { 'file' => 'TopClass.py', 'line' => 23, 'code' => "x = MoreObject(\"345\\n\")\n" },
  614. { 'file' => 'MoreClass.py', 'line' => 58, 'code' => "foo = bar" } ] } )
  615. end
  616. doc_ct += 1
  617. }
  618. assert_equal( doc_ct, 3 )
  619. end
  620. def test_spec_root_fold
  621. y = YAML::load( <<EOY
  622. --- >
  623. This YAML stream contains a single text value.
  624. The next stream is a log file - a sequence of
  625. log entries. Adding an entry to the log is a
  626. simple matter of appending it at the end.
  627. EOY
  628. )
  629. 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" )
  630. end
  631. def test_spec_root_mapping
  632. y = YAML::load( <<EOY
  633. # This stream is an example of a top-level mapping.
  634. invoice : 34843
  635. date : 2001-01-23
  636. total : 4443.52
  637. EOY
  638. )
  639. assert_equal( y, { 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ), 'total' => 4443.52 } )
  640. end
  641. def test_spec_oneline_docs
  642. doc_ct = 0
  643. YAML::load_documents( <<EOY
  644. # The following is a sequence of three documents.
  645. # The first contains an empty mapping, the second
  646. # an empty sequence, and the last an empty string.
  647. --- {}
  648. --- [ ]
  649. --- ''
  650. EOY
  651. ) { |doc|
  652. case doc_ct
  653. when 0
  654. assert_equal( doc, {} )
  655. when 1
  656. assert_equal( doc, [] )
  657. when 2
  658. assert_equal( doc, '' )
  659. end
  660. doc_ct += 1
  661. }
  662. assert_equal( doc_ct, 3 )
  663. end
  664. def test_spec_domain_prefix
  665. customer_proc = proc { |type, val|
  666. if Hash === val
  667. scheme, domain, type = type.split( ':', 3 )
  668. val['type'] = "domain #{type}"
  669. val
  670. else
  671. raise ArgumentError, "Not a Hash in domain.tld,2002/invoice: " + val.inspect
  672. end
  673. }
  674. YAML.add_domain_type( "domain.tld,2002", 'invoice', &customer_proc )
  675. YAML.add_domain_type( "domain.tld,2002", 'customer', &customer_proc )
  676. assert_parse_only( { "invoice"=> { "customers"=> [ { "given"=>"Chris", "type"=>"domain customer", "family"=>"Dumars" } ], "type"=>"domain invoice" } }, <<EOY
  677. # 'http://domain.tld,2002/invoice' is some type family.
  678. invoice: !domain.tld,2002/^invoice
  679. # 'seq' is shorthand for 'http://yaml.org/seq'.
  680. # This does not effect '^customer' below
  681. # because it is does not specify a prefix.
  682. customers: !seq
  683. # '^customer' is shorthand for the full
  684. # notation 'http://domain.tld,2002/customer'.
  685. - !^customer
  686. given : Chris
  687. family : Dumars
  688. EOY
  689. )
  690. end
  691. def test_spec_throwaway
  692. assert_parse_only(
  693. {"this"=>"contains three lines of text.\nThe third one starts with a\n# character. This isn't a comment.\n"}, <<EOY
  694. ### These are four throwaway comment ###
  695. ### lines (the second line is empty). ###
  696. this: | # Comments may trail lines.
  697. contains three lines of text.
  698. The third one starts with a
  699. # character. This isn't a comment.
  700. # These are three throwaway comment
  701. # lines (the first line is empty).
  702. EOY
  703. )
  704. end
  705. def test_spec_force_implicit
  706. # Force implicit
  707. assert_parse_only(
  708. { 'integer' => 12, 'also int' => 12, 'string' => '12' }, <<EOY
  709. integer: 12
  710. also int: ! "12"
  711. string: !str 12
  712. EOY
  713. )
  714. end
  715. def test_spec_private_types
  716. doc_ct = 0
  717. YAML::parse_documents( <<EOY
  718. # Private types are per-document.
  719. ---
  720. pool: !!ball
  721. number: 8
  722. color: black
  723. ---
  724. bearing: !!ball
  725. material: steel
  726. EOY
  727. ) { |doc|
  728. case doc_ct
  729. when 0
  730. assert_equal( doc['pool'].type_id, 'x-private:ball' )
  731. assert_equal( doc['pool'].transform.value, { 'number' => 8, 'color' => 'black' } )
  732. when 1
  733. assert_equal( doc['bearing'].type_id, 'x-private:ball' )
  734. assert_equal( doc['bearing'].transform.value, { 'material' => 'steel' } )
  735. end
  736. doc_ct += 1
  737. }
  738. assert_equal( doc_ct, 2 )
  739. end
  740. def test_spec_url_escaping
  741. YAML.add_domain_type( "domain.tld,2002", "type0" ) { |type, val|
  742. "ONE: #{val}"
  743. }
  744. YAML.add_domain_type( "domain.tld,2002", "type%30" ) { |type, val|
  745. "TWO: #{val}"
  746. }
  747. assert_parse_only(
  748. { 'same' => [ 'ONE: value', 'ONE: value' ], 'different' => [ 'TWO: value' ] }, <<EOY
  749. same:
  750. - !domain.tld,2002/type\\x30 value
  751. - !domain.tld,2002/type0 value
  752. different: # As far as the YAML parser is concerned
  753. - !domain.tld,2002/type%30 value
  754. EOY
  755. )
  756. end
  757. def test_spec_override_anchor
  758. # Override anchor
  759. a001 = "The alias node below is a repeated use of this value.\n"
  760. assert_parse_only(
  761. { 'anchor' => 'This scalar has an anchor.', 'override' => a001, 'alias' => a001 }, <<EOY
  762. anchor : &A001 This scalar has an anchor.
  763. override : &A001 >
  764. The alias node below is a
  765. repeated use of this value.
  766. alias : *A001
  767. EOY
  768. )
  769. end
  770. def test_spec_explicit_families
  771. YAML.add_domain_type( "somewhere.com,2002", 'type' ) { |type, val|
  772. "SOMEWHERE: #{val}"
  773. }
  774. assert_parse_only(
  775. { '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" }, <<EOY
  776. not-date: !str 2002-04-28
  777. picture: !binary |
  778. R0lGODlhDAAMAIQAAP//9/X
  779. 17unp5WZmZgAAAOfn515eXv
  780. Pz7Y6OjuDg4J+fn5OTk6enp
  781. 56enmleECcgggoBADs=
  782. hmm: !somewhere.com,2002/type |
  783. family above is short for
  784. http://somewhere.com/type
  785. EOY
  786. )
  787. end
  788. def test_spec_application_family
  789. # Testing the clarkevans.com graphs
  790. YAML.add_domain_type( "clarkevans.com,2002", 'graph/shape' ) { |type, val|
  791. if Array === val
  792. val << "Shape Container"
  793. val
  794. else
  795. raise ArgumentError, "Invalid graph of type #{val.class}: " + val.inspect
  796. end
  797. }
  798. one_shape_proc = Proc.new { |type, val|
  799. if Hash === val
  800. type = type.split( /:/ )
  801. val['TYPE'] = "Shape: #{type[2]}"
  802. val
  803. else
  804. raise ArgumentError, "Invalid graph of type #{val.class}: " + val.inspect
  805. end
  806. }
  807. YAML.add_domain_type( "clarkevans.com,2002", 'graph/circle', &one_shape_proc )
  808. YAML.add_domain_type( "clarkevans.com,2002", 'graph/line', &one_shape_proc )
  809. YAML.add_domain_type( "clarkevans.com,2002", 'graph/text', &one_shape_proc )
  810. assert_parse_only(
  811. [[{"radius"=>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"]], <<EOY
  812. - !clarkevans.com,2002/graph/^shape
  813. - !^circle
  814. center: &ORIGIN {x: 73, y: 129}
  815. radius: 7
  816. - !^line # !clarkevans.com,2002/graph/line
  817. start: *ORIGIN
  818. finish: { x: 89, y: 102 }
  819. - !^text
  820. start: *ORIGIN
  821. color: 0xFFEEBB
  822. value: Pretty vector drawing.
  823. EOY
  824. )
  825. end
  826. def test_spec_float_explicit
  827. assert_parse_only(
  828. [ 10.0, 10.0, 10.0, 10.0 ], <<EOY
  829. # All entries in the sequence
  830. # have the same type and value.
  831. - 10.0
  832. - !float 10
  833. - !yaml.org,2002/^float '10'
  834. - !yaml.org,2002/float "\\
  835. 1\\
  836. 0"
  837. EOY
  838. )
  839. end
  840. def test_spec_builtin_seq
  841. # Assortment of sequences
  842. assert_parse_only(
  843. { 'empty' => [], 'in-line' => [ 'one', 'two', 'three', 'four', 'five' ],
  844. 'nested' => [ 'First item in top sequence', [ 'Subordinate sequence entry' ],
  845. "A multi-line sequence entry\n", 'Sixth item in top sequence' ] }, <<EOY
  846. empty: []
  847. in-line: [ one, two, three # May span lines,
  848. , four, # indentation is
  849. five ] # mostly ignored.
  850. nested:
  851. - First item in top sequence
  852. -
  853. - Subordinate sequence entry
  854. - >
  855. A multi-line
  856. sequence entry
  857. - Sixth item in top sequence
  858. EOY
  859. )
  860. end
  861. def test_spec_builtin_map
  862. # Assortment of mappings
  863. assert_parse_only(
  864. { 'empty' => {}, 'in-line' => { 'one' => 1, 'two' => 2 },
  865. 'spanning' => { 'one' => 1, 'two' => 2 },
  866. 'nested' => { 'first' => 'First entry', 'second' =>
  867. { 'key' => 'Subordinate mapping' }, 'third' =>
  868. [ 'Subordinate sequence', {}, 'Previous mapping is empty.',
  869. { 'A key' => 'value pair in a sequence.', 'A second' => 'key:value pair.' },
  870. 'The previous entry is equal to the following one.',
  871. { 'A key' => 'value pair in a sequence.', 'A second' => 'key:value pair.' } ],
  872. 12.0 => 'This key is a float.', "?\n" => 'This key had to be protected.',
  873. "\a" => 'This key had to be escaped.',
  874. "This is a multi-line folded key\n" => "Whose value is also multi-line.\n",
  875. [ 'This key', 'is a sequence' ] => [ 'With a sequence value.' ] } }, <<EOY
  876. empty: {}
  877. in-line: { one: 1, two: 2 }
  878. spanning: { one: 1,
  879. two: 2 }
  880. nested:
  881. first : First entry
  882. second:
  883. key: Subordinate mapping
  884. third:
  885. - Subordinate sequence
  886. - { }
  887. - Previous mapping is empty.
  888. - A key: value pair in a sequence.
  889. A second: key:value pair.
  890. - The previous entry is equal to the following one.
  891. -
  892. A key: value pair in a sequence.
  893. A second: key:value pair.
  894. !float 12 : This key is a float.
  895. ? >
  896. ?
  897. : This key had to be protected.
  898. "\\a" : This key had to be escaped.
  899. ? >
  900. This is a
  901. multi-line
  902. folded key
  903. : >
  904. Whose value is
  905. also multi-line.
  906. ?
  907. - This key
  908. - is a sequence
  909. :
  910. - With a sequence value.
  911. # The following parses correctly,
  912. # but Ruby 1.6.* fails the comparison!
  913. # ?
  914. # This: key
  915. # is a: mapping
  916. # :
  917. # with a: mapping value.
  918. EOY
  919. )
  920. end
  921. def test_spec_builtin_literal_blocks
  922. # Assortment of literal scalar blocks
  923. assert_parse_only(
  924. {"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"}, <<EOY
  925. empty: |
  926. literal: |
  927. The \\ ' " characters may be
  928. freely used. Leading white
  929. space is significant.
  930. Line breaks are significant.
  931. Thus this value contains one
  932. empty line and ends with a
  933. single line break, but does
  934. not start with one.
  935. is equal to: "The \\ ' \\" characters may \\
  936. be\\nfreely used. Leading white\\n space \\
  937. is significant.\\n\\nLine breaks are \\
  938. significant.\\nThus this value contains \\
  939. one\\nempty line and ends with a\\nsingle \\
  940. line break, but does\\nnot start with one.\\n"
  941. # Comments may follow a nested
  942. # scalar value. They must be
  943. # less indented.
  944. # Modifiers may be combined in any order.
  945. indented and chomped: |2-
  946. This has no newline.
  947. also written as: |-2
  948. This has no newline.
  949. both are equal to: " This has no newline."
  950. EOY
  951. )
  952. str1 = "This has one newline.\n"
  953. str2 = "This has no newline."
  954. str3 = "This has two newlines.\n\n"
  955. assert_parse_only(
  956. { 'clipped' => str1, 'same as "clipped" above' => str1,
  957. 'stripped' => str2, 'same as "stripped" above' => str2,
  958. 'kept' => str3, 'same as "kept" above' => str3 }, <<EOY
  959. clipped: |
  960. This has one newline.
  961. same as "clipped" above: "This has one newline.\\n"
  962. stripped: |-
  963. This has no newline.
  964. same as "stripped" above: "This has no newline."
  965. kept: |+
  966. This has two newlines.
  967. same as "kept" above: "This has two newlines.\\n\\n"
  968. EOY
  969. )
  970. end
  971. def test_spec_span_single_quote
  972. assert_parse_only( {"third"=>"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"}, <<EOY
  973. empty: ''
  974. second: '! : \\ etc. can be used freely.'
  975. third: 'a single quote '' must be escaped.'
  976. span: 'this contains
  977. six spaces
  978. and one
  979. line break'
  980. is same as: "this contains six spaces\\nand one line break"
  981. EOY
  982. )
  983. end
  984. def test_spec_span_double_quote
  985. assert_parse_only( {"is equal to"=>"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"}, <<EOY
  986. empty: ""
  987. second: "! : etc. can be used freely."
  988. third: "a \\\" or a \\\\ must be escaped."
  989. fourth: "this value ends with an LF.\\n"
  990. span: "this contains
  991. four \\
  992. spaces"
  993. is equal to: "this contains four spaces"
  994. EOY
  995. )
  996. end
  997. def test_spec_builtin_time
  998. # Time
  999. assert_parse_only(
  1000. { "space separated" => mktime( 2001, 12, 14, 21, 59, 43, ".10", "-05:00" ),
  1001. "canonical" => mktime( 2001, 12, 15, 2, 59, 43, ".10" ),
  1002. "date (noon UTC)" => Date.new( 2002, 12, 14),
  1003. "valid iso8601" => mktime( 2001, 12, 14, 21, 59, 43, ".10", "-05:00" ) }, <<EOY
  1004. canonical: 2001-12-15T02:59:43.1Z
  1005. valid iso8601: 2001-12-14t21:59:43.10-05:00
  1006. space separated: 2001-12-14 21:59:43.10 -05:00
  1007. date (noon UTC): 2002-12-14
  1008. EOY
  1009. )
  1010. end
  1011. def test_spec_builtin_binary
  1012. arrow_gif = "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\236iiiccc\243\243\243\204\204\204\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371!\376\016Made with GIMP\000,\000\000\000\000\f\000\f\000\000\005, \216\2010\236\343@\024\350i\020\304\321\212\010\034\317\200M$z\357\3770\205p\270\2601f\r\e\316\001\303\001\036\020' \202\n\001\000;"
  1013. assert_parse_only(
  1014. { 'canonical' => arrow_gif, 'base64' => arrow_gif,
  1015. 'description' => "The binary value above is a tiny arrow encoded as a gif image.\n" }, <<EOY
  1016. canonical: !binary "\\
  1017. R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOf\\
  1018. n515eXvPz7Y6OjuDg4J+fn5OTk6enp56enmlpaW\\
  1019. NjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++\\
  1020. f/++f/++f/++f/++f/++f/++f/++SH+Dk1hZGUg\\
  1021. d2l0aCBHSU1QACwAAAAADAAMAAAFLCAgjoEwnuN\\
  1022. AFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84Bww\\
  1023. EeECcgggoBADs="
  1024. base64: !binary |
  1025. R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOf
  1026. n515eXvPz7Y6OjuDg4J+fn5OTk6enp56enmlpaW
  1027. NjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++
  1028. f/++f/++f/++f/++f/++f/++f/++SH+Dk1hZGUg
  1029. d2l0aCBHSU1QACwAAAAADAAMAAAFLCAgjoEwnuN
  1030. AFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84Bww
  1031. EeECcgggoBADs=
  1032. description: >
  1033. The binary value above is a tiny arrow
  1034. encoded as a gif image.
  1035. EOY
  1036. )
  1037. end
  1038. def test_ruby_regexp
  1039. # Test Ruby regular expressions
  1040. assert_to_yaml(
  1041. { 'simple' => /a.b/, 'complex' => %r'\A"((?:[^"]|\")+)"',
  1042. 'case-insensitive' => /George McFly/i }, <<EOY
  1043. case-insensitive: !ruby/regexp "/George McFly/i"
  1044. complex: !ruby/regexp "/\\\\A\\"((?:[^\\"]|\\\\\\")+)\\"/"
  1045. simple: !ruby/regexp "/a.b/"
  1046. EOY
  1047. )
  1048. end
  1049. #
  1050. # Test of Ranges
  1051. #
  1052. def test_ranges
  1053. # Simple numeric
  1054. assert_to_yaml( 1..3, <<EOY )
  1055. --- !ruby/range 1..3
  1056. EOY
  1057. # Simple alphabetic
  1058. assert_to_yaml( 'a'..'z', <<EOY )
  1059. --- !ruby/range a..z
  1060. EOY
  1061. # Float
  1062. assert_to_yaml( 10.5...30.3, <<EOY )
  1063. --- !ruby/range 10.5...30.3
  1064. EOY
  1065. end
  1066. def test_ruby_struct
  1067. # Ruby structures
  1068. book_struct = Struct::new( "BookStruct", :author, :title, :year, :isbn )
  1069. assert_to_yaml(
  1070. [ book_struct.new( "Yukihiro Matsumoto", "Ruby in a Nutshell", 2002, "0-596-00214-9" ),
  1071. book_struct.new( [ 'Dave Thomas', 'Andy Hunt' ], "The Pickaxe", 2002,
  1072. book_struct.new( "This should be the ISBN", "but I have another struct here", 2002, "None" )
  1073. ) ], <<EOY
  1074. - !ruby/struct:BookStruct
  1075. author: Yukihiro Matsumoto
  1076. title: Ruby in a Nutshell
  1077. year: 2002
  1078. isbn: 0-596-00214-9
  1079. - !ruby/struct:BookStruct
  1080. author:
  1081. - Dave Thomas
  1082. - Andy Hunt
  1083. title: The Pickaxe
  1084. year: 2002
  1085. isbn: !ruby/struct:BookStruct
  1086. author: This should be the ISBN
  1087. title: but I have another struct here
  1088. year: 2002
  1089. isbn: None
  1090. EOY
  1091. )
  1092. assert_to_yaml( YAML_Tests::StructTest.new( 123 ), <<EOY )
  1093. --- !ruby/struct:YAML_Tests::StructTest
  1094. c: 123
  1095. EOY
  1096. end
  1097. def test_ruby_rational
  1098. assert_to_yaml( Rational(1, 2), <<EOY )
  1099. --- !ruby/object:Rational
  1100. numerator: 1
  1101. denominator: 2
  1102. EOY
  1103. # Read YAML dumped by the ruby 1.8.3.
  1104. assert_to_yaml( Rational(1, 2), "!ruby/object:Rational 1/2\n" )
  1105. assert_raise( ArgumentError ) { YAML.load("!ruby/object:Rational INVALID/RATIONAL\n") }
  1106. end
  1107. def test_ruby_complex
  1108. assert_to_yaml( Complex(3, 4), <<EOY )
  1109. --- !ruby/object:Complex
  1110. image: 4
  1111. real: 3
  1112. EOY
  1113. # Read YAML dumped by the ruby 1.8.3.
  1114. assert_to_yaml( Complex(3, 4), "!ruby/object:Complex 3+4i\n" )
  1115. assert_raise( ArgumentError ) { YAML.load("!ruby/object:Complex INVALID+COMPLEXi\n") }
  1116. end
  1117. def test_emitting_indicators
  1118. assert_to_yaml( "Hi, from Object 1. You passed: please, pretty please", <<EOY
  1119. --- "Hi, from Object 1. You passed: please, pretty please"
  1120. EOY
  1121. )
  1122. end
  1123. #
  1124. # Test the YAML::Stream class -- INACTIVE at the moment
  1125. #
  1126. def test_document
  1127. y = YAML::Stream.new( :Indent => 2, :UseVersion => 0 )
  1128. y.add(
  1129. { 'hi' => 'hello', 'map' =>
  1130. { 'good' => 'two' },
  1131. 'time' => Time.now,
  1132. 'try' => /^po(.*)$/,
  1133. 'bye' => 'goodbye'
  1134. }
  1135. )
  1136. y.add( { 'po' => 'nil', 'oper' => 90 } )
  1137. y.add( { 'hi' => 'wow!', 'bye' => 'wow!' } )
  1138. y.add( { [ 'Red Socks', 'Boston' ] => [ 'One', 'Two', 'Three' ] } )
  1139. y.add( [ true, false, false ] )
  1140. end
  1141. #
  1142. # Test YPath choices parsing
  1143. #
  1144. def test_ypath_parsing
  1145. assert_path_segments( "/*/((one|three)/name|place)|//place",
  1146. [ ["*", "one", "name"],
  1147. ["*", "three", "name"],
  1148. ["*", "place"],
  1149. ["/", "place"] ]
  1150. )
  1151. end
  1152. #
  1153. # Tests from Tanaka Akira on [ruby-core]
  1154. #
  1155. def test_akira
  1156. # Commas in plain scalars [ruby-core:1066]
  1157. assert_to_yaml(
  1158. {"A"=>"A,","B"=>"B"}, <<EOY
  1159. A: "A,"
  1160. B: B
  1161. EOY
  1162. )
  1163. # Double-quoted keys [ruby-core:1069]
  1164. assert_to_yaml(
  1165. {"1"=>2, "2"=>3}, <<EOY
  1166. '1': 2
  1167. "2": 3
  1168. EOY
  1169. )
  1170. # Anchored mapping [ruby-core:1071]
  1171. assert_to_yaml(
  1172. [{"a"=>"b"}] * 2, <<EOY
  1173. - &id001
  1174. a: b
  1175. - *id001
  1176. EOY
  1177. )
  1178. # Stress test [ruby-core:1071]
  1179. # a = []; 1000.times { a << {"a"=>"b", "c"=>"d"} }
  1180. # YAML::load( a.to_yaml )
  1181. end
  1182. #
  1183. # Test Time.now cycle
  1184. #
  1185. def test_time_now_cycle
  1186. #
  1187. # From Minero Aoki [ruby-core:2305]
  1188. #
  1189. require 'yaml'
  1190. t = Time.now
  1191. t = Time.at(t.tv_sec, t.tv_usec)
  1192. 5.times do
  1193. assert_cycle(t)
  1194. end
  1195. end
  1196. #
  1197. # Test Range cycle
  1198. #
  1199. def test_range_cycle
  1200. #
  1201. # From Minero Aoki [ruby-core:02306]
  1202. #
  1203. assert_cycle("a".."z")
  1204. #
  1205. # From Nobu Nakada [ruby-core:02311]
  1206. #
  1207. assert_cycle(0..1)
  1208. assert_cycle(1.0e20 .. 2.0e20)
  1209. assert_cycle("0".."1")
  1210. assert_cycle(".."..."...")
  1211. assert_cycle(".rb"..".pl")
  1212. assert_cycle(".rb"...".pl")
  1213. assert_cycle('"'...".")
  1214. assert_cycle("'"...".")
  1215. end
  1216. #
  1217. # Circular references
  1218. #
  1219. def test_circular_references
  1220. a = []; a[0] = a; a[1] = a
  1221. inspect_str = "[[...], [...]]"
  1222. assert_equal( inspect_str, YAML::load( a.to_yaml ).inspect )
  1223. end
  1224. #
  1225. # Test Symbol cycle
  1226. #
  1227. def test_symbol_cycle
  1228. #
  1229. # From Aaron Schrab [ruby-Bugs:2535]
  1230. #
  1231. assert_cycle(:"^foo")
  1232. end
  1233. #
  1234. # Test Numeric cycle
  1235. #
  1236. class NumericTest < Numeric
  1237. def initialize(value)
  1238. @value = value
  1239. end
  1240. def ==(other)
  1241. @value == other.instance_eval{ @value }
  1242. end
  1243. end
  1244. def test_numeric_cycle
  1245. assert_cycle(1) # Fixnum
  1246. assert_cycle(111111111111111111111111111111111) # Bignum
  1247. assert_cycle(NumericTest.new(3)) # Subclass of Numeric
  1248. end
  1249. #
  1250. # Test empty map/seq in map cycle
  1251. #
  1252. def test_empty_map_key
  1253. #
  1254. # empty seq as key
  1255. #
  1256. o = YAML.load({[]=>""}.to_yaml)
  1257. assert_equal(Hash, o.class)
  1258. assert_equal([[]], o.keys)
  1259. #
  1260. # empty map as key
  1261. #
  1262. o = YAML.load({{}=>""}.to_yaml)
  1263. assert_equal(Hash, o.class)
  1264. assert_equal([{}], o.keys)
  1265. end
  1266. #
  1267. # contributed by riley lynch [ruby-Bugs-8548]
  1268. #
  1269. def test_object_id_collision
  1270. omap = YAML::Omap.new
  1271. 1000.times { |i| omap["key_#{i}"] = { "value" => i } }
  1272. raise "id collision in ordered map" if omap.to_yaml =~ /id\d+/
  1273. end
  1274. def test_date_out_of_range
  1275. assert_nothing_raised{YAML::load('1900-01-01T00:00:00+00:00')}
  1276. end
  1277. def test_normal_exit
  1278. YAML.load("2000-01-01 00:00:00.#{"0"*1000} +00:00\n")
  1279. # '[ruby-core:13735]'
  1280. end
  1281. end
  1282. end