File: filtered_queue_test.rb

package info (click to toggle)
ruby-backports 3.25.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,912 kB
  • sloc: ruby: 11,757; makefile: 6
file content (109 lines) | stat: -rw-r--r-- 2,787 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
require './test/test_helper'
require 'backports/2.3.0/queue/close'
require 'backports/ractor/filtered_queue'

class FilteredQueueTest < Test::Unit::TestCase
  def setup
    @q = ::Backports::FilteredQueue.new
  end

  def assert_remains(*values)
    remain = []
    remain << @q.pop until @q.empty?
    assert_equal values, remain
  end

  def test_basic
    @q << 1 << 2
    x = []
    x << @q.pop
    @q << 3
    x << @q.pop
    x << @q.pop
    t = Thread.new { sleep(0.1); @q << 4 << 5}
    x << @q.pop
    t.join
    assert_equal([1,2,3,4], x)
    assert_remains(5)
  end

  def test_close
    Thread.new { sleep(0.2); @q.close }
    assert_raise(::Backports::FilteredQueue::ClosedQueueError) { @q.pop }
    assert_raise(::Backports::FilteredQueue::ClosedQueueError) { @q.pop }
    assert_raise(::Backports::FilteredQueue::ClosedQueueError) { @q.pop(timeout: 0) }
    assert_raise(::Backports::FilteredQueue::ClosedQueueError) { @q << 42 }
  end

  def test_close_after
    @q << 1 << 2
    @q.close
    assert_equal(1, @q.pop)
    assert_equal(2, @q.pop)
    assert_raise(::Backports::FilteredQueue::ClosedQueueError) { @q.pop }
  end

  def test_timeout
    assert_raise(::Backports::FilteredQueue::TimeoutError) { @q.pop(timeout: 0) }
    Thread.new { sleep(0.2); @q << :done }
    assert_raise(::Backports::FilteredQueue::TimeoutError) { @q.pop(timeout: 0.1) }
    assert_equal(:done, @q.pop(timeout: 0.2))
  end

  def assert_eventually_equal(value)
    100.times do
      return true if value == yield
      sleep(0.01)
    end
    assert value == yield
  end

  def test_filter
    # send 0 to 7 to queue, with filters for 0 to 2.
    # start queue with `before` elements already present
    (0..4).each do |before|
      other = [4,5,6,7]
      calls = 0
      before.times { @q << other.shift }
      t = 3.times.map do |i|
        Thread.new do
          @q.pop { |n| calls += 1; Thread.pass; n == i }
        end
      end
      Thread.pass
      other.each { |i| @q << i }
      assert_eventually_equal(3) {@q.num_waiting}
      assert_eventually_equal(3 * 4) {calls}
      @q << :extra
      assert_eventually_equal(3 * 5) {calls}
      @q << 0 << 1 << 2 << 3
      t.each(&:join)
      assert_equal 0, @q.num_waiting
      assert_remains 4, 5, 6, 7, :extra, 3
    end
  end

  def test_non_standard_filters
    @q << 1 << 2 << 3
    @q.pop { break }
    @q.pop { raise 'err' } rescue nil
    assert_remains 3
  end

  def test_recursive_filter
    [
      [0, :other],
      [:other, 0],
    ].each do |a, b|
      @q << :first << a << b << :last
      inner = nil
      a = @q.pop do
        inner = @q.pop { |x| x == 0}
        false # => ignored
      end
      assert_equal :first, a
      assert_equal 0, inner
      assert_remains :other, :last
    end
  end
end