celluloid 0.16.0 → 0.17.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +394 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +28 -15
  5. data/culture/CONDUCT.md +28 -0
  6. data/culture/Gemfile +9 -0
  7. data/culture/LICENSE.txt +22 -0
  8. data/culture/README.md +22 -0
  9. data/culture/Rakefile +5 -0
  10. data/culture/SYNC.md +70 -0
  11. data/culture/celluloid-culture.gemspec +18 -0
  12. data/culture/gems/README.md +39 -0
  13. data/culture/gems/dependencies.yml +85 -0
  14. data/culture/gems/loader.rb +101 -0
  15. data/culture/rubocop/README.md +38 -0
  16. data/culture/rubocop/lint.yml +8 -0
  17. data/culture/rubocop/metrics.yml +15 -0
  18. data/culture/rubocop/perf.yml +0 -0
  19. data/culture/rubocop/rubocop.yml +5 -0
  20. data/culture/rubocop/style.yml +57 -0
  21. data/culture/spec/gems_spec.rb +2 -0
  22. data/culture/spec/spec_helper.rb +0 -0
  23. data/culture/spec/sync_spec.rb +2 -0
  24. data/culture/sync.rb +56 -0
  25. data/culture/tasks/rspec.rake +5 -0
  26. data/culture/tasks/rubocop.rake +2 -0
  27. data/examples/basic_usage.rb +49 -0
  28. data/examples/futures.rb +38 -0
  29. data/examples/ring.rb +61 -0
  30. data/examples/simple_pmap.rb +14 -0
  31. data/examples/stack.rb +47 -0
  32. data/examples/timers.rb +72 -0
  33. data/lib/celluloid/actor/manager.rb +7 -0
  34. data/lib/celluloid/actor/system.rb +163 -0
  35. data/lib/celluloid/actor.rb +53 -71
  36. data/lib/celluloid/autostart.rb +1 -1
  37. data/lib/celluloid/backported.rb +2 -0
  38. data/lib/celluloid/call/async.rb +16 -0
  39. data/lib/celluloid/call/block.rb +22 -0
  40. data/lib/celluloid/call/sync.rb +70 -0
  41. data/lib/celluloid/calls.rb +24 -114
  42. data/lib/celluloid/cell.rb +32 -20
  43. data/lib/celluloid/condition.rb +5 -6
  44. data/lib/celluloid/core_ext.rb +1 -1
  45. data/lib/celluloid/current.rb +2 -0
  46. data/lib/celluloid/debug.rb +1 -0
  47. data/lib/celluloid/deprecate.rb +21 -0
  48. data/lib/celluloid/exceptions.rb +22 -16
  49. data/lib/celluloid/fiber.rb +3 -3
  50. data/lib/celluloid/future.rb +46 -8
  51. data/lib/celluloid/group/pool.rb +125 -0
  52. data/lib/celluloid/group/spawner.rb +68 -0
  53. data/lib/celluloid/group.rb +61 -0
  54. data/lib/celluloid/logging.rb +5 -5
  55. data/lib/celluloid/mailbox/evented.rb +74 -0
  56. data/lib/celluloid/mailbox.rb +15 -14
  57. data/lib/celluloid/managed.rb +3 -0
  58. data/lib/celluloid/notices.rb +15 -0
  59. data/lib/celluloid/proxies.rb +11 -0
  60. data/lib/celluloid/proxy/abstract.rb +50 -0
  61. data/lib/celluloid/proxy/actor.rb +37 -0
  62. data/lib/celluloid/proxy/async.rb +15 -0
  63. data/lib/celluloid/proxy/block.rb +28 -0
  64. data/lib/celluloid/proxy/cell.rb +66 -0
  65. data/lib/celluloid/proxy/future.rb +20 -0
  66. data/lib/celluloid/proxy/sync.rb +24 -0
  67. data/lib/celluloid/rspec.rb +67 -9
  68. data/lib/celluloid/system_events.rb +69 -14
  69. data/lib/celluloid/task/fibered.rb +45 -0
  70. data/lib/celluloid/task/threaded.rb +59 -0
  71. data/lib/celluloid/{tasks.rb → task.rb} +30 -38
  72. data/lib/celluloid/test.rb +1 -1
  73. data/lib/celluloid/thread.rb +6 -1
  74. data/lib/celluloid/version.rb +3 -0
  75. data/lib/celluloid.rb +151 -130
  76. data/spec/celluloid/actor/system_spec.rb +83 -0
  77. data/spec/celluloid/actor_spec.rb +2 -2
  78. data/spec/celluloid/block_spec.rb +67 -8
  79. data/spec/celluloid/calls_spec.rb +28 -23
  80. data/spec/celluloid/condition_spec.rb +23 -14
  81. data/spec/celluloid/evented_mailbox_spec.rb +1 -31
  82. data/spec/celluloid/future_spec.rb +15 -12
  83. data/spec/celluloid/group/elastic_spec.rb +0 -0
  84. data/spec/celluloid/group/pool_spec.rb +8 -0
  85. data/spec/celluloid/group/spawner_spec.rb +17 -0
  86. data/spec/celluloid/mailbox/evented_spec.rb +40 -0
  87. data/spec/celluloid/mailbox_spec.rb +1 -3
  88. data/spec/celluloid/misc/leak_spec.rb +73 -0
  89. data/spec/celluloid/proxy_spec.rb +33 -0
  90. data/spec/celluloid/task/fibered_spec.rb +5 -0
  91. data/spec/celluloid/task/threaded_spec.rb +5 -0
  92. data/spec/celluloid/timer_spec.rb +14 -16
  93. data/spec/deprecate/actor_system_spec.rb +72 -0
  94. data/spec/deprecate/block_spec.rb +52 -0
  95. data/spec/deprecate/calls_spec.rb +39 -0
  96. data/spec/deprecate/evented_mailbox_spec.rb +34 -0
  97. data/spec/deprecate/future_spec.rb +32 -0
  98. data/spec/deprecate/internal_pool_spec.rb +4 -0
  99. data/spec/shared/actor_examples.rb +1259 -0
  100. data/spec/shared/group_examples.rb +121 -0
  101. data/spec/shared/mailbox_examples.rb +87 -0
  102. data/{lib/celluloid/rspec → spec/shared}/task_examples.rb +9 -8
  103. data/spec/spec_helper.rb +5 -42
  104. data/spec/support/configure_rspec.rb +77 -0
  105. data/spec/support/coverage.rb +4 -0
  106. data/spec/support/crash_checking.rb +68 -0
  107. data/spec/support/debugging.rb +31 -0
  108. data/spec/support/env.rb +21 -0
  109. data/{lib/celluloid/rspec/example_actor_class.rb → spec/support/examples/actor_class.rb} +21 -2
  110. data/spec/support/examples/call_class.rb +37 -0
  111. data/spec/support/examples/evented_mailbox_class.rb +27 -0
  112. data/spec/support/includer.rb +6 -0
  113. data/spec/support/logging.rb +55 -0
  114. data/spec/support/loose_threads.rb +68 -0
  115. data/spec/support/reset_class_variables.rb +27 -0
  116. data/spec/support/sleep_and_wait.rb +14 -0
  117. data/spec/support/stubbing.rb +14 -0
  118. metadata +276 -78
  119. data/lib/celluloid/actor_system.rb +0 -107
  120. data/lib/celluloid/call_chain.rb +0 -13
  121. data/lib/celluloid/cpu_counter.rb +0 -34
  122. data/lib/celluloid/evented_mailbox.rb +0 -73
  123. data/lib/celluloid/fsm.rb +0 -186
  124. data/lib/celluloid/handlers.rb +0 -41
  125. data/lib/celluloid/internal_pool.rb +0 -159
  126. data/lib/celluloid/legacy.rb +0 -9
  127. data/lib/celluloid/links.rb +0 -36
  128. data/lib/celluloid/logger.rb +0 -93
  129. data/lib/celluloid/logging/incident.rb +0 -21
  130. data/lib/celluloid/logging/incident_logger.rb +0 -129
  131. data/lib/celluloid/logging/incident_reporter.rb +0 -48
  132. data/lib/celluloid/logging/log_event.rb +0 -20
  133. data/lib/celluloid/logging/ring_buffer.rb +0 -65
  134. data/lib/celluloid/method.rb +0 -32
  135. data/lib/celluloid/notifications.rb +0 -83
  136. data/lib/celluloid/pool_manager.rb +0 -146
  137. data/lib/celluloid/probe.rb +0 -73
  138. data/lib/celluloid/properties.rb +0 -24
  139. data/lib/celluloid/proxies/abstract_proxy.rb +0 -20
  140. data/lib/celluloid/proxies/actor_proxy.rb +0 -38
  141. data/lib/celluloid/proxies/async_proxy.rb +0 -31
  142. data/lib/celluloid/proxies/block_proxy.rb +0 -29
  143. data/lib/celluloid/proxies/cell_proxy.rb +0 -68
  144. data/lib/celluloid/proxies/future_proxy.rb +0 -35
  145. data/lib/celluloid/proxies/sync_proxy.rb +0 -36
  146. data/lib/celluloid/receivers.rb +0 -63
  147. data/lib/celluloid/registry.rb +0 -57
  148. data/lib/celluloid/responses.rb +0 -44
  149. data/lib/celluloid/rspec/actor_examples.rb +0 -1054
  150. data/lib/celluloid/rspec/mailbox_examples.rb +0 -84
  151. data/lib/celluloid/signals.rb +0 -23
  152. data/lib/celluloid/stack_dump.rb +0 -133
  153. data/lib/celluloid/supervision_group.rb +0 -169
  154. data/lib/celluloid/supervisor.rb +0 -22
  155. data/lib/celluloid/task_set.rb +0 -49
  156. data/lib/celluloid/tasks/task_fiber.rb +0 -43
  157. data/lib/celluloid/tasks/task_thread.rb +0 -53
  158. data/lib/celluloid/thread_handle.rb +0 -50
  159. data/lib/celluloid/uuid.rb +0 -38
  160. data/spec/celluloid/actor_system_spec.rb +0 -69
  161. data/spec/celluloid/cpu_counter_spec.rb +0 -82
  162. data/spec/celluloid/fsm_spec.rb +0 -107
  163. data/spec/celluloid/internal_pool_spec.rb +0 -52
  164. data/spec/celluloid/links_spec.rb +0 -45
  165. data/spec/celluloid/logging/ring_buffer_spec.rb +0 -38
  166. data/spec/celluloid/notifications_spec.rb +0 -120
  167. data/spec/celluloid/pool_spec.rb +0 -92
  168. data/spec/celluloid/probe_spec.rb +0 -121
  169. data/spec/celluloid/properties_spec.rb +0 -42
  170. data/spec/celluloid/registry_spec.rb +0 -64
  171. data/spec/celluloid/stack_dump_spec.rb +0 -64
  172. data/spec/celluloid/supervision_group_spec.rb +0 -65
  173. data/spec/celluloid/supervisor_spec.rb +0 -103
  174. data/spec/celluloid/tasks/task_fiber_spec.rb +0 -5
  175. data/spec/celluloid/tasks/task_thread_spec.rb +0 -5
  176. data/spec/celluloid/thread_handle_spec.rb +0 -26
  177. data/spec/celluloid/uuid_spec.rb +0 -11
@@ -0,0 +1,121 @@
1
+ RSpec.shared_examples "a Celluloid Group" do
2
+ let!(:queue) { Queue.new }
3
+ let!(:busy_queue) { Queue.new }
4
+
5
+ let(:logger) { Specs::FakeLogger.current }
6
+
7
+ def wait_until_busy(busy_queue = nil)
8
+ return busy_queue.pop if busy_queue
9
+ Specs.sleep_and_wait_until { subject.busy? }
10
+ end
11
+
12
+ def wait_until_idle
13
+ Specs.sleep_and_wait_until { subject.idle? }
14
+ end
15
+
16
+ before { subject }
17
+
18
+ after do
19
+ subject.shutdown
20
+ end
21
+
22
+ it "gets threads" do
23
+ expect(subject.get { queue.pop }).to be_a Thread
24
+ queue << nil
25
+ wait_until_idle
26
+ end
27
+
28
+ [::StandardError, ::Exception].each do |exception_class|
29
+ context "with an #{exception_class} in the thread" do
30
+ before do
31
+ @wait_queue = Queue.new # doesn't work if in a let()
32
+
33
+ allow(logger).to receive(:crash)
34
+
35
+ subject.get do
36
+ busy_queue << nil
37
+ @wait_queue.pop
38
+ fail exception_class, "Error"
39
+ end
40
+
41
+ wait_until_busy(busy_queue)
42
+ end
43
+
44
+ it "logs the crash" do
45
+ expect(logger).to receive(:crash).with("thread crashed", exception_class)
46
+ @wait_queue << nil # let the thread fail
47
+ wait_until_idle
48
+ end
49
+
50
+ it "puts error'd threads back" do
51
+ @wait_queue << nil # let the thread fail
52
+ wait_until_idle
53
+ expect(subject.idle?).to be_truthy
54
+ end
55
+ end
56
+ end
57
+
58
+ context "when a thread has local variables" do
59
+ before do
60
+ @thread = subject.get do
61
+ Thread.current[:foo] = :bar
62
+ queue.pop
63
+ end
64
+
65
+ wait_until_busy
66
+
67
+ queue << nil # let the thread finish
68
+ if Celluloid.group_class == Celluloid::Group::Pool
69
+ # Wait until we get the same thread for a different proc
70
+ Specs.sleep_and_wait_until { subject.get { sleep 0.1 } == @thread }
71
+ else
72
+ wait_until_idle
73
+ end
74
+ end
75
+
76
+ # Cleaning not necessary for Spawner
77
+ unless Celluloid.group_class == Celluloid::Group::Spawner
78
+ it "cleans thread locals from old threads" do
79
+ expect(@thread[:foo]).to be_nil
80
+ end
81
+ end
82
+ end
83
+
84
+ it "shuts down" do
85
+ subject
86
+ thread = Queue.new
87
+
88
+ expect(
89
+ subject.get do
90
+ thread << Thread.current
91
+ sleep
92
+ end,
93
+ ).to be_a(Celluloid::Thread)
94
+
95
+ thread.pop # wait for 3rd-party thread to get strated
96
+
97
+ expect(subject.active?).to eq true
98
+ subject.shutdown
99
+ expect(subject.active?).to eq false
100
+ expect(subject.group.length).to eq 0
101
+ end
102
+
103
+ context "with a dead thread" do
104
+ before do
105
+ if Celluloid.group_class == Celluloid::Group::Pool
106
+ subject.max_idle = 0 # Instruct the pool to immediately shut down the thread.
107
+ end
108
+
109
+ subject.get { queue.pop }
110
+ wait_until_busy
111
+ queue << nil
112
+ wait_until_idle
113
+
114
+ subject.shutdown if Celluloid.group_class == Celluloid::Group::Spawner
115
+ end
116
+
117
+ it "doesn't leak dead threads" do
118
+ expect(subject.to_a.size).to eq(0)
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,87 @@
1
+ RSpec.shared_examples "a Celluloid Mailbox" do
2
+ after do
3
+ allow(Celluloid.logger).to receive(:debug)
4
+ subject.shutdown if subject.alive?
5
+ end
6
+
7
+ it "receives messages" do
8
+ message = :ohai
9
+
10
+ subject << message
11
+ expect(subject.receive).to eq(message)
12
+ end
13
+
14
+ it "prioritizes system events over other messages" do
15
+ subject << :dummy1
16
+ subject << :dummy2
17
+
18
+ subject << Celluloid::SystemEvent.new
19
+ expect(subject.receive).to be_a(Celluloid::SystemEvent)
20
+ end
21
+
22
+ it "selectively receives messages with a block" do
23
+ class Foo; end
24
+ class Bar; end
25
+ class Baz; end
26
+
27
+ foo = Foo.new
28
+ bar = Bar.new
29
+ baz = Baz.new
30
+
31
+ subject << baz
32
+ subject << foo
33
+ subject << bar
34
+
35
+ expect(subject.receive { |msg| msg.is_a? Foo }).to eq(foo)
36
+ expect(subject.receive { |msg| msg.is_a? Bar }).to eq(bar)
37
+ expect(subject.receive).to eq(baz)
38
+ end
39
+
40
+ it "waits for a given timeout interval" do
41
+ interval = 0.1
42
+ started_at = Time.now
43
+
44
+ expect do
45
+ subject.receive(interval) { false }
46
+ end.to raise_exception(Celluloid::TaskTimeout)
47
+
48
+ # Just check to make sure it didn't return earlier
49
+ expect(Time.now - started_at).to be >= interval
50
+ end
51
+
52
+ it "has a size" do
53
+ expect(subject).to respond_to(:size)
54
+ expect(subject.size).to be_zero
55
+ subject << :foo
56
+ subject << :foo
57
+ expect(subject.entries.size).to eq(2)
58
+ end
59
+
60
+ it "discards messages received when when full" do
61
+ subject.max_size = 2
62
+ subject << :first
63
+ subject << :second
64
+ subject << :third
65
+ expect(subject.to_a).to match_array([:first, :second])
66
+ end
67
+
68
+ it "logs discarded messages" do
69
+ expect(Celluloid.logger).to receive(:debug).with("Discarded message (mailbox is dead): third")
70
+
71
+ subject.max_size = 2
72
+ subject << :first
73
+ subject << :second
74
+ subject << :third
75
+ end
76
+
77
+ it "discard messages when dead" do
78
+ expect(Celluloid.logger).to receive(:debug).with("Discarded message (mailbox is dead): first")
79
+ expect(Celluloid.logger).to receive(:debug).with("Discarded message (mailbox is dead): second")
80
+ expect(Celluloid.logger).to receive(:debug).with("Discarded message (mailbox is dead): third")
81
+
82
+ subject << :first
83
+ subject << :second
84
+ subject.shutdown
85
+ subject << :third
86
+ end
87
+ end
@@ -9,12 +9,12 @@ class MockActor
9
9
  end
