celluloid 0.17.2 → 0.18.0

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 (174) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES.md +340 -75
  3. data/CONDUCT.md +13 -0
  4. data/CONTRIBUTING.md +39 -0
  5. data/LICENSE.txt +1 -1
  6. data/README.md +54 -150
  7. data/REFACTOR.md +1 -0
  8. data/architecture.md +120 -0
  9. data/examples/basic_usage.rb +1 -1
  10. data/examples/configurations.rb +78 -0
  11. data/examples/futures.rb +1 -1
  12. data/examples/ring.rb +5 -4
  13. data/examples/simple_pmap.rb +1 -1
  14. data/examples/stack.rb +2 -2
  15. data/examples/supervisors_and_registry.rb +82 -0
  16. data/examples/timers.rb +2 -2
  17. data/lib/celluloid.rb +78 -65
  18. data/lib/celluloid/actor.rb +27 -17
  19. data/lib/celluloid/actor/system.rb +13 -29
  20. data/lib/celluloid/autostart.rb +6 -1
  21. data/lib/celluloid/call/async.rb +2 -0
  22. data/lib/celluloid/call/sync.rb +10 -3
  23. data/lib/celluloid/calls.rb +13 -13
  24. data/lib/celluloid/cell.rb +5 -9
  25. data/lib/celluloid/condition.rb +3 -3
  26. data/lib/celluloid/core_ext.rb +0 -2
  27. data/lib/celluloid/debug.rb +3 -0
  28. data/lib/celluloid/exceptions.rb +2 -2
  29. data/lib/celluloid/future.rb +8 -10
  30. data/lib/celluloid/group.rb +16 -6
  31. data/lib/celluloid/group/pool.rb +1 -3
  32. data/lib/celluloid/group/spawner.rb +2 -6
  33. data/lib/celluloid/internals/call_chain.rb +15 -0
  34. data/lib/celluloid/internals/cpu_counter.rb +62 -0
  35. data/lib/celluloid/internals/handlers.rb +42 -0
  36. data/lib/celluloid/internals/links.rb +38 -0
  37. data/lib/celluloid/internals/logger.rb +104 -0
  38. data/lib/celluloid/internals/method.rb +34 -0
  39. data/lib/celluloid/internals/properties.rb +32 -0
  40. data/lib/celluloid/internals/receivers.rb +64 -0
  41. data/lib/celluloid/internals/registry.rb +102 -0
  42. data/lib/celluloid/internals/responses.rb +46 -0
  43. data/lib/celluloid/internals/signals.rb +24 -0
  44. data/lib/celluloid/internals/stack.rb +74 -0
  45. data/lib/celluloid/internals/stack/dump.rb +12 -0
  46. data/lib/celluloid/internals/stack/states.rb +72 -0
  47. data/lib/celluloid/internals/stack/summary.rb +12 -0
  48. data/lib/celluloid/internals/task_set.rb +51 -0
  49. data/lib/celluloid/internals/thread_handle.rb +52 -0
  50. data/lib/celluloid/internals/uuid.rb +40 -0
  51. data/lib/celluloid/logging/incident.rb +21 -0
  52. data/lib/celluloid/logging/incident_logger.rb +147 -0
  53. data/lib/celluloid/logging/incident_reporter.rb +49 -0
  54. data/lib/celluloid/logging/log_event.rb +20 -0
  55. data/lib/celluloid/logging/ring_buffer.rb +64 -0
  56. data/lib/celluloid/mailbox.rb +22 -9
  57. data/lib/celluloid/mailbox/evented.rb +13 -7
  58. data/lib/celluloid/notifications.rb +95 -0
  59. data/lib/celluloid/pool.rb +6 -0
  60. data/lib/celluloid/probe.rb +81 -0
  61. data/lib/celluloid/proxy/abstract.rb +38 -7
  62. data/lib/celluloid/proxy/actor.rb +0 -5
  63. data/lib/celluloid/proxy/async.rb +2 -18
  64. data/lib/celluloid/proxy/block.rb +2 -1
  65. data/lib/celluloid/proxy/cell.rb +1 -7
  66. data/lib/celluloid/proxy/future.rb +3 -21
  67. data/lib/celluloid/proxy/sync.rb +2 -20
  68. data/lib/celluloid/rspec.rb +22 -34
  69. data/lib/celluloid/supervision.rb +17 -0
  70. data/lib/celluloid/supervision/configuration.rb +169 -0
  71. data/lib/celluloid/supervision/configuration/injections.rb +8 -0
  72. data/lib/celluloid/supervision/configuration/instance.rb +113 -0
  73. data/lib/celluloid/supervision/constants.rb +123 -0
  74. data/lib/celluloid/supervision/container.rb +144 -0
  75. data/lib/celluloid/supervision/container/behavior.rb +89 -0
  76. data/lib/celluloid/supervision/container/behavior/pool.rb +71 -0
  77. data/lib/celluloid/supervision/container/behavior/tree.rb +23 -0
  78. data/lib/celluloid/supervision/container/injections.rb +8 -0
  79. data/lib/celluloid/supervision/container/instance.rb +116 -0
  80. data/lib/celluloid/supervision/container/pool.rb +210 -0
  81. data/lib/celluloid/supervision/service.rb +27 -0
  82. data/lib/celluloid/supervision/supervise.rb +34 -0
  83. data/lib/celluloid/supervision/validation.rb +40 -0
  84. data/lib/celluloid/supervision/version.rb +5 -0
  85. data/lib/celluloid/system_events.rb +10 -3
  86. data/lib/celluloid/task.rb +25 -12
  87. data/lib/celluloid/task/fibered.rb +6 -2
  88. data/lib/celluloid/task/threaded.rb +3 -3
  89. data/lib/celluloid/test.rb +5 -2
  90. data/lib/celluloid/thread.rb +0 -2
  91. data/lib/celluloid/version.rb +1 -1
  92. data/spec/celluloid/block_spec.rb +29 -32
  93. data/spec/celluloid/calls_spec.rb +5 -15
  94. data/spec/celluloid/future_spec.rb +7 -1
  95. data/spec/celluloid/internals/cpu_counter_spec.rb +129 -0
  96. data/spec/celluloid/internals/links_spec.rb +43 -0
  97. data/spec/celluloid/internals/properties_spec.rb +40 -0
  98. data/spec/celluloid/internals/registry_spec.rb +62 -0
  99. data/spec/celluloid/internals/stack/dump_spec.rb +4 -0
  100. data/spec/celluloid/internals/stack/summary_spec.rb +4 -0
  101. data/spec/celluloid/internals/thread_handle_spec.rb +60 -0
  102. data/spec/celluloid/internals/uuid_spec.rb +9 -0
  103. data/spec/celluloid/logging/ring_buffer_spec.rb +36 -0
  104. data/spec/celluloid/mailbox/evented_spec.rb +21 -19
  105. data/spec/celluloid/misc/leak_spec.rb +3 -4
  106. data/spec/celluloid/notifications_spec.rb +140 -0
  107. data/spec/celluloid/probe_spec.rb +102 -0
  108. data/spec/celluloid/proxy_spec.rb +33 -0
  109. data/spec/celluloid/supervision/behavior_spec.rb +74 -0
  110. data/spec/celluloid/supervision/configuration_spec.rb +181 -0
  111. data/spec/celluloid/supervision/container_spec.rb +72 -0
  112. data/spec/celluloid/supervision/instance_spec.rb +13 -0
  113. data/spec/celluloid/supervision/root_spec.rb +28 -0
  114. data/spec/celluloid/supervision/supervisor_spec.rb +93 -0
  115. data/spec/celluloid/task/fibered_spec.rb +1 -3
  116. data/spec/celluloid/task/threaded_spec.rb +1 -3
  117. data/spec/shared/actor_examples.rb +65 -29
  118. data/spec/shared/group_examples.rb +2 -2
  119. data/spec/shared/mailbox_examples.rb +1 -1
  120. data/spec/shared/stack_examples.rb +87 -0
  121. data/spec/shared/task_examples.rb +2 -3
  122. data/spec/spec_helper.rb +2 -4
  123. data/spec/support/configure_rspec.rb +3 -4
  124. data/spec/support/coverage.rb +2 -4
  125. data/spec/support/crash_checking.rb +2 -2
  126. data/spec/support/examples/actor_class.rb +3 -8
  127. data/spec/support/examples/call_class.rb +2 -2
  128. data/spec/support/examples/container_class.rb +35 -0
  129. data/spec/support/examples/evented_mailbox_class.rb +1 -2
  130. data/spec/support/examples/stack_classes.rb +58 -0
  131. data/spec/support/examples/stack_methods.rb +23 -0
  132. data/spec/support/examples/subordinate_class.rb +19 -0
  133. data/spec/support/logging.rb +3 -34
  134. data/spec/support/loose_threads.rb +3 -24
  135. data/spec/support/reset_class_variables.rb +5 -1
  136. data/spec/support/stubbing.rb +1 -1
  137. metadata +93 -291
  138. data/culture/CONDUCT.md +0 -28
  139. data/culture/Gemfile +0 -9
  140. data/culture/LICENSE.txt +0 -22
  141. data/culture/README.md +0 -22
  142. data/culture/Rakefile +0 -5
  143. data/culture/SYNC.md +0 -70
  144. data/culture/celluloid-culture.gemspec +0 -18
  145. data/culture/gems/README.md +0 -39
  146. data/culture/gems/dependencies.yml +0 -85
  147. data/culture/gems/loader.rb +0 -101
  148. data/culture/rubocop/README.md +0 -38
  149. data/culture/rubocop/lint.yml +0 -8
  150. data/culture/rubocop/metrics.yml +0 -15
  151. data/culture/rubocop/perf.yml +0 -0
  152. data/culture/rubocop/rubocop.yml +0 -5
  153. data/culture/rubocop/style.yml +0 -57
  154. data/culture/spec/gems_spec.rb +0 -2
  155. data/culture/spec/spec_helper.rb +0 -0
  156. data/culture/spec/sync_spec.rb +0 -2
  157. data/culture/sync.rb +0 -56
  158. data/culture/tasks/rspec.rake +0 -5
  159. data/culture/tasks/rubocop.rake +0 -2
  160. data/lib/celluloid/actor/manager.rb +0 -7
  161. data/lib/celluloid/backported.rb +0 -2
  162. data/lib/celluloid/current.rb +0 -2
  163. data/lib/celluloid/deprecate.rb +0 -21
  164. data/lib/celluloid/fiber.rb +0 -32
  165. data/lib/celluloid/managed.rb +0 -3
  166. data/lib/celluloid/notices.rb +0 -15
  167. data/spec/celluloid/actor/manager_spec.rb +0 -0
  168. data/spec/deprecate/actor_system_spec.rb +0 -72
  169. data/spec/deprecate/block_spec.rb +0 -52
  170. data/spec/deprecate/calls_spec.rb +0 -39
  171. data/spec/deprecate/evented_mailbox_spec.rb +0 -34
  172. data/spec/deprecate/future_spec.rb +0 -32
  173. data/spec/deprecate/internal_pool_spec.rb +0 -4
  174. data/spec/support/env.rb +0 -21
