PageRenderTime 28ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/test/ruby/test_enumerator.rb

http://github.com/ruby/ruby
Ruby | 883 lines | 762 code | 105 blank | 16 comment | 6 complexity | 227e8c2733d17dffb804c8459a8c6274 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-3.0
  1. # frozen_string_literal: false
  2. require 'test/unit'
  3. class TestEnumerator < Test::Unit::TestCase
  4. def setup
  5. @obj = Object.new
  6. class << @obj
  7. include Enumerable
  8. def foo(*a)
  9. a.each {|x| yield x }
  10. end
  11. end
  12. @sized = @obj.clone
  13. def @sized.size
  14. 42
  15. end
  16. end
  17. def enum_test obj
  18. obj.map{|e|
  19. e
  20. }.sort
  21. end
  22. def test_iterators
  23. assert_equal [0, 1, 2], enum_test(3.times)
  24. assert_equal [:x, :y, :z], enum_test([:x, :y, :z].each)
  25. assert_equal [[:x, 1], [:y, 2]], enum_test({:x=>1, :y=>2}.each)
  26. end
  27. ## Enumerator as Iterator
  28. def test_next
  29. e = 3.times
  30. 3.times{|i|
  31. assert_equal i, e.next
  32. }
  33. assert_raise(StopIteration){e.next}
  34. end
  35. def test_loop
  36. e = 3.times
  37. i = 0
  38. loop{
  39. assert_equal(i, e.next)
  40. i += 1
  41. }
  42. end
  43. def test_loop_return_value
  44. assert_equal nil, loop { break }
  45. assert_equal 42, loop { break 42 }
  46. e = Enumerator.new { |y| y << 1; y << 2; :stopped }
  47. assert_equal :stopped, loop { e.next while true }
  48. end
  49. def test_nested_iteration
  50. def (o = Object.new).each
  51. yield :ok1
  52. yield [:ok2, :x].each.next
  53. end
  54. e = o.to_enum
  55. assert_equal :ok1, e.next
  56. assert_equal :ok2, e.next
  57. assert_raise(StopIteration){e.next}
  58. end
  59. def test_initialize
  60. assert_equal([1, 2, 3], @obj.to_enum(:foo, 1, 2, 3).to_a)
  61. _, err = capture_io do
  62. assert_equal([1, 2, 3], Enumerator.new(@obj, :foo, 1, 2, 3).to_a)
  63. end
  64. assert_match 'Enumerator.new without a block is deprecated', err
  65. assert_equal([1, 2, 3], Enumerator.new { |y| i = 0; loop { y << (i += 1) } }.take(3))
  66. assert_raise(ArgumentError) { Enumerator.new }
  67. enum = @obj.to_enum
  68. assert_raise(NoMethodError) { enum.each {} }
  69. enum.freeze
  70. assert_raise(FrozenError) {
  71. capture_io do
  72. # warning: Enumerator.new without a block is deprecated; use Object#to_enum
  73. enum.__send__(:initialize, @obj, :foo)
  74. end
  75. }
  76. end
  77. def test_initialize_copy
  78. assert_equal([1, 2, 3], @obj.to_enum(:foo, 1, 2, 3).dup.to_a)
  79. e = @obj.to_enum(:foo, 1, 2, 3)
  80. assert_nothing_raised { assert_equal(1, e.next) }
  81. assert_raise(TypeError) { e.dup }
  82. e = Enumerator.new { |y| i = 0; loop { y << (i += 1) } }.dup
  83. assert_nothing_raised { assert_equal(1, e.next) }
  84. assert_raise(TypeError) { e.dup }
  85. end
  86. def test_gc
  87. assert_nothing_raised do
  88. 1.times do
  89. foo = [1,2,3].to_enum
  90. GC.start
  91. foo
  92. end
  93. GC.start
  94. end
  95. end
  96. def test_slice
  97. assert_equal([[1,2,3],[4,5,6],[7,8,9],[10]], (1..10).each_slice(3).to_a)
  98. end
  99. def test_each_slice_size
  100. assert_equal(4, (1..10).each_slice(3).size)
  101. assert_equal(Float::INFINITY, 1.step.each_slice(3).size)
  102. end
  103. def test_cons
  104. a = [[1,2,3], [2,3,4], [3,4,5], [4,5,6], [5,6,7], [6,7,8], [7,8,9], [8,9,10]]
  105. assert_equal(a, (1..10).each_cons(3).to_a)
  106. end
  107. def test_with_index
  108. assert_equal([[1,0],[2,1],[3,2]], @obj.to_enum(:foo, 1, 2, 3).with_index.to_a)
  109. assert_equal([[1,5],[2,6],[3,7]], @obj.to_enum(:foo, 1, 2, 3).with_index(5).to_a)
  110. end
  111. def test_with_index_large_offset
  112. bug8010 = '[ruby-dev:47131] [Bug #8010]'
  113. s = 1 << (8*1.size-2)
  114. assert_equal([[1,s],[2,s+1],[3,s+2]], @obj.to_enum(:foo, 1, 2, 3).with_index(s).to_a, bug8010)
  115. s <<= 1
  116. assert_equal([[1,s],[2,s+1],[3,s+2]], @obj.to_enum(:foo, 1, 2, 3).with_index(s).to_a, bug8010)
  117. end
  118. def test_with_index_nonnum_offset
  119. bug8010 = '[ruby-dev:47131] [Bug #8010]'
  120. s = Object.new
  121. def s.to_int; 1 end
  122. assert_equal([[1,1],[2,2],[3,3]], @obj.to_enum(:foo, 1, 2, 3).with_index(s).to_a, bug8010)
  123. end
  124. def test_with_index_string_offset
  125. bug8010 = '[ruby-dev:47131] [Bug #8010]'
  126. assert_raise(TypeError, bug8010){ @obj.to_enum(:foo, 1, 2, 3).with_index('1').to_a }
  127. end
  128. def test_with_index_dangling_memo
  129. bug9178 = '[ruby-core:58692] [Bug #9178]'
  130. assert_separately([], <<-"end;")
  131. bug = "#{bug9178}"
  132. e = [1].to_enum(:chunk).with_index {|c,i| i == 5}
  133. assert_kind_of(Enumerator, e)
  134. assert_equal([false, [1]], e.to_a[0], bug)
  135. end;
  136. end
  137. def test_with_object
  138. obj = [0, 1]
  139. ret = (1..10).each.with_object(obj) {|i, memo|
  140. memo[0] += i
  141. memo[1] *= i
  142. }
  143. assert_same(obj, ret)
  144. assert_equal([55, 3628800], ret)
  145. a = [2,5,2,1,5,3,4,2,1,0]
  146. obj = {}
  147. ret = a.delete_if.with_object(obj) {|i, seen|
  148. if seen.key?(i)
  149. true
  150. else
  151. seen[i] = true
  152. false
  153. end
  154. }
  155. assert_same(obj, ret)
  156. assert_equal([2, 5, 1, 3, 4, 0], a)
  157. end
  158. def test_next_rewind
  159. e = @obj.to_enum(:foo, 1, 2, 3)
  160. assert_equal(1, e.next)
  161. assert_equal(2, e.next)
  162. e.rewind
  163. assert_equal(1, e.next)
  164. assert_equal(2, e.next)
  165. assert_equal(3, e.next)
  166. assert_raise(StopIteration) { e.next }
  167. end
  168. def test_peek
  169. a = [1]
  170. e = a.each
  171. assert_equal(1, e.peek)
  172. assert_equal(1, e.peek)
  173. assert_equal(1, e.next)
  174. assert_raise(StopIteration) { e.peek }
  175. assert_raise(StopIteration) { e.peek }
  176. end
  177. def test_peek_modify
  178. o = Object.new
  179. def o.each
  180. yield 1,2
  181. end
  182. e = o.to_enum
  183. a = e.peek
  184. a << 3
  185. assert_equal([1,2], e.peek)
  186. end
  187. def test_peek_values_modify
  188. o = Object.new
  189. def o.each
  190. yield 1,2
  191. end
  192. e = o.to_enum
  193. a = e.peek_values
  194. a << 3
  195. assert_equal([1,2], e.peek)
  196. end
  197. def test_next_after_stopiteration
  198. a = [1]
  199. e = a.each
  200. assert_equal(1, e.next)
  201. assert_raise(StopIteration) { e.next }
  202. assert_raise(StopIteration) { e.next }
  203. e.rewind
  204. assert_equal(1, e.next)
  205. assert_raise(StopIteration) { e.next }
  206. assert_raise(StopIteration) { e.next }
  207. end
  208. def test_stop_result
  209. a = [1]
  210. res = a.each {}
  211. e = a.each
  212. assert_equal(1, e.next)
  213. exc = assert_raise(StopIteration) { e.next }
  214. assert_equal(res, exc.result)
  215. end
  216. def test_next_values
  217. o = Object.new
  218. def o.each
  219. yield
  220. yield 1
  221. yield 1, 2
  222. end
  223. e = o.to_enum
  224. assert_equal(nil, e.next)
  225. assert_equal(1, e.next)
  226. assert_equal([1,2], e.next)
  227. e = o.to_enum
  228. assert_equal([], e.next_values)
  229. assert_equal([1], e.next_values)
  230. assert_equal([1,2], e.next_values)
  231. end
  232. def test_peek_values
  233. o = Object.new
  234. def o.each
  235. yield
  236. yield 1
  237. yield 1, 2
  238. end
  239. e = o.to_enum
  240. assert_equal(nil, e.peek)
  241. assert_equal(nil, e.next)
  242. assert_equal(1, e.peek)
  243. assert_equal(1, e.next)
  244. assert_equal([1,2], e.peek)
  245. assert_equal([1,2], e.next)
  246. e = o.to_enum
  247. assert_equal([], e.peek_values)
  248. assert_equal([], e.next_values)
  249. assert_equal([1], e.peek_values)
  250. assert_equal([1], e.next_values)
  251. assert_equal([1,2], e.peek_values)
  252. assert_equal([1,2], e.next_values)
  253. e = o.to_enum
  254. assert_equal([], e.peek_values)
  255. assert_equal(nil, e.next)
  256. assert_equal([1], e.peek_values)
  257. assert_equal(1, e.next)
  258. assert_equal([1,2], e.peek_values)
  259. assert_equal([1,2], e.next)
  260. e = o.to_enum
  261. assert_equal(nil, e.peek)
  262. assert_equal([], e.next_values)
  263. assert_equal(1, e.peek)
  264. assert_equal([1], e.next_values)
  265. assert_equal([1,2], e.peek)
  266. assert_equal([1,2], e.next_values)
  267. end
  268. def test_each_arg
  269. o = Object.new
  270. def o.each(ary)
  271. ary << 1
  272. yield
  273. end
  274. ary = []
  275. e = o.to_enum { 1 }
  276. assert_equal(1, e.size)
  277. e_arg = e.each(ary)
  278. assert_equal(nil, e_arg.size)
  279. e_arg.next
  280. assert_equal([1], ary)
  281. end
  282. def test_feed
  283. o = Object.new
  284. def o.each(ary)
  285. ary << yield
  286. ary << yield
  287. ary << yield
  288. end
  289. ary = []
  290. e = o.to_enum(:each, ary)
  291. e.next
  292. e.feed 1
  293. e.next
  294. e.feed 2
  295. e.next
  296. e.feed 3
  297. assert_raise(StopIteration) { e.next }
  298. assert_equal([1,2,3], ary)
  299. end
  300. def test_feed_mixed
  301. o = Object.new
  302. def o.each(ary)
  303. ary << yield
  304. ary << yield
  305. ary << yield
  306. end
  307. ary = []
  308. e = o.to_enum(:each, ary)
  309. e.next
  310. e.feed 1
  311. e.next
  312. e.next
  313. e.feed 3
  314. assert_raise(StopIteration) { e.next }
  315. assert_equal([1,nil,3], ary)
  316. end
  317. def test_feed_twice
  318. o = Object.new
  319. def o.each(ary)
  320. ary << yield
  321. ary << yield
  322. ary << yield
  323. end
  324. ary = []
  325. e = o.to_enum(:each, ary)
  326. e.feed 1
  327. assert_raise(TypeError) { e.feed 2 }
  328. end
  329. def test_feed_before_first_next
  330. o = Object.new
  331. def o.each(ary)
  332. ary << yield
  333. ary << yield
  334. ary << yield
  335. end
  336. ary = []
  337. e = o.to_enum(:each, ary)
  338. e.feed 1
  339. e.next
  340. e.next
  341. assert_equal([1], ary)
  342. end
  343. def test_rewind_clear_feed
  344. o = Object.new
  345. def o.each(ary)
  346. ary << yield
  347. ary << yield
  348. ary << yield
  349. end
  350. ary = []
  351. e = o.to_enum(:each, ary)
  352. e.next
  353. e.feed 1
  354. e.next
  355. e.feed 2
  356. e.rewind
  357. e.next
  358. e.next
  359. assert_equal([1,nil], ary)
  360. end
  361. def test_feed_yielder
  362. x = nil
  363. e = Enumerator.new {|y| x = y.yield; 10 }
  364. e.next
  365. e.feed 100
  366. exc = assert_raise(StopIteration) { e.next }
  367. assert_equal(100, x)
  368. assert_equal(10, exc.result)
  369. end
  370. def test_inspect
  371. e = (0..10).each_cons(2)
  372. assert_equal("#<Enumerator: 0..10:each_cons(2)>", e.inspect)
  373. e = (0..10).each_with_object({})
  374. assert_equal("#<Enumerator: 0..10:each_with_object({})>", e.inspect)
  375. e = (0..10).each_with_object(a: 1)
  376. assert_equal("#<Enumerator: 0..10:each_with_object(a: 1)>", e.inspect)
  377. e = Enumerator.new {|y| y.yield; 10 }
  378. assert_match(/\A#<Enumerator: .*:each>/, e.inspect)
  379. a = []
  380. e = a.each_with_object(a)
  381. a << e
  382. assert_equal("#<Enumerator: [#<Enumerator: ...>]:each_with_object([#<Enumerator: ...>])>",
  383. e.inspect)
  384. end
  385. def test_inspect_verbose
  386. bug6214 = '[ruby-dev:45449]'
  387. assert_warning("", bug6214) { "".bytes.inspect }
  388. assert_warning("", bug6214) { [].lazy.inspect }
  389. end
  390. def test_inspect_encoding
  391. c = Class.new{define_method("\u{3042}"){}}
  392. e = c.new.enum_for("\u{3042}")
  393. s = assert_nothing_raised(Encoding::CompatibilityError) {break e.inspect}
  394. assert_equal(Encoding::UTF_8, s.encoding)
  395. assert_match(/\A#<Enumerator: .*:\u{3042}>\z/, s)
  396. end
  397. def test_generator
  398. # note: Enumerator::Generator is a class just for internal
  399. g = Enumerator::Generator.new {|y| y << 1 << 2 << 3; :foo }
  400. g2 = g.dup
  401. a = []
  402. assert_equal(:foo, g.each {|x| a << x })
  403. assert_equal([1, 2, 3], a)
  404. a = []
  405. assert_equal(:foo, g2.each {|x| a << x })
  406. assert_equal([1, 2, 3], a)
  407. g.freeze
  408. assert_raise(FrozenError) {
  409. g.__send__ :initialize, proc { |y| y << 4 << 5 }
  410. }
  411. g = Enumerator::Generator.new(proc {|y| y << 4 << 5; :foo })
  412. a = []
  413. assert_equal(:foo, g.each {|x| a << x })
  414. assert_equal([4, 5], a)
  415. assert_raise(LocalJumpError) {Enumerator::Generator.new}
  416. assert_raise(TypeError) {Enumerator::Generator.new(1)}
  417. obj = eval("class C\u{1f5ff}; self; end").new
  418. assert_raise_with_message(TypeError, /C\u{1f5ff}/) {
  419. Enumerator::Generator.new(obj)
  420. }
  421. end
  422. def test_generator_args
  423. g = Enumerator::Generator.new {|y, x| y << 1 << 2 << 3; x }
  424. a = []
  425. assert_equal(:bar, g.each(:bar) {|x| a << x })
  426. assert_equal([1, 2, 3], a)
  427. end
  428. def test_yielder
  429. # note: Enumerator::Yielder is a class just for internal
  430. a = []
  431. y = Enumerator::Yielder.new {|x| a << x }
  432. assert_equal(y, y << 1 << 2 << 3)
  433. assert_equal([1, 2, 3], a)
  434. a = []
  435. y = Enumerator::Yielder.new {|x| a << x }
  436. assert_equal([1], y.yield(1))
  437. assert_equal([1, 2], y.yield(2))
  438. assert_equal([1, 2, 3], y.yield(3))
  439. assert_equal([1, 2, 3, 4], y.yield(4, 5))
  440. a = []
  441. y = Enumerator::Yielder.new {|*x| a.concat(x) }
  442. assert_equal([1], y.yield(1))
  443. assert_equal([1, 2, 3], y.yield(2, 3))
  444. assert_raise(LocalJumpError) { Enumerator::Yielder.new }
  445. # to_proc (explicit)
  446. a = []
  447. y = Enumerator::Yielder.new {|x| a << x }
  448. b = y.to_proc
  449. assert_kind_of(Proc, b)
  450. assert_equal([1], b.call(1))
  451. assert_equal([1], a)
  452. # to_proc (implicit)
  453. e = Enumerator.new { |y|
  454. assert_kind_of(Enumerator::Yielder, y)
  455. [1, 2, 3].each(&y)
  456. }
  457. assert_equal([1, 2, 3], e.to_a)
  458. end
  459. def test_size
  460. assert_equal nil, Enumerator.new{}.size
  461. assert_equal 42, Enumerator.new(->{42}){}.size
  462. obj = Object.new
  463. def obj.call; 42; end
  464. assert_equal 42, Enumerator.new(obj){}.size
  465. assert_equal 42, Enumerator.new(42){}.size
  466. assert_equal 1 << 70, Enumerator.new(1 << 70){}.size
  467. assert_equal Float::INFINITY, Enumerator.new(Float::INFINITY){}.size
  468. assert_equal nil, Enumerator.new(nil){}.size
  469. assert_raise(TypeError) { Enumerator.new("42"){} }
  470. assert_equal nil, @obj.to_enum(:foo, 0, 1).size
  471. assert_equal 2, @obj.to_enum(:foo, 0, 1){ 2 }.size
  472. end
  473. def test_size_for_enum_created_by_enumerators
  474. enum = to_enum{ 42 }
  475. assert_equal 42, enum.with_index.size
  476. assert_equal 42, enum.with_object(:foo).size
  477. end
  478. def test_size_for_enum_created_from_array
  479. arr = %w[hello world]
  480. %i[each each_with_index reverse_each sort_by! sort_by map map!
  481. keep_if reject! reject select! select filter! filter delete_if].each do |method|
  482. assert_equal arr.size, arr.send(method).size
  483. end
  484. end
  485. def test_size_for_enum_created_from_enumerable
  486. %i[find_all reject map flat_map partition group_by sort_by min_by max_by
  487. minmax_by each_with_index reverse_each each_entry filter_map].each do |method|
  488. assert_equal nil, @obj.send(method).size
  489. assert_equal 42, @sized.send(method).size
  490. end
  491. assert_equal nil, @obj.each_with_object(nil).size
  492. assert_equal 42, @sized.each_with_object(nil).size
  493. end
  494. def test_size_for_enum_created_from_hash
  495. h = {a: 1, b: 2, c: 3}
  496. methods = %i[delete_if reject reject! select select! filter filter! keep_if each each_key each_pair]
  497. enums = methods.map {|method| h.send(method)}
  498. s = enums.group_by(&:size)
  499. assert_equal([3], s.keys, ->{s.reject!{|k| k==3}.inspect})
  500. h[:d] = 4
  501. s = enums.group_by(&:size)
  502. assert_equal([4], s.keys, ->{s.reject!{|k| k==4}.inspect})
  503. end
  504. def test_size_for_enum_created_from_env
  505. %i[each_pair reject! delete_if select select! filter filter! keep_if].each do |method|
  506. assert_equal ENV.size, ENV.send(method).size
  507. end
  508. end
  509. def test_size_for_enum_created_from_struct
  510. s = Struct.new(:foo, :bar, :baz).new(1, 2)
  511. %i[each each_pair select].each do |method|
  512. assert_equal 3, s.send(method).size
  513. end
  514. end
  515. def check_consistency_for_combinatorics(method)
  516. [ [], [:a, :b, :c, :d, :e] ].product([-2, 0, 2, 5, 6]) do |array, arg|
  517. assert_equal array.send(method, arg).to_a.size, array.send(method, arg).size,
  518. "inconsistent size for #{array}.#{method}(#{arg})"
  519. end
  520. end
  521. def test_size_for_array_combinatorics
  522. check_consistency_for_combinatorics(:permutation)
  523. assert_equal 24, [0, 1, 2, 4].permutation.size
  524. assert_equal 2933197128679486453788761052665610240000000,
  525. (1..42).to_a.permutation(30).size # 1.upto(42).inject(:*) / 1.upto(12).inject(:*)
  526. check_consistency_for_combinatorics(:combination)
  527. assert_equal 28258808871162574166368460400,
  528. (1..100).to_a.combination(42).size
  529. # 1.upto(100).inject(:*) / 1.upto(42).inject(:*) / 1.upto(58).inject(:*)
  530. check_consistency_for_combinatorics(:repeated_permutation)
  531. assert_equal 291733167875766667063796853374976,
  532. (1..42).to_a.repeated_permutation(20).size # 42 ** 20
  533. check_consistency_for_combinatorics(:repeated_combination)
  534. assert_equal 28258808871162574166368460400,
  535. (1..59).to_a.repeated_combination(42).size
  536. # 1.upto(100).inject(:*) / 1.upto(42).inject(:*) / 1.upto(58).inject(:*)
  537. end
  538. def test_size_for_cycle
  539. assert_equal Float::INFINITY, [:foo].cycle.size
  540. assert_equal 10, [:foo, :bar].cycle(5).size
  541. assert_equal 0, [:foo, :bar].cycle(-10).size
  542. assert_equal Float::INFINITY, {foo: 1}.cycle.size
  543. assert_equal 10, {foo: 1, bar: 2}.cycle(5).size
  544. assert_equal 0, {foo: 1, bar: 2}.cycle(-10).size
  545. assert_equal 0, [].cycle.size
  546. assert_equal 0, [].cycle(5).size
  547. assert_equal 0, {}.cycle.size
  548. assert_equal 0, {}.cycle(5).size
  549. assert_equal nil, @obj.cycle.size
  550. assert_equal nil, @obj.cycle(5).size
  551. assert_equal Float::INFINITY, @sized.cycle.size
  552. assert_equal 126, @sized.cycle(3).size
  553. assert_equal Float::INFINITY, [].to_enum { 42 }.cycle.size
  554. assert_equal 0, [].to_enum { 0 }.cycle.size
  555. assert_raise(TypeError) {[].to_enum { 0 }.cycle("").size}
  556. end
  557. def test_size_for_loops
  558. assert_equal Float::INFINITY, loop.size
  559. assert_equal 42, 42.times.size
  560. end
  561. def test_size_for_each_slice
  562. assert_equal nil, @obj.each_slice(3).size
  563. assert_equal 6, @sized.each_slice(7).size
  564. assert_equal 5, @sized.each_slice(10).size
  565. assert_equal 1, @sized.each_slice(70).size
  566. assert_raise(ArgumentError){ @obj.each_slice(0).size }
  567. end
  568. def test_size_for_each_cons
  569. assert_equal nil, @obj.each_cons(3).size
  570. assert_equal 33, @sized.each_cons(10).size
  571. assert_equal 0, @sized.each_cons(70).size
  572. assert_raise(ArgumentError){ @obj.each_cons(0).size }
  573. end
  574. def test_size_for_step
  575. assert_equal 42, 5.step(46).size
  576. assert_equal 4, 1.step(10, 3).size
  577. assert_equal 3, 1.step(9, 3).size
  578. assert_equal 0, 1.step(-11).size
  579. assert_equal 0, 1.step(-11, 2).size
  580. assert_equal 7, 1.step(-11, -2).size
  581. assert_equal 7, 1.step(-11.1, -2).size
  582. assert_equal 0, 42.step(Float::INFINITY, -2).size
  583. assert_equal 1, 42.step(55, Float::INFINITY).size
  584. assert_equal 1, 42.step(Float::INFINITY, Float::INFINITY).size
  585. assert_equal 14, 0.1.step(4.2, 0.3).size
  586. assert_equal Float::INFINITY, 42.step(Float::INFINITY, 2).size
  587. assert_equal 10, (1..10).step.size
  588. assert_equal 4, (1..10).step(3).size
  589. assert_equal 3, (1...10).step(3).size
  590. assert_equal Float::INFINITY, (42..Float::INFINITY).step(2).size
  591. assert_equal 0, (1..10).step(-2).size
  592. end
  593. def test_size_for_downup_to
  594. assert_equal 0, 1.upto(-100).size
  595. assert_equal 102, 1.downto(-100).size
  596. assert_equal Float::INFINITY, 42.upto(Float::INFINITY).size
  597. end
  598. def test_size_for_string
  599. assert_equal 5, 'hello'.each_byte.size
  600. assert_equal 5, 'hello'.each_char.size
  601. assert_equal 5, 'hello'.each_codepoint.size
  602. end
  603. def test_peek_for_enumerator_objects
  604. e = 2.times
  605. assert_equal(0, e.peek)
  606. e.next
  607. assert_equal(1, e.peek)
  608. e.next
  609. assert_raise(StopIteration) { e.peek }
  610. end
  611. def test_uniq
  612. u = [0, 1, 0, 1].to_enum.lazy.uniq
  613. assert_equal([0, 1], u.force)
  614. assert_equal([0, 1], u.force)
  615. end
  616. def test_enum_chain_and_plus
  617. r = 1..5
  618. e1 = r.chain()
  619. assert_kind_of(Enumerator::Chain, e1)
  620. assert_equal(5, e1.size)
  621. ary = []
  622. e1.each { |x| ary << x }
  623. assert_equal([1, 2, 3, 4, 5], ary)
  624. e2 = r.chain([6, 7, 8])
  625. assert_kind_of(Enumerator::Chain, e2)
  626. assert_equal(8, e2.size)
  627. ary = []
  628. e2.each { |x| ary << x }
  629. assert_equal([1, 2, 3, 4, 5, 6, 7, 8], ary)
  630. e3 = r.chain([6, 7], 8.step)
  631. assert_kind_of(Enumerator::Chain, e3)
  632. assert_equal(Float::INFINITY, e3.size)
  633. ary = []
  634. e3.take(10).each { |x| ary << x }
  635. assert_equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], ary)
  636. # `a + b + c` should not return `Enumerator::Chain.new(a, b, c)`
  637. # because it is expected that `(a + b).each` be called.
  638. e4 = e2.dup
  639. class << e4
  640. attr_reader :each_is_called
  641. def each
  642. super
  643. @each_is_called = true
  644. end
  645. end
  646. e5 = e4 + 9.step
  647. assert_kind_of(Enumerator::Chain, e5)
  648. assert_equal(Float::INFINITY, e5.size)
  649. ary = []
  650. e5.take(10).each { |x| ary << x }
  651. assert_equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], ary)
  652. assert_equal(true, e4.each_is_called)
  653. end
  654. def test_chained_enums
  655. a = (1..5).each
  656. e0 = Enumerator::Chain.new()
  657. assert_kind_of(Enumerator::Chain, e0)
  658. assert_equal(0, e0.size)
  659. ary = []
  660. e0.each { |x| ary << x }
  661. assert_equal([], ary)
  662. e1 = Enumerator::Chain.new(a)
  663. assert_kind_of(Enumerator::Chain, e1)
  664. assert_equal(5, e1.size)
  665. ary = []
  666. e1.each { |x| ary << x }
  667. assert_equal([1, 2, 3, 4, 5], ary)
  668. e2 = Enumerator::Chain.new(a, [6, 7, 8])
  669. assert_kind_of(Enumerator::Chain, e2)
  670. assert_equal(8, e2.size)
  671. ary = []
  672. e2.each { |x| ary << x }
  673. assert_equal([1, 2, 3, 4, 5, 6, 7, 8], ary)
  674. e3 = Enumerator::Chain.new(a, [6, 7], 8.step)
  675. assert_kind_of(Enumerator::Chain, e3)
  676. assert_equal(Float::INFINITY, e3.size)
  677. ary = []
  678. e3.take(10).each { |x| ary << x }
  679. assert_equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], ary)
  680. e4 = Enumerator::Chain.new(a, Enumerator.new { |y| y << 6 << 7 << 8 })
  681. assert_kind_of(Enumerator::Chain, e4)
  682. assert_equal(nil, e4.size)
  683. ary = []
  684. e4.each { |x| ary << x }
  685. assert_equal([1, 2, 3, 4, 5, 6, 7, 8], ary)
  686. e5 = Enumerator::Chain.new(e1, e2)
  687. assert_kind_of(Enumerator::Chain, e5)
  688. assert_equal(13, e5.size)
  689. ary = []
  690. e5.each { |x| ary << x }
  691. assert_equal([1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 7, 8], ary)
  692. rewound = []
  693. e1.define_singleton_method(:rewind) { rewound << object_id }
  694. e2.define_singleton_method(:rewind) { rewound << object_id }
  695. e5.rewind
  696. assert_equal(rewound, [e2.object_id, e1.object_id])
  697. rewound = []
  698. a = [1]
  699. e6 = Enumerator::Chain.new(a)
  700. a.define_singleton_method(:rewind) { rewound << object_id }
  701. e6.rewind
  702. assert_equal(rewound, [])
  703. assert_equal(
  704. '#<Enumerator::Chain: [' +
  705. '#<Enumerator::Chain: [' +
  706. '#<Enumerator: 1..5:each>' +
  707. ']>, ' +
  708. '#<Enumerator::Chain: [' +
  709. '#<Enumerator: 1..5:each>, ' +
  710. '[6, 7, 8]' +
  711. ']>' +
  712. ']>',
  713. e5.inspect
  714. )
  715. end
  716. def test_produce
  717. assert_raise(ArgumentError) { Enumerator.produce }
  718. # Without initial object
  719. passed_args = []
  720. enum = Enumerator.produce { |obj| passed_args << obj; (obj || 0).succ }
  721. assert_instance_of(Enumerator, enum)
  722. assert_equal Float::INFINITY, enum.size
  723. assert_equal [1, 2, 3], enum.take(3)
  724. assert_equal [nil, 1, 2], passed_args
  725. # With initial object
  726. passed_args = []
  727. enum = Enumerator.produce(1) { |obj| passed_args << obj; obj.succ }
  728. assert_instance_of(Enumerator, enum)
  729. assert_equal Float::INFINITY, enum.size
  730. assert_equal [1, 2, 3], enum.take(3)
  731. assert_equal [1, 2], passed_args
  732. # With initial keyword arguments
  733. passed_args = []
  734. enum = Enumerator.produce(a: 1, b: 1) { |obj| passed_args << obj; obj.shift if obj.respond_to?(:shift)}
  735. assert_instance_of(Enumerator, enum)
  736. assert_equal Float::INFINITY, enum.size
  737. assert_equal [{b: 1}, [1], :a, nil], enum.take(4)
  738. assert_equal [{b: 1}, [1], :a], passed_args
  739. # Raising StopIteration
  740. words = "The quick brown fox jumps over the lazy dog.".scan(/\w+/)
  741. enum = Enumerator.produce { words.shift or raise StopIteration }
  742. assert_equal Float::INFINITY, enum.size
  743. assert_instance_of(Enumerator, enum)
  744. assert_equal %w[The quick brown fox jumps over the lazy dog], enum.to_a
  745. # Raising StopIteration
  746. object = [[[["abc", "def"], "ghi", "jkl"], "mno", "pqr"], "stuv", "wxyz"]
  747. enum = Enumerator.produce(object) { |obj|
  748. obj.respond_to?(:first) or raise StopIteration
  749. obj.first
  750. }
  751. assert_equal Float::INFINITY, enum.size
  752. assert_instance_of(Enumerator, enum)
  753. assert_nothing_raised {
  754. assert_equal [
  755. [[[["abc", "def"], "ghi", "jkl"], "mno", "pqr"], "stuv", "wxyz"],
  756. [[["abc", "def"], "ghi", "jkl"], "mno", "pqr"],
  757. [["abc", "def"], "ghi", "jkl"],
  758. ["abc", "def"],
  759. "abc",
  760. ], enum.to_a
  761. }
  762. end
  763. def test_chain_each_lambda
  764. c = Class.new do
  765. include Enumerable
  766. attr_reader :is_lambda
  767. def each(&block)
  768. return to_enum unless block
  769. @is_lambda = block.lambda?
  770. end
  771. end
  772. e = c.new
  773. e.chain.each{}
  774. assert_equal(false, e.is_lambda)
  775. e.chain.each(&->{})
  776. assert_equal(true, e.is_lambda)
  777. end
  778. end