10
10
  end
11
11
 
12
- shared_context "a Celluloid Task" do |task_class|
12
+ RSpec.shared_examples "a Celluloid Task" do
13
13
  let(:task_type) { :foobar }
14
14
  let(:suspend_state) { :doing_something }
15
15
  let(:actor) { MockActor.new }
16
16
 
17
- subject { task_class.new(task_type, {}) { Celluloid::Task.suspend(suspend_state) } }
17
+ subject { Celluloid.task_class.new(task_type, {}) { Celluloid::Task.suspend(suspend_state) } }
18
18
 
19
19
  before :each do
20
20
  Thread.current[:celluloid_actor_system] = Celluloid.actor_system
@@ -22,25 +22,26 @@ shared_context "a Celluloid Task" do |task_class|
22
22
  end
23
23
 
24
24
  after :each do
25
+ Thread.current[:celluloid_actor_system].shutdown
25
26
  Thread.current[:celluloid_actor] = nil
26
27
  Thread.current[:celluloid_actor_system] = nil
27
28
  end
28
29
 
29
30
  it "begins with status :new" do
30
- subject.status.should be :new
31
+ expect(subject.status).to be :new
31
32
  end
32
33
 
33
34
  it "resumes" do
34
- subject.should be_running
35
+ expect(subject).to be_running
35
36
  subject.resume