@@ -2,26 +2,28 @@ RSpec.describe Celluloid::Mailbox::Evented do
2
2
  subject { TestEventedMailbox.new }
3
3
  it_behaves_like "a Celluloid Mailbox"
4
4
 
5
- # NOTE: this example seems too exotic to "have to" succeed on RBX, though I
6
- # don't know why it hangs on subject.receive and the timeout never occurs
7
- #
8
- # Other than
9
- #
10
- # Links:
11
- # https://github.com/celluloid/celluloid-io/pull/98
12
- # https://github.com/celluloid/celluloid-io/issues/56
13
- #
14
- unless RUBY_ENGINE == "rbx"
15
- it "recovers from timeout exceeded to process mailbox message" do
16
- timeout_interval = Specs::TIMER_QUANTUM + 0.1
17
- started_at = Time.now
18
- expect do
19
- Kernel.send(:timeout, timeout_interval) do
20
- subject.receive { false }
21
- end
22
- end.to raise_exception(Timeout::Error)
5
+ it "recovers from timeout exceeded to process mailbox message" do
6
+ timeout_interval = Specs::TIMER_QUANTUM + 0.1
7
+ started_at = Time.now
8
+ expect do
9
+ ::Timeout.timeout(timeout_interval) do
10
+ subject.receive { false }
11
+ end
12
+ end.to raise_exception(Timeout::Error)
23
13
 
