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,80 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cuboid::Support::Cache::LeastRecentlyUsed do
4
+ it_behaves_like 'cache'
5
+
6
+ it 'prunes itself by removing Least Recently Used entries' do
7
+ subject.max_size = 3
8
+
9
+ subject[:k] = '1'
10
+ subject[:k2] = '2'
11
+ subject[:k]
12
+ subject[:k3] = '3'
13
+ subject[:k4] = '4'
14
+
15
+ expect(subject.size).to eq(3)
16
+
17
+ expect(subject[:k]).to be_truthy
18
+ expect(subject[:k4]).to be_truthy
19
+ expect(subject[:k3]).to be_truthy
20
+ expect(subject[:k2]).to be_nil
21
+ end
22
+
23
+ describe '#[]=' do
24
+ it 'stores an object' do
25
+ v = 'val'
26
+ expect(subject[:key] = v).to eq(v)
27
+ expect(subject[:key]).to eq(v)
28
+ end
29
+ it 'alias of #store' do
30
+ v = 'val2'
31
+ expect(subject.store( :key2, v )).to eq(v)
32
+ expect(subject[:key2]).to eq(v)
33
+ end
34
+ end
35
+
36
+ describe '#[]' do
37
+ it 'retrieves an object by key' do
38
+ v = 'val2'
39
+ subject[:key] = v
40
+ expect(subject[:key]).to eq(v)
41
+ expect(subject.empty?).to be_falsey
42
+ end
43
+
44
+ context 'when the key does not exist' do
45
+ it 'returns nil' do
46
+ expect(subject[:some_key]).to be_nil
47
+ end
48
+ end
49
+ end
50
+
51
+ describe '#delete' do
52
+ context 'when the key exists' do
53
+ it 'deletes a key and return its value' do
54
+ v = 'my_val'
55
+ subject[:my_key] = v
56
+ expect(subject.delete( :my_key )).to eq(v)
57
+ expect(subject[:my_key]).to be_nil
58
+ expect(subject.include?( :my_key )).to be_falsey
59
+ end
60
+ end
61
+ context 'when the key does not exist' do
62
+ it 'returns nil' do
63
+ expect(subject.delete( :my_key2 )).to be_nil
64
+ end
65
+ end
66
+ end
67
+
68
+ describe '#clear' do
69
+ it 'empties the cache' do
70
+ subject[:my_key2] = 'v'
71
+ expect(subject.size).to be > 0
72
+ expect(subject.empty?).to be_falsey
73
+ subject.clear
74
+
75
+ expect(subject.size).to eq(0)
76
+ expect(subject.empty?).to be_truthy
77
+ end
78
+ end
79
+
80
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cuboid::Support::Cache::Preference do
4
+ it_behaves_like 'cache'
5
+
6
+ it 'prunes itself by removing entries returned by the given block' do
7
+ subject.max_size = 3
8
+
9
+ subject.prefer { :k2 }
10
+
11
+ k = [ :k, :k2, :k3, :k4 ]
12
+ subject[k[0]] = '1'
13
+ subject[k[1]] = '2'
14
+ subject[k[2]] = '3'
15
+ subject[k[3]] = '4'
16
+ expect(subject.size).to eq(3)
17
+
18
+ expect(k.map { |key| subject[key] }.count( nil )).to eq(1)
19
+
20
+ subject.clear
21
+ end
22
+
23
+ it 'does not remove entries which are not preferred even if the max size has been exceeded' do
24
+ subject.prefer { :k2 }
25
+
26
+ k = [ :k, :k2, :k3, :k4 ]
27
+
28
+ subject.max_size = 1
29
+ subject[k[0]] = '1'
30
+ subject[k[1]] = '3'
31
+ subject[k[2]] = '4'
32
+ expect(subject.size).to eq(2)
33
+
34
+ expect(k[0...3].map { |key| subject[key] }.count( nil )).to eq(1)
35
+ end
36
+
37
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cuboid::Support::Cache::RandomReplacement do
4
+ it_behaves_like 'cache'
5
+
6
+ it 'prunes itself by removing random entries (Random Replacement)' do
7
+ subject.max_size = 3
8
+
9
+ k = [ :k, :k2, :k3, :k4 ]
10
+ subject[k[0]] = '1'
11
+ subject[k[1]] = '2'
12
+ subject[k[2]] = '3'
13
+ subject[k[3]] = '4'
14
+ expect(subject.size).to eq(3)
15
+
16
+ expect(k.map { |key| subject[key] }.count( nil )).to eq(1)
17
+
18
+ subject.clear
19
+
20
+ subject.max_size = 1
21
+ subject[k[0]] = '1'
22
+ subject[k[1]] = '3'
23
+ subject[k[2]] = '4'
24
+ expect(subject.size).to eq(1)
25
+
26
+ expect(k[0...3].map { |key| subject[key] }.count( nil )).to eq(2)
27
+ end
28
+
29
+ describe '#[]=' do
30
+ it 'stores an object' do
31
+ v = 'val'
32
+ expect(subject[:key] = v).to eq(v)
33
+ expect(subject[:key]).to eq(v)
34
+ end
35
+ it 'alias of #store' do
36
+ v = 'val2'
37
+ expect(subject.store( :key2, v )).to eq(v)
38
+ expect(subject[:key2]).to eq(v)
39
+ end
40
+ end
41
+
42
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+ require 'tempfile'
3
+
4
+ describe Cuboid::Support::Crypto::RSA_AES_CBC do
5
+
6
+ SEED = 'seed data'
7
+
8
+ let(:public_key_file_path) do
9
+ key = private_key.public_key
10
+ file = Tempfile.new( 'public_key.pem' )
11
+ file.write( key.to_pem )
12
+ file.close
13
+ file.path
14
+ end
15
+ let(:private_key_file_path) do
16
+ file = Tempfile.new( 'private_key.pem' )
17
+ file.write( private_key.to_pem )
18
+ file.close
19
+ file.path
20
+ end
21
+ let(:private_key) { OpenSSL::PKey::RSA.generate( 1024 ) }
22
+ subject { described_class.new( public_key_file_path, private_key_file_path ) }
23
+
24
+ it 'generates matching encrypted and decrypted data' do
25
+ expect(subject.decrypt( subject.encrypt( SEED ) )).to eq(SEED)
26
+ end
27
+
28
+ end
@@ -0,0 +1,327 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cuboid::Support::Database::CategorizedQueue do
4
+
5
+ class Item
6
+ attr_accessor :category
7
+ attr_accessor :data
8
+
9
+ def initialize( data )
10
+ @data = data
11
+ end
12
+
13
+ def ==( other )
14
+ data == other.data
15
+ end
16
+
17
+ def hash
18
+ data.hash
19
+ end
20
+ end
21
+
22
+ subject { described_class.new {} }
23
+
24
+ let(:sample_size) { 2 * subject.max_buffer_size }
25
+
26
+ it 'maintains stability and consistency under load' do
27
+ subject
28
+
29
+ entries = 1000
30
+ poped = Queue.new
31
+ t = []
32
+
33
+ 10.times do
34
+ t << Thread.new do
35
+ loop do
36
+ poped << subject.pop
37
+ end
38
+ end
39
+ end
40
+
41
+ entries.times do |i|
42
+ subject << Item.new( 'a' * i )
43
+ end
44
+
45
+ sleep 0.1 while !subject.empty?
46
+
47
+ consumed = []
48
+ consumed << poped.pop.data while !poped.empty?
49
+
50
+ expect(consumed.sort).to eq((0...entries).map { |i| 'a' * i })
51
+ end
52
+
53
+ describe "#{described_class}::DEFAULT_MAX_BUFFER_SIZE" do
54
+ it 'returns 100' do
55
+ expect(described_class::DEFAULT_MAX_BUFFER_SIZE).to eq(100)
56
+ end
57
+ end
58
+
59
+ describe '#initialize' do
60
+ describe ':max_buffer_size' do
61
+ it 'sets #max_buffer_size' do
62
+ expect(
63
+ described_class.new( max_buffer_size: 1 ){}.max_buffer_size
64
+ ).to eq 1
65
+ end
66
+ end
67
+
68
+ describe ':dumper' do
69
+ it 'defaults to Marshal'
70
+
71
+ context 'it responds to :dump' do
72
+ it 'gets called to serialize the object'
73
+ end
74
+
75
+ context 'it responds to :call' do
76
+ it 'gets called to serialize the object'
77
+ end
78
+ end
79
+
80
+ describe ':load' do
81
+ context 'it responds to :load' do
82
+ it 'gets called to unserialize the object'
83
+ end
84
+
85
+ context 'it responds to :call' do
86
+ it 'gets called to serialize the object'
87
+ end
88
+ end
89
+
90
+ describe '&block' do
91
+ it 'sets the #prefer block' do
92
+ prefer = proc {}
93
+
94
+ expect( described_class.new( &prefer ).prefer ).to be prefer
95
+ end
96
+ end
97
+ end
98
+
99
+ describe '#max_buffer_size' do
100
+ context 'by default' do
101
+ it "returns #{described_class}::DEFAULT_MAX_BUFFER_SIZE" do
102
+ expect(subject.max_buffer_size).to eq(described_class::DEFAULT_MAX_BUFFER_SIZE)
103
+ end
104
+ end
105
+ end
106
+
107
+ describe '#max_buffer_size=' do
108
+ it 'sets #max_buffer_size' do
109
+ subject.max_buffer_size = 10
110
+ expect(subject.max_buffer_size).to eq(10)
111
+ end
112
+ end
113
+
114
+ describe '#empty?' do
115
+ context 'when the queue is empty' do
116
+ it 'returns true' do
117
+ expect(subject.empty?).to be_truthy
118
+ end
119
+ end
120
+
121
+ context 'when the queue is not empty' do
122
+ it 'returns false' do
123
+ subject << Item.new( :stuff )
124
+ expect(subject.empty?).to be_falsey
125
+ end
126
+ end
127
+ end
128
+
129
+ describe '#<<' do
130
+ it 'pushes an object' do
131
+ sample_size.times do |i|
132
+ subject << Item.new( "stuff #{i}" )
133
+ end
134
+
135
+ sample_size.times do |i|
136
+ expect(subject.pop).to eq(Item.new( "stuff #{i}" ))
137
+ end
138
+ end
139
+
140
+ context 'when no #prefer block has been set' do
141
+ it "raises #{ArgumentError}" do
142
+ expect {
143
+ described_class.new << Item.new( '' )
144
+ }.to raise_error ArgumentError
145
+ end
146
+ end
147
+ end
148
+
149
+ describe '#push' do
150
+ it 'pushes an object' do
151
+ subject.push Item.new( :stuff )
152
+ expect(subject.pop).to eq(Item.new( :stuff ))
153
+ end
154
+
155
+ it 'increments .disk_space' do
156
+ sz = described_class.disk_space
157
+
158
+ subject.max_buffer_size = 0
159
+ subject.push Item.new( :stuff )
160
+
161
+ expect(described_class.disk_space).to be > sz
162
+ end
163
+ end
164
+
165
+ describe '#enq' do
166
+ it 'pushes an object' do
167
+ subject.enq Item.new( :stuff )
168
+ expect(subject.pop).to eq(Item.new( :stuff ))
169
+ end
170
+ end
171
+
172
+ describe '#pop' do
173
+ it 'removes an object' do
174
+ sample_size.times do |i|
175
+ subject << Item.new( "stuff #{i}" )
176
+ end
177
+
178
+ sample_size.times do |i|
179
+ expect(subject.pop).to eq(Item.new( "stuff #{i}" ))
180
+ end
181
+ end
182
+
183
+ it 'blocks until an entry is available' do
184
+ val = nil
185
+
186
+ t = Thread.new { val = subject.pop }
187
+ sleep 1
188
+ Thread.new { subject << Item.new( :stuff ) }
189
+ t.join
190
+
191
+ expect(val).to eq(Item.new( :stuff ))
192
+ end
193
+
194
+ it 'gives preference to the category provided by the block' do
195
+ subject = described_class.new { :stuff2 }
196
+
197
+ subject << Item.new( 1 ).tap { |s| s.category = :stuff }
198
+ subject << Item.new( 2 ).tap { |s| s.category = :stuff2 }
199
+ subject << Item.new( 3 ).tap { |s| s.category = :stuff3 }
200
+
201
+ expect(subject.pop.data).to eq 2
202
+ expect(subject.pop.data).to eq 3
203
+ expect(subject.pop.data).to eq 1
204
+ end
205
+
206
+ it 'decrements .disk_space' do
207
+ subject.max_buffer_size = 0
208
+ subject.push Item.new( "stuff" )
209
+
210
+ sz = described_class.disk_space
211
+ subject.pop
212
+
213
+ expect(described_class.disk_space).to be < sz
214
+ end
215
+
216
+ context 'when the block specified category is empty' do
217
+ it 'returns an item from the next one' do
218
+ subject = described_class.new { :stuff4 }
219
+
220
+ subject << Item.new( 1 ).tap { |s| s.category = :stuff }
221
+ subject << Item.new( 2 ).tap { |s| s.category = :stuff2 }
222
+ subject << Item.new( 3 ).tap { |s| s.category = :stuff3 }
223
+
224
+ expect(subject.pop.data).to eq 3
225
+ expect(subject.pop.data).to eq 2
226
+ expect(subject.pop.data).to eq 1
227
+ end
228
+ end
229
+
230
+ context 'when no #prefer block has been set' do
231
+ it "raises #{ArgumentError}" do
232
+ expect {
233
+ described_class.new.pop
234
+ }.to raise_error ArgumentError
235
+ end
236
+ end
237
+ end
238
+
239
+ describe '#deq' do
240
+ it 'removes an object' do
241
+ subject << Item.new( :stuff )
242
+ expect(subject.deq).to eq(Item.new( :stuff ))
243
+ end
244
+ end
245
+
246
+ describe '#shift' do
247
+ it 'removes an object' do
248
+ subject << Item.new( :stuff )
249
+ expect(subject.shift).to eq(Item.new( :stuff ))
250
+ end
251
+ end
252
+
253
+ describe '#size' do
254
+ it 'returns the size of the queue' do
255
+ sample_size.times { |i| subject << Item.new( i ) }
256
+ expect(subject.size).to eq(sample_size)
257
+ end
258
+ end
259
+
260
+ describe '#free_buffer_size' do
261
+ it 'returns the size of the available buffer' do
262
+ (subject.max_buffer_size - 2).times { |i| subject << Item.new( i ) }
263
+ expect(subject.free_buffer_size).to eq(2)
264
+ end
265
+ end
266
+
267
+ describe '#buffer_size' do
268
+ it 'returns the size of the in-memory entries' do
269
+ expect(subject.buffer_size).to eq(0)
270
+
271
+ (subject.max_buffer_size - 1).times { |i| subject << Item.new( i ) }
272
+ expect(subject.buffer_size).to eq(subject.max_buffer_size - 1)
273
+
274
+ subject.clear
275
+
276
+ sample_size.times { |i| subject << Item.new( i ) }
277
+ expect(subject.buffer_size).to eq(subject.max_buffer_size)
278
+ end
279
+ end
280
+
281
+ describe '#disk_size' do
282
+ it 'returns the size of the disk entries' do
283
+ expect(subject.buffer_size).to eq(0)
284
+
285
+ (subject.max_buffer_size + 1).times { |i| subject << Item.new( i ) }
286
+ expect(subject.disk_size).to eq(1)
287
+
288
+ subject.clear
289
+
290
+ sample_size.times { |i| subject << Item.new( i ) }
291
+ expect(subject.disk_size).to eq(sample_size - subject.max_buffer_size)
292
+ end
293
+ end
294
+
295
+ describe '#num_waiting' do
296
+ it 'returns the amount of threads waiting to pop' do
297
+ expect(subject.num_waiting).to eq(0)
298
+
299
+ 2.times do
300
+ Thread.new { subject.pop }
301
+ end
302
+ sleep 0.1
303
+
304
+ expect(subject.num_waiting).to eq(2)
305
+ end
306
+ end
307
+
308
+ describe '#clear' do
309
+ it 'empties the queue' do
310
+ sample_size.times { |i| subject << Item.new( i ) }
311
+ subject.clear
312
+ expect(subject.size).to eq(0)
313
+ expect((subject.pop( true ) rescue nil)).to eq(nil)
314
+ end
315
+
316
+ it 'decrements .disk_space' do
317
+ subject.max_buffer_size = 0
318
+ subject.push Item.new( "stuff" )
319
+
320
+ sz = described_class.disk_space
321
+ subject.clear
322
+
323
+ expect(described_class.disk_space).to be < sz
324
+ end
325
+ end
326
+
327
+ end