wamp-worker 0.1.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 (129) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +5 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +204 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/bin/wamp-worker +46 -0
  13. data/lib/wamp/worker.rb +132 -0
  14. data/lib/wamp/worker/config.rb +184 -0
  15. data/lib/wamp/worker/handler.rb +196 -0
  16. data/lib/wamp/worker/proxy/backgrounder.rb +38 -0
  17. data/lib/wamp/worker/proxy/base.rb +101 -0
  18. data/lib/wamp/worker/proxy/dispatcher.rb +115 -0
  19. data/lib/wamp/worker/proxy/requestor.rb +91 -0
  20. data/lib/wamp/worker/queue.rb +135 -0
  21. data/lib/wamp/worker/rails.rb +28 -0
  22. data/lib/wamp/worker/runner.rb +240 -0
  23. data/lib/wamp/worker/ticker.rb +30 -0
  24. data/lib/wamp/worker/version.rb +5 -0
  25. data/spec/spec_helper.rb +29 -0
  26. data/spec/support/client_stub.rb +47 -0
  27. data/spec/support/handler_stub.rb +105 -0
  28. data/spec/support/redis_stub.rb +89 -0
  29. data/spec/support/session_stub.rb +101 -0
  30. data/spec/wamp/worker/config_spec.rb +90 -0
  31. data/spec/wamp/worker/handler_spec.rb +162 -0
  32. data/spec/wamp/worker/proxy_spec.rb +153 -0
  33. data/spec/wamp/worker/queue_spec.rb +49 -0
  34. data/spec/wamp/worker/runner_spec.rb +108 -0
  35. data/spec/wamp/worker_spec.rb +8 -0
  36. data/test/app_test.rb +124 -0
  37. data/test/hello.py +50 -0
  38. data/test/sidekiq.yml +5 -0
  39. data/test/wamp_test/.generators +8 -0
  40. data/test/wamp_test/.ruby-version +1 -0
  41. data/test/wamp_test/Gemfile +65 -0
  42. data/test/wamp_test/Gemfile.lock +246 -0
  43. data/test/wamp_test/README.md +24 -0
  44. data/test/wamp_test/Rakefile +6 -0
  45. data/test/wamp_test/app/assets/config/manifest.js +3 -0
  46. data/test/wamp_test/app/assets/images/.keep +0 -0
  47. data/test/wamp_test/app/assets/javascripts/application.js +16 -0
  48. data/test/wamp_test/app/assets/javascripts/cable.js +13 -0
  49. data/test/wamp_test/app/assets/javascripts/channels/.keep +0 -0
  50. data/test/wamp_test/app/assets/stylesheets/application.css +15 -0
  51. data/test/wamp_test/app/channels/application_cable/channel.rb +4 -0
  52. data/test/wamp_test/app/channels/application_cable/connection.rb +4 -0
  53. data/test/wamp_test/app/controllers/add_controller.rb +11 -0
  54. data/test/wamp_test/app/controllers/application_controller.rb +3 -0
  55. data/test/wamp_test/app/controllers/concerns/.keep +0 -0
  56. data/test/wamp_test/app/controllers/ping_controller.rb +7 -0
  57. data/test/wamp_test/app/handlers/add_handler.rb +9 -0
  58. data/test/wamp_test/app/handlers/back_add_handler.rb +26 -0
  59. data/test/wamp_test/app/handlers/back_ping_handler.rb +10 -0
  60. data/test/wamp_test/app/handlers/ping_handler.rb +10 -0
  61. data/test/wamp_test/app/helpers/application_helper.rb +2 -0
  62. data/test/wamp_test/app/jobs/application_job.rb +2 -0
  63. data/test/wamp_test/app/mailers/application_mailer.rb +4 -0
  64. data/test/wamp_test/app/models/application_record.rb +3 -0
  65. data/test/wamp_test/app/models/concerns/.keep +0 -0
  66. data/test/wamp_test/app/views/layouts/application.html.erb +15 -0
  67. data/test/wamp_test/app/views/layouts/mailer.html.erb +13 -0
  68. data/test/wamp_test/app/views/layouts/mailer.text.erb +1 -0
  69. data/test/wamp_test/bin/bundle +3 -0
  70. data/test/wamp_test/bin/rails +9 -0
  71. data/test/wamp_test/bin/rake +9 -0
  72. data/test/wamp_test/bin/setup +36 -0
  73. data/test/wamp_test/bin/spring +17 -0
  74. data/test/wamp_test/bin/update +31 -0
  75. data/test/wamp_test/bin/yarn +11 -0
  76. data/test/wamp_test/config.ru +5 -0
  77. data/test/wamp_test/config/application.rb +19 -0
  78. data/test/wamp_test/config/boot.rb +4 -0
  79. data/test/wamp_test/config/cable.yml +10 -0
  80. data/test/wamp_test/config/credentials.yml.enc +1 -0
  81. data/test/wamp_test/config/database.yml +25 -0
  82. data/test/wamp_test/config/environment.rb +5 -0
  83. data/test/wamp_test/config/environments/development.rb +61 -0
  84. data/test/wamp_test/config/environments/production.rb +94 -0
  85. data/test/wamp_test/config/environments/test.rb +46 -0
  86. data/test/wamp_test/config/initializers/application_controller_renderer.rb +8 -0
  87. data/test/wamp_test/config/initializers/assets.rb +14 -0
  88. data/test/wamp_test/config/initializers/backtrace_silencers.rb +7 -0
  89. data/test/wamp_test/config/initializers/content_security_policy.rb +25 -0
  90. data/test/wamp_test/config/initializers/cookies_serializer.rb +5 -0
  91. data/test/wamp_test/config/initializers/filter_parameter_logging.rb +4 -0
  92. data/test/wamp_test/config/initializers/inflections.rb +16 -0
  93. data/test/wamp_test/config/initializers/mime_types.rb +4 -0
  94. data/test/wamp_test/config/initializers/wamp-worker.rb +8 -0
  95. data/test/wamp_test/config/initializers/wrap_parameters.rb +14 -0
  96. data/test/wamp_test/config/locales/en.yml +33 -0
  97. data/test/wamp_test/config/master.key +1 -0
  98. data/test/wamp_test/config/puma.rb +34 -0
  99. data/test/wamp_test/config/routes.rb +4 -0
  100. data/test/wamp_test/config/sidekiq.yml +6 -0
  101. data/test/wamp_test/config/spring.rb +6 -0
  102. data/test/wamp_test/config/storage.yml +34 -0
  103. data/test/wamp_test/db/development.sqlite3 +0 -0
  104. data/test/wamp_test/db/seeds.rb +7 -0
  105. data/test/wamp_test/lib/assets/.keep +0 -0
  106. data/test/wamp_test/lib/tasks/.keep +0 -0
  107. data/test/wamp_test/package.json +5 -0
  108. data/test/wamp_test/public/404.html +67 -0
  109. data/test/wamp_test/public/422.html +67 -0
  110. data/test/wamp_test/public/500.html +66 -0
  111. data/test/wamp_test/public/apple-touch-icon-precomposed.png +0 -0
  112. data/test/wamp_test/public/apple-touch-icon.png +0 -0
  113. data/test/wamp_test/public/favicon.ico +0 -0
  114. data/test/wamp_test/public/robots.txt +1 -0
  115. data/test/wamp_test/storage/.keep +0 -0
  116. data/test/wamp_test/test/application_system_test_case.rb +5 -0
  117. data/test/wamp_test/test/controllers/.keep +0 -0
  118. data/test/wamp_test/test/fixtures/.keep +0 -0
  119. data/test/wamp_test/test/fixtures/files/.keep +0 -0
  120. data/test/wamp_test/test/helpers/.keep +0 -0
  121. data/test/wamp_test/test/integration/.keep +0 -0
  122. data/test/wamp_test/test/mailers/.keep +0 -0
  123. data/test/wamp_test/test/models/.keep +0 -0
  124. data/test/wamp_test/test/system/.keep +0 -0
  125. data/test/wamp_test/test/test_helper.rb +10 -0
  126. data/test/wamp_test/vendor/.keep +0 -0
  127. data/test/web/index.html +101 -0
  128. data/wamp-worker.gemspec +32 -0
  129. metadata +395 -0
