flipper 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. data/Guardfile +3 -8
  2. data/README.md +26 -38
  3. data/examples/percentage_of_actors.rb +17 -12
  4. data/examples/percentage_of_random.rb +3 -7
  5. data/lib/flipper.rb +8 -1
  6. data/lib/flipper/adapter.rb +2 -208
  7. data/lib/flipper/adapters/decorator.rb +9 -0
  8. data/lib/flipper/adapters/instrumented.rb +92 -0
  9. data/lib/flipper/adapters/memoizable.rb +88 -0
  10. data/lib/flipper/adapters/memory.rb +89 -7
  11. data/lib/flipper/adapters/operation_logger.rb +31 -45
  12. data/lib/flipper/decorator.rb +6 -0
  13. data/lib/flipper/dsl.rb +29 -2
  14. data/lib/flipper/feature.rb +83 -49
  15. data/lib/flipper/gate.rb +24 -41
  16. data/lib/flipper/gates/actor.rb +24 -24
  17. data/lib/flipper/gates/boolean.rb +28 -15
  18. data/lib/flipper/gates/group.rb +25 -34
  19. data/lib/flipper/gates/percentage_of_actors.rb +21 -13
  20. data/lib/flipper/gates/percentage_of_random.rb +20 -12
  21. data/lib/flipper/instrumentation/log_subscriber.rb +14 -22
  22. data/lib/flipper/middleware/memoizer.rb +23 -0
  23. data/lib/flipper/spec/shared_adapter_specs.rb +141 -92
  24. data/lib/flipper/types/boolean.rb +5 -1
  25. data/lib/flipper/version.rb +1 -1
  26. data/spec/flipper/adapters/instrumented_spec.rb +92 -0
  27. data/spec/flipper/adapters/memoizable_spec.rb +184 -0
  28. data/spec/flipper/adapters/memory_spec.rb +1 -11
  29. data/spec/flipper/adapters/operation_logger_spec.rb +93 -0
  30. data/spec/flipper/dsl_spec.rb +18 -43
  31. data/spec/flipper/feature_spec.rb +25 -9
  32. data/spec/flipper/gate_spec.rb +8 -20
  33. data/spec/flipper/gates/actor_spec.rb +6 -14
  34. data/spec/flipper/gates/boolean_spec.rb +80 -13
  35. data/spec/flipper/gates/group_spec.rb +8 -18
  36. data/spec/flipper/gates/percentage_of_actors_spec.rb +12 -28
  37. data/spec/flipper/gates/percentage_of_random_spec.rb +6 -14
  38. data/spec/flipper/instrumentation/log_subscriber_spec.rb +15 -8
  39. data/spec/flipper/instrumentation/metriks_subscriber_spec.rb +3 -6
  40. data/spec/flipper/middleware/{local_cache_spec.rb → memoizer_spec.rb} +25 -55
  41. data/spec/flipper/types/boolean_spec.rb +13 -3
  42. data/spec/flipper_spec.rb +7 -0
  43. data/spec/helper.rb +21 -3
  44. data/spec/integration_spec.rb +115 -116
  45. metadata +17 -27
  46. data/lib/flipper/adapters/memoized.rb +0 -55
  47. data/lib/flipper/key.rb +0 -38
  48. data/lib/flipper/middleware/local_cache.rb +0 -36
  49. data/lib/flipper/toggle.rb +0 -54
  50. data/lib/flipper/toggles/boolean.rb +0 -54
  51. data/lib/flipper/toggles/set.rb +0 -25
  52. data/lib/flipper/toggles/value.rb +0 -25
  53. data/spec/flipper/adapter_spec.rb +0 -463
  54. data/spec/flipper/adapters/memoized_spec.rb +0 -93
  55. data/spec/flipper/key_spec.rb +0 -23
  56. data/spec/flipper/toggle_spec.rb +0 -22
  57. data/spec/flipper/toggles/boolean_spec.rb +0 -40
  58. data/spec/flipper/toggles/set_spec.rb +0 -35
  59. data/spec/flipper/toggles/value_spec.rb +0 -55
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flipper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-06 00:00:00.000000000 Z
12
+ date: 2013-02-16 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Feature flipper for any adapter
15
15
  email:
@@ -38,9 +38,12 @@ files:
38
38
  - flipper.gemspec
39
39
  - lib/flipper.rb
40
40
  - lib/flipper/adapter.rb
41
- - lib/flipper/adapters/memoized.rb
41
+ - lib/flipper/adapters/decorator.rb
42
+ - lib/flipper/adapters/instrumented.rb
43
+ - lib/flipper/adapters/memoizable.rb
42
44
  - lib/flipper/adapters/memory.rb
43
45
  - lib/flipper/adapters/operation_logger.rb
46
+ - lib/flipper/decorator.rb
44
47
  - lib/flipper/dsl.rb
45
48
  - lib/flipper/errors.rb
46
49
  - lib/flipper/feature.rb
@@ -55,14 +58,9 @@ files:
55
58
  - lib/flipper/instrumentation/metriks_subscriber.rb
56
59
  - lib/flipper/instrumenters/memory.rb
57
60
  - lib/flipper/instrumenters/noop.rb
58
- - lib/flipper/key.rb
59
- - lib/flipper/middleware/local_cache.rb
61
+ - lib/flipper/middleware/memoizer.rb
60
62
  - lib/flipper/registry.rb
61
63
  - lib/flipper/spec/shared_adapter_specs.rb
62
- - lib/flipper/toggle.rb
63
- - lib/flipper/toggles/boolean.rb
64
- - lib/flipper/toggles/set.rb
65
- - lib/flipper/toggles/value.rb
66
64
  - lib/flipper/type.rb
67
65
  - lib/flipper/types/actor.rb
68
66
  - lib/flipper/types/boolean.rb
@@ -71,9 +69,10 @@ files:
71
69
  - lib/flipper/types/percentage_of_actors.rb
72
70
  - lib/flipper/types/percentage_of_random.rb
73
71
  - lib/flipper/version.rb
74
- - spec/flipper/adapter_spec.rb
75
- - spec/flipper/adapters/memoized_spec.rb
72
+ - spec/flipper/adapters/instrumented_spec.rb
73
+ - spec/flipper/adapters/memoizable_spec.rb
76
74
  - spec/flipper/adapters/memory_spec.rb
75
+ - spec/flipper/adapters/operation_logger_spec.rb
77
76
  - spec/flipper/dsl_spec.rb
78
77
  - spec/flipper/feature_spec.rb
79
78
  - spec/flipper/gate_spec.rb
@@ -86,13 +85,8 @@ files:
86
85
  - spec/flipper/instrumentation/metriks_subscriber_spec.rb
87
86
  - spec/flipper/instrumenters/memory_spec.rb
88
87
  - spec/flipper/instrumenters/noop_spec.rb
89
- - spec/flipper/key_spec.rb
90
- - spec/flipper/middleware/local_cache_spec.rb
88
+ - spec/flipper/middleware/memoizer_spec.rb
91
89
  - spec/flipper/registry_spec.rb
92
- - spec/flipper/toggle_spec.rb
93
- - spec/flipper/toggles/boolean_spec.rb
94
- - spec/flipper/toggles/set_spec.rb
95
- - spec/flipper/toggles/value_spec.rb
96
90
  - spec/flipper/types/actor_spec.rb
97
91
  - spec/flipper/types/boolean_spec.rb
98
92
  - spec/flipper/types/group_spec.rb
@@ -116,7 +110,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
116
110
  version: '0'
117
111
  segments:
118
112
  - 0
119
- hash: 890771361704353632
113
+ hash: -4560839249202297958
120
114
  required_rubygems_version: !ruby/object:Gem::Requirement
121
115
  none: false
122
116
  requirements:
@@ -125,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
119
  version: '0'
126
120
  segments:
127
121
  - 0
128
- hash: 890771361704353632
122
+ hash: -4560839249202297958
129
123
  requirements: []
130
124
  rubyforge_project:
131
125
  rubygems_version: 1.8.23
@@ -133,9 +127,10 @@ signing_key:
133
127
  specification_version: 3
134
128
  summary: Feature flipper for any adapter
135
129
  test_files:
136
- - spec/flipper/adapter_spec.rb
137
- - spec/flipper/adapters/memoized_spec.rb
130
+ - spec/flipper/adapters/instrumented_spec.rb
131
+ - spec/flipper/adapters/memoizable_spec.rb
138
132
  - spec/flipper/adapters/memory_spec.rb
133
+ - spec/flipper/adapters/operation_logger_spec.rb
139
134
  - spec/flipper/dsl_spec.rb
140
135
  - spec/flipper/feature_spec.rb
141
136
  - spec/flipper/gate_spec.rb
@@ -148,13 +143,8 @@ test_files:
148
143
  - spec/flipper/instrumentation/metriks_subscriber_spec.rb
149
144
  - spec/flipper/instrumenters/memory_spec.rb
150
145
  - spec/flipper/instrumenters/noop_spec.rb
151
- - spec/flipper/key_spec.rb
152
- - spec/flipper/middleware/local_cache_spec.rb
146
+ - spec/flipper/middleware/memoizer_spec.rb
153
147
  - spec/flipper/registry_spec.rb
154
- - spec/flipper/toggle_spec.rb
155
- - spec/flipper/toggles/boolean_spec.rb
156
- - spec/flipper/toggles/set_spec.rb
157
- - spec/flipper/toggles/value_spec.rb
158
148
  - spec/flipper/types/actor_spec.rb
159
149
  - spec/flipper/types/boolean_spec.rb
160
150
  - spec/flipper/types/group_spec.rb
@@ -1,55 +0,0 @@
1
- require 'set'
2
-
3
- module Flipper
4
- module Adapters
5
- class Memoized
6
- # Public
7
- def initialize(adapter, cache = {})
8
- @adapter = adapter
9
- @cache = cache
10
- end
11
-
12
- # Public
13
- def read(key)
14
- @cache.fetch(key) {
15
- @cache[key] = @adapter.read(key)
16
- }
17
- end
18
-
19
- # Public
20
- def write(key, value)
21
- result = @adapter.write(key, value)
22
- @cache.delete(key)
23
- result
24
- end
25
-
26
- # Public
27
- def delete(key)
28
- result = @adapter.delete(key)
29
- @cache.delete(key)
30
- result
31
- end
32
-
33
- # Public
34
- def set_add(key, value)
35
- result = @adapter.set_add(key, value)
36
- @cache.delete(key)
37
- result
38
- end
39
-
40
- # Public
41
- def set_delete(key, value)
42
- result = @adapter.set_delete(key, value)
43
- @cache.delete(key)
44
- result
45
- end
46
-
47
- # Public
48
- def set_members(key)
49
- @cache.fetch(key) {
50
- @cache[key] = @adapter.set_members(key)
51
- }
52
- end
53
- end
54
- end
55
- end
data/lib/flipper/key.rb DELETED
@@ -1,38 +0,0 @@
1
- module Flipper
2
- # Private: Used internally in flipper to create key to be used for feature in
3
- # the adapter. You should never need to use this.
4
- class Key
5
- # Private
6
- Separator = '/'
7
-
8
- # Private
9
- attr_reader :feature_name
10
-
11
- # Private
12
- attr_reader :gate_key
13
-
14
- # Internal
15
- def initialize(feature_name, gate_key)
16
- @feature_name, @gate_key = feature_name, gate_key
17
- end
18
-
19
- # Private
20
- def separator
21
- Separator.dup
22
- end
23
-
24
- # Private
25
- def to_s
26
- "#{feature_name}#{separator}#{gate_key}"
27
- end
28
-
29
- # Internal: Pretty string version for debugging.
30
- def inspect
31
- attributes = [
32
- "feature_name=#{feature_name.inspect}",
33
- "gate_key=#{gate_key.inspect}",
34
- ]
35
- "#<#{self.class.name}:#{object_id} #{attributes.join(', ')}>"
36
- end
37
- end
38
- end
@@ -1,36 +0,0 @@
1
- module Flipper
2
- module Middleware
3
- class LocalCache
4
- class Body
5
- def initialize(target, flipper, original)
6
- @target = target
7
- @flipper = flipper
8
- @original = original
9
- end
10
-
11
- def each(&block)
12
- @target.each(&block)
13
- end
14
-
15
- def close
16
- @target.close if @target.respond_to?(:close)
17
- ensure
18
- @flipper.adapter.use_local_cache = @original
19
- end
20
- end
21
-
22
- def initialize(app, flipper)
23
- @app = app
24
- @flipper = flipper
25
- end
26
-
27
- def call(env)
28
- original = @flipper.adapter.using_local_cache?
29
- @flipper.adapter.use_local_cache = true
30
-
31
- status, headers, body = @app.call(env)
32
- [status, headers, Body.new(body, @flipper, original)]
33
- end
34
- end
35
- end
36
- end
@@ -1,54 +0,0 @@
1
- require 'forwardable'
2
-
3
- module Flipper
4
- # Internal: Used by gate to toggle values (true/false, add/delete from set, etc.).
5
- # Named poorly maybe, but haven't come up with a better name yet.
6
- class Toggle
7
- extend Forwardable
8
-
9
- attr_reader :gate
10
-
11
- def_delegators :@gate, :adapter_key, :feature, :adapter
12
-
13
- def initialize(gate)
14
- @gate = gate
15
- end
16
-
17
- # Internal: Enables thing for gate and adds feature to known features.
18
- #
19
- # Returns Boolean (currently always true).
20
- def enable(thing)
21
- add_feature_to_set
22
- end
23
-
24
- # Internal: Disables thing for gate and adds feature to known features.
25
- #
26
- # Returns Boolean (currently always true).
27
- def disable(thing)
28
- add_feature_to_set
29
- end
30
-
31
- def value
32
- raise 'Not implemented'
33
- end
34
-
35
- # Public: Pretty string version for debugging.
36
- def inspect
37
- attributes = [
38
- "gate=#{gate.inspect}",
39
- "value=#{value}",
40
- ]
41
- "#<#{self.class.name}:#{object_id} #{attributes.join(', ')}>"
42
- end
43
-
44
- private
45
-
46
- def add_feature_to_set
47
- adapter.feature_add adapter_key.feature_name
48
- end
49
- end
50
- end
51
-
52
- require 'flipper/toggles/boolean'
53
- require 'flipper/toggles/set'
54
- require 'flipper/toggles/value'
@@ -1,54 +0,0 @@
1
- module Flipper
2
- module Toggles
3
- class Boolean < Toggle
4
- TruthMap = {
5
- true => true,
6
- 'true' => true,
7
- 'TRUE' => true,
8
- 'True' => true,
9
- 't' => true,
10
- 'T' => true,
11
- '1' => true,
12
- 'on' => true,
13
- 'ON' => true,
14
- 1 => true,
15
- 1.0 => true,
16
- false => false,
17
- 'false' => false,
18
- 'FALSE' => false,
19
- 'False' => false,
20
- 'f' => false,
21
- 'F' => false,
22
- '0' => false,
23
- 'off' => false,
24
- 'OFF' => false,
25
- 0 => false,
26
- 0.0 => false,
27
- nil => false,
28
- }
29
-
30
- def enable(thing)
31
- super
32
- adapter.write adapter_key, thing.value
33
- true
34
- end
35
-
36
- def disable(thing)
37
- super
38
- feature.gates.each do |gate|
39
- gate.adapter.delete gate.adapter_key
40
- end
41
- true
42
- end
43
-
44
- def value
45
- value = adapter.read(adapter_key)
46
- !!TruthMap[value]
47
- end
48
-
49
- def enabled?
50
- value
51
- end
52
- end
53
- end
54
- end
@@ -1,25 +0,0 @@
1
- module Flipper
2
- module Toggles
3
- class Set < Toggle
4
- def enable(thing)
5
- super
6
- adapter.set_add adapter_key, thing.value
7
- true
8
- end
9
-
10
- def disable(thing)
11
- super
12
- adapter.set_delete adapter_key, thing.value
13
- true
14
- end
15
-
16
- def value
17
- adapter.set_members adapter_key
18
- end
19
-
20
- def enabled?
21
- !value.empty?
22
- end
23
- end
24
- end
25
- end
@@ -1,25 +0,0 @@
1
- module Flipper
2
- module Toggles
3
- class Value < Toggle
4
- def enable(thing)
5
- super
6
- adapter.write adapter_key, thing.value
7
- true
8
- end
9
-
10
- def disable(thing)
11
- super
12
- adapter.delete adapter_key
13
- true
14
- end
15
-
16
- def value
17
- adapter.read adapter_key
18
- end
19
-
20
- def enabled?
21
- !value.nil? && value.to_i > 0
22
- end
23
- end
24
- end
25
- end
@@ -1,463 +0,0 @@
1
- require 'helper'
2
- require 'flipper/adapter'
3
- require 'flipper/adapters/memory'
4
- require 'flipper/instrumenters/memory'
5
-
6
- describe Flipper::Adapter do
7
- let(:local_cache) { {} }
8
- let(:source) { {} }
9
- let(:adapter) { Flipper::Adapters::Memory.new(source) }
10
- let(:features_key) { described_class::FeaturesKey }
11
-
12
- subject { described_class.new(adapter, :local_cache => local_cache) }
13
-
14
- describe ".wrap" do
15
- context "with Flipper::Adapter instance" do
16
- before do
17
- @result = described_class.wrap(subject)
18
- end
19
-
20
- it "returns same Flipper::Adapter instance" do
21
- @result.should equal(subject)
22
- end
23
-
24
- it "wraps adapter that instance was wrapping" do
25
- @result.adapter.should be(subject.adapter)
26
- end
27
- end
28
-
29
- context "with adapter instance" do
30
- before do
31
- @result = described_class.wrap(adapter)
32
- end
33
-
34
- it "returns Flipper::Adapter instance" do
35
- @result.should be_instance_of(described_class)
36
- end
37
-
38
- it "wraps adapter" do
39
- @result.adapter.should be(adapter)
40
- end
41
- end
42
-
43
- context "with adapter instance and options" do
44
- let(:instrumenter) { double('Instrumentor') }
45
-
46
- before do
47
- @result = described_class.wrap(adapter, :instrumenter => instrumenter)
48
- end
49
-
50
- it "returns Flipper::Adapter instance" do
51
- @result.should be_instance_of(described_class)
52
- end
53
-
54
- it "wraps adapter" do
55
- @result.adapter.should be(adapter)
56
- end
57
-
58
- it "passes options to initialization" do
59
- @result.instrumenter.should be(instrumenter)
60
- end
61
- end
62
- end
63
-
64
- describe "#initialize" do
65
- it "sets adapter" do
66
- instance = described_class.new(adapter)
67
- instance.adapter.should be(adapter)
68
- end
69
-
70
- it "sets adapter name" do
71
- instance = described_class.new(adapter)
72
- instance.name.should be(:memory)
73
- end
74
-
75
- it "defaults instrumenter" do
76
- instance = described_class.new(adapter)
77
- instance.instrumenter.should be(Flipper::Instrumenters::Noop)
78
- end
79
-
80
- it "allows overriding instrumenter" do
81
- instrumenter = double('Instrumentor', :instrument => nil)
82
- instance = described_class.new(adapter, :instrumenter => instrumenter)
83
- instance.instrumenter.should be(instrumenter)
84
- end
85
- end
86
-
87
- describe "#use_local_cache=" do
88
- it "sets value" do
89
- subject.use_local_cache = true
90
- subject.using_local_cache?.should be_true
91
-
92
- subject.use_local_cache = false
93
- subject.using_local_cache?.should be_false
94
- end
95
-
96
- it "clears the local cache" do
97
- local_cache.should_receive(:clear)
98
- subject.use_local_cache = true
99
- end
100
- end
101
-
102
- describe "#using_local_cache?" do
103
- it "returns true if enabled" do
104
- subject.use_local_cache = true
105
- subject.using_local_cache?.should be_true
106
- end
107
-
108
- it "returns false if disabled" do
109
- subject.use_local_cache = false
110
- subject.using_local_cache?.should be_false
111
- end
112
- end
113
-
114
- context "with local cache enabled" do
115
- before do
116
- subject.use_local_cache = true
117
- end
118
-
119
- describe "#read" do
120
- before do
121
- adapter.write 'foo', 'bar'
122
- @result = subject.read('foo')
123
- end
124
-
125
- it "returns result of adapter read" do
126
- @result.should eq('bar')
127
- end
128
-
129
- it "memoizes adapter read value" do
130
- local_cache['foo'].should eq('bar')
131
- adapter.should_not_receive(:read)
132
- subject.read('foo').should eq('bar')
133
- end
134
- end
135
-
136
- describe "#set_members" do
137
- before do
138
- source['foo'] = Set['1', '2']
139
- @result = subject.set_members('foo')
140
- end
141
-
142
- it "returns result of adapter set members" do
143
- @result.should eq(Set['1', '2'])
144
- end
145
-
146
- it "memoizes key" do
147
- local_cache['foo'].should eq(Set['1', '2'])
148
- adapter.should_not_receive(:set_members)
149
- subject.set_members('foo').should eq(Set['1', '2'])
150
- end
151
- end
152
-
153
- describe "#write" do
154
- before do
155
- subject.write 'foo', 'swanky'
156
- end
157
-
158
- it "performs adapter write" do
159
- adapter.read('foo').should eq('swanky')
160
- end
161
-
162
- it "unmemoizes key" do
163
- local_cache.key?('foo').should be_false
164
- end
165
- end
166
-
167
- describe "#delete" do
168
- before do
169
- adapter.write 'foo', 'bar'
170
- subject.delete 'foo'
171
- end
172
-
173
- it "performs adapter delete" do
174
- adapter.read('foo').should be_nil
175
- end
176
-
177
- it "unmemoizes key" do
178
- local_cache.key?('foo').should be_false
179
- end
180
- end
181
-
182
- describe "#set_add" do
183
- before do
184
- source['foo'] = Set['1']
185
- local_cache['foo'] = Set['1']
186
- subject.set_add 'foo', '2'
187
- end
188
-
189
- it "returns result of adapter set members" do
190
- adapter.set_members('foo').should eq(Set['1', '2'])
191
- end
192
-
193
- it "unmemoizes key" do
194
- local_cache.key?('foo').should be_false
195
- end
196
- end
197
-
198
- describe "#set_delete" do
199
- before do
200
- source['foo'] = Set['1', '2', '3']
201
- local_cache['foo'] = Set['1', '2', '3']
202
- subject.set_delete 'foo', '3'
203
- end
204
-
205
- it "returns result of adapter set members" do
206
- adapter.set_members('foo').should eq(Set['1', '2'])
207
- end
208
-
209
- it "unmemoizes key" do
210
- local_cache.key?('foo').should be_false
211
- end
212
- end
213
- end
214
-
215
- context "with local cache disabled" do
216
- before do
217
- subject.use_local_cache = false
218
- end
219
-
220
- describe "#read" do
221
- before do
222
- adapter.write 'foo', 'bar'
223
- @result = subject.read('foo')
224
- end
225
-
226
- it "returns result of adapter read" do
227
- @result.should eq('bar')
228
- end
229
-
230
- it "does not memoize adapter read value" do
231
- local_cache.key?('foo').should be_false
232
- end
233
- end
234
-
235
- describe "#set_members" do
236
- before do
237
- source['foo'] = Set['1', '2']
238
- @result = subject.set_members('foo')
239
- end
240
-
241
- it "returns result of adapter set members" do
242
- @result.should eq(Set['1', '2'])
243
- end
244
-
245
- it "does not memoize the adapter set member result" do
246
- local_cache.key?('foo').should be_false
247
- end
248
- end
249
-
250
- describe "#write" do
251
- before do
252
- adapter.write 'foo', 'bar'
253
- local_cache['foo'] = 'bar'
254
- subject.write 'foo', 'swanky'
255
- end
256
-
257
- it "performs adapter write" do
258
- adapter.read('foo').should eq('swanky')
259
- end
260
-
261
- it "does not attempt to delete local cache key" do
262
- local_cache.key?('foo').should be_true
263
- end
264
- end
265
-
266
- describe "#delete" do
267
- before do
268
- adapter.write 'foo', 'bar'
269
- local_cache['foo'] = 'bar'
270
- subject.delete 'foo'
271
- end
272
-
273
- it "performs adapter delete" do
274
- adapter.read('foo').should be_nil
275
- end
276
-
277
- it "does not attempt to delete local cache key" do
278
- local_cache.key?('foo').should be_true
279
- end
280
- end
281
-
282
- describe "#set_add" do
283
- before do
284
- source['foo'] = Set['1']
285
- local_cache['foo'] = Set['1']
286
- subject.set_add 'foo', '2'
287
- end
288
-
289
- it "performs adapter set add" do
290
- adapter.set_members('foo').should eq(Set['1', '2'])
291
- end
292
-
293
- it "does not attempt to delete local cache key" do
294
- local_cache.key?('foo').should be_true
295
- end
296
- end
297
-
298
- describe "#set_delete" do
299
- before do
300
- source['foo'] = Set['1', '2', '3']
301
- local_cache['foo'] = Set['1', '2', '3']
302
- subject.set_delete 'foo', '3'
303
- end
304
-
305
- it "performs adapter set delete" do
306
- adapter.set_members('foo').should eq(Set['1', '2'])
307
- end
308
-
309
- it "does not attempt to delete local cache key" do
310
- local_cache.key?('foo').should be_true
311
- end
312
- end
313
- end
314
-
315
- describe "#eql?" do
316
- it "returns true for same class and adapter" do
317
- subject.eql?(described_class.new(adapter)).should be_true
318
- end
319
-
320
- it "returns false for different adapter" do
321
- instance = described_class.new(Flipper::Adapters::Memory.new)
322
- subject.eql?(instance).should be_false
323
- end
324
-
325
- it "returns false for different class" do
326
- subject.eql?(Object.new).should be_false
327
- end
328
-
329
- it "is aliased to ==" do
330
- (subject == described_class.new(adapter)).should be_true
331
- end
332
- end
333
-
334
- describe "#features" do
335
- context "with no features enabled/disabled" do
336
- it "defaults to empty set" do
337
- subject.features.should eq(Set.new)
338
- end
339
- end
340
-
341
- context "with features enabled and disabled" do
342
- before do
343
- subject.set_add(features_key, 'stats')
344
- subject.set_add(features_key, 'cache')
345
- subject.set_add(features_key, 'search')
346
- end
347
-
348
- it "returns set of feature names" do
349
- subject.features.should be_instance_of(Set)
350
- subject.features.sort.should eq(['cache', 'search', 'stats'])
351
- end
352
- end
353
- end
354
-
355
- describe "#feature_add" do
356
- context "with string name" do
357
- before do
358
- subject.feature_add('search')
359
- end
360
-
361
- it "adds string to set" do
362
- subject.set_members(features_key).should include('search')
363
- end
364
- end
365
-
366
- context "with symbol name" do
367
- before do
368
- subject.feature_add(:search)
369
- end
370
-
371
- it "adds string to set" do
372
- subject.set_members(features_key).should include('search')
373
- end
374
- end
375
- end
376
-
377
- describe "instrumentation" do
378
- let(:instrumenter) { Flipper::Instrumenters::Memory.new }
379
-
380
- subject {
381
- described_class.new(adapter, :instrumenter => instrumenter)
382
- }
383
-
384
- it "is recorded for read" do
385
- subject.read('foo')
386
-
387
- event = instrumenter.events.last
388
- event.should_not be_nil
389
- event.name.should eq('adapter_operation.flipper')
390
- event.payload[:key].should eq('foo')
391
- event.payload[:operation].should eq(:read)
392
- event.payload[:adapter_name].should eq(:memory)
393
- event.payload[:result].should be_nil
394
- end
395
-
396
- it "is recorded for write" do
397
- subject.write('foo', 'bar')
398
-
399
- event = instrumenter.events.last
400
- event.should_not be_nil
401
- event.name.should eq('adapter_operation.flipper')
402
- event.payload[:key].should eq('foo')
403
- event.payload[:value].should eq('bar')
404
- event.payload[:operation].should eq(:write)
405
- event.payload[:adapter_name].should eq(:memory)
406
- event.payload[:result].should eq('bar')
407
- end
408
-
409
- it "is recorded for delete" do
410
- subject.delete('foo')
411
-
412
- event = instrumenter.events.last
413
- event.should_not be_nil
414
- event.name.should eq('adapter_operation.flipper')
415
- event.payload[:key].should eq('foo')
416
- event.payload[:operation].should eq(:delete)
417
- event.payload[:adapter_name].should eq(:memory)
418
- event.payload[:result].should be_nil
419
- end
420
-
421
- it "is recorded for set_members" do
422
- subject.set_members('foo')
423
-
424
- event = instrumenter.events.last
425
- event.should_not be_nil
426
- event.name.should eq('adapter_operation.flipper')
427
- event.payload[:key].should eq('foo')
428
- event.payload[:operation].should eq(:set_members)
429
- event.payload[:adapter_name].should eq(:memory)
430
- event.payload[:result].should eq(Set.new)
431
- end
432
-
433
- it "is recorded for set_add" do
434
- subject.set_add('foo', 'bar')
435
-
436
- event = instrumenter.events.last
437
- event.should_not be_nil
438
- event.name.should eq('adapter_operation.flipper')
439
- event.payload[:key].should eq('foo')
440
- event.payload[:operation].should eq(:set_add)
441
- event.payload[:adapter_name].should eq(:memory)
442
- event.payload[:result].should eq(Set['bar'])
443
- end
444
-
445
- it "is recorded for set_delete" do
446
- subject.set_delete('foo', 'bar')
447
-
448
- event = instrumenter.events.last
449
- event.should_not be_nil
450
- event.name.should eq('adapter_operation.flipper')
451
- event.payload[:key].should eq('foo')
452
- event.payload[:operation].should eq(:set_delete)
453
- event.payload[:adapter_name].should eq(:memory)
454
- event.payload[:result].should eq(Set.new)
455
- end
456
- end
457
-
458
- describe "#inspect" do
459
- it "returns easy to read string representation" do
460
- subject.inspect.should eq("#<Flipper::Adapter:#{subject.object_id} name=:memory, use_local_cache=nil>")
461
- end
462
- end
463
- end