File: thread_test.rb

package info (click to toggle)
ruby-delayer-deferred 2.2.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 316 kB
  • sloc: ruby: 1,650; sh: 2; makefile: 2
file content (185 lines) | stat: -rw-r--r-- 5,051 bytes parent folder | download | duplicates (3)
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# -*- coding: utf-8 -*-

require_relative 'helper'

describe(Thread) do
  include TestUtils

  before do
    Delayer.default = Delayer.generate_class
  end

  describe 'Generic thread operation' do
    describe 'Exception in thread' do
      before do
        @error = Class.new(RuntimeError)
        @thread = Thread.new {
          raise @error
        }
      end

      it 'should takes the exception' do
        assert_raises(@error) do
          @thread.value
        end
      end
    end
  end

  it "defer with Deferred#next" do
    thread = succeed = result = false
    uuid = SecureRandom.uuid
    eval_all_events do
      Thread.new {
        thread = true
        uuid
      }.next do |param|
        succeed = true
        result = param
      end end
    assert thread, "Thread did not executed."
    assert succeed, "next block did not executed."
    assert_equal uuid, result
  end

  it "defer with another Delayer" do
    thread = succeed = failure = result = false
    uuid = SecureRandom.uuid
    delayer = Delayer.generate_class
    assert_equal delayer, delayer.Deferred.Thread.delayer
    eval_all_events(delayer) do
      delayer.Deferred.Thread.new {
        thread = true
        uuid
      }.next{ |param|
        succeed = true
        result = param
      }.trap{ |exception|
        failure = exception } end
    assert_equal false, failure, 'Unexpected failed.'
    assert thread, "Thread did not executed."
    assert succeed, "next block did not executed."
    assert_equal uuid, result
  end

  it "error handling" do
    delayer = Delayer.generate_class
    succeed = failure = recover = false
    uuid = SecureRandom.uuid
    eval_all_events(delayer) do
      delayer.Deferred.Thread.new {
        raise uuid
      }.next {
        succeed = true
      }.trap { |value|
        failure = value
      }.next {
        recover = true } end
    refute succeed, "Raised exception but it was executed successed route."
    assert_instance_of RuntimeError, failure, "trap block takes incorrect value"
    assert_equal uuid, failure.message, "trap block takes incorrect value"
    assert recover, "next block did not executed when after trap"
  end

  it "exception handling" do
    succeed = failure = recover = false
    delayer = Delayer.generate_class
    eval_all_events(delayer) do
      delayer.Deferred.Thread.new {
        raise 'error test'
      }.next {
        succeed = true
      }.trap {
        failure = true
      }.next {
        recover = true } end
    refute succeed, "Raised exception but it was executed successed route."
    assert failure, "trap block did not executed"
    assert recover, "next block did not executed when after trap"
  end

  it "wait end of Deferredable if Deferredable block returns Thread" do
    result = failure = false
    delayer = Delayer.generate_class
    uuid = SecureRandom.uuid
    node = eval_all_events(delayer) do
      delayer.Deferred.new.next{
        delayer.Deferred.new.next{
          delayer.Deferred.Thread.new{
            uuid
          }
        }
      }.next{ |value|
        result = value
      }.trap{ |exception|
        failure = exception }
    end
    assert_equal uuid, result, ->{ "[[#{node.graph_draw}]]" }
    assert_equal false, failure
  end

  describe 'Race conditions' do
    it "calls Thread#next for running thread" do
      thread = succeed = result = false
      uuid = SecureRandom.uuid
      eval_all_events do
        lock = true
        th = Thread.new {
          while lock; Thread.pass end
          thread = true
          uuid
        }
        th.next do |param|
          succeed = true
          result = param
        end
        lock = false
      end
      assert thread, "Thread did not executed."
      assert succeed, "next block did not executed."
      assert_equal uuid, result
    end

    it "calls Thread#next for stopped thread" do
      thread = succeed = result = false
      uuid = SecureRandom.uuid
      eval_all_events do
        th = Thread.new {
          thread = true
          uuid
        }
        while th.alive?; Thread.pass end
        th.next do |param|
          succeed = true
          result = param
        end
      end
      assert thread, "Thread did not executed."
      assert succeed, "next block did not executed."
      assert_equal uuid, result
    end
  end

  it "wait ended Thread for +thread" do
    result = failure = false
    delayer = Delayer.generate_class
    uuid1, uuid2, uuid3 = SecureRandom.uuid, SecureRandom.uuid, SecureRandom.uuid
    eval_all_events(delayer) do
      delayer.Deferred.new.next{
        [
          +delayer.Deferred.Thread.new{ uuid1 },
          +delayer.Deferred.Thread.new{ uuid2 },
          +delayer.Deferred.Thread.new{ uuid3 }
        ]
      }.next{ |value|
        result = value
      }.trap{ |exception|
        failure = exception }
    end
    assert_equal false, failure
    assert_instance_of Array, result
    assert_equal uuid1, result[0]
    assert_equal uuid2, result[1]
    assert_equal uuid3, result[2]
  end
end