@@ -0,0 +1,162 @@
1
+ require "spec_helper"
2
+
3
+ describe Wamp::Worker::Handler do
4
+ let(:name) { :default }
5
+ let(:session) { SessionStub.new }
6
+ let(:proxy) { Wamp::Worker::Proxy::Dispatcher.new(name, session) }
7
+
8
+ it "registers the handlers" do
9
+ config = Wamp::Worker.config
10
+
11
+ expect(config.subscriptions.count).to eq(2)
12
+ expect(config.subscriptions(name).count).to eq(2)
13
+ expect(config.subscriptions(:other).count).to eq(2)
14
+
15
+ expect(config.registrations.count).to eq(16)
16
+ expect(config.registrations(name).count).to eq(16)
17
+ expect(config.registrations(:other).count).to eq(2)
18
+ end
19
+
20
+ def setup_handlers
21
+ Wamp::Worker.subscribe_topics(name, proxy, session)
22
+ Wamp::Worker.register_procedures(name, proxy, session)
23
+ end
24
+
25
+ it "executes the normal handlers" do
26
+ setup_handlers
27
+
28
+ expect{
29
+ session.publish("topic", nil, nil)
30
+
31
+ session.call("return_error", nil, nil) do |result, error, details|
32
+ expect(error[:error]).to eq("error")
33
+ end
34
+
35
+ session.call("throw_error", nil, nil) do |result, error, details|
36
+ expect(error[:error]).to eq("error")
37
+ end
38
+
39
+ session.call("throw_exception", nil, nil) do |result, error, details|
40
+ expect(error[:error]).to eq("wamp.error.runtime")
41
+ expect(error[:args][0]).to eq("error")
42
+ end
43
+
44
+ session.call("call_result", [3], nil) do |result, error, details|
45
+ expect(result[:args][0]).to eq(5)
46
+ end
47
+
48
+ session.call("normal_result", [3], nil) do |result, error, details|
49
+ expect(result[:args][0]).to eq(6)
50
+ end
51
+
52
+ session.call("nil_result", [3], nil) do |result, error, details|
53
+ expect(result[:args][0]).to eq(nil)
54
+ end
55
+
56
+ session.call("proxy_result", [3], nil) do |result, error, details|
57
+ expect(result[:args][0]).to eq(6)
58
+ end
59
+ }.to change{ NormalHandler.run_count }.by(9)
60
+
61
+ end
62
+
63
+ it "executes the background handlers" do
64
+ setup_handlers
65
+
66
+ queue_count = 0
67
+ queue_params = nil
68
+
69
+ allow_any_instance_of(Wamp::Worker::Queue).to receive(:push) do |queue, queue_name, command, params, handle|
70
+ queue_params = params[:result]
71
+ queue_count += 1
72
+ expect(command).to eq(:yield)
73
+ end
74
+
75
+ expect{
76
+ session.publish("back.topic", nil, nil)
77
+
78
+ session.call("back.return_error", nil, nil)
79
+ expect(queue_params[:error]).to eq("error")
80
+
81
+ session.call("back.throw_error", nil, nil)
82
+ expect(queue_params[:error]).to eq("error")
83
+
84
+ session.call("back.throw_exception", nil, nil)
85
+ expect(queue_params[:error]).to eq("wamp.error.runtime")
86
+
87
+ session.call("back.call_result", [3], nil)
88
+ expect(queue_params[:args][0]).to eq(5)
89
+
90
+ session.call("back.normal_result", [3], nil)
91
+ expect(queue_params[:args][0]).to eq(6)
92
+
93
+ session.call("back.nil_result", [3], nil)
94
+ expect(queue_params[:args][0]).to eq(nil)
95
+ }.to change{ BackgroundHandler.run_count }.by(7)
96
+
97
+ expect(queue_count).to eq(6)
98
+ end
99
+
100
+ context "progress" do
101
+ before(:each) {
102
+ setup_handlers
103
+ }
104
+
105
+ it "reports the progress in the foreground" do
106
+ count = 0
107
+
108
+ session.call("progress_result", [3], nil, { receive_progress: true }) do |result, error, details|
109
+ case count
110
+ when 0
111
+ expect(result[:args][0]).to eq(0)
112
+ expect(details[:progress]).to eq(true)
113
+ when 1
114
+ expect(result[:args][0]).to eq(0.5)
115
+ expect(details[:progress]).to eq(true)
116
+ when 2
117
+ expect(result[:args][0]).to eq(1.0)
118
+ expect(details[:progress]).to eq(true)
119
+ else
120
+ expect(result[:args][0]).to eq(7)
121
+ expect(details[:progress]).not_to eq(true)
122
+ end
123
+
124
+ count += 1
125
+ end
126
+
127
+ expect(count).to eq(4)
128
+ end
129
+
130
+ it "reports the progress in the background" do
131
+ count = 0
132
+
133
+ allow_any_instance_of(Wamp::Worker::Queue).to receive(:push) do |queue, queue_name, command, params, handle|
134
+ result = params[:result]
135
+ options = params[:options]
136
+
137
+ case count
138
+ when 0
139
+ expect(result[:args][0]).to eq(0)
140
+ expect(options[:progress]).to eq(true)
141
+ when 1
142
+ expect(result[:args][0]).to eq(0.5)
143
+ expect(options[:progress]).to eq(true)
144
+ when 2
145
+ expect(result[:args][0]).to eq(1.0)
146
+ expect(options[:progress]).to eq(true)
147
+ else
148
+ expect(result[:args][0]).to eq(7)
149
+ expect(options[:progress]).not_to eq(true)
150
+ end
151
+
152
+ count += 1
153
+ end
154
+
155
+ session.call("back.progress_result", [3], nil, { receive_progress: true })
156
+
157
+ expect(count).to eq(4)
158
+ end
159
+ end
160
+
161
+ end
162
+
@@ -0,0 +1,153 @@
1
+ require "spec_helper"
2
+ require "thread"
3
+
4
+ class RequestorClass
5
+ include Wamp::Worker::Session.new(method: :temp_session)
6
+ end
7
+
8
+ describe Wamp::Worker::Proxy do
9
+ let(:name) { :default }
10
+ let(:topic) { "topic" }
11
+ let(:procedure) { "procedure" }
12
+ let(:session) { SessionStub.new }
13
+ let(:dispatcher) { described_class::Dispatcher.new(name, session) }
14
+ let(:requestor) { RequestorClass.new.temp_session }
15
+
16
+ before(:each) {
17
+ Wamp::Worker.subscribe_topics(name, dispatcher, session)
18
+ Wamp::Worker.register_procedures(name, dispatcher, session)
19
+ }
20
+
21
+ def check_method(times, method, *args)
22
+ check_result = nil
23
+ check_error = nil
24
+
25
+ # Create a thread to run the dispatcher
26
+ thread = Thread.new do
27
+ times.times do
28
+ descriptor = dispatcher.check_queues
29
+ dispatcher.process(descriptor)
30
+ end
31
+ end
32
+
33
+ requestor.send(method, *args) do |result, error, details|
34
+ check_result = result
35
+ check_error = error
36
+ end
37
+
38
+ # Wait for the thread to complete
39
+ thread.join
40
+
41
+ yield(check_result, check_error)
42
+ end
43
+
44
+ context "command/response flow" do
45
+
46
+ it "executes a call command" do
47
+ expect {
48
+ check_method(1, :call, "normal_result", [7]) do |result, error|
49
+ expect(result[:args][0]).to eq(10)
50
+ expect(error).to be_nil
51
+ end
52
+ }.to change{ NormalHandler.run_count }.by(1)
53
+ end
54
+
55
+ it "executes a call command with invalid procedure" do
56
+ expect {
57
+ check_method(1, :call, "invalid_procedure", [7]) do |result, error|
58
+ expect(result).to be_nil
59
+ expect(error).to eq({ error: "wamp.no_procedure", args:[], kwargs:{} })
60
+ end
61
+ }.to change{ NormalHandler.run_count }.by(0)
62
+ end
63
+
64
+ it "executes a call command with throw error" do
65
+ expect {
66
+ check_method(1, :call, "throw_error", [7]) do |result, error|
67
+ expect(result).to be_nil
68
+ expect(error).to eq({ error: "error", args:[], kwargs:{} })
69
+ end
70
+ }.to change{ NormalHandler.run_count }.by(1)
71
+ end
72
+
73
+ it "executes a publish command w/o acknowledge" do
74
+ expect {
75
+ check_method(1, :publish, "topic", [7]) do |result, error|
76
+ expect(result).to be_nil
77
+ expect(error).to be_nil
78
+ end
79
+ }.to change{ NormalHandler.run_count }.by(1)
80
+ end
81
+
82
+ it "executes a publish command w/ acknowledge" do
83
+ expect {
84
+ check_method(1, :publish, "topic", [7], {}, { acknowledge: true }) do |result, error|
85
+ expect(result).to eq(1234)
86
+ expect(error).to be_nil
87
+ end
88
+ }.to change{ NormalHandler.run_count }.by(1)
89
+ end
90
+
91
+ it "executes a publish command w/ acknowledge and error" do
92
+ expect {
93
+ check_method(1, :publish, "invalid_topic", [7], {}, { acknowledge: true }) do |result, error|
94
+ expect(result).to eq(1234)
95
+ expect(error).to eq({ error: "wamp.no_subscriber", args:[], kwargs:{} })
96
+ end
97
+ }.to change{ NormalHandler.run_count }.by(0)
98
+ end
99
+
100
+ it "errors on unsupported proxy command" do
101
+ requestor.queue.push requestor.command_req_queue, :bad, {}, "handle"
102
+
103
+ descriptor = dispatcher.check_queues
104
+ dispatcher.process(descriptor)
105
+
106
+ descriptor = requestor.queue.pop("handle")
107
+ expect(descriptor.command).to eq(:bad)
108
+ expect(descriptor.params[:error][:error]).to eq("wamp.error.runtime")
109
+ expect(descriptor.params[:error][:args][0]).to eq("unsupported proxy command 'bad'")
110
+ end
111
+ end
112
+
113
+ context "dispatcher/backgrounder flow" do
114
+
115
+ it "executes a 'call' command" do
116
+ expect {
117
+ check_method(2, :call, "back.normal_result", [7]) do |result, error|
118
+ expect(result[:args][0]).to eq(10)
119
+ expect(error).to be_nil
120
+ end
121
+ }.to change{ BackgroundHandler.run_count }.by(1)
122
+ end
123
+
124
+ it "executes a 'call' command with throw error" do
125
+ expect {
126
+ check_method(2, :call, "back.throw_error", [7]) do |result, error|
127
+ expect(result).to be_nil
128
+ expect(error).to eq({ error: "error", args:[], kwargs:{} })
129
+ end
130
+ }.to change{ BackgroundHandler.run_count }.by(1)
131
+ end
132
+
133
+ it "executes a 'publish' command w/o acknowledge" do
134
+ expect {
135
+ check_method(1, :publish, "back.topic", [7]) do |result, error|
136
+ expect(result).to be_nil
137
+ expect(error).to be_nil
138
+ end
139
+ }.to change{ BackgroundHandler.run_count }.by(1)
140
+ end
141
+
142
+ it "executes a 'publish' command w/ acknowledge" do
143
+ expect {
144
+ check_method(1, :publish, "back.topic", [7], {}, { acknowledge: true }) do |result, error|
145
+ expect(result).to eq(1234)
146
+ expect(error).to be_nil
147
+ end
148
+ }.to change{ BackgroundHandler.run_count }.by(1)
149
+ end
150
+ end
151
+
152
+ end
153
+
@@ -0,0 +1,49 @@
1
+ require "spec_helper"
2
+
3
+ describe Wamp::Worker::Queue do
4
+ let(:name) { :default }
5
+ let(:queue) { described_class.new(name) }
6
+ let(:queue_name) { "test:command" }
7
+ let(:handle) { "test:response" }
8
+ let(:params) { { temp: true } }
9
+
10
+ it "general push/pop" do
11
+ # Push the request
12
+ queue.push queue_name, :call, params, handle
13
+
14
+ # Pop the request
15
+ descriptor = queue.pop(queue_name, wait: true)
16
+ expect(descriptor.command).to eq(:call)
17
+ expect(descriptor.handle).to eq(handle)
18
+ expect(descriptor.params).to eq(params)
19
+
20
+ # Check and make sure the key still exists
21
+ expect(queue.redis.exists(queue_name)).to eq(true)
22
+ end
23
+
24
+ it "deletes on pop" do
25
+ expect(queue.redis.exists(queue_name)).to eq(false)
26
+
27
+ # Push the request
28
+ queue.push queue_name, :call, params, handle
29
+
30
+ expect(queue.redis.exists(queue_name)).to eq(true)
31
+
32
+ # Pop the request
33
+ descriptor = queue.pop(queue_name, delete: true)
34
+ expect(descriptor.command).to eq(:call)
35
+ expect(descriptor.handle).to eq(handle)
36
+ expect(descriptor.params).to eq(params)
37
+
38
+ expect(queue.redis.exists(queue_name)).to eq(false)
39
+ end
40
+
41
+ it "timeout" do
42
+ # Pop the descriptor
43
+ descriptor = queue.pop(queue_name, wait: true, timeout: 1)
44
+
45
+ # It should be nil
46
+ expect(descriptor).to eq(nil)
47
+ end
48
+
49
+ end
@@ -0,0 +1,108 @@
1
+ require "spec_helper"
2
+
3
+ describe Wamp::Worker::Runner do
4
+ let(:name) { :other }
5
+ let(:runner) { described_class::Main.new(name) }
6
+ let(:requestor) { Wamp::Worker.requestor(name) }
7
+
8
+ def execute_runner
9
+
10
+ # Start the runner
11
+ runner.start
12
+
13
+ # Start it and the event machine on a different thread
14
+ thread = Thread.new do
15
+ EM.run {}
16
+ end
17
+
18
+ yield
19
+
20
+ # Stop the event machine
21
+ runner.client.transport_class.stop_event_machine
22
+ thread.join
23
+
24
+ # Stop the runner
25
+ runner.stop
26
+
27
+ end
28
+
29
+ it "registers and subscribes" do
30
+
31
+ # Check attributes
32
+ expect(runner.active?).to eq(false)
33
+ expect(runner.dispatcher.session).to be_nil
34
+
35
+ execute_runner do
36
+
37
+ # Check attributes
38
+ expect(runner.active?).to eq(true)
39
+ expect(runner.dispatcher.session).to be(runner.client.session)
40
+
41
+ # Check that some of the handlers work
42
+ expect{
43
+ requestor.call("other.call_result", [3], nil) do |result, error, details|
44
+ expect(result[:args][0]).to eq(5)
45
+ end
46
+ }.to change{ NormalHandler.run_count }.by(1)
47
+
48
+ expect{
49
+ requestor.call("back.other.call_result", [4], nil) do |result, error, details|
50
+ expect(result[:args][0]).to eq(6)
51
+ end
52
+ }.to change{ BackgroundHandler.run_count }.by(1)
53
+
54
+ end
55
+
56
+ # Check attributes
57
+ expect(runner.active?).to eq(false)
58
+ expect(runner.dispatcher.session).to be_nil
59
+ end
60
+
61
+ it "synchronizes the UUID between all of the runners" do
62
+ uuid = runner.dispatcher.uuid
63
+ expect(runner.queue_monitor.dispatcher.uuid).to eq(uuid)
64
+ end
65
+
66
+ it "increments the ticker" do
67
+ expect(runner.dispatcher.ticker.get).to eq(0)
68
+
69
+ expect {
70
+ execute_runner do
71
+ sleep(2.5)
72
+ end
73
+ }.to change{ runner.dispatcher.ticker.get }.by(3)
74
+ end
75
+
76
+ context "challenge" do
77
+ it "errors if challenge is called but no method was passed in" do
78
+ runner = described_class::Main.new :test, client: ClientStub.new({should_challenge: true})
79
+
80
+ # Errors because the callback wasn't defined
81
+ expect {
82
+ runner.start
83
+ }.to raise_error(ArgumentError)
84
+
85
+ # Ensure that the runner terminated
86
+ expect(runner.active?).to eq(false)
87
+ end
88
+
89
+ it "does not error when the challenge is defined" do
90
+ value = 0
91
+
92
+ # Create the runner passing it the challenge method
93
+ runner = described_class::Main.new :test,
94
+ challenge: -> authmethod, details {value += 1},
95
+ client: ClientStub.new({should_challenge: true})
96
+
97
+ # Start the runner
98
+ runner.start
99
+
100
+ # Expect that the challenge method was called
101
+ expect(value).to eq(1)
102
+
103
+ # Stop the runner
104
+ runner.stop
105
+ end
106
+
107
+ end
108
+ end