empathy 0.0.1.RC0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.rdoc +135 -0
  5. data/Rakefile +33 -0
  6. data/TESTING.rdoc +11 -0
  7. data/empathy.gemspec +23 -0
  8. data/empathy.mspec +34 -0
  9. data/lib/empathy.rb +162 -0
  10. data/lib/empathy/em/condition_variable.rb +57 -0
  11. data/lib/empathy/em/mutex.rb +70 -0
  12. data/lib/empathy/em/queue.rb +84 -0
  13. data/lib/empathy/em/thread.rb +363 -0
  14. data/lib/empathy/object.rb +19 -0
  15. data/lib/empathy/thread.rb +8 -0
  16. data/lib/empathy/version.rb +3 -0
  17. data/mspec/lib/mspec/empathy.rb +19 -0
  18. data/mspec/lib/mspec/guards/empathy.rb +10 -0
  19. data/rubyspec/core/kernel/fixtures/__method__.rb +25 -0
  20. data/rubyspec/core/kernel/fixtures/autoload_b.rb +5 -0
  21. data/rubyspec/core/kernel/fixtures/autoload_c.rb +5 -0
  22. data/rubyspec/core/kernel/fixtures/autoload_d.rb +5 -0
  23. data/rubyspec/core/kernel/fixtures/caller_fixture1.rb +42 -0
  24. data/rubyspec/core/kernel/fixtures/caller_fixture2.rb +26 -0
  25. data/rubyspec/core/kernel/fixtures/chomp.rb +4 -0
  26. data/rubyspec/core/kernel/fixtures/chomp_f.rb +4 -0
  27. data/rubyspec/core/kernel/fixtures/chop.rb +4 -0
  28. data/rubyspec/core/kernel/fixtures/chop_f.rb +4 -0
  29. data/rubyspec/core/kernel/fixtures/classes.rb +410 -0
  30. data/rubyspec/core/kernel/fixtures/eval_locals.rb +6 -0
  31. data/rubyspec/core/kernel/fixtures/eval_return_with_lambda.rb +12 -0
  32. data/rubyspec/core/kernel/fixtures/eval_return_without_lambda.rb +14 -0
  33. data/rubyspec/core/kernel/fixtures/test.rb +362 -0
  34. data/rubyspec/core/kernel/sleep_spec.rb +43 -0
  35. data/rubyspec/core/mutex/lock_spec.rb +8 -0
  36. data/rubyspec/core/mutex/locked_spec.rb +8 -0
  37. data/rubyspec/core/mutex/sleep_spec.rb +56 -0
  38. data/rubyspec/core/mutex/synchronize_spec.rb +8 -0
  39. data/rubyspec/core/mutex/try_lock_spec.rb +8 -0
  40. data/rubyspec/core/mutex/unlock_spec.rb +8 -0
  41. data/rubyspec/core/thread/abort_on_exception_spec.rb +126 -0
  42. data/rubyspec/core/thread/add_trace_func_spec.rb +7 -0
  43. data/rubyspec/core/thread/alive_spec.rb +60 -0
  44. data/rubyspec/core/thread/allocate_spec.rb +9 -0
  45. data/rubyspec/core/thread/backtrace_spec.rb +7 -0
  46. data/rubyspec/core/thread/critical_spec.rb +96 -0
  47. data/rubyspec/core/thread/current_spec.rb +15 -0
  48. data/rubyspec/core/thread/element_reference_spec.rb +53 -0
  49. data/rubyspec/core/thread/element_set_spec.rb +46 -0
  50. data/rubyspec/core/thread/exclusive_spec.rb +20 -0
  51. data/rubyspec/core/thread/exit_spec.rb +21 -0
  52. data/rubyspec/core/thread/fixtures/classes.rb +291 -0
  53. data/rubyspec/core/thread/fork_spec.rb +9 -0
  54. data/rubyspec/core/thread/group_spec.rb +5 -0
  55. data/rubyspec/core/thread/initialize_spec.rb +26 -0
  56. data/rubyspec/core/thread/inspect_spec.rb +48 -0
  57. data/rubyspec/core/thread/join_spec.rb +63 -0
  58. data/rubyspec/core/thread/key_spec.rb +64 -0
  59. data/rubyspec/core/thread/keys_spec.rb +47 -0
  60. data/rubyspec/core/thread/kill_spec.rb +21 -0
  61. data/rubyspec/core/thread/list_spec.rb +38 -0
  62. data/rubyspec/core/thread/main_spec.rb +10 -0
  63. data/rubyspec/core/thread/new_spec.rb +56 -0
  64. data/rubyspec/core/thread/pass_spec.rb +8 -0
  65. data/rubyspec/core/thread/priority_spec.rb +9 -0
  66. data/rubyspec/core/thread/raise_spec.rb +225 -0
  67. data/rubyspec/core/thread/run_spec.rb +9 -0
  68. data/rubyspec/core/thread/safe_level_spec.rb +6 -0
  69. data/rubyspec/core/thread/set_trace_func_spec.rb +7 -0
  70. data/rubyspec/core/thread/shared/exit.rb +173 -0
  71. data/rubyspec/core/thread/shared/start.rb +51 -0
  72. data/rubyspec/core/thread/shared/wakeup.rb +59 -0
  73. data/rubyspec/core/thread/start_spec.rb +9 -0
  74. data/rubyspec/core/thread/status_spec.rb +48 -0
  75. data/rubyspec/core/thread/stop_spec.rb +66 -0
  76. data/rubyspec/core/thread/terminate_spec.rb +11 -0
  77. data/rubyspec/core/thread/value_spec.rb +36 -0
  78. data/rubyspec/core/thread/wakeup_spec.rb +7 -0
  79. data/rubyspec/empathy_spec.rb +26 -0
  80. data/rubyspec/library/conditionvariable/broadcast_spec.rb +62 -0
  81. data/rubyspec/library/conditionvariable/signal_spec.rb +64 -0
  82. data/rubyspec/library/conditionvariable/wait_spec.rb +21 -0
  83. data/rubyspec/library/mutex/lock_spec.rb +10 -0
  84. data/rubyspec/library/mutex/locked_spec.rb +10 -0
  85. data/rubyspec/library/mutex/synchronize_spec.rb +10 -0
  86. data/rubyspec/library/mutex/try_lock_spec.rb +10 -0
  87. data/rubyspec/library/mutex/unlock_spec.rb +10 -0
  88. data/rubyspec/library/queue/append_spec.rb +7 -0
  89. data/rubyspec/library/queue/clear_spec.rb +15 -0
  90. data/rubyspec/library/queue/deq_spec.rb +7 -0
  91. data/rubyspec/library/queue/empty_spec.rb +15 -0
  92. data/rubyspec/library/queue/enq_spec.rb +7 -0
  93. data/rubyspec/library/queue/length_spec.rb +7 -0
  94. data/rubyspec/library/queue/num_waiting_spec.rb +19 -0
  95. data/rubyspec/library/queue/pop_spec.rb +7 -0
  96. data/rubyspec/library/queue/push_spec.rb +7 -0
  97. data/rubyspec/library/queue/shared/deque.rb +37 -0
  98. data/rubyspec/library/queue/shared/enque.rb +10 -0
  99. data/rubyspec/library/queue/shared/length.rb +9 -0
  100. data/rubyspec/library/queue/shift_spec.rb +7 -0
  101. data/rubyspec/library/queue/size_spec.rb +7 -0
  102. data/rubyspec/shared/kernel/raise.rb +68 -0
  103. data/rubyspec/shared/mutex/lock.rb +52 -0
  104. data/rubyspec/shared/mutex/locked.rb +31 -0
  105. data/rubyspec/shared/mutex/synchronize.rb +23 -0
  106. data/rubyspec/shared/mutex/try_lock.rb +30 -0
  107. data/rubyspec/shared/mutex/unlock.rb +35 -0
  108. data/rubyspec/spec_helper.rb +48 -0
  109. data/spec/empathy_spec.rb +129 -0
  110. data/spec/library_spec.rb +79 -0
  111. data/spec/spec_helper.rb +6 -0
  112. metadata +222 -0