36
- subject.status.should eq(suspend_state)
37
+ expect(subject.status).to eq(suspend_state)
37
38
  subject.resume
38
- subject.should_not be_running
39
+ expect(subject).not_to be_running
39
40
  end
40
41
 
41
42
  it "raises exceptions outside" do
42
- task = task_class.new(task_type, {}) do
43
- raise "failure"
43
+ task = Celluloid.task_class.new(task_type, {}) do
44
+ fail "failure"
44
45
  end
45
46
  expect do
46
47
  task.resume
data/spec/spec_helper.rb CHANGED
@@ -1,44 +1,7 @@
1
- require 'coveralls'
2
- Coveralls.wear!
1
+ require "rubygems"
2
+ require "bundler/setup"
3
3
 
4
- require 'rubygems'
5
- require 'bundler/setup'
6
- require 'celluloid/rspec'
7
- require 'celluloid/probe'
4
+ require "celluloid/rspec"
5
+ require "celluloid/essentials"
8
6
 
9
- logfile = File.open(File.expand_path("../../log/test.log", __FILE__), 'a')
10
- logfile.sync = true
11
-
12
- Celluloid.logger = Logger.new(logfile)
13
-
14
- Celluloid.shutdown_timeout = 1
15
-
16
- Dir['./spec/support/*.rb'].map {|f| require f }
17
-
18
- RSpec.configure do |config|
19
- config.filter_run :focus => true
20
- config.run_all_when_everything_filtered = true
21
-
22
- config.around do |ex|
23
- Celluloid.actor_system = nil
24
- Thread.list.each do |thread|
25
- next if thread == Thread.current
26
- thread.kill
27
- end
28
-
29
- ex.run
30
- end
31
-
32
- config.around actor_system: :global do |ex|
33
- Celluloid.boot
34
- ex.run
35
- Celluloid.shutdown
36
- end
37
-
38
- config.around actor_system: :within do |ex|
39
- Celluloid::ActorSystem.new.within do
40
- ex.run
41
- end
42
- end
43
-
44
- end
7
+ Dir[*Specs::INCLUDE_PATHS].map { |f| require f }
@@ -0,0 +1,77 @@
1
+ RSpec.configure do |config|
2
+ config.filter_run focus: true unless Nenv.ci?
3
+ config.run_all_when_everything_filtered = true
4
+ config.disable_monkey_patching!
5
+ config.profile_examples = 3
6
+ config.filter_gems_from_backtrace(*Specs::BACKTRACE_OMITTED)
7
+
8
+ config.verbose_retry = true
9
+ config.default_retry_count = Specs::ALLOW_RETRIES
10
+ config.display_try_failure_messages = true
11
+ config.default_sleep_interval = 1
12
+ config.exceptions_to_retry = [Timeout::Error, Celluloid::ThreadLeak]
13
+
14
+ config.mock_with :rspec do |mocks|
15
+ mocks.verify_doubled_constant_names = true
16
+ mocks.verify_partial_doubles = true
17
+ end
18
+
19
+ config.before(:suite) do
20
+ Specs.stub_out_class_method(Celluloid::Internals::Logger, :crash) do |*args|
21
+ _name, ex = *args
22
+ fail "Unstubbed Logger.crash() was called:\n crash(\n #{args.map(&:inspect).join(",\n ")})"\
23
+ "\nException backtrace: \n (#{ex.class}) #{ex.backtrace * "\n (#{ex.class}) "}"
24
+ end
25
+ end
26
+
27
+ config.before(:each) do |example|
28
+ @fake_logger = Specs::FakeLogger.new(Celluloid.logger, example.description)
29
+ stub_const("Celluloid::Internals::Logger", @fake_logger)
30
+ end
31
+
32
+ config.around do |ex|
33
+ # Needed because some specs mock/stub/expect on the logger
34
+ Celluloid.logger = Specs.logger
35
+ Celluloid.actor_system = nil
36
+ Specs.reset_class_variables(ex.description) do
37
+ Timeout.timeout(Specs::MAX_EXECUTION) { ex.run }
38
+ end
39
+ if @fake_logger.crashes?
40
+ crashes = @fake_logger.crashes.map do |args, call_stack|
41
+ msg, ex = *args
42
+ "\n** Crash: #{msg.inspect}(#{ex.inspect})\n Backtrace:\n (crash) #{call_stack * "\n (crash) "}"\
43
+ "\n Exception Backtrace (#{ex.inspect}):\n (ex) #{ex.backtrace * "\n (ex) "}"
44
+ end.join("\n")
45
+ fail "Actor crashes occured (please stub/mock if these are expected): #{crashes}"
46
+ end
47
+ @fake_logger = nil
48
+ Specs.assert_no_loose_threads!("after example: #{ex.description}") if Specs::CHECK_LOOSE_THREADS
49
+ end
50
+
51
+ config.around :each, library: :IO do |ex|
52
+ Celluloid.init
53
+ FileUtils.rm("/tmp/cell_sock") if File.exist?("/tmp/cell_sock")
54
+ ex.run
55
+ Celluloid.shutdown
56
+ end
57
+
58
+ config.around :each, library: :ZMQ do |ex|
59
+ Celluloid::ZMQ.init(1) unless ex.metadata[:no_init]
60
+ Celluloid.boot
61
+ ex.run
62
+ Celluloid.shutdown
63
+ Celluloid::ZMQ.terminate
64
+ end
65
+
66
+ config.around :each, actor_system: :global do |ex|
67
+ Celluloid.boot
68
+ ex.run
69
+ Celluloid.shutdown
70
+ end
71
+
72
+ config.around :each, actor_system: :within do |ex|
73
+ Celluloid::Actor::System.new.within do
74
+ ex.run
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,4 @@
1
+ if Nenv.ci?
2
+ require "coveralls"
3
+ Coveralls.wear!
4
+ end
@@ -0,0 +1,68 @@
1
+ module Specs
2
+ class FakeLogger
3
+ class << self
4
+ def current
5
+ allowed_logger.first
6
+ end
7
+
8
+ attr_accessor :allowed_logger
9
+ end
10
+
11
+ def initialize(real_logger, example)
12
+ @mutex = Mutex.new
13
+ @real_logger = real_logger
14
+ @crashes = Queue.new
15
+ @details = nil
16
+ @example = example
17
+ self.class.allowed_logger = [self, example]
18
+ end
19
+
20
+ def crash(*args)
21
+ check
22
+ fail "Testing block has already ended!" if @details
23
+ @crashes << [args, caller.dup]
24
+ end
25
+
26
+ def debug(*args)
27
+ check
28
+ @real_logger.debug(*args)
29
+ end
30
+
31
+ def warn(*args)
32
+ check
33
+ @real_logger.warn(*args)
34
+ end
35
+
36
+ def with_backtrace(_backtrace)
37
+ check
38
+ yield self
39
+ end
40
+
41
+ def crashes
42
+ check
43
+ @mutex.synchronize do
44
+ return @details if @details
45
+ @details = []
46
+ @details << @crashes.pop until @crashes.empty?
47
+ @crashes = nil
48
+ @details
49
+ end
50
+ end
51
+
52
+ def crashes?
53
+ check
54
+ !crashes.empty?
55
+ end
56
+
57
+ private
58
+
59
+ def check
60
+ return if self.class.allowed_logger.first == self
61
+
62
+ fail "Incorrect logger used:"\
63
+ " active/allowed: \n#{clas.allowed_logger.inspect},\n"\
64
+ " actual/self: \n#{[self, @example].inspect}\n"\
65
+ " (maybe an actor from another test is still running?)"
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,31 @@
1
+ module Debugging
2
+ # Attempt to safely convert an object to a useful string (without side
3
+ # effects if possible)
4
+ #
5
+ # Feel free to add support for more objects/responses/etc.
6
+ def self.dump(obj)
7
+ case obj
8
+ when ::Symbol
9
+ obj.inspect
10
+ when ::String
11
+ obj
12
+ when ::Regexp
13
+ obj.inspect
14
+ when ::IO
15
+ obj.inspect
16
+ when ::Array
17
+ obj.map { |a| Debugging.dump(a) }.to_s
18
+ when ::Celluloid::Response::Success
19
+ "SuccessResponse(#{dump(obj.value)}) (#{dump(obj.call)})"
20
+ when ::Celluloid::Call
21
+ args = obj.arguments.map { |a| Debugging.dump(a) }
22
+ "Call: #{obj}-> #{obj.method.inspect}(#{args.join(', ')})"
23
+ else
24
+ begin
25
+ obj.__send__(:__class__).to_s
26
+ rescue NoMethodError
27
+ obj.__send__(:class).to_s
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ require "nenv"
2
+ require "dotenv"
3
+
4
+ # Default to `pwd`/.env-* ( whatever is in the current directory )
5
+ # Otherwise take the `.env-*` from the gem itself.
6
+ unless env = Nenv("celluloid").config_file
7
+ env = Nenv.ci? ? ".env-ci" : ".env-dev"
8
+ unless File.exist?(env)
9
+ env = File.expand_path("../../../#{env}", __FILE__)
10
+ end
11
+ end
12
+
13
+ Dotenv.load!(env) rescue nil # If for some reason no .env-* files are available at all, use defaults.
14
+
15
+ module Specs
16
+ class << self
17
+ def env
18
+ @env ||= Nenv("celluloid_specs")
19
+ end
20
+ end
21
+ end
@@ -1,3 +1,7 @@
1
+ class ExampleCrash < Celluloid::Error
2
+ attr_accessor :foo
3
+ end
4
+
1
5
  module ExampleActorClass
2
6
  def self.create(included_module, task_klass)
3
7
  Class.new do
@@ -41,7 +45,7 @@ module ExampleActorClass
41
45
  end
42
46
 
43
47
  def crash
44
- raise ExampleCrash, "the spec purposely crashed me :("
48
+ fail ExampleCrash, "the spec purposely crashed me :("
45
49
  end
46
50
 
47
51
  def crash_with_abort(reason, foo = nil)
@@ -74,6 +78,8 @@ module ExampleActorClass
74
78
  terminate
75
79
  end
76
80
 
81
+ # Ideally, this class should implement "fake methods"
82
+ # consistently, including :methods, :public_methods, etc.
77
83
  def method_missing(method_name, *args, &block)
78
84
  if delegates?(method_name)
79
85
  @delegate.send method_name, *args, &block
@@ -83,7 +89,19 @@ module ExampleActorClass
83
89
  end
84
90
 
85
91
  def respond_to?(method_name, include_private = false)
86
- super || delegates?(method_name)
92
+ if delegates?(method_name)
93
+ delegates?(method_name)
94
+ else
95
+ super
96
+ end
97
+ end
98
+
99
+ def method(method_name)
100
+ if delegates?(method_name)
101
+ @delegate.method(method_name)
102
+ else
103
+ super
104
+ end
87
105
  end
88
106
 
89
107
  def call_private
@@ -102,6 +120,7 @@ module ExampleActorClass
102
120
  private
103
121
 
104
122
  def delegates?(method_name)
123
+ return false unless @delegate ||= nil
105
124
  @delegate.respond_to?(method_name)
106
125
  end
107
126
  end
@@ -0,0 +1,37 @@
1
+ class CallExampleActor
2
+ include Celluloid
3
+
4
+ def initialize(next_actor = nil)
5
+ @next = next_actor
6
+ end
7
+
8
+ def actual_method; end
9
+
10
+ def inspect
11
+ fail "Don't call!"
12
+ end
13
+
14
+ def chained_call_ids
15
+ [call_chain_id, @next.call_chain_id]
16
+ end
17
+ end
18
+
19
+ # de DEPRECATE:
20
+
21
+ class DeprecatedCallExampleActor
22
+ include Celluloid
23
+
24
+ def initialize(next_actor = nil)
25
+ @next = next_actor
26
+ end
27
+
28
+ def actual_method; end
29
+
30
+ def inspect
31
+ fail "Please don't call me! I'm not ready yet!"
32
+ end
33
+
34
+ def chained_call_ids
35
+ [call_chain_id, @next.call_chain_id]
36
+ end
37
+ end
@@ -0,0 +1,27 @@
1
+ class TestEventedMailbox < Celluloid::Mailbox::Evented
2
+ class Reactor
3
+ def initialize
4
+ @condition = ConditionVariable.new
5
+ @mutex = Mutex.new
6
+ end
7
+
8
+ def wakeup
9
+ @mutex.synchronize do
10
+ @condition.signal
11
+ end
12
+ end
13
+
14
+ def run_once(timeout)
15
+ @mutex.synchronize do
16
+ @condition.wait(@mutex, timeout)
17
+ end
18
+ end
19
+
20
+ def shutdown
21
+ end
22
+ end
23
+
24
+ def initialize
25
+ super(Reactor)
26
+ end
27
+ end
@@ -0,0 +1,6 @@
1
+ module CelluloidSpecs
2
+ def self.included_module
3
+ # Celluloid::IO implements this with with 'Celluloid::IO'
4
+ (defined? INCLUDED_MODULE) ? INCLUDED_MODULE : Celluloid
5
+ end
6
+ end
@@ -0,0 +1,55 @@
1
+ module Specs
2
+ class << self
3
+ def log
4
+ # Setup ENV variable handling with sane defaults
5
+ @log ||= Nenv("celluloid_specs_log") do |env|
6
+ env.create_method(:file) { |f| f || "log/default.log" }
7
+ env.create_method(:sync?) { |s| s || !Nenv.ci? }
8
+
9
+ env.create_method(:strategy) do |strategy|
10
+ strategy || default_strategy
11
+ end
12
+
13
+ env.create_method(:level) { |level| default_level_for(env, level) }
14
+ end
15
+ end
16
+
17
+ def logger
18
+ @logger ||= default_logger.tap { |logger| logger.level = log.level }
19
+ end
20
+
21
+ attr_writer :logger
22
+
23
+ private
24
+
25
+ def default_logger
26
+ case log.strategy
27
+ when "stderr"
28
+ Logger.new(STDERR)
29
+ when "single"
30
+ Logger.new(open_logfile(log.file, log.sync?))
31
+ else
32
+ fail "Unknown logger strategy: #{strategy.inspect}."\
33
+ " Expected 'single' or 'stderr'."
34
+ end
35
+ end
36
+
37
+ def open_logfile(rel_path, sync)
38
+ root = Pathname(__FILE__).dirname.dirname.dirname
39
+ log_path = root + rel_path
40
+ logfile = File.open(log_path.to_s, "a")
41
+ logfile.sync if sync
42
+ logfile
43
+ end
44
+
45
+ def default_strategy
46
+ (Nenv.ci? ? "stderr" : "single")
47
+ end
48
+
49
+ def default_level_for(env, level)
50
+ Integer(level)
51
+ rescue
52
+ env.strategy == "stderr" ? Logger::WARN : Logger::DEBUG
53
+ end
54
+ end
55
+ end