PageRenderTime 41ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/test/ruby/test_hash.rb

http://github.com/ruby/ruby
Ruby | 1852 lines | 1543 code | 300 blank | 9 comment | 28 complexity | fd7a85c2bf0b75eb2f377291bcede31f MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-3.0
  1. # -*- coding: us-ascii -*-
  2. # frozen_string_literal: false
  3. require 'test/unit'
  4. EnvUtil.suppress_warning {require 'continuation'}
  5. class TestHash < Test::Unit::TestCase
  6. def test_hash
  7. x = @cls[1=>2, 2=>4, 3=>6]
  8. y = @cls[1=>2, 2=>4, 3=>6] # y = {1, 2, 2, 4, 3, 6} # 1.9 doesn't support
  9. assert_equal(2, x[1])
  10. assert(begin
  11. for k,v in y
  12. raise if k*2 != v
  13. end
  14. true
  15. rescue
  16. false
  17. end)
  18. assert_equal(3, x.length)
  19. assert_send([x, :has_key?, 1])
  20. assert_send([x, :has_value?, 4])
  21. assert_equal([4,6], x.values_at(2,3))
  22. assert_equal({1=>2, 2=>4, 3=>6}, x)
  23. z = y.keys.join(":")
  24. assert_equal("1:2:3", z)
  25. z = y.values.join(":")
  26. assert_equal("2:4:6", z)
  27. assert_equal(x, y)
  28. y.shift
  29. assert_equal(2, y.length)
  30. z = [1,2]
  31. y[z] = 256
  32. assert_equal(256, y[z])
  33. x = Hash.new(0)
  34. x[1] = 1
  35. assert_equal(1, x[1])
  36. assert_equal(0, x[2])
  37. x = Hash.new([])
  38. assert_equal([], x[22])
  39. assert_same(x[22], x[22])
  40. x = Hash.new{[]}
  41. assert_equal([], x[22])
  42. assert_not_same(x[22], x[22])
  43. x = Hash.new{|h,kk| z = kk; h[kk] = kk*2}
  44. z = 0
  45. assert_equal(44, x[22])
  46. assert_equal(22, z)
  47. z = 0
  48. assert_equal(44, x[22])
  49. assert_equal(0, z)
  50. x.default = 5
  51. assert_equal(5, x[23])
  52. x = Hash.new
  53. def x.default(k)
  54. $z = k
  55. self[k] = k*2
  56. end
  57. $z = 0
  58. assert_equal(44, x[22])
  59. assert_equal(22, $z)
  60. $z = 0
  61. assert_equal(44, x[22])
  62. assert_equal(0, $z)
  63. end
  64. # From rubicon
  65. def setup
  66. @cls ||= Hash
  67. @h = @cls[
  68. 1 => 'one', 2 => 'two', 3 => 'three',
  69. self => 'self', true => 'true', nil => 'nil',
  70. 'nil' => nil
  71. ]
  72. @verbose = $VERBOSE
  73. $VERBOSE = nil
  74. end
  75. def teardown
  76. $VERBOSE = @verbose
  77. end
  78. def test_bad_initialize_copy
  79. h = Class.new(Hash) {
  80. def initialize_copy(h)
  81. super(Object.new)
  82. end
  83. }.new
  84. assert_raise(TypeError) { h.dup }
  85. end
  86. def test_clear_initialize_copy
  87. h = @cls[1=>2]
  88. h.instance_eval {initialize_copy({})}
  89. assert_empty(h)
  90. end
  91. def test_self_initialize_copy
  92. h = @cls[1=>2]
  93. h.instance_eval {initialize_copy(h)}
  94. assert_equal(2, h[1])
  95. end
  96. def test_dup_will_rehash
  97. set1 = @cls[]
  98. set2 = @cls[set1 => true]
  99. set1[set1] = true
  100. assert_equal set2, set2.dup
  101. end
  102. def test_s_AREF
  103. h = @cls["a" => 100, "b" => 200]
  104. assert_equal(100, h['a'])
  105. assert_equal(200, h['b'])
  106. assert_nil(h['c'])
  107. h = @cls.[]("a" => 100, "b" => 200)
  108. assert_equal(100, h['a'])
  109. assert_equal(200, h['b'])
  110. assert_nil(h['c'])
  111. h = @cls["a", 100, "b", 200]
  112. assert_equal(100, h['a'])
  113. assert_equal(200, h['b'])
  114. assert_nil(h['c'])
  115. h = @cls[[["a", 100], ["b", 200]]]
  116. assert_equal(100, h['a'])
  117. assert_equal(200, h['b'])
  118. assert_nil(h['c'])
  119. h = @cls[[["a", 100], ["b"], ["c", 300]]]
  120. assert_equal(100, h['a'])
  121. assert_equal(nil, h['b'])
  122. assert_equal(300, h['c'])
  123. assert_raise(ArgumentError) do
  124. @cls[[["a", 100], "b", ["c", 300]]]
  125. end
  126. end
  127. def test_s_AREF_duplicated_key
  128. alist = [["a", 100], ["b", 200], ["a", 300], ["a", 400]]
  129. h = @cls[alist]
  130. assert_equal(2, h.size)
  131. assert_equal(400, h['a'])
  132. assert_equal(200, h['b'])
  133. assert_nil(h['c'])
  134. assert_equal(nil, h.key('300'))
  135. end
  136. def test_s_AREF_frozen_key_id
  137. key = "a".freeze
  138. h = @cls[key, 100]
  139. assert_equal(100, h['a'])
  140. assert_same(key, *h.keys)
  141. end
  142. def test_s_AREF_key_tampering
  143. key = "a".dup
  144. h = @cls[key, 100]
  145. key.upcase!
  146. assert_equal(100, h['a'])
  147. end
  148. def test_s_new
  149. h = @cls.new
  150. assert_instance_of(@cls, h)
  151. assert_nil(h.default)
  152. assert_nil(h['spurious'])
  153. h = @cls.new('default')
  154. assert_instance_of(@cls, h)
  155. assert_equal('default', h.default)
  156. assert_equal('default', h['spurious'])
  157. end
  158. def test_try_convert
  159. assert_equal({1=>2}, Hash.try_convert({1=>2}))
  160. assert_equal(nil, Hash.try_convert("1=>2"))
  161. o = Object.new
  162. def o.to_hash; {3=>4} end
  163. assert_equal({3=>4}, Hash.try_convert(o))
  164. end
  165. def test_AREF # '[]'
  166. t = Time.now
  167. h = @cls[
  168. 1 => 'one', 2 => 'two', 3 => 'three',
  169. self => 'self', t => 'time', nil => 'nil',
  170. 'nil' => nil
  171. ]
  172. assert_equal('one', h[1])
  173. assert_equal('two', h[2])
  174. assert_equal('three', h[3])
  175. assert_equal('self', h[self])
  176. assert_equal('time', h[t])
  177. assert_equal('nil', h[nil])
  178. assert_equal(nil, h['nil'])
  179. assert_equal(nil, h['koala'])
  180. h1 = h.dup
  181. h1.default = :default
  182. assert_equal('one', h1[1])
  183. assert_equal('two', h1[2])
  184. assert_equal('three', h1[3])
  185. assert_equal('self', h1[self])
  186. assert_equal('time', h1[t])
  187. assert_equal('nil', h1[nil])
  188. assert_equal(nil, h1['nil'])
  189. assert_equal(:default, h1['koala'])
  190. end
  191. def test_ASET # '[]='
  192. t = Time.now
  193. h = @cls.new
  194. h[1] = 'one'
  195. h[2] = 'two'
  196. h[3] = 'three'
  197. h[self] = 'self'
  198. h[t] = 'time'
  199. h[nil] = 'nil'
  200. h['nil'] = nil
  201. assert_equal('one', h[1])
  202. assert_equal('two', h[2])
  203. assert_equal('three', h[3])
  204. assert_equal('self', h[self])
  205. assert_equal('time', h[t])
  206. assert_equal('nil', h[nil])
  207. assert_equal(nil, h['nil'])
  208. assert_equal(nil, h['koala'])
  209. h[1] = 1
  210. h[nil] = 99
  211. h['nil'] = nil
  212. z = [1,2]
  213. h[z] = 256
  214. assert_equal(1, h[1])
  215. assert_equal('two', h[2])
  216. assert_equal('three', h[3])
  217. assert_equal('self', h[self])
  218. assert_equal('time', h[t])
  219. assert_equal(99, h[nil])
  220. assert_equal(nil, h['nil'])
  221. assert_equal(nil, h['koala'])
  222. assert_equal(256, h[z])
  223. end
  224. def test_AREF_fstring_key
  225. # warmup ObjectSpace.count_objects
  226. ObjectSpace.count_objects
  227. h = {"abc" => 1}
  228. before = ObjectSpace.count_objects[:T_STRING]
  229. 5.times{ h["abc"] }
  230. assert_equal before, ObjectSpace.count_objects[:T_STRING]
  231. end
  232. def test_ASET_fstring_key
  233. a, b = {}, {}
  234. assert_equal 1, a["abc"] = 1
  235. assert_equal 1, b["abc"] = 1
  236. assert_same a.keys[0], b.keys[0]
  237. end
  238. def test_ASET_fstring_non_literal_key
  239. underscore = "_"
  240. non_literal_strings = Proc.new{ ["abc#{underscore}def", "abc" * 5, "abc" + "def", "" << "ghi" << "jkl"] }
  241. a, b = {}, {}
  242. non_literal_strings.call.each do |string|
  243. assert_equal 1, a[string] = 1
  244. end
  245. non_literal_strings.call.each do |string|
  246. assert_equal 1, b[string] = 1
  247. end
  248. [a.keys, b.keys].transpose.each do |key_a, key_b|
  249. assert_same key_a, key_b
  250. end
  251. end
  252. def test_hash_aset_fstring_identity
  253. h = {}.compare_by_identity
  254. h['abc'] = 1
  255. h['abc'] = 2
  256. assert_equal 2, h.size, '[ruby-core:78783] [Bug #12855]'
  257. end
  258. def test_hash_aref_fstring_identity
  259. h = {}.compare_by_identity
  260. h['abc'] = 1
  261. assert_nil h['abc'], '[ruby-core:78783] [Bug #12855]'
  262. end
  263. def test_NEWHASH_fstring_key
  264. a = {"ABC" => :t}
  265. b = {"ABC" => :t}
  266. assert_same a.keys[0], b.keys[0]
  267. assert_same "ABC".freeze, a.keys[0]
  268. var = +'ABC'
  269. c = { var => :t }
  270. assert_same "ABC".freeze, c.keys[0]
  271. end
  272. def test_EQUAL # '=='
  273. h1 = @cls[ "a" => 1, "c" => 2 ]
  274. h2 = @cls[ "a" => 1, "c" => 2, 7 => 35 ]
  275. h3 = @cls[ "a" => 1, "c" => 2, 7 => 35 ]
  276. h4 = @cls[ ]
  277. assert_equal(h1, h1)
  278. assert_equal(h2, h2)
  279. assert_equal(h3, h3)
  280. assert_equal(h4, h4)
  281. assert_not_equal(h1, h2)
  282. assert_equal(h2, h3)
  283. assert_not_equal(h3, h4)
  284. end
  285. def test_clear
  286. assert_operator(@h.size, :>, 0)
  287. @h.clear
  288. assert_equal(0, @h.size)
  289. assert_nil(@h[1])
  290. end
  291. def test_clone
  292. for frozen in [ false, true ]
  293. a = @h.clone
  294. a.freeze if frozen
  295. b = a.clone
  296. assert_equal(a, b)
  297. assert_not_same(a, b)
  298. assert_equal(a.frozen?, b.frozen?)
  299. end
  300. end
  301. def test_default
  302. assert_nil(@h.default)
  303. h = @cls.new(:xyzzy)
  304. assert_equal(:xyzzy, h.default)
  305. end
  306. def test_default=
  307. assert_nil(@h.default)
  308. @h.default = :xyzzy
  309. assert_equal(:xyzzy, @h.default)
  310. end
  311. def test_delete
  312. h1 = @cls[ 1 => 'one', 2 => 'two', true => 'true' ]
  313. h2 = @cls[ 1 => 'one', 2 => 'two' ]
  314. h3 = @cls[ 2 => 'two' ]
  315. assert_equal('true', h1.delete(true))
  316. assert_equal(h2, h1)
  317. assert_equal('one', h1.delete(1))
  318. assert_equal(h3, h1)
  319. assert_equal('two', h1.delete(2))
  320. assert_equal(@cls[], h1)
  321. assert_nil(h1.delete(99))
  322. assert_equal(@cls[], h1)
  323. assert_equal('default 99', h1.delete(99) {|i| "default #{i}" })
  324. end
  325. def test_delete_if
  326. base = @cls[ 1 => 'one', 2 => false, true => 'true', 'cat' => 99 ]
  327. h1 = @cls[ 1 => 'one', 2 => false, true => 'true' ]
  328. h2 = @cls[ 2 => false, 'cat' => 99 ]
  329. h3 = @cls[ 2 => false ]
  330. h = base.dup
  331. assert_equal(h, h.delete_if { false })
  332. assert_equal(@cls[], h.delete_if { true })
  333. h = base.dup
  334. assert_equal(h1, h.delete_if {|k,v| k.instance_of?(String) })
  335. assert_equal(h1, h)
  336. h = base.dup
  337. assert_equal(h2, h.delete_if {|k,v| v.instance_of?(String) })
  338. assert_equal(h2, h)
  339. h = base.dup
  340. assert_equal(h3, h.delete_if {|k,v| v })
  341. assert_equal(h3, h)
  342. h = base.dup
  343. n = 0
  344. h.delete_if {|*a|
  345. n += 1
  346. assert_equal(2, a.size)
  347. assert_equal(base[a[0]], a[1])
  348. h.shift
  349. true
  350. }
  351. assert_equal(base.size, n)
  352. end
  353. def test_keep_if
  354. h = @cls[1=>2,3=>4,5=>6]
  355. assert_equal({3=>4,5=>6}, h.keep_if {|k, v| k + v >= 7 })
  356. h = @cls[1=>2,3=>4,5=>6]
  357. assert_equal({1=>2,3=>4,5=>6}, h.keep_if{true})
  358. end
  359. def test_compact
  360. h = @cls[a: 1, b: nil, c: false, d: true, e: nil]
  361. assert_equal({a: 1, c: false, d: true}, h.compact)
  362. assert_equal({a: 1, b: nil, c: false, d: true, e: nil}, h)
  363. assert_same(h, h.compact!)
  364. assert_equal({a: 1, c: false, d: true}, h)
  365. assert_nil(h.compact!)
  366. end
  367. def test_dup
  368. for frozen in [ false, true ]
  369. a = @h.dup
  370. a.freeze if frozen
  371. b = a.dup
  372. assert_equal(a, b)
  373. assert_not_same(a, b)
  374. assert_equal(false, b.frozen?)
  375. end
  376. end
  377. def test_dup_equality
  378. h = @cls['k' => 'v']
  379. assert_equal(h, h.dup)
  380. h1 = @cls[h => 1]
  381. assert_equal(h1, h1.dup)
  382. h[1] = 2
  383. assert_equal(h1, h1.dup)
  384. end
  385. def test_each
  386. count = 0
  387. @cls[].each { |k, v| count + 1 }
  388. assert_equal(0, count)
  389. h = @h
  390. h.each do |k, v|
  391. assert_equal(v, h.delete(k))
  392. end
  393. assert_equal(@cls[], h)
  394. h = @cls[]
  395. h[1] = 1
  396. h[2] = 2
  397. assert_equal([[1,1],[2,2]], h.each.to_a)
  398. end
  399. def test_each_key
  400. count = 0
  401. @cls[].each_key { |k| count + 1 }
  402. assert_equal(0, count)
  403. h = @h
  404. h.each_key do |k|
  405. h.delete(k)
  406. end
  407. assert_equal(@cls[], h)
  408. end
  409. def test_each_pair
  410. count = 0
  411. @cls[].each_pair { |k, v| count + 1 }
  412. assert_equal(0, count)
  413. h = @h
  414. h.each_pair do |k, v|
  415. assert_equal(v, h.delete(k))
  416. end
  417. assert_equal(@cls[], h)
  418. end
  419. def test_each_value
  420. res = []
  421. @cls[].each_value { |v| res << v }
  422. assert_equal(0, [].length)
  423. @h.each_value { |v| res << v }
  424. assert_equal(0, [].length)
  425. expected = []
  426. @h.each { |k, v| expected << v }
  427. assert_equal([], expected - res)
  428. assert_equal([], res - expected)
  429. end
  430. def test_empty?
  431. assert_empty(@cls[])
  432. assert_not_empty(@h)
  433. end
  434. def test_fetch
  435. assert_equal('gumbygumby', @h.fetch('gumby') {|k| k * 2 })
  436. assert_equal('pokey', @h.fetch('gumby', 'pokey'))
  437. assert_equal('one', @h.fetch(1))
  438. assert_equal(nil, @h.fetch('nil'))
  439. assert_equal('nil', @h.fetch(nil))
  440. end
  441. def test_fetch_error
  442. assert_raise(KeyError) { @cls[].fetch(1) }
  443. assert_raise(KeyError) { @h.fetch('gumby') }
  444. e = assert_raise(KeyError) { @h.fetch('gumby'*20) }
  445. assert_match(/key not found: "gumbygumby/, e.message)
  446. assert_match(/\.\.\.\z/, e.message)
  447. assert_same(@h, e.receiver)
  448. assert_equal('gumby'*20, e.key)
  449. end
  450. def test_key2?
  451. assert_not_send([@cls[], :key?, 1])
  452. assert_not_send([@cls[], :key?, nil])
  453. assert_send([@h, :key?, nil])
  454. assert_send([@h, :key?, 1])
  455. assert_not_send([@h, :key?, 'gumby'])
  456. end
  457. def test_value?
  458. assert_not_send([@cls[], :value?, 1])
  459. assert_not_send([@cls[], :value?, nil])
  460. assert_send([@h, :value?, 'one'])
  461. assert_send([@h, :value?, nil])
  462. assert_not_send([@h, :value?, 'gumby'])
  463. end
  464. def test_include?
  465. assert_not_send([@cls[], :include?, 1])
  466. assert_not_send([@cls[], :include?, nil])
  467. assert_send([@h, :include?, nil])
  468. assert_send([@h, :include?, 1])
  469. assert_not_send([@h, :include?, 'gumby'])
  470. end
  471. def test_key
  472. assert_equal(1, @h.key('one'))
  473. assert_equal(nil, @h.key('nil'))
  474. assert_equal('nil', @h.key(nil))
  475. assert_equal(nil, @h.key('gumby'))
  476. assert_equal(nil, @cls[].key('gumby'))
  477. end
  478. def test_values_at
  479. res = @h.values_at('dog', 'cat', 'horse')
  480. assert_equal(3, res.length)
  481. assert_equal([nil, nil, nil], res)
  482. res = @h.values_at
  483. assert_equal(0, res.length)
  484. res = @h.values_at(3, 2, 1, nil)
  485. assert_equal 4, res.length
  486. assert_equal %w( three two one nil ), res
  487. res = @h.values_at(3, 99, 1, nil)
  488. assert_equal 4, res.length
  489. assert_equal ['three', nil, 'one', 'nil'], res
  490. end
  491. def test_fetch_values
  492. res = @h.fetch_values
  493. assert_equal(0, res.length)
  494. res = @h.fetch_values(3, 2, 1, nil)
  495. assert_equal(4, res.length)
  496. assert_equal %w( three two one nil ), res
  497. e = assert_raise KeyError do
  498. @h.fetch_values(3, 'invalid')
  499. end
  500. assert_same(@h, e.receiver)
  501. assert_equal('invalid', e.key)
  502. res = @h.fetch_values(3, 'invalid') { |k| k.upcase }
  503. assert_equal %w( three INVALID ), res
  504. end
  505. def test_invert
  506. h = @h.invert
  507. assert_equal(1, h['one'])
  508. assert_equal(true, h['true'])
  509. assert_equal(nil, h['nil'])
  510. h.each do |k, v|
  511. assert_send([@h, :key?, v]) # not true in general, but works here
  512. end
  513. h = @cls[ 'a' => 1, 'b' => 2, 'c' => 1].invert
  514. assert_equal(2, h.length)
  515. assert_include(%w[a c], h[1])
  516. assert_equal('b', h[2])
  517. end
  518. def test_key?
  519. assert_not_send([@cls[], :key?, 1])
  520. assert_not_send([@cls[], :key?, nil])
  521. assert_send([@h, :key?, nil])
  522. assert_send([@h, :key?, 1])
  523. assert_not_send([@h, :key?, 'gumby'])
  524. end
  525. def test_keys
  526. assert_equal([], @cls[].keys)
  527. keys = @h.keys
  528. expected = []
  529. @h.each { |k, v| expected << k }
  530. assert_equal([], keys - expected)
  531. assert_equal([], expected - keys)
  532. end
  533. def test_length
  534. assert_equal(0, @cls[].length)
  535. assert_equal(7, @h.length)
  536. end
  537. def test_member?
  538. assert_not_send([@cls[], :member?, 1])
  539. assert_not_send([@cls[], :member?, nil])
  540. assert_send([@h, :member?, nil])
  541. assert_send([@h, :member?, 1])
  542. assert_not_send([@h, :member?, 'gumby'])
  543. end
  544. def hash_hint hv
  545. hv & 0xff
  546. end
  547. def test_rehash
  548. a = [ "a", "b" ]
  549. c = [ "c", "d" ]
  550. h = @cls[ a => 100, c => 300 ]
  551. assert_equal(100, h[a])
  552. hv = a.hash
  553. begin
  554. a[0] << "z"
  555. end while hash_hint(a.hash) == hash_hint(hv)
  556. assert_nil(h[a])
  557. h.rehash
  558. assert_equal(100, h[a])
  559. end
  560. def test_reject
  561. assert_equal({3=>4,5=>6}, @cls[1=>2,3=>4,5=>6].reject {|k, v| k + v < 7 })
  562. base = @cls[ 1 => 'one', 2 => false, true => 'true', 'cat' => 99 ]
  563. h1 = @cls[ 1 => 'one', 2 => false, true => 'true' ]
  564. h2 = @cls[ 2 => false, 'cat' => 99 ]
  565. h3 = @cls[ 2 => false ]
  566. h = base.dup
  567. assert_equal(h, h.reject { false })
  568. assert_equal(@cls[], h.reject { true })
  569. h = base.dup
  570. assert_equal(h1, h.reject {|k,v| k.instance_of?(String) })
  571. assert_equal(h2, h.reject {|k,v| v.instance_of?(String) })
  572. assert_equal(h3, h.reject {|k,v| v })
  573. assert_equal(base, h)
  574. h.instance_variable_set(:@foo, :foo)
  575. h.default = 42
  576. h = EnvUtil.suppress_warning {h.reject {false}}
  577. assert_instance_of(Hash, h)
  578. assert_nil(h.default)
  579. assert_not_send([h, :instance_variable_defined?, :@foo])
  580. end
  581. def test_reject!
  582. base = @cls[ 1 => 'one', 2 => false, true => 'true', 'cat' => 99 ]
  583. h1 = @cls[ 1 => 'one', 2 => false, true => 'true' ]
  584. h2 = @cls[ 2 => false, 'cat' => 99 ]
  585. h3 = @cls[ 2 => false ]
  586. h = base.dup
  587. assert_equal(nil, h.reject! { false })
  588. assert_equal(@cls[], h.reject! { true })
  589. h = base.dup
  590. assert_equal(h1, h.reject! {|k,v| k.instance_of?(String) })
  591. assert_equal(h1, h)
  592. h = base.dup
  593. assert_equal(h2, h.reject! {|k,v| v.instance_of?(String) })
  594. assert_equal(h2, h)
  595. h = base.dup
  596. assert_equal(h3, h.reject! {|k,v| v })
  597. assert_equal(h3, h)
  598. end
  599. def test_replace
  600. h = @cls[ 1 => 2, 3 => 4 ]
  601. h1 = h.replace(@cls[ 9 => 8, 7 => 6 ])
  602. assert_equal(h, h1)
  603. assert_equal(8, h[9])
  604. assert_equal(6, h[7])
  605. assert_nil(h[1])
  606. assert_nil(h[2])
  607. end
  608. def test_replace_bug9230
  609. h = @cls[]
  610. h.replace(@cls[])
  611. assert_empty h
  612. h = @cls[]
  613. h.replace(@cls[].compare_by_identity)
  614. assert_predicate(h, :compare_by_identity?)
  615. end
  616. def test_replace_bug15358
  617. h1 = {}
  618. h2 = {a:1,b:2,c:3,d:4,e:5}
  619. h2.replace(h1)
  620. GC.start
  621. assert(true)
  622. end
  623. def test_shift
  624. h = @h.dup
  625. @h.length.times {
  626. k, v = h.shift
  627. assert_send([@h, :key?, k])
  628. assert_equal(@h[k], v)
  629. }
  630. assert_equal(0, h.length)
  631. end
  632. def test_size
  633. assert_equal(0, @cls[].length)
  634. assert_equal(7, @h.length)
  635. end
  636. def test_sort
  637. h = @cls[].sort
  638. assert_equal([], h)
  639. h = @cls[ 1 => 1, 2 => 1 ].sort
  640. assert_equal([[1,1], [2,1]], h)
  641. h = @cls[ 'cat' => 'feline', 'ass' => 'asinine', 'bee' => 'beeline' ]
  642. h1 = h.sort
  643. assert_equal([ %w(ass asinine), %w(bee beeline), %w(cat feline)], h1)
  644. end
  645. def test_store
  646. t = Time.now
  647. h = @cls.new
  648. h.store(1, 'one')
  649. h.store(2, 'two')
  650. h.store(3, 'three')
  651. h.store(self, 'self')
  652. h.store(t, 'time')
  653. h.store(nil, 'nil')
  654. h.store('nil', nil)
  655. assert_equal('one', h[1])
  656. assert_equal('two', h[2])
  657. assert_equal('three', h[3])
  658. assert_equal('self', h[self])
  659. assert_equal('time', h[t])
  660. assert_equal('nil', h[nil])
  661. assert_equal(nil, h['nil'])
  662. assert_equal(nil, h['koala'])
  663. h.store(1, 1)
  664. h.store(nil, 99)
  665. h.store('nil', nil)
  666. assert_equal(1, h[1])
  667. assert_equal('two', h[2])
  668. assert_equal('three', h[3])
  669. assert_equal('self', h[self])
  670. assert_equal('time', h[t])
  671. assert_equal(99, h[nil])
  672. assert_equal(nil, h['nil'])
  673. assert_equal(nil, h['koala'])
  674. end
  675. def test_to_a
  676. assert_equal([], @cls[].to_a)
  677. assert_equal([[1,2]], @cls[ 1=>2 ].to_a)
  678. a = @cls[ 1=>2, 3=>4, 5=>6 ].to_a
  679. assert_equal([1,2], a.delete([1,2]))
  680. assert_equal([3,4], a.delete([3,4]))
  681. assert_equal([5,6], a.delete([5,6]))
  682. assert_equal(0, a.length)
  683. end
  684. def test_to_hash
  685. h = @h.to_hash
  686. assert_equal(@h, h)
  687. assert_instance_of(@cls, h)
  688. end
  689. def test_to_h
  690. h = @h.to_h
  691. assert_equal(@h, h)
  692. assert_instance_of(Hash, h)
  693. end
  694. def test_to_h_instance_variable
  695. @h.instance_variable_set(:@x, 42)
  696. h = @h.to_h
  697. if @cls == Hash
  698. assert_equal(42, h.instance_variable_get(:@x))
  699. else
  700. assert_not_send([h, :instance_variable_defined?, :@x])
  701. end
  702. end
  703. def test_to_h_default_value
  704. @h.default = :foo
  705. h = @h.to_h
  706. assert_equal(:foo, h.default)
  707. end
  708. def test_to_h_default_proc
  709. @h.default_proc = ->(_,k) {"nope#{k}"}
  710. h = @h.to_h
  711. assert_equal("nope42", h[42])
  712. end
  713. def test_to_h_block
  714. h = @h.to_h {|k, v| [k.to_s, v.to_s]}
  715. assert_equal({
  716. "1"=>"one", "2"=>"two", "3"=>"three", to_s=>"self",
  717. "true"=>"true", ""=>"nil", "nil"=>""
  718. },
  719. h)
  720. assert_instance_of(Hash, h)
  721. end
  722. def test_nil_to_h
  723. h = nil.to_h
  724. assert_equal({}, h)
  725. assert_nil(h.default)
  726. assert_nil(h.default_proc)
  727. end
  728. def test_to_s
  729. h = @cls[ 1 => 2, "cat" => "dog", 1.5 => :fred ]
  730. assert_equal(h.inspect, h.to_s)
  731. $, = ":"
  732. assert_equal(h.inspect, h.to_s)
  733. h = @cls[]
  734. assert_equal(h.inspect, h.to_s)
  735. ensure
  736. $, = nil
  737. end
  738. def test_update
  739. h1 = @cls[ 1 => 2, 2 => 3, 3 => 4 ]
  740. h2 = @cls[ 2 => 'two', 4 => 'four' ]
  741. ha = @cls[ 1 => 2, 2 => 'two', 3 => 4, 4 => 'four' ]
  742. hb = @cls[ 1 => 2, 2 => 3, 3 => 4, 4 => 'four' ]
  743. assert_equal(ha, h1.update(h2))
  744. assert_equal(ha, h1)
  745. h1 = @cls[ 1 => 2, 2 => 3, 3 => 4 ]
  746. h2 = @cls[ 2 => 'two', 4 => 'four' ]
  747. assert_equal(hb, h2.update(h1))
  748. assert_equal(hb, h2)
  749. end
  750. def test_value2?
  751. assert_not_send([@cls[], :value?, 1])
  752. assert_not_send([@cls[], :value?, nil])
  753. assert_send([@h, :value?, nil])
  754. assert_send([@h, :value?, 'one'])
  755. assert_not_send([@h, :value?, 'gumby'])
  756. end
  757. def test_values
  758. assert_equal([], @cls[].values)
  759. vals = @h.values
  760. expected = []
  761. @h.each { |k, v| expected << v }
  762. assert_equal([], vals - expected)
  763. assert_equal([], expected - vals)
  764. end
  765. def test_initialize_wrong_arguments
  766. assert_raise(ArgumentError) do
  767. Hash.new(0) { }
  768. end
  769. end
  770. def test_create
  771. assert_equal({1=>2, 3=>4}, @cls[[[1,2],[3,4]]])
  772. assert_raise(ArgumentError) { @cls[0, 1, 2] }
  773. assert_raise(ArgumentError) { @cls[[[0, 1], 2]] }
  774. bug5406 = '[ruby-core:39945]'
  775. assert_raise(ArgumentError, bug5406) { @cls[[[1, 2], [3, 4, 5]]] }
  776. assert_equal({1=>2, 3=>4}, @cls[1,2,3,4])
  777. o = Object.new
  778. def o.to_hash() {1=>2} end
  779. assert_equal({1=>2}, @cls[o], "[ruby-dev:34555]")
  780. end
  781. def test_rehash2
  782. h = @cls[1 => 2, 3 => 4]
  783. assert_equal(h.dup, h.rehash)
  784. assert_raise(RuntimeError) { h.each { h.rehash } }
  785. assert_equal({}, @cls[].rehash)
  786. end
  787. def test_fetch2
  788. assert_equal(:bar, @h.fetch(0, :foo) { :bar })
  789. end
  790. def test_default_proc
  791. h = @cls.new {|hh, k| hh + k + "baz" }
  792. assert_equal("foobarbaz", h.default_proc.call("foo", "bar"))
  793. assert_nil(h.default_proc = nil)
  794. assert_nil(h.default_proc)
  795. h.default_proc = ->(_,_){ true }
  796. assert_equal(true, h[:nope])
  797. h = @cls[]
  798. assert_nil(h.default_proc)
  799. end
  800. def test_shift2
  801. h = @cls.new {|hh, k| :foo }
  802. h[1] = 2
  803. assert_equal([1, 2], h.shift)
  804. assert_equal(:foo, h.shift)
  805. assert_equal(:foo, h.shift)
  806. h = @cls.new(:foo)
  807. h[1] = 2
  808. assert_equal([1, 2], h.shift)
  809. assert_equal(:foo, h.shift)
  810. assert_equal(:foo, h.shift)
  811. h =@cls[1=>2]
  812. h.each { assert_equal([1, 2], h.shift) }
  813. end
  814. def test_shift_none
  815. h = @cls.new {|hh, k| "foo"}
  816. def h.default(k = nil)
  817. super.upcase
  818. end
  819. assert_equal("FOO", h.shift)
  820. end
  821. def test_reject_bang2
  822. assert_equal({1=>2}, @cls[1=>2,3=>4].reject! {|k, v| k + v == 7 })
  823. assert_nil(@cls[1=>2,3=>4].reject! {|k, v| k == 5 })
  824. assert_nil(@cls[].reject! { })
  825. end
  826. def test_select
  827. assert_equal({3=>4,5=>6}, @cls[1=>2,3=>4,5=>6].select {|k, v| k + v >= 7 })
  828. base = @cls[ 1 => 'one', '2' => false, true => 'true', 'cat' => 99 ]
  829. h1 = @cls[ '2' => false, 'cat' => 99 ]
  830. h2 = @cls[ 1 => 'one', true => 'true' ]
  831. h3 = @cls[ 1 => 'one', true => 'true', 'cat' => 99 ]
  832. h = base.dup
  833. assert_equal(h, h.select { true })
  834. assert_equal(@cls[], h.select { false })
  835. h = base.dup
  836. assert_equal(h1, h.select {|k,v| k.instance_of?(String) })
  837. assert_equal(h2, h.select {|k,v| v.instance_of?(String) })
  838. assert_equal(h3, h.select {|k,v| v })
  839. assert_equal(base, h)
  840. h.instance_variable_set(:@foo, :foo)
  841. h.default = 42
  842. h = h.select {true}
  843. assert_instance_of(Hash, h)
  844. assert_nil(h.default)
  845. assert_not_send([h, :instance_variable_defined?, :@foo])
  846. end
  847. def test_select!
  848. h = @cls[1=>2,3=>4,5=>6]
  849. assert_equal(h, h.select! {|k, v| k + v >= 7 })
  850. assert_equal({3=>4,5=>6}, h)
  851. h = @cls[1=>2,3=>4,5=>6]
  852. assert_equal(nil, h.select!{true})
  853. end
  854. def test_slice
  855. h = @cls[1=>2,3=>4,5=>6]
  856. assert_equal({1=>2, 3=>4}, h.slice(1, 3))
  857. assert_equal({}, h.slice(7))
  858. assert_equal({}, h.slice)
  859. assert_equal({}, {}.slice)
  860. end
  861. def test_filter
  862. assert_equal({3=>4,5=>6}, @cls[1=>2,3=>4,5=>6].filter {|k, v| k + v >= 7 })
  863. base = @cls[ 1 => 'one', '2' => false, true => 'true', 'cat' => 99 ]
  864. h1 = @cls[ '2' => false, 'cat' => 99 ]
  865. h2 = @cls[ 1 => 'one', true => 'true' ]
  866. h3 = @cls[ 1 => 'one', true => 'true', 'cat' => 99 ]
  867. h = base.dup
  868. assert_equal(h, h.filter { true })
  869. assert_equal(@cls[], h.filter { false })
  870. h = base.dup
  871. assert_equal(h1, h.filter {|k,v| k.instance_of?(String) })
  872. assert_equal(h2, h.filter {|k,v| v.instance_of?(String) })
  873. assert_equal(h3, h.filter {|k,v| v })
  874. assert_equal(base, h)
  875. h.instance_variable_set(:@foo, :foo)
  876. h.default = 42
  877. h = h.filter {true}
  878. assert_instance_of(Hash, h)
  879. assert_nil(h.default)
  880. assert_not_send([h, :instance_variable_defined?, :@foo])
  881. end
  882. def test_filter!
  883. h = @cls[1=>2,3=>4,5=>6]
  884. assert_equal(h, h.filter! {|k, v| k + v >= 7 })
  885. assert_equal({3=>4,5=>6}, h)
  886. h = @cls[1=>2,3=>4,5=>6]
  887. assert_equal(nil, h.filter!{true})
  888. end
  889. def test_clear2
  890. assert_equal({}, @cls[1=>2,3=>4,5=>6].clear)
  891. h = @cls[1=>2,3=>4,5=>6]
  892. h.each { h.clear }
  893. assert_equal({}, h)
  894. end
  895. def test_replace2
  896. h1 = @cls.new { :foo }
  897. h2 = @cls.new
  898. h2.replace h1
  899. assert_equal(:foo, h2[0])
  900. assert_raise(ArgumentError) { h2.replace() }
  901. assert_raise(TypeError) { h2.replace(1) }
  902. h2.freeze
  903. assert_raise(ArgumentError) { h2.replace() }
  904. assert_raise(FrozenError) { h2.replace(h1) }
  905. assert_raise(FrozenError) { h2.replace(42) }
  906. end
  907. def test_size2
  908. assert_equal(0, @cls[].size)
  909. end
  910. def test_equal2
  911. assert_not_equal(0, @cls[])
  912. o = Object.new
  913. o.instance_variable_set(:@cls, @cls)
  914. def o.to_hash; @cls[]; end
  915. def o.==(x); true; end
  916. assert_equal({}, o)
  917. def o.==(x); false; end
  918. assert_not_equal({}, o)
  919. h1 = @cls[1=>2]; h2 = @cls[3=>4]
  920. assert_not_equal(h1, h2)
  921. h1 = @cls[1=>2]; h2 = @cls[1=>4]
  922. assert_not_equal(h1, h2)
  923. end
  924. def test_eql
  925. assert_not_send([@cls[], :eql?, 0])
  926. o = Object.new
  927. o.instance_variable_set(:@cls, @cls)
  928. def o.to_hash; @cls[]; end
  929. def o.eql?(x); true; end
  930. assert_send([@cls[], :eql?, o])
  931. def o.eql?(x); false; end
  932. assert_not_send([@cls[], :eql?, o])
  933. end
  934. def test_hash2
  935. assert_kind_of(Integer, @cls[].hash)
  936. h = @cls[1=>2]
  937. h.shift
  938. assert_equal({}.hash, h.hash, '[ruby-core:38650]')
  939. bug9231 = '[ruby-core:58993] [Bug #9231]'
  940. assert_not_equal(0, @cls[].hash, bug9231)
  941. end
  942. def test_update2
  943. h1 = @cls[1=>2, 3=>4]
  944. h2 = {1=>3, 5=>7}
  945. h1.update(h2) {|k, v1, v2| k + v1 + v2 }
  946. assert_equal({1=>6, 3=>4, 5=>7}, h1)
  947. end
  948. def test_update3
  949. h1 = @cls[1=>2, 3=>4]
  950. h1.update()
  951. assert_equal({1=>2, 3=>4}, h1)
  952. h2 = {1=>3, 5=>7}
  953. h3 = {1=>1, 2=>4}
  954. h1.update(h2, h3)
  955. assert_equal({1=>1, 2=>4, 3=>4, 5=>7}, h1)
  956. end
  957. def test_update4
  958. h1 = @cls[1=>2, 3=>4]
  959. h1.update(){|k, v1, v2| k + v1 + v2 }
  960. assert_equal({1=>2, 3=>4}, h1)
  961. h2 = {1=>3, 5=>7}
  962. h3 = {1=>1, 2=>4}
  963. h1.update(h2, h3){|k, v1, v2| k + v1 + v2 }
  964. assert_equal({1=>8, 2=>4, 3=>4, 5=>7}, h1)
  965. end
  966. def test_merge
  967. h1 = @cls[1=>2, 3=>4]
  968. h2 = {1=>3, 5=>7}
  969. h3 = {1=>1, 2=>4}
  970. assert_equal({1=>2, 3=>4}, h1.merge())
  971. assert_equal({1=>3, 3=>4, 5=>7}, h1.merge(h2))
  972. assert_equal({1=>6, 3=>4, 5=>7}, h1.merge(h2) {|k, v1, v2| k + v1 + v2 })
  973. assert_equal({1=>1, 2=>4, 3=>4, 5=>7}, h1.merge(h2, h3))
  974. assert_equal({1=>8, 2=>4, 3=>4, 5=>7}, h1.merge(h2, h3) {|k, v1, v2| k + v1 + v2 })
  975. end
  976. def test_assoc
  977. assert_equal([3,4], @cls[1=>2, 3=>4, 5=>6].assoc(3))
  978. assert_nil(@cls[1=>2, 3=>4, 5=>6].assoc(4))
  979. assert_equal([1.0,1], @cls[1.0=>1].assoc(1))
  980. end
  981. def test_assoc_compare_by_identity
  982. h = @cls[]
  983. h.compare_by_identity
  984. h["a"] = 1
  985. h["a".dup] = 2
  986. assert_equal(["a",1], h.assoc("a"))
  987. end
  988. def test_rassoc
  989. assert_equal([3,4], @cls[1=>2, 3=>4, 5=>6].rassoc(4))
  990. assert_nil({1=>2, 3=>4, 5=>6}.rassoc(3))
  991. end
  992. def test_flatten
  993. assert_equal([[1], [2]], @cls[[1] => [2]].flatten)
  994. a = @cls[1=> "one", 2 => [2,"two"], 3 => [3, ["three"]]]
  995. assert_equal([1, "one", 2, [2, "two"], 3, [3, ["three"]]], a.flatten)
  996. assert_equal([[1, "one"], [2, [2, "two"]], [3, [3, ["three"]]]], a.flatten(0))
  997. assert_equal([1, "one", 2, [2, "two"], 3, [3, ["three"]]], a.flatten(1))
  998. assert_equal([1, "one", 2, 2, "two", 3, 3, ["three"]], a.flatten(2))
  999. assert_equal([1, "one", 2, 2, "two", 3, 3, "three"], a.flatten(3))
  1000. assert_equal([1, "one", 2, 2, "two", 3, 3, "three"], a.flatten(-1))
  1001. assert_raise(TypeError){ a.flatten(nil) }
  1002. end
  1003. def test_flatten_arity
  1004. a = @cls[1=> "one", 2 => [2,"two"], 3 => [3, ["three"]]]
  1005. assert_raise(ArgumentError){ a.flatten(1, 2) }
  1006. end
  1007. def test_callcc
  1008. h = @cls[1=>2]
  1009. c = nil
  1010. f = false
  1011. h.each { callcc {|c2| c = c2 } }
  1012. unless f
  1013. f = true
  1014. c.call
  1015. end
  1016. assert_raise(RuntimeError) { h.each { h.rehash } }
  1017. h = @cls[1=>2]
  1018. c = nil
  1019. assert_raise(RuntimeError) do
  1020. h.each { callcc {|c2| c = c2 } }
  1021. h.clear
  1022. c.call
  1023. end
  1024. end
  1025. def test_callcc_iter_level
  1026. bug9105 = '[ruby-dev:47803] [Bug #9105]'
  1027. h = @cls[1=>2, 3=>4]
  1028. c = nil
  1029. f = false
  1030. h.each {callcc {|c2| c = c2}}
  1031. unless f
  1032. f = true
  1033. c.call
  1034. end
  1035. assert_nothing_raised(RuntimeError, bug9105) do
  1036. h.each {|i, j|
  1037. h.delete(i);
  1038. assert_not_equal(false, i, bug9105)
  1039. }
  1040. end
  1041. end
  1042. def test_callcc_escape
  1043. bug9105 = '[ruby-dev:47803] [Bug #9105]'
  1044. assert_nothing_raised(RuntimeError, bug9105) do
  1045. h=@cls[]
  1046. cnt=0
  1047. c = callcc {|cc|cc}
  1048. h[cnt] = true
  1049. h.each{|i|
  1050. cnt+=1
  1051. c.call if cnt == 1
  1052. }
  1053. end
  1054. end
  1055. def test_callcc_reenter
  1056. bug9105 = '[ruby-dev:47803] [Bug #9105]'
  1057. assert_nothing_raised(RuntimeError, bug9105) do
  1058. h = @cls[1=>2,3=>4]
  1059. c = nil
  1060. f = false
  1061. h.each { |i|
  1062. callcc {|c2| c = c2 } unless c
  1063. h.delete(1) if f
  1064. }
  1065. unless f
  1066. f = true
  1067. c.call
  1068. end
  1069. end
  1070. end
  1071. def test_threaded_iter_level
  1072. bug9105 = '[ruby-dev:47807] [Bug #9105]'
  1073. h = @cls[1=>2]
  1074. 2.times.map {
  1075. f = false
  1076. th = Thread.start {h.each {f = true; sleep}}
  1077. Thread.pass until f
  1078. Thread.pass until th.stop?
  1079. th
  1080. }.each {|th| th.run; th.join}
  1081. assert_nothing_raised(RuntimeError, bug9105) do
  1082. h[5] = 6
  1083. end
  1084. assert_equal(6, h[5], bug9105)
  1085. end
  1086. def test_compare_by_identity
  1087. a = "foo"
  1088. assert_not_predicate(@cls[], :compare_by_identity?)
  1089. h = @cls[a => "bar"]
  1090. assert_not_predicate(h, :compare_by_identity?)
  1091. h.compare_by_identity
  1092. assert_predicate(h, :compare_by_identity?)
  1093. #assert_equal("bar", h[a])
  1094. assert_nil(h["foo"])
  1095. bug8703 = '[ruby-core:56256] [Bug #8703] copied identhash'
  1096. h.clear
  1097. assert_predicate(h.dup, :compare_by_identity?, bug8703)
  1098. end
  1099. def test_same_key
  1100. bug9646 = '[ruby-dev:48047] [Bug #9646] Infinite loop at Hash#each'
  1101. h = @cls[a=[], 1]
  1102. a << 1
  1103. h[[]] = 2
  1104. a.clear
  1105. cnt = 0
  1106. r = h.each{ break nil if (cnt+=1) > 100 }
  1107. assert_not_nil(r,bug9646)
  1108. end
  1109. class ObjWithHash
  1110. def initialize(value, hash)
  1111. @value = value
  1112. @hash = hash
  1113. end
  1114. attr_reader :value, :hash
  1115. def eql?(other)
  1116. @value == other.value
  1117. end
  1118. end
  1119. def test_hash_hash
  1120. assert_equal({0=>2,11=>1}.hash, @cls[11=>1,0=>2].hash)
  1121. o1 = ObjWithHash.new(0,1)
  1122. o2 = ObjWithHash.new(11,1)
  1123. assert_equal({o1=>1,o2=>2}.hash, @cls[o2=>2,o1=>1].hash)
  1124. end
  1125. def test_hash_bignum_hash
  1126. x = 2<<(32-3)-1
  1127. assert_equal({x=>1}.hash, @cls[x=>1].hash)
  1128. x = 2<<(64-3)-1
  1129. assert_equal({x=>1}.hash, @cls[x=>1].hash)
  1130. o = Object.new
  1131. def o.hash; 2 << 100; end
  1132. assert_equal({o=>1}.hash, @cls[o=>1].hash)
  1133. end
  1134. def test_hash_popped
  1135. assert_nothing_raised { eval("a = 1; @cls[a => a]; a") }
  1136. end
  1137. def test_recursive_key
  1138. h = @cls[]
  1139. assert_nothing_raised { h[h] = :foo }
  1140. h.rehash
  1141. assert_equal(:foo, h[h])
  1142. end
  1143. def test_inverse_hash
  1144. feature4262 = '[ruby-core:34334]'
  1145. [@cls[1=>2], @cls[123=>"abc"]].each do |h|
  1146. assert_not_equal(h.hash, h.invert.hash, feature4262)
  1147. end
  1148. end
  1149. def test_recursive_hash_value_struct
  1150. bug9151 = '[ruby-core:58567] [Bug #9151]'
  1151. s = Struct.new(:x) {def hash; [x,""].hash; end}
  1152. a = s.new
  1153. b = s.new
  1154. a.x = b
  1155. b.x = a
  1156. assert_nothing_raised(SystemStackError, bug9151) {a.hash}
  1157. assert_nothing_raised(SystemStackError, bug9151) {b.hash}
  1158. h = @cls[]
  1159. h[[a,"hello"]] = 1
  1160. assert_equal(1, h.size)
  1161. h[[b,"world"]] = 2
  1162. assert_equal(2, h.size)
  1163. obj = Object.new
  1164. h = @cls[a => obj]
  1165. assert_same(obj, h[b])
  1166. end
  1167. def test_recursive_hash_value_array
  1168. h = @cls[]
  1169. h[[[1]]] = 1
  1170. assert_equal(1, h.size)
  1171. h[[[2]]] = 1
  1172. assert_equal(2, h.size)
  1173. a = []
  1174. a << a
  1175. h = @cls[]
  1176. h[[a, 1]] = 1
  1177. assert_equal(1, h.size)
  1178. h[[a, 2]] = 2
  1179. assert_equal(2, h.size)
  1180. h[[a, a]] = 3
  1181. assert_equal(3, h.size)
  1182. obj = Object.new
  1183. h = @cls[a => obj]
  1184. assert_same(obj, h[[[a]]])
  1185. end
  1186. def test_recursive_hash_value_array_hash
  1187. h = @cls[]
  1188. rec = [h]
  1189. h[:x] = rec
  1190. obj = Object.new
  1191. h2 = {rec => obj}
  1192. [h, {x: rec}].each do |k|
  1193. k = [k]
  1194. assert_same(obj, h2[k], ->{k.inspect})
  1195. end
  1196. end
  1197. def test_recursive_hash_value_hash_array
  1198. h = @cls[]
  1199. rec = [h]
  1200. h[:x] = rec
  1201. obj = Object.new
  1202. h2 = {h => obj}
  1203. [rec, [h]].each do |k|
  1204. k = {x: k}
  1205. assert_same(obj, h2[k], ->{k.inspect})
  1206. end
  1207. end
  1208. def test_exception_in_rehash_memory_leak
  1209. return unless @cls == Hash
  1210. bug9187 = '[ruby-core:58728] [Bug #9187]'
  1211. prepare = <<-EOS
  1212. class Foo
  1213. def initialize
  1214. @raise = false
  1215. end
  1216. def hash
  1217. raise if @raise
  1218. @raise = true
  1219. return 0
  1220. end
  1221. end
  1222. h = {Foo.new => true}
  1223. EOS
  1224. code = <<-EOS
  1225. 10_0000.times do
  1226. h.rehash rescue nil
  1227. end
  1228. GC.start
  1229. EOS
  1230. assert_no_memory_leak([], prepare, code, bug9187)
  1231. end
  1232. def test_wrapper
  1233. bug9381 = '[ruby-core:59638] [Bug #9381]'
  1234. wrapper = Class.new do
  1235. def initialize(obj)
  1236. @obj = obj
  1237. end
  1238. def hash
  1239. @obj.hash
  1240. end
  1241. def eql?(other)
  1242. @obj.eql?(other)
  1243. end
  1244. end
  1245. bad = [
  1246. 5, true, false, nil,
  1247. 0.0, 1.72723e-77,
  1248. :foo, "dsym_#{self.object_id.to_s(16)}_#{Time.now.to_i.to_s(16)}".to_sym,
  1249. "str",
  1250. ].select do |x|
  1251. hash = {x => bug9381}
  1252. hash[wrapper.new(x)] != bug9381
  1253. end
  1254. assert_empty(bad, bug9381)
  1255. end
  1256. def assert_hash_random(obj, dump = obj.inspect)
  1257. a = [obj.hash.to_s]
  1258. 3.times {
  1259. assert_in_out_err(["-e", "print (#{dump}).hash"], "") do |r, e|
  1260. a += r
  1261. assert_equal([], e)
  1262. end
  1263. }
  1264. assert_not_equal([obj.hash.to_s], a.uniq)
  1265. assert_operator(a.uniq.size, :>, 2, proc {a.inspect})
  1266. end
  1267. def test_string_hash_random
  1268. assert_hash_random('abc')
  1269. end
  1270. def test_symbol_hash_random
  1271. assert_hash_random(:-)
  1272. assert_hash_random(:foo)
  1273. assert_hash_random("dsym_#{self.object_id.to_s(16)}_#{Time.now.to_i.to_s(16)}".to_sym)
  1274. end
  1275. def test_integer_hash_random
  1276. assert_hash_random(0)
  1277. assert_hash_random(+1)
  1278. assert_hash_random(-1)
  1279. assert_hash_random(+(1<<100))
  1280. assert_hash_random(-(1<<100))
  1281. end
  1282. def test_float_hash_random
  1283. assert_hash_random(0.0)
  1284. assert_hash_random(+1.0)
  1285. assert_hash_random(-1.0)
  1286. assert_hash_random(1.72723e-77)
  1287. assert_hash_random(Float::INFINITY, "Float::INFINITY")
  1288. end
  1289. def test_label_syntax
  1290. return unless @cls == Hash
  1291. feature4935 = '[ruby-core:37553] [Feature #4935]'
  1292. x = 'world'
  1293. hash = assert_nothing_raised(SyntaxError, feature4935) do
  1294. break eval(%q({foo: 1, "foo-bar": 2, "hello-#{x}": 3, 'hello-#{x}': 4, 'bar': {}}))
  1295. end
  1296. assert_equal({:foo => 1, :'foo-bar' => 2, :'hello-world' => 3, :'hello-#{x}' => 4, :bar => {}}, hash, feature4935)
  1297. x = x
  1298. end
  1299. def test_dig
  1300. h = @cls[a: @cls[b: [1, 2, 3]], c: 4]
  1301. assert_equal(1, h.dig(:a, :b, 0))
  1302. assert_nil(h.dig(:b, 1))
  1303. assert_raise(TypeError) {h.dig(:c, 1)}
  1304. o = Object.new
  1305. def o.dig(*args)
  1306. {dug: args}
  1307. end
  1308. h[:d] = o
  1309. assert_equal({dug: [:foo, :bar]}, h.dig(:d, :foo, :bar))
  1310. end
  1311. def test_dig_with_respond_to
  1312. bug12030 = '[ruby-core:73556] [Bug #12030]'
  1313. o = Object.new
  1314. def o.respond_to?(*args)
  1315. super
  1316. end
  1317. assert_raise(TypeError, bug12030) {{foo: o}.dig(:foo, :foo)}
  1318. end
  1319. def test_cmp
  1320. h1 = {a:1, b:2}
  1321. h2 = {a:1, b:2, c:3}
  1322. assert_operator(h1, :<=, h1)
  1323. assert_operator(h1, :<=, h2)
  1324. assert_not_operator(h2, :<=, h1)
  1325. assert_operator(h2, :<=, h2)
  1326. assert_operator(h1, :>=, h1)
  1327. assert_not_operator(h1, :>=, h2)
  1328. assert_operator(h2, :>=, h1)
  1329. assert_operator(h2, :>=, h2)
  1330. assert_not_operator(h1, :<, h1)
  1331. assert_operator(h1, :<, h2)
  1332. assert_not_operator(h2, :<, h1)
  1333. assert_not_operator(h2, :<, h2)
  1334. assert_not_operator(h1, :>, h1)
  1335. assert_not_operator(h1, :>, h2)
  1336. assert_operator(h2, :>, h1)
  1337. assert_not_operator(h2, :>, h2)
  1338. end
  1339. def test_cmp_samekeys
  1340. h1 = {a:1}
  1341. h2 = {a:2}
  1342. assert_operator(h1, :<=, h1)
  1343. assert_not_operator(h1, :<=, h2)
  1344. assert_not_operator(h2, :<=, h1)
  1345. assert_operator(h2, :<=, h2)
  1346. assert_operator(h1, :>=, h1)
  1347. assert_not_operator(h1, :>=, h2)
  1348. assert_not_operator(h2, :>=, h1)
  1349. assert_operator(h2, :>=, h2)
  1350. assert_not_operator(h1, :<, h1)
  1351. assert_not_operator(h1, :<, h2)
  1352. assert_not_operator(h2, :<, h1)
  1353. assert_not_operator(h2, :<, h2)
  1354. assert_not_operator(h1, :>, h1)
  1355. assert_not_operator(h1, :>, h2)
  1356. assert_not_operator(h2, :>, h1)
  1357. assert_not_operator(h2, :>, h2)
  1358. end
  1359. def test_to_proc
  1360. h = {
  1361. 1 => 10,
  1362. 2 => 20,
  1363. 3 => 30,
  1364. }
  1365. assert_equal([10, 20, 30], [1, 2, 3].map(&h))
  1366. assert_equal(true, h.to_proc.lambda?)
  1367. end
  1368. def test_transform_keys
  1369. x = @cls[a: 1, b: 2, c: 3]
  1370. y = x.transform_keys {|k| :"#{k}!" }
  1371. assert_equal({a: 1, b: 2, c: 3}, x)
  1372. assert_equal({a!: 1, b!: 2, c!: 3}, y)
  1373. enum = x.transform_keys
  1374. assert_equal(x.size, enum.size)
  1375. assert_instance_of(Enumerator, enum)
  1376. y = x.transform_keys.with_index {|k, i| "#{k}.#{i}" }
  1377. assert_equal(%w(a.0 b.1 c.2), y.keys)
  1378. assert_equal({A: 1, B: 2, c: 3}, x.transform_keys({a: :A, b: :B, d: :D}))
  1379. assert_equal({A: 1, B: 2, "c" => 3}, x.transform_keys({a: :A, b: :B, d: :D}, &:to_s))
  1380. end
  1381. def test_transform_keys_bang
  1382. x = @cls[a: 1, b: 2, c: 3]
  1383. y = x.transform_keys! {|k| :"#{k}!" }
  1384. assert_equal({a!: 1, b!: 2, c!: 3}, x)
  1385. assert_same(x, y)
  1386. enum = x.transform_keys!
  1387. assert_equal(x.size, enum.size)
  1388. assert_instance_of(Enumerator, enum)
  1389. x.transform_keys!.with_index {|k, i| "#{k}.#{i}" }
  1390. assert_equal(%w(a!.0 b!.1 c!.2), x.keys)
  1391. x = @cls[1 => :a, -1 => :b]
  1392. x.transform_keys! {|k| -k }
  1393. assert_equal([-1, :a, 1, :b], x.flatten)
  1394. x = @cls[true => :a, false => :b]
  1395. x.transform_keys! {|k| !k }
  1396. assert_equal([false, :a, true, :b], x.flatten)
  1397. x = @cls[a: 1, b: 2, c: 3]
  1398. x.transform_keys!({a: :A, b: :B, d: :D})
  1399. assert_equal({A: 1, B: 2, c: 3}, x)
  1400. x = @cls[a: 1, b: 2, c: 3]
  1401. x.transform_keys!({a: :A, b: :B, d: :D}, &:to_s)
  1402. assert_equal({A: 1, B: 2, "c" => 3}, x)
  1403. end
  1404. def test_transform_values
  1405. x = @cls[a: 1, b: 2, c: 3]
  1406. x.default = 42
  1407. y = x.transform_values {|v| v ** 2 }
  1408. assert_equal([1, 4, 9], y.values_at(:a, :b, :c))
  1409. assert_not_same(x, y)
  1410. assert_nil(y.default)
  1411. x.default_proc = proc {|h, k| k}
  1412. y = x.transform_values {|v| v ** 2 }
  1413. assert_nil(y.default_proc)
  1414. y = x.transform_values.with_index {|v, i| "#{v}.#{i}" }
  1415. assert_equal(%w(1.0 2.1 3.2), y.values_at(:a, :b, :c))
  1416. end
  1417. def test_transform_values_bang
  1418. x = @cls[a: 1, b: 2, c: 3]
  1419. y = x.transform_values! {|v| v ** 2 }
  1420. assert_equal([1, 4, 9], y.values_at(:a, :b, :c))
  1421. assert_same(x, y)
  1422. x = @cls[a: 1, b: 2, c: 3]
  1423. y = x.transform_values!.with_index {|v, i| "#{v}.#{i}" }
  1424. assert_equal(%w(1.0 2.1 3.2), y.values_at(:a, :b, :c))
  1425. end
  1426. def test_broken_hash_value
  1427. bug14218 = '[ruby-core:84395] [Bug #14218]'
  1428. assert_equal(0, 1_000_000.times.count{a=Object.new.hash; b=Object.new.hash; a < 0 && b < 0 && a + b > 0}, bug14218)
  1429. assert_equal(0, 1_000_000.times.count{a=Object.new.hash; b=Object.new.hash; 0 + a + b != 0 + b + a}, bug14218)
  1430. end
  1431. def test_reserved_hash_val
  1432. s = Struct.new(:hash)
  1433. h = {}
  1434. keys = [*0..8]
  1435. keys.each {|i| h[s.new(i)]=true}
  1436. msg = proc {h.inspect}
  1437. assert_equal(keys, h.keys.map(&:hash), msg)
  1438. end
  1439. def hrec h, n, &b
  1440. if n > 0
  1441. h.each{hrec(h, n-1, &b)}
  1442. else
  1443. yield
  1444. end
  1445. end
  1446. def test_huge_iter_level
  1447. nrec = 200
  1448. h = @cls[a: 1]
  1449. hrec(h, nrec){}
  1450. h[:c] = 3
  1451. assert_equal(3, h[:c])
  1452. h = @cls[a: 1]
  1453. h.freeze # set hidden attribute for a frozen object
  1454. hrec(h, nrec){}
  1455. assert_equal(1, h.size)
  1456. h = @cls[a: 1]
  1457. assert_raise(RuntimeError){
  1458. hrec(h, nrec){ h[:c] = 3 }
  1459. }
  1460. rescue SystemStackError
  1461. # ignore
  1462. end
  1463. class TestSubHash < TestHash
  1464. class SubHash < Hash
  1465. def reject(*)
  1466. super
  1467. end
  1468. end
  1469. def setup
  1470. @cls = SubHash
  1471. super
  1472. end
  1473. end
  1474. ruby2_keywords def get_flagged_hash(*args)
  1475. args.last
  1476. end
  1477. def check_flagged_hash(k: :NG)
  1478. k
  1479. end
  1480. def test_ruby2_keywords_hash?
  1481. flagged_hash = get_flagged_hash(k: 1)
  1482. assert_equal(true, Hash.ruby2_keywords_hash?(flagged_hash))
  1483. assert_equal(false, Hash.ruby2_keywords_hash?({}))
  1484. assert_raise(TypeError) { Hash.ruby2_keywords_hash?(1) }
  1485. end
  1486. def test_ruby2_keywords_hash
  1487. hash = {k: 1}
  1488. assert_equal(false, Hash.ruby2_keywords_hash?(hash))
  1489. hash = Hash.ruby2_keywords_hash(hash)
  1490. assert_equal(true, Hash.ruby2_keywords_hash?(hash))
  1491. assert_equal(1, check_flagged_hash(*[hash]))
  1492. assert_raise(TypeError) { Hash.ruby2_keywords_hash(1) }
  1493. end
  1494. def test_ar2st
  1495. # insert
  1496. obj = Object.new
  1497. obj.instance_variable_set(:@h, h = {})
  1498. def obj.hash
  1499. 10.times{|i| @h[i] = i}
  1500. 0
  1501. end
  1502. def obj.inspect
  1503. 'test'
  1504. end
  1505. h[obj] = true
  1506. assert_equal '{0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5, 6=>6, 7=>7, 8=>8, 9=>9, test=>true}', h.inspect
  1507. # delete
  1508. obj = Object.new
  1509. obj.instance_variable_set(:@h, h = {})
  1510. def obj.hash
  1511. 10.times{|i| @h[i] = i}
  1512. 0
  1513. end
  1514. def obj.inspect
  1515. 'test'
  1516. end
  1517. def obj.eql? other
  1518. other.class == Object
  1519. end
  1520. obj2 = Object.new
  1521. def obj2.hash
  1522. 0
  1523. end
  1524. h[obj2] = true
  1525. h.delete obj
  1526. assert_equal '{0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5, 6=>6, 7=>7, 8=>8, 9=>9}', h.inspect
  1527. # lookup
  1528. obj = Object.new
  1529. obj.instance_variable_set(:@h, h = {})
  1530. def obj.hash
  1531. 10.times{|i| @h[i] = i}
  1532. 0
  1533. end
  1534. def obj.inspect
  1535. 'test'
  1536. end
  1537. def obj.eql? other
  1538. other.class == Object
  1539. end
  1540. obj2 = Object.new
  1541. def obj2.hash
  1542. 0
  1543. end
  1544. h[obj2] = true
  1545. assert_equal true, h[obj]
  1546. end
  1547. def test_bug_12706
  1548. assert_raise(ArgumentError) do
  1549. {a: 1}.each(&->(k, v) {})
  1550. end
  1551. end
  1552. end