@@ -0,0 +1,7 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+ require 'thread'
3
+ require File.expand_path('../shared/deque', __FILE__)
4
+
5
+ describe "Queue#shift" do
6
+ it_behaves_like :queue_deq, :shift
7
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+ require 'thread'
3
+ require File.expand_path('../shared/length', __FILE__)
4
+
5
+ describe "Queue#size" do
6
+ it_behaves_like :queue_length, :size
7
+ end
@@ -0,0 +1,68 @@
1
+ describe :kernel_raise, :shared => true do
2
+ before :each do
3
+ ScratchPad.clear
4
+ end
5
+
6
+ it "aborts execution" do
7
+ lambda do
8
+ @object.raise Exception, "abort"
9
+ ScratchPad.record :no_abort
10
+ end.should raise_error(Exception, "abort")
11
+
12
+ ScratchPad.recorded.should be_nil
13
+ end
14
+
15
+ it "raises RuntimeError if no exception class is given" do
16
+ lambda { @object.raise }.should raise_error(RuntimeError)
17
+ end
18
+
19
+ it "raises a given Exception instance" do
20
+ error = RuntimeError.new
21
+ lambda { @object.raise(error) }.should raise_error(error)
22
+ end
23
+
24
+ it "raises a RuntimeError if string given" do
25
+ lambda { @object.raise("a bad thing") }.should raise_error(RuntimeError)
26
+ end
27
+
28
+ it "raises a TypeError when passed a non-Exception object" do
29
+ lambda { @object.raise(Object.new) }.should raise_error(TypeError)
30
+ end
31
+
32
+ it "raises a TypeError when passed true" do
33
+ lambda { @object.raise(true) }.should raise_error(TypeError)
34
+ end
35
+
36
+ it "raises a TypeError when passed false" do
37
+ lambda { @object.raise(false) }.should raise_error(TypeError)
38
+ end
39
+
40
+ it "raises a TypeError when passed nil" do
41
+ lambda { @object.raise(nil) }.should raise_error(TypeError)
42
+ end
43
+
44
+ it "re-raises the rescued exception" do
45
+ lambda do
46
+ begin
47
+ raise Exception, "outer"
48
+ ScratchPad.record :no_abort
49
+ rescue
50
+ begin
51
+ raise StandardError, "inner"
52
+ rescue
53
+ end
54
+
55
+ @object.raise
56
+ ScratchPad.record :no_reraise
57
+ end
58
+ end.should raise_error(Exception, "outer")
59
+
60
+ ScratchPad.recorded.should be_nil
61
+ end
62
+
63
+ it "allows Exception, message, and backtrace parameters" do
64
+ lambda do
65
+ @object.raise(ArgumentError, "message", caller)
66
+ end.should raise_error(ArgumentError, "message")
67
+ end
68
+ end
@@ -0,0 +1,52 @@
1
+ describe :mutex_lock, :shared => true do
2
+ before :each do
3
+ ScratchPad.clear
4
+ end
5
+
6
+ it "returns self" do
7
+ m = Mutex.new
8
+ m.lock.should == m
9
+ m.unlock
10
+ end
11
+
12
+ it "waits if the lock is not available" do
13
+ m = Mutex.new
14
+
15
+ m.lock
16
+
17
+ th = Thread.new do
18
+ m.lock
19
+ ScratchPad.record :after_lock
20
+ end
21
+
22
+ Thread.pass while th.status and th.status != "sleep"
23
+
24
+ ScratchPad.recorded.should be_nil
25
+ m.unlock
26
+ th.join
27
+ ScratchPad.recorded.should == :after_lock
28
+ end
29
+
30
+ # Unable to find a specific ticket but behavior change may be
31
+ # related to this ML thread.
32
+ ruby_bug "[ruby-core:23457]", "1.8.7.174" do
33
+ it "raises a ThreadError when used recursively" do
34
+ m = Mutex.new
35
+
36
+ th = Thread.new do
37
+ m.lock
38
+ m.lock
39
+ v = 1
40
+ end
41
+
42
+ Thread.pass while th.status and th.status != "sleep"
43
+
44
+ ScratchPad.recorded.should be_nil
45
+
46
+ lambda do
47
+ th.kill
48
+ th.join
49
+ end.should raise_error(ThreadError)
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,31 @@
1
+ describe :mutex_locked, :shared => true do
2
+ it "returns true if locked" do
3
+ m = Mutex.new
4
+ m.lock
5
+ m.locked?.should be_true
6
+ end
7
+
8
+ it "returns false if unlocked" do
9
+ m = Mutex.new
10
+ m.locked?.should be_false
11
+ end
12
+
13
+ it "returns the status of the lock" do
14
+ m1 = Mutex.new
15
+ m2 = Mutex.new
16
+
17
+ m2.lock # hold th with only m1 locked
18
+
19
+ th = Thread.new do
20
+ m1.lock
21
+ m2.lock
22
+ end
23
+
24
+ Thread.pass while th.status and th.status != "sleep"
25
+
26
+ m1.locked?.should be_true
27
+ m2.unlock # release th
28
+ th.join
29
+ m1.locked?.should be_false
30
+ end
31
+ end
@@ -0,0 +1,23 @@
1
+ describe :mutex_synchronize, :shared => true do
2
+ it "wraps the lock/unlock pair in an ensure" do
3
+ m1 = Mutex.new
4
+ m2 = Mutex.new
5
+ m2.lock
6
+
7
+ th = Thread.new do
8
+ lambda do
9
+ m1.synchronize do
10
+ m2.lock
11
+ raise Exception
12
+ end
13
+ end.should raise_error(Exception)
14
+ end
15
+
16
+ Thread.pass while th.status and th.status != "sleep"
17
+
18
+ m1.locked?.should be_true
19
+ m2.unlock
20
+ th.join
21
+ m1.locked?.should be_false
22
+ end
23
+ end
@@ -0,0 +1,30 @@
1
+ describe :mutex_try_lock, :shared => true do
2
+ describe "when unlocked" do
3
+ it "returns true" do
4
+ m = Mutex.new
5
+ m.try_lock.should be_true
6
+ end
7
+
8
+ it "locks the mutex" do
9
+ m = Mutex.new
10
+ m.try_lock
11
+ m.locked?.should be_true
12
+ end
13
+ end
14
+
15
+ describe "when locked by the current thread" do
16
+ it "returns false" do
17
+ m = Mutex.new
18
+ m.lock
19
+ m.try_lock.should be_false
20
+ end
21
+ end
22
+
23
+ describe "when locked by another thread" do
24
+ it "returns false" do
25
+ m = Mutex.new
26
+ m.lock
27
+ Thread.new { m.try_lock }.value.should be_false
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,35 @@
1
+ describe :mutex_unlock, :shared => true do
2
+ it "raises ThreadError unless Mutex is locked" do
3
+ mutex = Mutex.new
4
+ lambda { mutex.unlock }.should raise_error(ThreadError)
5
+ end
6
+
7
+ it "raises ThreadError unless thread owns Mutex" do
8
+ mutex = Mutex.new
9
+ wait = Mutex.new
10
+ wait.lock
11
+ th = Thread.new do
12
+ mutex.lock
13
+ wait.lock
14
+ end
15
+
16
+ # avoid race on mutex.lock
17
+ Thread.pass while th.status and th.status != "sleep"
18
+
19
+ lambda { mutex.unlock }.should raise_error(ThreadError)
20
+
21
+ wait.unlock
22
+ th.join
23
+ end
24
+
25
+ it "raises ThreadError if previously locking thread is gone" do
26
+ mutex = Mutex.new
27
+ th = Thread.new do
28
+ mutex.lock
29
+ end
30
+
31
+ th.join
32
+
33
+ lambda { mutex.unlock }.should raise_error(ThreadError)
34
+ end
35
+ end
@@ -0,0 +1,48 @@
1
+ # encoding: UTF-8
2
+ unless ENV['MSPEC_RUNNER']
3
+ begin
4
+ require "pp"
5
+ require 'mspec/version'
6
+ require 'mspec/helpers'
7
+ require 'mspec/guards'
8
+ require 'mspec/runner/shared'
9
+ require 'mspec/matchers/be_ancestor_of'
10
+ require 'mspec/matchers/output'
11
+ require 'mspec/matchers/output_to_fd'
12
+ require 'mspec/matchers/complain'
13
+ require 'mspec/matchers/equal_element'
14
+ require 'mspec/matchers/equal_utf16'
15
+ require 'mspec/matchers/match_yaml'
16
+
17
+ # Code to setup HOME directory correctly on Windows
18
+ # This duplicates Ruby 1.9 semantics for defining HOME
19
+ platform_is :windows do
20
+ if ENV['HOME']
21
+ ENV['HOME'] = ENV['HOME'].tr '\\', '/'
22
+ elsif ENV['HOMEDIR'] && ENV['HOMEDRIVE']
23
+ ENV['HOME'] = File.join(ENV['HOMEDRIVE'], ENV['HOMEDIR'])
24
+ elsif ENV['HOMEDIR']
25
+ ENV['HOME'] = ENV['HOMEDIR']
26
+ elsif ENV['HOMEDRIVE']
27
+ ENV['HOME'] = ENV['HOMEDRIVE']
28
+ elsif ENV['USERPROFILE']
29
+ ENV['HOME'] = ENV['USERPROFILE']
30
+ else
31
+ puts "No suitable HOME environment found. This means that all of"
32
+ puts "HOME, HOMEDIR, HOMEDRIVE, and USERPROFILE are not set"
33
+ exit 1
34
+ end
35
+ end
36
+ rescue LoadError
37
+ puts "Please install the MSpec gem to run the specs."
38
+ exit 1
39
+ end
40
+ end
41
+
42
+ minimum_version = "1.5.18"
43
+ unless MSpec::VERSION >= minimum_version
44
+ puts "Please install MSpec version >= #{minimum_version} to run the specs"
45
+ exit 1
46
+ end
47
+
48
+ $VERBOSE = nil unless ENV['OUTPUT_WARNINGS']
@@ -0,0 +1,129 @@
1
+ require 'spec_helper'
2
+
3
+ # Test class delegation
4
+ class EmTest
5
+ def self.test_class_method(an_arg=:test_class_method,&block)
6
+ return block.call if block_given?
7
+ an_arg
8
+ end
9
+
10
+ def whoami
11
+ :test
12
+ end
13
+ end
14
+
15
+ module Empathy
16
+ module EM
17
+ class EmTest
18
+ def self.test_class_method(an_arg=:em_test_class_method,&block)
19
+ return block.call if block_given?
20
+ an_arg
21
+ end
22
+
23
+ def whoami
24
+ :em_test
25
+ end
26
+ end
27
+ end
28
+
29
+ create_delegate_module('EmTest',:new, :test_class_method)
30
+ end
31
+
32
+ describe Empathy do
33
+
34
+ describe "#run" do
35
+ it "raise errors when block raises error" do
36
+ lambda do
37
+ Empathy.run { raise RuntimeError }
38
+ end.should raise_error(RuntimeError)
39
+ EventMachine.reactor_running?.should be_false
40
+ end
41
+ end
42
+
43
+ shared_examples_for "empathy_delegation" do
44
+ it "delegates Thread" do
45
+ t = Empathy::Thread.new() { }
46
+ t.should be_kind_of(thread_class)
47
+ Empathy::Thread.list.should == thread_class.list
48
+ Empathy::Thread.current.should == thread_class.current
49
+ Empathy::Thread.main.should == thread_class.main
50
+ Empathy::Thread.singleton_methods.should include(:stop,:pass)
51
+ end
52
+
53
+ it "delegates Queue" do
54
+ q = Empathy::Queue.new()
55
+ q.should be_kind_of(queue_class)
56
+ end
57
+
58
+ it "delegates ConditionVariable" do
59
+ q = Empathy::ConditionVariable.new()
60
+ q.should be_kind_of(condition_variable_class)
61
+ end
62
+
63
+ it "delegates Mutex" do
64
+ q = Empathy::Mutex.new()
65
+ q.should be_kind_of(mutex_class)
66
+ end
67
+
68
+ it "delegates Kernel.sleep" do
69
+ Empathy::Kernel.singleton_methods.should include(:sleep)
70
+ end
71
+
72
+ it "rescues errors" do
73
+ lambda do
74
+ begin
75
+ raise error_class
76
+ rescue Empathy::ThreadError
77
+ # do nothing
78
+ end
79
+ end.should_not raise_error
80
+ end
81
+ end
82
+
83
+ context "in eventmachine" do
84
+ around(:each) do |example|
85
+ Empathy.run { example.run }
86
+ end
87
+
88
+ let (:thread_class) { Empathy::EM::Thread }
89
+ let (:queue_class) { Empathy::EM::Queue }
90
+ let (:condition_variable_class) { Empathy::EM::ConditionVariable }
91
+ let (:mutex_class) { Empathy::EM::Mutex }
92
+ let (:error_class) { ::FiberError }
93
+
94
+ it "delegates to Empathy::EM classes" do
95
+ Empathy.run do
96
+ Empathy.event_machine?.should be_true
97
+ t = Empathy::EmTest.new
98
+ t.should be_kind_of(Empathy::EM::EmTest)
99
+ t.whoami.should == :em_test
100
+ Empathy::EmTest.test_class_method.should == :em_test_class_method
101
+ Empathy::EmTest.test_class_method(:em_hello).should == :em_hello
102
+ Empathy::EmTest.test_class_method() { :em_with_block }.should == :em_with_block
103
+ end
104
+ end
105
+
106
+ include_examples "empathy_delegation"
107
+ end
108
+
109
+ context "outside eventmachine" do
110
+ let (:thread_class) { ::Thread }
111
+ let (:queue_class) { ::Queue }
112
+ let (:condition_variable_class) { ::ConditionVariable }
113
+ let (:mutex_class) { ::Mutex }
114
+ let (:error_class) { ::ThreadError }
115
+
116
+ it "delegate to ruby top level classes" do
117
+ EventMachine.reactor_running?.should be_false
118
+ Empathy.event_machine?.should be_false
119
+ t = Empathy::EmTest.new
120
+ t.should be_kind_of(EmTest)
121
+ t.whoami.should == :test
122
+ Empathy::EmTest.test_class_method.should == :test_class_method
123
+ Empathy::EmTest.test_class_method(:hello).should == :hello
124
+ Empathy::EmTest.test_class_method() { :with_block }.should == :with_block
125
+ end
126
+
127
+ include_examples "empathy_delegation"
128
+ end
129
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+
3
+ module TestReactorLibrary
4
+ def self.test_thread_error
5
+ raise ::FiberError, "oops"
6
+ rescue ThreadError
7
+ :rescued
8
+ end
9
+ end
10
+
11
+ Empathy::EM.empathise(TestReactorLibrary)
12
+
13
+ module TestLibrary
14
+ def self.test_thread_error
15
+ begin
16
+ raise ::FiberError, "fiber error"
17
+ rescue ThreadError
18
+ end
19
+
20
+ begin
21
+ raise ::ThreadError, "thread error"
22
+ rescue ThreadError
23
+ end
24
+ :ok
25
+ end
26
+ end
27
+
28
+ Empathy.empathise(TestLibrary)
29
+
30
+ shared_examples_for "Empathy.empathise" do
31
+ it "rescues thread and fiber exceptions" do
32
+ TestLibrary.test_thread_error.should == :ok
33
+ end
34
+ end
35
+
36
+ describe "Empathy.empathise" do
37
+
38
+ it "defines constants in Library namespace" do
39
+ TestLibrary::Thread.should == Empathy::Thread
40
+ TestLibrary::Queue.should == Empathy::Queue
41
+ TestLibrary::ConditionVariable.should == Empathy::ConditionVariable
42
+ TestLibrary::Mutex.should == Empathy::Mutex
43
+ TestLibrary::ThreadError.should == Empathy::ThreadError
44
+ end
45
+
46
+ context "in reactor" do
47
+ around :each do |example|
48
+ Empathy.run { example.run }
49
+ end
50
+
51
+ include_examples "Empathy.empathise"
52
+ end
53
+
54
+ context "outside reactor" do
55
+ include_examples "Empathy.empathise"
56
+ end
57
+
58
+ end
59
+
60
+ describe "Empathy::EM.empathise" do
61
+
62
+ it "defines constants in Library namespace" do
63
+ TestReactorLibrary::Thread.should == Empathy::EM::Thread
64
+ TestReactorLibrary::Queue.should == Empathy::EM::Queue
65
+ TestReactorLibrary::ConditionVariable.should == Empathy::EM::ConditionVariable
66
+ TestReactorLibrary::Mutex.should == Empathy::EM::Mutex
67
+ TestReactorLibrary::ThreadError.should == FiberError
68
+ end
69
+
70
+ context "in reactor" do
71
+ around :each do |example|
72
+ Empathy.run { example.run }
73
+ end
74
+
75
+ it "rescues fiber errors" do
76
+ TestReactorLibrary.test_thread_error.should == :rescued
77
+ end
78
+ end
79
+ end