cuboid 0.0.0 → 0.0.1alpha

Sign up to get free protection for your applications and to get access to all the features.
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