cuboid 0.0.0 → 0.0.1alpha

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 (221) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +0 -0
  3. data/Gemfile +20 -5
  4. data/LICENSE.md +22 -0
  5. data/README.md +158 -19
  6. data/Rakefile +56 -3
  7. data/config/paths.yml +15 -0
  8. data/cuboid.gemspec +61 -23
  9. data/lib/cuboid.rb +96 -4
  10. data/lib/cuboid/application.rb +326 -0
  11. data/lib/cuboid/application/parts/data.rb +18 -0
  12. data/lib/cuboid/application/parts/report.rb +29 -0
  13. data/lib/cuboid/application/parts/state.rb +274 -0
  14. data/lib/cuboid/application/runtime.rb +25 -0
  15. data/lib/cuboid/banner.rb +13 -0
  16. data/lib/cuboid/data.rb +86 -0
  17. data/lib/cuboid/data/application.rb +52 -0
  18. data/lib/cuboid/error.rb +9 -0
  19. data/lib/cuboid/option_group.rb +129 -0
  20. data/lib/cuboid/option_groups.rb +8 -0
  21. data/lib/cuboid/option_groups/datastore.rb +23 -0
  22. data/lib/cuboid/option_groups/dispatcher.rb +38 -0
  23. data/lib/cuboid/option_groups/output.rb +14 -0
  24. data/lib/cuboid/option_groups/paths.rb +184 -0
  25. data/lib/cuboid/option_groups/report.rb +39 -0
  26. data/lib/cuboid/option_groups/rpc.rb +105 -0
  27. data/lib/cuboid/option_groups/scheduler.rb +27 -0
  28. data/lib/cuboid/option_groups/snapshot.rb +13 -0
  29. data/lib/cuboid/option_groups/system.rb +10 -0
  30. data/lib/cuboid/options.rb +254 -0
  31. data/lib/cuboid/processes.rb +13 -0
  32. data/lib/cuboid/processes/dispatchers.rb +140 -0
  33. data/lib/cuboid/processes/executables/base.rb +54 -0
  34. data/lib/cuboid/processes/executables/dispatcher.rb +5 -0
  35. data/lib/cuboid/processes/executables/instance.rb +12 -0
  36. data/lib/cuboid/processes/executables/rest_service.rb +13 -0
  37. data/lib/cuboid/processes/executables/scheduler.rb +5 -0
  38. data/lib/cuboid/processes/helpers.rb +4 -0
  39. data/lib/cuboid/processes/helpers/dispatchers.rb +23 -0
  40. data/lib/cuboid/processes/helpers/instances.rb +39 -0
  41. data/lib/cuboid/processes/helpers/processes.rb +23 -0
  42. data/lib/cuboid/processes/helpers/schedulers.rb +23 -0
  43. data/lib/cuboid/processes/instances.rb +203 -0
  44. data/lib/cuboid/processes/manager.rb +262 -0
  45. data/lib/cuboid/processes/schedulers.rb +128 -0
  46. data/lib/cuboid/report.rb +220 -0
  47. data/lib/cuboid/rest/server.rb +165 -0
  48. data/lib/cuboid/rest/server/instance_helpers.rb +99 -0
  49. data/lib/cuboid/rest/server/routes/dispatcher.rb +41 -0
  50. data/lib/cuboid/rest/server/routes/grid.rb +41 -0
  51. data/lib/cuboid/rest/server/routes/instances.rb +131 -0
  52. data/lib/cuboid/rest/server/routes/scheduler.rb +140 -0
  53. data/lib/cuboid/rpc/client.rb +3 -0
  54. data/lib/cuboid/rpc/client/base.rb +58 -0
  55. data/lib/cuboid/rpc/client/dispatcher.rb +58 -0
  56. data/lib/cuboid/rpc/client/instance.rb +100 -0
  57. data/lib/cuboid/rpc/client/instance/service.rb +37 -0
  58. data/lib/cuboid/rpc/client/scheduler.rb +46 -0
  59. data/lib/cuboid/rpc/serializer.rb +92 -0
  60. data/lib/cuboid/rpc/server/active_options.rb +38 -0
  61. data/lib/cuboid/rpc/server/application_wrapper.rb +138 -0
  62. data/lib/cuboid/rpc/server/base.rb +63 -0
  63. data/lib/cuboid/rpc/server/dispatcher.rb +317 -0
  64. data/lib/cuboid/rpc/server/dispatcher/node.rb +247 -0
  65. data/lib/cuboid/rpc/server/dispatcher/service.rb +145 -0
  66. data/lib/cuboid/rpc/server/instance.rb +338 -0
  67. data/lib/cuboid/rpc/server/output.rb +92 -0
  68. data/lib/cuboid/rpc/server/scheduler.rb +482 -0
  69. data/lib/cuboid/ruby.rb +4 -0
  70. data/lib/cuboid/ruby/array.rb +17 -0
  71. data/lib/cuboid/ruby/hash.rb +41 -0
  72. data/lib/cuboid/ruby/object.rb +32 -0
  73. data/lib/cuboid/snapshot.rb +186 -0
  74. data/lib/cuboid/state.rb +94 -0
  75. data/lib/cuboid/state/application.rb +309 -0
  76. data/lib/cuboid/state/options.rb +27 -0
  77. data/lib/cuboid/support.rb +11 -0
  78. data/lib/cuboid/support/buffer.rb +3 -0
  79. data/lib/cuboid/support/buffer/autoflush.rb +61 -0
  80. data/lib/cuboid/support/buffer/base.rb +91 -0
  81. data/lib/cuboid/support/cache.rb +7 -0
  82. data/lib/cuboid/support/cache/base.rb +226 -0
  83. data/lib/cuboid/support/cache/least_cost_replacement.rb +77 -0
  84. data/lib/cuboid/support/cache/least_recently_pushed.rb +21 -0
  85. data/lib/cuboid/support/cache/least_recently_used.rb +31 -0
  86. data/lib/cuboid/support/cache/preference.rb +31 -0
  87. data/lib/cuboid/support/cache/random_replacement.rb +20 -0
  88. data/lib/cuboid/support/crypto.rb +2 -0
  89. data/lib/cuboid/support/crypto/rsa_aes_cbc.rb +86 -0
  90. data/lib/cuboid/support/database.rb +5 -0
  91. data/lib/cuboid/support/database/base.rb +177 -0
  92. data/lib/cuboid/support/database/categorized_queue.rb +195 -0
  93. data/lib/cuboid/support/database/hash.rb +300 -0
  94. data/lib/cuboid/support/database/queue.rb +149 -0
  95. data/lib/cuboid/support/filter.rb +3 -0
  96. data/lib/cuboid/support/filter/base.rb +110 -0
  97. data/lib/cuboid/support/filter/set.rb +29 -0
  98. data/lib/cuboid/support/glob.rb +27 -0
  99. data/lib/cuboid/support/mixins.rb +8 -0
  100. data/lib/cuboid/support/mixins/observable.rb +99 -0
  101. data/lib/cuboid/support/mixins/parts.rb +20 -0
  102. data/lib/cuboid/support/mixins/profiler.rb +93 -0
  103. data/lib/cuboid/support/mixins/spec_instances.rb +65 -0
  104. data/lib/cuboid/support/mixins/terminal.rb +57 -0
  105. data/lib/cuboid/system.rb +119 -0
  106. data/lib/cuboid/system/platforms.rb +84 -0
  107. data/lib/cuboid/system/platforms/linux.rb +26 -0
  108. data/lib/cuboid/system/platforms/mixins/unix.rb +46 -0
  109. data/lib/cuboid/system/platforms/osx.rb +25 -0
  110. data/lib/cuboid/system/platforms/windows.rb +81 -0
  111. data/lib/cuboid/system/slots.rb +143 -0
  112. data/lib/cuboid/ui/output.rb +52 -0
  113. data/lib/cuboid/ui/output_interface.rb +43 -0
  114. data/lib/cuboid/ui/output_interface/abstract.rb +68 -0
  115. data/lib/cuboid/ui/output_interface/controls.rb +84 -0
  116. data/lib/cuboid/ui/output_interface/error_logging.rb +119 -0
  117. data/lib/cuboid/ui/output_interface/implemented.rb +58 -0
  118. data/lib/cuboid/ui/output_interface/personalization.rb +62 -0
  119. data/lib/cuboid/utilities.rb +155 -0
  120. data/lib/cuboid/version.rb +4 -3
  121. data/lib/version +1 -0
  122. data/logs/placeholder +0 -0
  123. data/spec/cuboid/application/parts/data_spec.rb +12 -0
  124. data/spec/cuboid/application/parts/report_spec.rb +6 -0
  125. data/spec/cuboid/application/parts/state_spec.rb +192 -0
  126. data/spec/cuboid/application/runtime_spec.rb +21 -0
  127. data/spec/cuboid/application_spec.rb +37 -0
  128. data/spec/cuboid/data/application_spec.rb +22 -0
  129. data/spec/cuboid/data_spec.rb +47 -0
  130. data/spec/cuboid/error_spec.rb +23 -0
  131. data/spec/cuboid/option_groups/datastore_spec.rb +54 -0
  132. data/spec/cuboid/option_groups/dispatcher_spec.rb +12 -0
  133. data/spec/cuboid/option_groups/output_spec.rb +11 -0
  134. data/spec/cuboid/option_groups/paths_spec.rb +184 -0
  135. data/spec/cuboid/option_groups/report_spec.rb +26 -0
  136. data/spec/cuboid/option_groups/rpc_spec.rb +53 -0
  137. data/spec/cuboid/option_groups/snapshot_spec.rb +26 -0
  138. data/spec/cuboid/option_groups/system.rb +12 -0
  139. data/spec/cuboid/options_spec.rb +218 -0
  140. data/spec/cuboid/report_spec.rb +221 -0
  141. data/spec/cuboid/rest/server_spec.rb +1205 -0
  142. data/spec/cuboid/rpc/client/base_spec.rb +151 -0
  143. data/spec/cuboid/rpc/client/dispatcher_spec.rb +13 -0
  144. data/spec/cuboid/rpc/client/instance_spec.rb +38 -0
  145. data/spec/cuboid/rpc/server/active_options_spec.rb +21 -0
  146. data/spec/cuboid/rpc/server/base_spec.rb +60 -0
  147. data/spec/cuboid/rpc/server/dispatcher/node_spec.rb +222 -0
  148. data/spec/cuboid/rpc/server/dispatcher/service_spec.rb +112 -0
  149. data/spec/cuboid/rpc/server/dispatcher_spec.rb +317 -0
  150. data/spec/cuboid/rpc/server/instance_spec.rb +307 -0
  151. data/spec/cuboid/rpc/server/output_spec.rb +32 -0
  152. data/spec/cuboid/rpc/server/scheduler_spec.rb +400 -0
  153. data/spec/cuboid/ruby/array_spec.rb +77 -0
  154. data/spec/cuboid/ruby/hash_spec.rb +63 -0
  155. data/spec/cuboid/ruby/object_spec.rb +22 -0
  156. data/spec/cuboid/snapshot_spec.rb +123 -0
  157. data/spec/cuboid/state/application_spec.rb +538 -0
  158. data/spec/cuboid/state/options_spec.rb +37 -0
  159. data/spec/cuboid/state_spec.rb +53 -0
  160. data/spec/cuboid/support/buffer/autoflush_spec.rb +78 -0
  161. data/spec/cuboid/support/buffer/base_spec.rb +193 -0
  162. data/spec/cuboid/support/cache/least_cost_replacement_spec.rb +61 -0
  163. data/spec/cuboid/support/cache/least_recently_pushed_spec.rb +90 -0
  164. data/spec/cuboid/support/cache/least_recently_used_spec.rb +80 -0
  165. data/spec/cuboid/support/cache/preference_spec.rb +37 -0
  166. data/spec/cuboid/support/cache/random_replacement_spec.rb +42 -0
  167. data/spec/cuboid/support/crypto/rsa_aes_cbc_spec.rb +28 -0
  168. data/spec/cuboid/support/database/categorized_queue_spec.rb +327 -0
  169. data/spec/cuboid/support/database/hash_spec.rb +204 -0
  170. data/spec/cuboid/support/database/scheduler_spec.rb +325 -0
  171. data/spec/cuboid/support/filter/set_spec.rb +19 -0
  172. data/spec/cuboid/support/glob_spec.rb +75 -0
  173. data/spec/cuboid/support/mixins/observable_spec.rb +95 -0
  174. data/spec/cuboid/system/platforms/linux_spec.rb +31 -0
  175. data/spec/cuboid/system/platforms/osx_spec.rb +32 -0
  176. data/spec/cuboid/system/platforms/windows_spec.rb +41 -0
  177. data/spec/cuboid/system/slots_spec.rb +202 -0
  178. data/spec/cuboid/system_spec.rb +105 -0
  179. data/spec/cuboid/utilities_spec.rb +131 -0
  180. data/spec/spec_helper.rb +46 -0
  181. data/spec/support/factories/placeholder +0 -0
  182. data/spec/support/factories/scan_report.rb +18 -0
  183. data/spec/support/fixtures/empty/placeholder +0 -0
  184. data/spec/support/fixtures/executables/node.rb +50 -0
  185. data/spec/support/fixtures/mock_app.rb +61 -0
  186. data/spec/support/fixtures/mock_app/test_service.rb +64 -0
  187. data/spec/support/fixtures/services/echo.rb +64 -0
  188. data/spec/support/helpers/framework.rb +3 -0
  189. data/spec/support/helpers/matchers.rb +5 -0
  190. data/spec/support/helpers/misc.rb +3 -0
  191. data/spec/support/helpers/paths.rb +15 -0
  192. data/spec/support/helpers/request_helpers.rb +38 -0
  193. data/spec/support/helpers/requires.rb +8 -0
  194. data/spec/support/helpers/resets.rb +52 -0
  195. data/spec/support/helpers/web_server.rb +15 -0
  196. data/spec/support/lib/factory.rb +107 -0
  197. data/spec/support/lib/web_server_client.rb +41 -0
  198. data/spec/support/lib/web_server_dispatcher.rb +25 -0
  199. data/spec/support/lib/web_server_manager.rb +118 -0
  200. data/spec/support/logs/placeholder +0 -0
  201. data/spec/support/pems/cacert.pem +37 -0
  202. data/spec/support/pems/client/cert.pem +37 -0
  203. data/spec/support/pems/client/foo-cert.pem +39 -0
  204. data/spec/support/pems/client/foo-key.pem +51 -0
  205. data/spec/support/pems/client/key.pem +51 -0
  206. data/spec/support/pems/server/cert.pem +37 -0
  207. data/spec/support/pems/server/key.pem +51 -0
  208. data/spec/support/reports/placeholder +0 -0
  209. data/spec/support/shared/application.rb +10 -0
  210. data/spec/support/shared/component.rb +31 -0
  211. data/spec/support/shared/component/options/base.rb +187 -0
  212. data/spec/support/shared/option_group.rb +98 -0
  213. data/spec/support/shared/support/cache.rb +419 -0
  214. data/spec/support/shared/support/filter.rb +143 -0
  215. data/spec/support/shared/system/platforms/base.rb +25 -0
  216. data/spec/support/shared/system/platforms/mixins/unix.rb +37 -0
  217. data/spec/support/snapshots/placeholder +0 -0
  218. metadata +566 -21
  219. data/.gitignore +0 -8
  220. data/bin/console +0 -15
  221. data/bin/setup +0 -8
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ require Cuboid::Options.paths.lib + 'rpc/server/output'
4
+
5
+ class RPCOutput
6
+ include Cuboid::UI::Output
7
+ end
8
+
9
+ describe Cuboid::UI::Output do
10
+
11
+ subject { RPCOutput.new }
12
+ let(:message) { 'This is a msg!' }
13
+ let(:logfile ) do
14
+ Cuboid::Options.paths.logs + "output_spec_#{Process.pid}.log"
15
+ end
16
+ let(:exception) do
17
+ e = Exception.new( 'Stuff' )
18
+ e.set_backtrace( [ 'backtrace line1', 'backtrace line2' ] )
19
+ s
20
+ end
21
+
22
+ context 'when rerouting messages to a logfile' do
23
+ before( :each ) do
24
+ subject.reroute_to_file( logfile )
25
+ end
26
+
27
+ it 'sends output to the logfile' do
28
+ subject.print_line( 'blah' )
29
+ expect(IO.read( logfile ).split( "\n" ).size).to eq(1)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,400 @@
1
+ require 'spec_helper'
2
+
3
+ require "#{Cuboid::Options.paths.lib}/rpc/server/scheduler"
4
+
5
+ describe Cuboid::RPC::Server::Scheduler do
6
+ before( :each ) do
7
+ Cuboid::Options.system.max_slots = 10
8
+ Cuboid::Options.scheduler.ping_interval = 0.5
9
+ end
10
+
11
+ subject { scheduler_spawn( application: "#{fixtures_path}/mock_app.rb" ) }
12
+ let(:options) { {} }
13
+
14
+ context 'when there are queued scans' do
15
+ it 'performs them' do
16
+ expect(subject.completed).to be_empty
17
+
18
+ ids = []
19
+ 3.times do
20
+ ids << subject.push( options )
21
+ end
22
+
23
+ sleep 1 while subject.completed.size != 3
24
+
25
+ expect(subject.completed.keys.sort).to eq ids.sort
26
+
27
+ subject.completed.values.each do |report|
28
+ expect do
29
+ Cuboid::Report.load( report )
30
+ end.to_not raise_error
31
+ end
32
+ end
33
+
34
+ it 'stores the reports' do
35
+ subject.push( options )
36
+ sleep 0.1 while subject.completed.empty?
37
+
38
+ expect(subject.completed.values.first).to start_with Cuboid::Options.paths.reports
39
+ end
40
+
41
+ it 'shuts down the Instance' do
42
+ subject.push( options )
43
+ sleep 0.1 while subject.running.empty?
44
+
45
+ pid = subject.running.values.first['pid']
46
+ expect(Cuboid::Processes::Manager.alive?( pid )).to be true
47
+
48
+ sleep 0.1 while subject.completed.empty?
49
+ sleep 2
50
+
51
+ expect(Cuboid::Processes::Manager.alive?( pid )).to be false
52
+ end
53
+ end
54
+
55
+ context 'when a Dispatcher has been set' do
56
+ subject { Cuboid::Processes::Schedulers.spawn dispatcher: dispatcher.url }
57
+ let(:dispatcher) do
58
+ Cuboid::Processes::Dispatchers.spawn( application: "#{fixtures_path}/mock_app.rb" )
59
+ end
60
+
61
+ it 'gets Instances from it' do
62
+ expect(dispatcher.finished_instances).to be_empty
63
+
64
+ subject.push( options )
65
+ sleep 0.1 while subject.completed.empty?
66
+ sleep 2
67
+
68
+ expect(dispatcher.finished_instances).to be_any
69
+ end
70
+
71
+ it 'sets OptionGroups::Scheduler#url' do
72
+ id = subject.push( options )
73
+ sleep 0.1 while subject.running.empty?
74
+
75
+ info = subject.running[id]
76
+ expect(instance_connect( info['url'], info['token'] ).scheduler_url).to eq subject.url
77
+ end
78
+
79
+ context 'but becomes unavailable' do
80
+ it 'does not consume the queue' do
81
+ subject
82
+
83
+ Cuboid::Processes::Dispatchers.killall
84
+ sleep 3
85
+
86
+ expect(subject.size).to be 0
87
+
88
+ subject.push( options )
89
+ sleep 5
90
+
91
+ expect(subject.size).to be 1
92
+ expect(subject.errors.join("\n")).to include "Failed to contact Dispatcher at: #{dispatcher.url}"
93
+ end
94
+ end
95
+ end
96
+
97
+ describe '#alive?' do
98
+ it 'returns true' do
99
+ expect(subject.alive?).to be_truthy
100
+ end
101
+ end
102
+
103
+ describe '#empty?' do
104
+ context 'when the queue is empty' do
105
+ it 'returns true' do
106
+ expect(subject.empty?).to be_truthy
107
+ end
108
+ end
109
+
110
+ context 'when the queue is not empty' do
111
+ it 'returns true' do
112
+ subject.push( options )
113
+ expect(subject.empty?).to be_falsey
114
+ end
115
+ end
116
+ end
117
+
118
+ describe '#any?' do
119
+ context 'when the queue is empty' do
120
+ it 'returns false' do
121
+ expect(subject.any?).to_not be_truthy
122
+ end
123
+ end
124
+
125
+ context 'when the queue is not empty' do
126
+ it 'returns true' do
127
+ subject.push( options )
128
+ expect(subject.any?).to be_truthy
129
+ end
130
+ end
131
+ end
132
+
133
+ describe '#size' do
134
+ it 'returns the queue size' do
135
+ expect(subject.size).to be 0
136
+ subject.push( options )
137
+ expect(subject.size).to be 1
138
+ end
139
+ end
140
+
141
+ describe '#list' do
142
+ it 'returns the queue entries grouped and sorted by priority' do
143
+ medium = subject.push( options, priority: 0 )
144
+ low = subject.push( options, priority: -1 )
145
+ high = subject.push( options, priority: 1 )
146
+
147
+ expect(subject.list).to eq(
148
+ 1 => [high],
149
+ 0 => [medium],
150
+ -1 => [low],
151
+ )
152
+ end
153
+ end
154
+
155
+ describe '#running' do
156
+ it 'returns running scans' do
157
+ expect(subject.running).to be_empty
158
+
159
+ ids = []
160
+ 3.times do
161
+ ids << subject.push( options )
162
+ end
163
+ sleep 0.1 while subject.running.empty?
164
+
165
+ expect(subject.running.keys & ids).to be_any
166
+ expect(subject.running.values.first).to include 'url'
167
+ expect(subject.running.values.first).to include 'token'
168
+ expect(subject.running.values.first).to include 'pid'
169
+ end
170
+ end
171
+
172
+ describe '#detach' do
173
+ it 'detaches a running scan' do
174
+ id = subject.push( options )
175
+ sleep 0.1 while subject.running.empty?
176
+
177
+ info = subject.detach( id )
178
+
179
+ expect(info.keys.sort).to eq %w(url token pid).sort
180
+
181
+ client = instance_connect( info['url'], info['token'] )
182
+
183
+ expect(subject.running).to be_empty
184
+
185
+ sleep 0.1 while client.busy?
186
+ client.shutdown
187
+ sleep 2
188
+
189
+ expect(subject.completed).to be_empty
190
+ expect(subject.failed).to be_empty
191
+ end
192
+
193
+ it 'removes OptionGroups::Scheduler#url' do
194
+ id = subject.push( options )
195
+ sleep 0.1 while subject.running.empty?
196
+
197
+ info = subject.detach( id )
198
+ client = instance_connect( info['url'], info['token'] )
199
+
200
+ expect(client.scheduler_url).to be_nil
201
+ end
202
+
203
+ context 'when no scan with that ID is found' do
204
+ it 'returns nil' do
205
+ subject.push( options )
206
+ sleep 0.1 while subject.running.empty?
207
+
208
+ expect(subject.detach( 'id' )).to be_nil
209
+ end
210
+ end
211
+ end
212
+
213
+ describe '#attach' do
214
+ let(:client) { instance_spawn( application: "#{fixtures_path}/mock_app.rb" ) }
215
+
216
+ it 'attaches a running Instance to the queue' do
217
+ expect(subject.attach( client.url, client.token )).to eq client.token
218
+
219
+ id = client.token
220
+ expect(subject.running).to eq(
221
+ id => {
222
+ 'url' => client.url,
223
+ 'token' => client.token,
224
+ 'pid' => nil
225
+ }
226
+ )
227
+
228
+ client.run( options )
229
+ sleep 0.1 while subject.completed.empty?
230
+
231
+ expect(subject.completed.keys).to eq [id]
232
+ end
233
+
234
+ it 'sets OptionGroups::Scheduler#url' do
235
+ expect(client.scheduler_url).to be_nil
236
+
237
+ subject.attach( client.url, client.token )
238
+
239
+ client.run( options )
240
+ sleep 0.1 while subject.running.empty?
241
+
242
+ expect(client.scheduler_url).to eq subject.url
243
+ end
244
+
245
+ context 'when the Instance is already attached to a Scheduler' do
246
+ it 'returns false' do
247
+ expect(client.scheduler_url).to be_nil
248
+
249
+ subject.attach( client.url, client.token )
250
+ expect(client.scheduler_url).to eq subject.url
251
+
252
+ q = scheduler_spawn
253
+
254
+ expect(q.attach( client.url, client.token )).to be_falsey
255
+ expect(client.scheduler_url).to eq subject.url
256
+ end
257
+ end
258
+
259
+ context 'when the Instance could not be accessed' do
260
+ it 'returns nil' do
261
+ expect(subject.attach( '127.0.0.1:3333', 'fdfdfd' )).to be_nil
262
+ end
263
+ end
264
+ end
265
+
266
+ describe '#completed' do
267
+ it 'returns completed scans' do
268
+ expect(subject.completed).to be_empty
269
+
270
+ ids = []
271
+ 3.times do
272
+ ids << subject.push( options )
273
+ end
274
+ sleep 0.1 while subject.completed.size != 3
275
+
276
+ expect(subject.completed.keys.sort).to eq ids.sort
277
+
278
+ subject.completed.values.each do |report|
279
+ expect do
280
+ Cuboid::Report.load( report )
281
+ end.to_not raise_error
282
+ end
283
+ end
284
+ end
285
+
286
+ describe '#failed' do
287
+ it 'returns failed scans' do
288
+ expect(subject.completed).to be_empty
289
+
290
+ id = subject.push( options )
291
+ sleep 0.1 while subject.running.empty?
292
+
293
+ process_kill( subject.running.values.first['pid'] )
294
+ sleep 0.1 while subject.failed.empty?
295
+
296
+ expect(subject.failed[id]['error']).to eq 'Arachni::RPC::Exceptions::ConnectionError'
297
+ expect(subject.failed[id]['description']).to include 'Connection closed'
298
+ end
299
+ end
300
+
301
+ describe '#get' do
302
+ it "returns a queued scan's info" do
303
+ info = subject.get( subject.push( options ) )
304
+ expect(info).to eq(
305
+ 'options' => options,
306
+ 'priority' => 0
307
+ )
308
+ end
309
+
310
+ context 'when no scan matching the ID is queued' do
311
+ it 'returns nil' do
312
+ expect(subject.get( '1' )).to be_nil
313
+ end
314
+ end
315
+ end
316
+
317
+ describe '#push' do
318
+ it 'queues a scan' do
319
+ subject.push( options )
320
+ expect(subject.any?).to be_truthy
321
+ end
322
+
323
+ it 'returns an ID' do
324
+ id = subject.push( options )
325
+ expect(subject.get( id )).to be_truthy
326
+ end
327
+
328
+ it 'sets OptionGroups::Scheduler#url' do
329
+ id = subject.push( options )
330
+ sleep 0.1 while subject.running.empty?
331
+
332
+ info = subject.running[id]
333
+ client = instance_connect( info['url'], info['token'] )
334
+
335
+ expect(client.scheduler_url).to eq subject.url
336
+ end
337
+
338
+ context 'on invalid options' do
339
+ it 'raises ArgumentError' do
340
+ expect do
341
+ subject.push invalid: :test
342
+ end.to raise_error Arachni::RPC::Exceptions::RemoteException
343
+ end
344
+ end
345
+
346
+ context 'when no priority is specified' do
347
+ it 'uses 0' do
348
+ id = subject.push( options )
349
+ expect(subject.get( id )['priority']).to be 0
350
+ end
351
+ end
352
+
353
+ context 'when priority is specified' do
354
+ it 'uses it' do
355
+ id = subject.push( options, priority: 1 )
356
+ expect(subject.get( id )['priority']).to be 1
357
+ end
358
+ end
359
+ end
360
+
361
+ describe '#remove' do
362
+ it 'removes a scan from the queue' do
363
+ id = subject.push( options )
364
+ expect(subject.remove( id )).to be true
365
+ end
366
+
367
+ context 'when the scan does not exist' do
368
+ it 'returns false' do
369
+ expect(subject.remove( 'id' )).to be false
370
+ end
371
+ end
372
+ end
373
+
374
+ describe '#clear' do
375
+ it 'clears the queue' do
376
+ expect(subject.empty?).to be_truthy
377
+
378
+ 10.times do
379
+ subject.push( options )
380
+ end
381
+
382
+ expect(subject.any?).to be_truthy
383
+
384
+ subject.clear
385
+
386
+ expect(subject.empty?).to be_truthy
387
+ end
388
+ end
389
+
390
+ describe '#shutdown' do
391
+ it 'shuts down the server' do
392
+ subject.shutdown
393
+ sleep 2
394
+
395
+ expect do
396
+ subject.alive?
397
+ end.to raise_error Arachni::RPC::Exceptions::ConnectionError
398
+ end
399
+ end
400
+ end
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ describe Array do
4
+ subject do
5
+ arr = described_class.new
6
+ 50.times { |i| arr << i }
7
+ arr
8
+ end
9
+
10
+ describe '#includes_tag?' do
11
+ context 'when passed' do
12
+ context 'nil' do
13
+ it 'returns false' do
14
+ expect(subject.includes_tags?( nil )).to eq(false)
15
+ end
16
+ end
17
+
18
+ context '[]' do
19
+ it 'returns false' do
20
+ expect(subject.includes_tags?( [] )).to eq(false)
21
+ end
22
+ end
23
+
24
+ context 'String' do
25
+ context 'when includes the given tag (as either a String or a Symbol)' do
26
+ it 'returns true' do
27
+ expect([ 1 ].includes_tags?( 1 )).to eq(true)
28
+ expect([ :tag ].includes_tags?( :tag )).to eq(true)
29
+ expect([ :tag ].includes_tags?( 'tag' )).to eq(true)
30
+ expect(%w(tag).includes_tags?( 'tag' )).to eq(true)
31
+ expect(%w(tag).includes_tags?( :tag )).to eq(true)
32
+ expect([ :tag, 'tag' ].includes_tags?( :tag )).to eq(true)
33
+ expect([ :tag, 'tag' ].includes_tags?( 'tag' )).to eq(true)
34
+ end
35
+ end
36
+ context 'when it does not includes the given tag (as either a String or a Symbol)' do
37
+ it 'returns false' do
38
+ expect([ 1 ].includes_tags?( 2 )).to eq(false)
39
+ expect([ :tag ].includes_tags?( :tag1 )).to eq(false)
40
+ expect([ :tag ].includes_tags?( 'tag2' )).to eq(false)
41
+ expect(%w(tag).includes_tags?( 'tag3' )).to eq(false)
42
+ expect(%w(tag).includes_tags?( :tag5 )).to eq(false)
43
+ expect([ :tag, 'tag' ].includes_tags?( :ta5g )).to eq(false)
44
+ expect([ :tag, 'tag' ].includes_tags?( 'ta4g' )).to eq(false)
45
+ expect([ :t3ag, 'tag1' ].includes_tags?( 'tag' )).to eq(false)
46
+ end
47
+ end
48
+ end
49
+
50
+ context 'Array' do
51
+ context 'when includes any of the given tags (as either a String or a Symbol)' do
52
+ it 'returns true' do
53
+ expect([ 1, 2, 3 ].includes_tags?( [1] )).to eq(true)
54
+ expect([ :tag ].includes_tags?( [:tag] )).to eq(true)
55
+ expect([ :tag ].includes_tags?( ['tag', 12] )).to eq(true)
56
+ expect(%w(tag).includes_tags?( ['tag', nil] )).to eq(true)
57
+ expect(%w(tag).includes_tags?( [:tag] )).to eq(true)
58
+ expect([ :tag, 'tag' ].includes_tags?( [:tag] )).to eq(true)
59
+ expect([ :tag, 'tag' ].includes_tags?( ['tag', :blah] )).to eq(true)
60
+ end
61
+ end
62
+ context 'when it does not include any of the given tags (as either a String or a Symbol)' do
63
+ it 'returns true' do
64
+ expect([ 1, 2, 3 ].includes_tags?( [4, 5] )).to eq(false)
65
+ expect([ :tag ].includes_tags?( [:ta3g] )).to eq(false)
66
+ expect([ :tag ].includes_tags?( ['ta3g', 12] )).to eq(false)
67
+ expect(%w(tag).includes_tags?( ['ta3g', nil] )).to eq(false)
68
+ expect(%w(tag).includes_tags?( [:t4ag] )).to eq(false)
69
+ expect([ :tag, 'tag' ].includes_tags?( [:t3ag] )).to eq(false)
70
+ expect([ :tag, 'tag' ].includes_tags?( ['t2ag', :b3lah] )).to eq(false)
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ end