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,98 @@
1
+ shared_examples_for 'option_group' do
2
+ it { is_expected.to respond_to :to_h }
3
+
4
+ describe '#to_rpc_data' do
5
+ let(:data) { subject.to_rpc_data }
6
+
7
+ it 'converts self to a serializable hash' do
8
+ expect(data).to be_kind_of Hash
9
+
10
+ expect(Cuboid::RPC::Serializer.load(
11
+ Cuboid::RPC::Serializer.dump( data )
12
+ )).to eq(data)
13
+ end
14
+ end
15
+
16
+ described_class.defaults.each do |k, v|
17
+ describe "##{k}" do
18
+ it "defaults to #{v}" do
19
+ expect(subject.instance_variable_get( "@#{k}".to_sym )).to eq(v)
20
+ expect(subject.send( k )).to eq(v)
21
+ end
22
+ end
23
+ end
24
+
25
+ it 'honors default values for attributes' do
26
+ subject.defaults.each do |k, v|
27
+ subject.send "#{k}=", nil
28
+ expect(subject.instance_variable_get( "@#{k}".to_sym )).to eq(v)
29
+ expect(subject.send( k )).to eq(v)
30
+ end
31
+ end
32
+
33
+ describe '#to_hash' do
34
+ it 'returns a hash' do
35
+ expect(subject.to_hash).to be_kind_of Hash
36
+ end
37
+ end
38
+
39
+ describe '#to_h' do
40
+ it 'returns a hash' do
41
+ expect(subject.to_h).to be_kind_of Hash
42
+ end
43
+
44
+ it 'only includes attributes with accessors' do
45
+ method = subject.methods.find { |m| m.to_s.end_with? '=' }
46
+ if method == :=== || method == :==
47
+ expect(subject.to_h).to be_empty
48
+ next
49
+ end
50
+
51
+ subject.send( method, subject.defaults[method.to_s[0..-1].to_sym] )
52
+
53
+ hash = subject.to_h
54
+ expect(hash).to be_any
55
+ hash.each do |k, v|
56
+ expect(subject).to respond_to "#{k}="
57
+ end
58
+ end
59
+ end
60
+
61
+ describe '#update' do
62
+ it 'updates self with the values of the given hash' do
63
+ method = subject.methods.find { |m| m.to_s.end_with? '=' }
64
+ next if method == :=== || method == :==
65
+
66
+ method = method.to_s[0...-1].to_sym
67
+ value = subject.defaults[method.to_s[0..-1].to_sym]
68
+
69
+ subject.update( { method => value } )
70
+ expect(subject.send( method )).to eq(value)
71
+ end
72
+
73
+ it 'returns self' do
74
+ expect(subject.update({})).to eq(subject)
75
+ end
76
+ end
77
+
78
+ describe '#merge' do
79
+ it 'updates self with the values of the given OptionGroup' do
80
+ method = subject.methods.find { |m| m.to_s.end_with? '=' }
81
+ next if method == :=== || method == :==
82
+
83
+ method = method.to_s[0...-1].to_sym
84
+ value = subject.defaults[method.to_s[0..-1].to_sym]
85
+
86
+ group = described_class.new
87
+ group.update( { method => value } )
88
+
89
+ subject.merge( group )
90
+ expect(subject.send( method )).to eq(value)
91
+ end
92
+
93
+ it 'returns self' do
94
+ group = described_class.new
95
+ expect(subject.merge( group )).to eq(subject)
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,419 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for 'cache' do
4
+ subject { described_class.new }
5
+
6
+ describe '#new' do
7
+ describe ':max_size' do
8
+ describe 'default' do
9
+ it 'leaves the cache uncapped' do
10
+ expect(described_class.new.capped?).to be_falsey
11
+ end
12
+ end
13
+
14
+ describe 'Integer' do
15
+ it 'imposes a limit to the size of the cache' do
16
+ expect(described_class.new( size: 10 ).capped?).to be_truthy
17
+ end
18
+ end
19
+ end
20
+
21
+ describe ':freeze' do
22
+ subject { described_class.new freeze: freeze }
23
+
24
+ describe 'default' do
25
+ let(:freeze) {}
26
+
27
+ it 'freezes items' do
28
+ s = 'f'
29
+ subject[1] = s
30
+
31
+ expect(subject[1]).to be_frozen
32
+ end
33
+ end
34
+
35
+ describe 'true' do
36
+ let(:freeze) { true }
37
+
38
+ it 'freezes items' do
39
+ s = 'f'
40
+ subject[1] = s
41
+
42
+ expect(subject[1]).to be_frozen
43
+ end
44
+ end
45
+
46
+ describe 'false' do
47
+ let(:freeze) { false }
48
+
49
+ it 'does not freeze items' do
50
+ s = 'f'
51
+ subject[1] = s
52
+
53
+ expect(subject[1]).to_not be_frozen
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ describe '#max_size' do
60
+ context 'when just initialized' do
61
+ it 'returns nil (unlimited)' do
62
+ expect(subject.max_size).to be_nil
63
+ end
64
+ end
65
+ context 'when set' do
66
+ it 'returns the set value' do
67
+ expect(subject.max_size = 50).to eq(50)
68
+ expect(subject.max_size).to eq(50)
69
+ end
70
+ end
71
+ end
72
+
73
+ describe '#uncap' do
74
+ it 'removes the size limit' do
75
+ subject.max_size = 1
76
+ subject.uncap
77
+ subject.max_size = nil
78
+ end
79
+ end
80
+
81
+ describe '#capped?' do
82
+ context 'when the cache has no size limit' do
83
+ it 'returns false' do
84
+ subject.uncap
85
+ expect(subject.capped?).to be_falsey
86
+ expect(subject.max_size).to be_nil
87
+ end
88
+ end
89
+ context 'when the cache has a size limit' do
90
+ it 'returns true' do
91
+ subject.max_size = 1
92
+ expect(subject.capped?).to be_truthy
93
+ end
94
+ end
95
+ end
96
+
97
+ describe '#uncapped?' do
98
+ context 'when the cache has no size limit' do
99
+ it 'returns true' do
100
+ subject.uncap
101
+ expect(subject.uncapped?).to be_truthy
102
+ expect(subject.max_size).to be_nil
103
+ end
104
+ end
105
+ context 'when the cache has a size limit' do
106
+ it 'returns false' do
107
+ subject.max_size = 1
108
+ expect(subject.max_size).to eq(1)
109
+ expect(subject.uncapped?).to be_falsey
110
+ end
111
+ end
112
+ end
113
+
114
+ describe '#uncap' do
115
+ it 'removes the size limit' do
116
+ subject.max_size = 1
117
+ expect(subject.uncapped?).to be_falsey
118
+ expect(subject.max_size).to eq(1)
119
+
120
+ subject.uncap
121
+ expect(subject.uncapped?).to be_truthy
122
+ expect(subject.max_size).to be_nil
123
+ end
124
+ end
125
+
126
+ describe '#max_size=' do
127
+ it 'sets the maximum size for the cache' do
128
+ expect(subject.max_size = 100).to eq(100)
129
+ expect(subject.max_size).to eq(100)
130
+ end
131
+
132
+ context 'when passed < 0' do
133
+ it 'throwes an exception' do
134
+ raised = false
135
+ begin
136
+ subject.max_size = 0
137
+ rescue
138
+ raised = true
139
+ end
140
+ expect(raised).to be_truthy
141
+ end
142
+ end
143
+ end
144
+
145
+ describe '#size' do
146
+ context 'when the cache is empty' do
147
+ it 'returns 0' do
148
+ expect(subject.size).to eq(0)
149
+ end
150
+ end
151
+
152
+ context 'when the cache is not empty' do
153
+ it 'returns a value > 0' do
154
+ subject['stuff'] = [ 'ff ' ]
155
+ expect(subject.size).to be > 0
156
+ end
157
+ end
158
+ end
159
+
160
+ describe '#empty?' do
161
+ context 'when the cache is empty' do
162
+ it 'returns true' do
163
+ expect(subject.empty?).to be_truthy
164
+ end
165
+ end
166
+ context 'when the cache is not empty' do
167
+ it 'returns false' do
168
+ subject['stuff2'] = 'ff'
169
+ expect(subject.empty?).to be_falsey
170
+ end
171
+ end
172
+ end
173
+
174
+ describe '#any?' do
175
+ context 'when the cache is empty' do
176
+ it 'returns true' do
177
+ expect(subject.any?).to be_falsey
178
+ end
179
+ end
180
+ context 'when the cache is not empty' do
181
+ it 'returns false' do
182
+ subject['stuff3'] = [ 'ff ' ]
183
+ expect(subject.any?).to be_truthy
184
+ end
185
+ end
186
+ end
187
+
188
+ describe '#[]=' do
189
+ it 'stores an object' do
190
+ v = 'val'
191
+ expect(subject[:key] = v).to eq(v)
192
+ expect(subject[:key]).to eq(v)
193
+ end
194
+ it 'is alias of #store' do
195
+ v = 'val2'
196
+ expect(subject.store( :key2, v )).to eq(v)
197
+ expect(subject[:key2]).to eq(v)
198
+ end
199
+ end
200
+
201
+ describe '#[]' do
202
+ it 'retrieves an object by key' do
203
+ v = 'val2'
204
+ subject[:key] = v
205
+ expect(subject[:key]).to eq(v)
206
+ expect(subject.empty?).to be_falsey
207
+ end
208
+
209
+ it 'increments :hits' do
210
+ expect(subject.statistics[:hits]).to eq 0
211
+
212
+ v = 'val2'
213
+ subject[:key] = v
214
+ subject[:key]
215
+
216
+ expect(subject.statistics[:hits]).to eq 1
217
+ end
218
+
219
+ context 'when the key does not exist' do
220
+ it 'returns nil' do
221
+ expect(subject[:some_key]).to be_nil
222
+ end
223
+
224
+ it 'increments :misses' do
225
+ expect(subject.statistics[:misses]).to eq 0
226
+ subject[:some_key]
227
+ expect(subject.statistics[:misses]).to eq 1
228
+ end
229
+ end
230
+ end
231
+
232
+ describe '#fetch' do
233
+ context 'when the passed key exists' do
234
+ it 'returns its value' do
235
+ old_val = 'my val'
236
+ new_val = 'new val'
237
+
238
+ cache = described_class.new
239
+ cache[:my_key] = old_val
240
+ cache.fetch(:my_key ) { new_val }
241
+
242
+ expect(cache[:my_key]).to eq(old_val)
243
+ end
244
+
245
+ it 'increments :hits' do
246
+ old_val = 'my val'
247
+ new_val = 'new val'
248
+
249
+ cache = described_class.new
250
+ cache[:my_key] = old_val
251
+
252
+ expect(cache.statistics[:hits]).to eq 0
253
+
254
+ cache.fetch(:my_key ) { new_val }
255
+
256
+ expect(cache.statistics[:hits]).to eq 1
257
+ end
258
+ end
259
+
260
+ context 'when the passed key does not exist' do
261
+ it 'assigns to it the return value of the given block' do
262
+ new_val = 'new val'
263
+ cache = described_class.new
264
+ cache.fetch(:my_key ) { new_val }
265
+
266
+ expect(cache[:my_key]).to eq(new_val)
267
+ end
268
+
269
+ it 'increments :misses' do
270
+ new_val = 'new val'
271
+ cache = described_class.new
272
+ expect(cache.statistics[:misses]).to eq 0
273
+
274
+ cache.fetch(:my_key ) { new_val }
275
+
276
+ expect(cache.statistics[:misses]).to eq 1
277
+ end
278
+ end
279
+ end
280
+
281
+ describe '#include?' do
282
+ context 'when the key exists' do
283
+ it 'returns true' do
284
+ subject[:key1] = 'v'
285
+ expect(subject.include?( :key1 )).to be_truthy
286
+ end
287
+ end
288
+ context 'when the key does not exist' do
289
+ it 'returns false' do
290
+ expect(subject.include?( :key2 )).to be_falsey
291
+ end
292
+ end
293
+ end
294
+
295
+ describe '#delete' do
296
+ context 'when the key exists' do
297
+ it 'deletes a key' do
298
+ v = 'my_val'
299
+ subject[:my_key] = v
300
+ expect(subject.delete( :my_key )).to eq(v)
301
+ expect(subject[:my_key]).to be_nil
302
+ expect(subject.include?( :my_key )).to be_falsey
303
+ end
304
+ it 'returns its value' do
305
+ v = 'my_val'
306
+ subject[:my_key] = v
307
+ expect(subject.delete( :my_key )).to eq(v)
308
+ expect(subject[:my_key]).to be_nil
309
+ expect(subject.include?( :my_key )).to be_falsey
310
+ end
311
+ end
312
+ context 'when the key does not exist' do
313
+ it 'should return nil' do
314
+ expect(subject.delete( :my_key2 )).to be_nil
315
+ end
316
+ end
317
+ end
318
+
319
+ describe '#empty?' do
320
+ context 'when cache is empty' do
321
+ it 'returns true' do
322
+ expect(subject.empty?).to be_truthy
323
+ end
324
+ end
325
+ context 'when cache is not empty' do
326
+ it 'returns false' do
327
+ subject['ee'] = 'rr'
328
+ expect(subject.empty?).to be_falsey
329
+ end
330
+ end
331
+ end
332
+
333
+ describe '#any?' do
334
+ context 'when cache is empty' do
335
+ it 'returns false' do
336
+ expect(subject.any?).to be_falsey
337
+ end
338
+ end
339
+ context 'when cache is not empty' do
340
+ it 'returns true' do
341
+ subject['ee'] = 'rr'
342
+ expect(subject.any?).to be_truthy
343
+ end
344
+ end
345
+ end
346
+
347
+ describe '#clear' do
348
+ it 'empties the cache' do
349
+ subject[:my_key2] = 'v'
350
+ expect(subject.size).to be > 0
351
+ expect(subject.empty?).to be_falsey
352
+ subject.clear
353
+
354
+ expect(subject.size).to eq(0)
355
+ expect(subject.empty?).to be_truthy
356
+ end
357
+ end
358
+
359
+ describe '#==' do
360
+ context 'when 2 lists are equal' do
361
+ it 'returns true' do
362
+ new = described_class.new
363
+
364
+ subject[:test_key] = 'test_val'.freeze
365
+ new[:test_key] = 'test_val'.freeze
366
+
367
+ expect(subject).to eq(new)
368
+ end
369
+ end
370
+
371
+ context 'when 2 lists are not equal' do
372
+ it 'returns false' do
373
+ new = described_class.new
374
+
375
+ subject[:test_key] = 'test_val'
376
+ new[:test_key] = 'test_val2'
377
+
378
+ expect(subject).not_to eq(new)
379
+ end
380
+ end
381
+ end
382
+
383
+ describe '#hash' do
384
+ context 'when 2 lists are equal' do
385
+ it 'returns the same value' do
386
+ new = described_class.new
387
+
388
+ subject[:test_key] = 'test_val'.freeze
389
+ new[:test_key] = 'test_val'.freeze
390
+
391
+ expect(subject.hash).to eq(new.hash)
392
+ end
393
+ end
394
+
395
+ context 'when 2 lists are not equal' do
396
+ it 'returns different values' do
397
+ new = described_class.new
398
+
399
+ subject[:test_key] = 'test_val'
400
+ new[:test_key] = 'test_val2'
401
+
402
+ expect(subject.hash).not_to eq(new.hash)
403
+ end
404
+ end
405
+ end
406
+
407
+ describe '#dup' do
408
+ it 'returns a copy' do
409
+ subject[:test_key] = 'test_val'
410
+ copy = subject.dup
411
+
412
+ expect(copy).to eq(subject)
413
+
414
+ copy[:test_key] = 'test_val2'
415
+
416
+ expect(copy).not_to eq(subject)
417
+ end
418
+ end
419
+ end