24
- expect(Time.now - started_at).to be_within(Specs::TIMER_QUANTUM).of timeout_interval
14
+ expect(Time.now - started_at).to be_within(Specs::TIMER_QUANTUM).of timeout_interval
15
+ end
16
+
17
+ it "discard messages when reactor wakeup fails" do
18
+ expect(Celluloid::Internals::Logger).to receive(:crash).with("reactor crashed", RuntimeError)
19
+ expect(Celluloid.logger).to receive(:debug).with("Discarded message (mailbox is dead): first")
20
+
21
+ bad_reactor = Class.new do
22
+ def wakeup
23
+ raise
24
+ end
25
25
  end
26
+ mailbox = Celluloid::Mailbox::Evented.new(bad_reactor)
27
+ mailbox << :first
26
28
  end
27
29
  end
@@ -13,11 +13,10 @@ RSpec.describe "Leaks", actor_system: :global, leaktest: true,
13
13
  []
14
14
  end
15
15
 
16
- def terminate
17
- end
16
+ def terminate; end
18
17
  end
19
18
 
20
- def wait_for_release(weak, _what, count=1000)
19
+ def wait_for_release(weak, _what, count = 1000)
21
20
  trash = []
22
21
  count.times do |step|
23
22
  GC.start
@@ -43,7 +42,7 @@ RSpec.describe "Leaks", actor_system: :global, leaktest: true,
43
42
  end
44
43
 
45
44
  context "celluloid actor" do
46
- it "is properly destroyed upon termination" do
45
+ xit "is properly destroyed upon termination" do
47
46
  actor_life("actor") do |actor|
48
47
  WeakRef.new actor
49
48
  end
@@ -0,0 +1,140 @@
1
+ RSpec.describe Celluloid::Notifications, actor_system: :global do
2
+ class Admirer
3
+ include Celluloid
4
+ include Celluloid::Notifications
5
+
6
+ attr_reader :mourning
7
+ attr_reader :mourning_count
8
+
9
+ def someone_died(_topic, name)
10
+ @mourning = name
11
+ @mourning_count ||= 0
12
+ @mourning_count += 1
13
+ end
14
+ end
15
+
16
+ class President
17
+ include Celluloid
18
+ include Celluloid::Notifications
19
+
20
+ def die(topic = "death")
21
+ publish(topic, "Mr. President")
22
+ end
23
+ end
24
+
25
+ it "notifies relevant subscribers" do
26
+ marilyn = Admirer.new
27
+ jackie = Admirer.new
28
+
29
+ marilyn.subscribe("death", :someone_died)
30
+ jackie.subscribe("alive", :someone_died)
31
+
32
+ president = President.new
33
+
34
+ president.die
35
+ expect(marilyn.mourning).to eq("Mr. President")
36
+ expect(jackie.mourning).not_to eq("Mr. President")
37
+ end
38
+
39
+ it "allows multiple subscriptions from the same actor" do
40
+ marilyn = Admirer.new
41
+
42
+ marilyn.subscribe("death", :someone_died)
43
+ marilyn.subscribe("death", :someone_died)
44
+
45
+ president = President.new
46
+
47
+ president.die
48
+ expect(marilyn.mourning_count).to be(2)
49
+ end
50
+
51
+ it "notifies subscribers" do
52
+ marilyn = Admirer.new
53
+ jackie = Admirer.new
54
+
55
+ marilyn.subscribe("death", :someone_died)
56
+ jackie.subscribe("death", :someone_died)
57
+
58
+ president = President.new
59
+
60
+ president.die
61
+ expect(marilyn.mourning).to eq("Mr. President")
62
+ expect(jackie.mourning).to eq("Mr. President")
63
+ end
64
+
65
+ it "publishes even if there are no subscribers" do
66
+ president = President.new
67
+ president.die
68
+ end
69
+
70
+ it "allows symbol subscriptions" do
71
+ marilyn = Admirer.new
72
+ jackie = Admirer.new
73
+
74
+ marilyn.subscribe(:death, :someone_died)
75
+ jackie.subscribe("death", :someone_died)
76
+
77
+ president = President.new
78
+ president.die(:death)
79
+ expect(marilyn.mourning).to eq("Mr. President")
80
+ expect(jackie.mourning).to eq("Mr. President")
81
+ end
82
+
83
+ it "allows regex subscriptions" do
84
+ marilyn = Admirer.new
85
+
86
+ marilyn.subscribe(/(death|assassination)/, :someone_died)
87
+
88
+ president = President.new
89
+ president.die
90
+ expect(marilyn.mourning).to eq("Mr. President")
91
+ end
92
+
93
+ it "matches symbols against regex subscriptions" do
94
+ marilyn = Admirer.new
95
+
96
+ marilyn.subscribe(/(death|assassination)/, :someone_died)
97
+
98
+ president = President.new
99
+ president.die(:assassination)
100
+ expect(marilyn.mourning).to eq("Mr. President")
101
+ end
102
+
103
+ it "allows unsubscribing" do
104
+ marilyn = Admirer.new
105
+
106
+ subscription = marilyn.subscribe("death", :someone_died)
107
+ marilyn.unsubscribe(subscription)
108
+
109
+ president = President.new
110
+ president.die
111
+ expect(marilyn.mourning).to be_nil
112
+ end
113
+
114
+ it "prunes dead subscriptions" do
115
+ marilyn = Admirer.new
116
+ jackie = Admirer.new
117
+
118
+ marilyn.subscribe("death", :someone_died)
119
+ jackie.subscribe("death", :someone_died)
120
+
121
+ listeners = Celluloid::Notifications.notifier.listeners_for("death").size
122
+ marilyn.terminate
123
+ after_listeners = Celluloid::Notifications.notifier.listeners_for("death").size
124
+
125
+ expect(after_listeners).to eq(listeners - 1)
126
+ end
127
+
128
+ it "prunes multiple subscriptions from a dead actor" do
129
+ marilyn = Admirer.new
130
+
131
+ marilyn.subscribe("death", :someone_died)
132
+ marilyn.subscribe("death", :someone_died)
133
+
134
+ listeners = Celluloid::Notifications.notifier.listeners_for("death").size
135
+ marilyn.terminate
136
+ after_listeners = Celluloid::Notifications.notifier.listeners_for("death").size
137
+
138
+ expect(after_listeners).to eq(listeners - 2)
139
+ end
140
+ end
@@ -0,0 +1,102 @@
1
+ require "celluloid/probe"
2
+
3
+ class DummyActor; include Celluloid; end
4
+
5
+ class TestProbeClient
6
+ include Celluloid
7
+ include Celluloid::Notifications
8
+
9
+ attr_reader :buffer
10
+ finalizer :do_unsubscribe
11
+
12
+ def initialize(queue)
13
+ @events = queue
14
+ subscribe(/celluloid\.events\..+/, :event_received)
15
+ end
16
+
17
+ def event_received(topic, args)
18
+ @events << [topic, args[0], args[1]]
19
+ end
20
+
21
+ def do_unsubscribe
22
+ # TODO: shouldn't be necessary
23
+ return unless Actor[:notifications_fanout]
24
+
25
+ unsubscribe
26
+ rescue Celluloid::DeadActorError
27
+ # Something is wrong with the shutdown seq. Whatever...
28
+ rescue => ex
29
+ STDERR.puts "Exception while finalizing TestProbeClient: #{ex.inspect}"
30
+ STDERR.puts "BACKTRACE: #{ex.backtrace * "\n (ex) "}"
31
+ sleep 5
32
+ end
33
+ end
34
+
35
+ RSpec.describe "Probe", actor_system: :global do
36
+ let(:logger) { Specs::FakeLogger.current }
37
+
38
+ def addr(actor)
39
+ return nil unless actor
40
+ return nil unless actor.mailbox
41
+ return nil unless actor.mailbox.address
42
+ actor.mailbox.address
43
+ rescue Celluloid::DeadActorError
44
+ "(dead actor)"
45
+ end
46
+
47
+ def wait_for_match(queue, topic, actor1 = nil, actor2 = nil)
48
+ started = Time.now.to_f
49
+ actors = [actor1, actor2]
50
+ expected = ([topic] + actors.map { |a| addr(a) }).dup
51
+
52
+ received = []
53
+ last_event_timestamp = nil
54
+
55
+ Timeout.timeout(5) do
56
+ loop do
57
+ event = queue.pop
58
+ actual = ([event[0]] + event[1..-1].map { |a| addr(a) }).dup
59
+ received << actual
60
+ last_event_timestamp = Time.now.to_f
61
+ return event if actual == expected
62
+ end
63
+ end
64
+ rescue Timeout::Error => e
65
+ q = Celluloid::Probe::EVENTS_BUFFER
66
+ unprocessed = []
67
+ loop do
68
+ break if q.empty?
69
+ name, args = q.pop
70
+ actual = ([name] + args.map { |a| addr(a) }).dup
71
+ unprocessed << actual
72
+ end
73
+
74
+ last_event_offset = if last_event_timestamp
75
+ last_event_timestamp - started
76
+ else
77
+ "(no events ever received)"
78
+ end
79
+
80
+ raise "wait_for_match: no matching event received for #{topic.inspect}! (#{e.inspect})\n"\
81
+ "Expected: #{expected.inspect}\n"\
82
+ "Events received: \n #{received.map(&:inspect) * "\n "}\n"\
83
+ "Current time offset: #{(Time.now.to_f - started).inspect}\n"\
84
+ "Last event offset: #{last_event_offset.inspect}\n"\
85
+ "Unprocessed probe events: #{unprocessed.map(&:inspect) * "\n "}\n"\
86
+ end
87
+
88
+ def flush_probe_queue
89
+ # Probe doesn't process the queue periodically, so some events can get in
90
+ # while previous events are being processed.
91
+ #
92
+ # So, we generate another event, so Probe processed the queue (containing
93
+ # the previously unprocessed event).
94
+ Celluloid::Actor["an_extra_event"] = Class.new { include Celluloid }.new
95
+ end
96
+
97
+ let(:queue) { Queue.new }
98
+
99
+ describe ".run" do
100
+ pending "cannot unsupervise the Probe yet (#573)"
101
+ end
102
+ end
@@ -0,0 +1,33 @@
1
+ RSpec.describe Celluloid::Proxy::Abstract do
2
+ around do |ex|
3
+ Celluloid.boot
4
+ ex.run
5
+ Celluloid.shutdown
6
+ end
7
+
8
+ let(:task_klass) { Celluloid.task_class }
9
+ let(:actor_class) { ExampleActorClass.create(CelluloidSpecs.included_module, task_klass) }
10
+ let(:actor) { actor_class.new "Troy McClure" }
11
+
12
+ let(:logger) { Specs::FakeLogger.current }
13
+
14
+ it "should be eql? to self" do
15
+ expect(actor.eql?(actor)).to be_truthy
16
+ end
17
+
18
+ it "should be eql? to self even if dead" do
19
+ actor.terminate
20
+ expect(actor.eql?(actor)).to be_truthy
21
+ end
22
+
23
+ it "should not be eql? to other proxy objects" do
24
+ other_future = Celluloid::Proxy::Future.new(actor.mailbox, actor.__klass__)
25
+
26
+ expect(actor.future.eql?(other_future)).to be_truthy
27
+ end
28
+
29
+ it "should be possible to compare with non-proxy objects" do
30
+ expect(actor.eql?("string")).to be_falsey
31
+ expect("string".eql?(actor)).to be_falsey
32
+ end
33
+ end
@@ -0,0 +1,74 @@
1
+ RSpec.describe Celluloid::Supervision::Container::Behavior do
2
+ class WellBehaved
3
+ include Celluloid
4
+ end
5
+
6
+ let(:typeless) do
7
+ {
8
+ as: :testing_behaviors,
9
+ supervises: [
10
+ {
11
+ as: :testing_behaved_instances,
12
+ type: WellBehaved
13
+ }
14
+ ]
15
+ }
16
+ end
17
+
18
+ let(:normal) do
19
+ {
20
+ as: :testing_behaviors,
21
+ supervises: [
22
+ {
23
+ as: :testing_behaved_instances,
24
+ type: WellBehaved
25
+ }
26
+ ]
27
+ }
28
+ end
29
+
30
+ let(:mutant) do
31
+ {
32
+ as: :testing_behaviors,
33
+ supervise: [],
34
+ supervises: [
35
+ {
36
+ as: :testing_behaved_instances,
37
+ type: WellBehaved
38
+ }
39
+ ]
40
+ }
41
+ end
42
+
43
+ subject { Celluloid::Supervision::Configuration.new }
44
+
45
+ it("detects default type if not provided, and provides it") do
46
+ end
47
+
48
+ it("prejudicially rejects mutants") do
49
+ expect { subject.define(mutant) }.to raise_error(Celluloid::Supervision::Container::Behavior::Error::Mutant)
50
+ end
51
+
52
+ context("allows definition of new plugins") do
53
+ class TestPlugin
54
+ include Celluloid::Supervision::Container::Behavior
55
+ identifier! :identifying_parameter, :aliased_identifier
56
+ end
57
+
58
+ xit("and adds a plugin parameter") do
59
+ expect(Celluloid::Supervision::Configuration.parameters(:plugins)).to include(:identifying_parameter)
60
+ end
61
+
62
+ xit("and adds aliased parameters") do
63
+ expect(Celluloid::Supervision::Configuration.aliases.keys?).to include(:aliased_identifier)
64
+ end
65
+ end
66
+
67
+ context("allows inclusion by Module") do
68
+ xit("with automatic addition of injections") do
69
+ end
70
+
71
+ xit("with correct handling of injections made") do
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,181 @@
1
+ RSpec.describe Celluloid::Supervision::Configuration, actor_system: :global do
2
+ class TestActor
3
+ include Celluloid
4
+ def identity
5
+ :testing
6
+ end
7
+ end
8
+
9
+ let(:succeeding) do
10
+ {
11
+ as: :testing,
12
+ type: TestActor
13
+ }
14
+ end
15
+
16
+ let(:failing) do
17
+ {
18
+ as: :testing,
19
+ type: TestActor,
20
+ args: [:fail]
21
+ }
22
+ end
23
+
24
+ after(:each) do
25
+ Celluloid::Supervision::Configuration.resync_parameters
26
+ subject.resync_accessors
27
+ end
28
+
29
+ context("remains reusable without being mutated") do
30
+ it("properly") do
31
+ expect(Celluloid.actor_system.root_configuration.export).to eq(Celluloid::Actor::System::ROOT_SERVICES)
32
+ end
33
+ end
34
+
35
+ context("metaprogramming") do
36
+ context("Celluloid.services accessor") do
37
+ it("is dynamically added, and available") do
38
+ expect(Celluloid.services.respond_to?(:supervise)).to be_truthy
39
+ end
40
+ it("allows supervision") do
41
+ Celluloid.services.supervise(type: TestActor, as: :test_actor)
42
+ expect(Celluloid.services.test_actor.identity).to eq(:testing)
43
+ end
44
+ end
45
+
46
+ context("supervised actors can create accessors") do
47
+ it("which are dynamically added, and available as Celluloid.accessor") do
48
+ TestActor.supervise(as: :test_actor, accessors: [:test_actor])
49
+ expect(Celluloid.test_actor.identity).to eq(:testing)
50
+ end
51
+ end
52
+ end
53
+
54
+ context("parameters") do
55
+ context("can be added to") do
56
+ context("can be given new :mandatory parameters") do
57
+ before(:each) do
58
+ Celluloid::Supervision::Configuration.parameter! :mandatory, :special_requirement
59
+ subject.resync_accessors
60
+ end
61
+
62
+ it("programmatically") do
63
+ expect(Celluloid::Supervision::Configuration.parameters(:mandatory)).to include(:special_requirement)
64
+ end
65
+
66
+ it("and respond appropriately") do
67
+ subject.resync_accessors
68
+ expect(subject.methods).to include(:special_requirement)
69
+ expect(subject.respond_to?(:special_requirement!)).to be_truthy
70
+ expect(subject.respond_to?(:special_requirement?)).to be_truthy
71
+ expect(subject.respond_to?(:special_requirement=)).to be_truthy
72
+ expect(subject.respond_to?(:special_requirement)).to be_truthy
73
+ end
74
+
75
+ it("and instances will respond appropriately") do
76
+ subject.instances.first.resync_accessors
77
+ subject.define(type: TestActor, special_requirement: :valid)
78
+ expect(subject.respond_to?(:special_requirement)).to be_truthy
79
+ end
80
+
81
+ it("and be reset to defaults") do
82
+ Celluloid::Supervision::Configuration.resync_parameters
83
+ expect(Celluloid::Supervision::Configuration.parameters(:mandatory)).not_to include(:special_requirement)
84
+ end
85
+ end
86
+
87
+ context("can be aliased") do
88
+ before(:each) do
89
+ Celluloid::Supervision::Configuration.resync_parameters
90
+ Celluloid::Supervision::Configuration.alias! :nick, :as
91
+ subject.resync_accessors
92
+ end
93
+
94
+ it("programmatically") do
95
+ expect(Celluloid::Supervision::Configuration.aliases.keys).to include(:nick)
96
+ end
97
+
98
+ it("and respond appropriately by method") do
99
+ subject.define(type: TestActor, as: :test_name)
100
+ expect(subject.respond_to?(:nick!)).to be_truthy
101
+ expect(subject.respond_to?(:nick?)).to be_truthy
102
+ expect(subject.respond_to?(:nick=)).to be_truthy
103
+ expect(subject.respond_to?(:nick)).to be_truthy
104
+ expect(subject.nick).to eq(:test_name)
105
+ end
106
+
107
+ xit("and respond properly by current_instance, by method") do
108
+ # subject.current_instance[:aliased] gets subject.current_instance[:original]
109
+ end
110
+
111
+ it("and instances will respond properly by method") do
112
+ subject.define(as: :test_name, type: TestActor)
113
+ expect(subject.instances.first.respond_to?(:nick!)).to be_truthy
114
+ expect(subject.instances.first.respond_to?(:nick?)).to be_truthy
115
+ expect(subject.instances.first.respond_to?(:nick=)).to be_truthy
116
+ expect(subject.instances.first.respond_to?(:nick)).to be_truthy
117
+ expect(subject.instances.first.nick).to eq(:test_name)
118
+ end
119
+
120
+ xit("and respond appropriately by key") do
121
+ # subject[:aliased] gets subject[:original]
122
+ end
123
+
124
+ xit("and instances respond properly by current_instance, by key") do
125
+ # subject.instances.first[:aliased] gets subject.instances.first[:original]
126
+ end
127
+
128
+ xit("and instances respond properly by key") do
129
+ # subject.instances.first[:aliased] gets subject.instances.first[:original]
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ context("Configuration.define class method") do
136
+ xit("can take individual instance configuration") do
137
+ end
138
+
139
+ xit("can take array of instance configurations") do
140
+ end
141
+ end
142
+
143
+ context("Configuration#define instance method") do
144
+ xit("can take individual instance configuration") do
145
+ end
146
+
147
+ xit("can take array of instance configurations") do
148
+ end
149
+ end
150
+
151
+ context("Configuration.deploy class method") do
152
+ xit("can take individual instance configuration") do
153
+ end
154
+
155
+ xit("can take array of instance configurations") do
156
+ end
157
+ end
158
+
159
+ context("Configuration#deploy instance method") do
160
+ xit("can take individual instance configuration") do
161
+ end
162
+
163
+ xit("can take array of instance configurations") do
164
+ end
165
+ end
166
+
167
+ context("accessing information") do
168
+ before(:each) { subject.define(succeeding) }
169
+ it("can get values out of current level of configuration by [:key]") do
170
+ expect(subject[:as]).to eq(:testing)
171
+ end
172
+
173
+ it("can get values out of current level of configuration by #key") do
174
+ expect(subject.as).to eq(:testing)
175
+ end
176
+ end
177
+
178
+ it("verifies arity of intended actor's initialize method") do
179
+ expect { subject.define(failing) }.to raise_exception(ArgumentError)
180
+ end
181
+ end