bigbertha 0.0.1

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.
@@ -0,0 +1,99 @@
1
+ module Bigbertha
2
+ class Snapshot
3
+
4
+ class Node
5
+ attr_accessor :priority, :name, :parent, :children, :value
6
+
7
+ def initialize( name )
8
+ @name = name
9
+ @priority = nil
10
+ @children = []
11
+ @value = nil
12
+ @parent = nil
13
+ end
14
+
15
+ def add_child( child )
16
+ child.parent = self
17
+ children << child
18
+ end
19
+
20
+ def to_map
21
+ map = Map.new
22
+ order( map )
23
+ map
24
+ end
25
+
26
+ def dump
27
+ puts "#{' '*level}#{name} [#{priority.inspect}] --#{value.inspect}"
28
+ children.sort_by do |c|
29
+ if c.priority and c.priority.is_a? Integer
30
+ "b_#{c.priority}_#{c.name}"
31
+ elsif c.priority
32
+ "z_#{c.priority}_#{c.name}"
33
+ else
34
+ "a_#{c.name}"
35
+ end
36
+ end.each do |c|
37
+ c.dump
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def order( map )
44
+ map[name] = children.empty? ? value : Map.new
45
+ children.sort_by do |c|
46
+ if c.priority and c.priority.is_a? Numeric
47
+ "b_#{'%05.2f' % c.priority}_#{c.name}"
48
+ elsif c.priority
49
+ "z_#{c.priority}_#{c.name}"
50
+ else
51
+ "a_#{c.name}"
52
+ end
53
+ end.each do |c|
54
+ c.send( :order, map[name] )
55
+ end
56
+ end
57
+
58
+ def level
59
+ level = 0
60
+ node = self
61
+ while node.parent do
62
+ level +=1
63
+ node = node.parent
64
+ end
65
+ level
66
+ end
67
+ end
68
+
69
+ def initialize( map )
70
+ @map = map
71
+ @root = Node.new( 'root' )
72
+ build( @map, @root )
73
+ end
74
+
75
+ def to_map
76
+ @root.to_map.root
77
+ end
78
+
79
+ def dump
80
+ @root.dump
81
+ end
82
+
83
+ private
84
+
85
+ def build( map, root )
86
+ map.each_pair do |k,v|
87
+ node = Node.new( k )
88
+ if v.is_a? Hash
89
+ priority = v.delete('.priority')
90
+ node.priority = priority if priority
91
+ build( v, node )
92
+ else
93
+ node.value = v.is_a?(String) ? v.to_val : v
94
+ end
95
+ root.add_child( node )
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,3 @@
1
+ module Bigbertha
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe Map do
4
+ describe '#diff' do
5
+ describe 'single vals' do
6
+ it "tracks value changes correctly" do
7
+ prev = Map(:a,1)
8
+ curr = Map(:a,2)
9
+ evts = prev.diff( curr )
10
+ evts.should have(1).item
11
+ evts.first.event_type.should == Bigbertha::Load.evt_value
12
+ evts.first.ref.should == 'a'
13
+ end
14
+
15
+ it "tracks adds correctly" do
16
+ prev = Map.new
17
+ curr = Map(:a,2)
18
+ evts = prev.diff( curr )
19
+ evts.should have(1).item
20
+ evts.first.event_type.should == Bigbertha::Load.evt_child_added
21
+ evts.first.ref.should == 'a'
22
+ end
23
+
24
+ it "tracks deletes correctly" do
25
+ prev = Map(:a,2)
26
+ curr = Map.new
27
+ evts = prev.diff( curr )
28
+ evts.should have(1).item
29
+ evts.first.event_type.should == Bigbertha::Load.evt_child_removed
30
+ evts.first.ref.should == 'a'
31
+ end
32
+ end
33
+
34
+ describe 'multi vals' do
35
+ it 'tracks multi value changes correctly' do
36
+ prev = Map(:a,1)
37
+ curr = Map({a:{a_1:10, a_2:20}})
38
+ evts = prev.diff( curr )
39
+ evts.should have(1).item
40
+ evts.first.event_type.should == Bigbertha::Load.evt_value
41
+ evts.first.ref.should == 'a'
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe String do
4
+ describe '#to_val' do
5
+ it "keep strings unchanged" do
6
+ "fred".to_val.should == "fred"
7
+ end
8
+
9
+ it "converts an integer correctly" do
10
+ "10".to_val.should == 10
11
+ end
12
+
13
+ it "converts an float correctly" do
14
+ "10.5".to_val.should == 10.5
15
+ end
16
+
17
+ it "converts a boolean correctly" do
18
+ "true".to_val.should == true
19
+ "false".to_val.should == false
20
+ end
21
+
22
+ it 'converts null correctly' do
23
+ 'null'.to_val.should == "null"
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,109 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bigbertha::Ref do
4
+ before :all do
5
+ @ref = Bigbertha::Load.new( ENV['fb_url'] )
6
+ end
7
+
8
+ describe '#child?' do
9
+ it "retrieves complex values correctly" do
10
+ @ref.set( a:{b:{c:1, d:"hello"}} )
11
+ @ref.child?( :a ).should == true
12
+ @ref.child?( 'a/b' ).should == true
13
+ @ref.child?( :z ).should == false
14
+ end
15
+ end
16
+
17
+ describe '#children?' do
18
+ it "retrieves complex values correctly" do
19
+ @ref.set( a:{b:{c:1, d:"hello"}} )
20
+ @ref.child(:a).children?.should == true
21
+ @ref.child('a/b').children?.should == true
22
+ @ref.child( 'a/b/c' ).children?.should == false
23
+ end
24
+ end
25
+
26
+ describe '#num_children' do
27
+ it "retrieves complex values correctly" do
28
+ @ref.set( a:{b:{c:1, d:"hello"}} )
29
+ @ref.child(:a).num_children.should == 1
30
+ @ref.child('a/b').num_children.should == 2
31
+ @ref.child( 'a/b/c' ).num_children.should == 0
32
+ end
33
+ end
34
+
35
+ describe '#val' do
36
+ it "retrieves simple value correctly" do
37
+ @ref.set( a:1 )
38
+ @ref.child( :a ).val.to_i.should == 1
39
+ end
40
+
41
+ it "retrieves complex values correctly" do
42
+ @ref.set( a:{b:{c:1, d:"hello"}} )
43
+ @ref.child( :a ).val.should == {b:{c:1, d:"hello"}}
44
+ end
45
+ end
46
+
47
+ describe '#child' do
48
+ it "creates a child ref correctly" do
49
+ child_ref = @ref.child( 'fred')
50
+ child_ref.name.should == 'fred'
51
+ child_ref.parent.to_s.should == ENV['fb_url']
52
+ end
53
+
54
+ it "creates a deep child ref correctly" do
55
+ child_ref = @ref.child( 'fred/blee/duh')
56
+ child_ref.name.should == 'duh'
57
+ child_ref.parent.to_s.should == ENV['fb_url'] + '/fred/blee'
58
+ end
59
+ end
60
+
61
+ describe '#name' do
62
+ it "identifies / as the root name correctly" do
63
+ @ref.name.should be_nil
64
+ end
65
+
66
+ it "identifies a url name correctly" do
67
+ ref = Bigbertha::Load.new( ENV['fb_url'] + '/fred/blee' )
68
+ ref.name.should == 'blee'
69
+ end
70
+ end
71
+
72
+ describe '#root' do
73
+ it "identifies / as root correctly" do
74
+ @ref.root.should == @ref
75
+ end
76
+
77
+ it "identifies non root url correctly" do
78
+ ref = Bigbertha::Load.new( ENV['fb_url'] + '/fred/blee' )
79
+ ref.root.to_s.should == ENV['fb_url']
80
+ end
81
+ end
82
+
83
+ describe '#root?' do
84
+ it "identifies root correctly" do
85
+ @ref.should be_root
86
+ end
87
+
88
+ it "identifies / as root correctly" do
89
+ ref = Bigbertha::Load.new( ENV['fb_url'] + '/' )
90
+ ref.should be_root
91
+ end
92
+
93
+ it "identifies non root correctly" do
94
+ ref = Bigbertha::Load.new( ENV['fb_url'] + '/fred' )
95
+ ref.should_not be_root
96
+ end
97
+ end
98
+
99
+ describe '#parent' do
100
+ it "identifies parent from root correctly" do
101
+ @ref.parent.should be_nil
102
+ end
103
+
104
+ it "identifies a parent correctly" do
105
+ ref = Bigbertha::Load.new( ENV['fb_url'] + '/fred/blee' )
106
+ ref.parent.to_s.should == ENV['fb_url'] + '/fred'
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,301 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bigbertha::Load do
4
+ before :all do
5
+ @url = ENV['fb_url']
6
+ @fb = Bigbertha::Load.new( @url )
7
+ end
8
+
9
+ describe '#inc' do
10
+ before :all do
11
+ @fb.remove
12
+ @fb.set(
13
+ {
14
+ a: {
15
+ a_1: 1,
16
+ },
17
+ b: {
18
+ b_1: 1.5
19
+ },
20
+ c: {
21
+ c_1: "fred"
22
+ }
23
+ }
24
+ )
25
+ end
26
+
27
+ it "increases an integer value correctly" do
28
+ @fb.child( :a ).inc( :a_1 )
29
+ @fb.child( 'a/a_1' ).read.should == 2
30
+ end
31
+
32
+ it "increases an float value correctly" do
33
+ @fb.child( :b ).inc( :b_1 )
34
+ @fb.child( 'b/b_1' ).read.should == 2.5
35
+ end
36
+
37
+ it "set the value to zero is the data does not exist" do
38
+ @fb.child( :b ).inc( :b_2 )
39
+ @fb.child( 'b/b_2' ).read.should == 0
40
+ end
41
+
42
+ it "fails if the field is non numeric" do
43
+ lambda { @fb.child( :c ).inc( :c_1 ) }.should raise_error( Bigbertha::Load::NonNumericFieldError )
44
+ end
45
+ end
46
+
47
+ describe '#dec' do
48
+ before :all do
49
+ @fb.remove
50
+ @fb.set(
51
+ {
52
+ a: {
53
+ a_1: 2,
54
+ },
55
+ b: {
56
+ b_1: 1.5
57
+ },
58
+ c: {
59
+ c_1: "fred"
60
+ }
61
+ }
62
+ )
63
+ end
64
+
65
+ it "decreases an integer value correctly" do
66
+ @fb.child( :a ).dec( :a_1 )
67
+ @fb.child( 'a/a_1' ).read.should == 1
68
+ end
69
+
70
+ it "decreases an float value correctly" do
71
+ @fb.child( :b ).dec( :b_1 )
72
+ @fb.child( 'b/b_1' ).read.should == 0.5
73
+ end
74
+
75
+ it "set the value to zero is the data does not exist" do
76
+ @fb.child( :b ).dec( :b_2 )
77
+ @fb.child( 'b/b_2' ).read.should == 0
78
+ end
79
+
80
+ it "fails if the field is non numeric" do
81
+ lambda { @fb.child( :c ).dec( :c_1 ) }.should raise_error( Bigbertha::Load::NonNumericFieldError )
82
+ end
83
+ end
84
+
85
+ describe '#set_rules' do
86
+ before :each do
87
+ @auth_fb = Bigbertha::Load.new( @url, ENV['fb_auth_token'] )
88
+ end
89
+
90
+ after :each do
91
+ @auth_fb.set_rules( { '.read' => true, '.write' => true } )
92
+ end
93
+
94
+ it "fetch security rules correctly" do
95
+ @auth_fb.set( tmp: { a: 0, b: 1 } )
96
+ @auth_fb.set_rules(
97
+ { '.read' => true, '.write' => false,
98
+ "tmp" => { '.read' => true, '.write' => false }
99
+ })
100
+ res= @auth_fb.get_rules
101
+ res.rules.tmp['.read'].should be_true
102
+ res.rules.tmp['.write'].should be_false
103
+
104
+ res = @fb.child(:tmp).read
105
+ res.should == { a: 0, b: 1 }
106
+
107
+ lambda { @fb.set( tmp: { d: 0 } ) }.should raise_error Bigbertha::Load::PermissionDeniedError
108
+ end
109
+ end
110
+
111
+ describe "#read" do
112
+ before :all do
113
+ @fb.remove
114
+ @fb.set( {
115
+ test_1: {
116
+ test_1_1: {
117
+ key_1: 'Hello',
118
+ key_2: 'World'
119
+ },
120
+ test_1_2: {
121
+ key_1: 10,
122
+ key_2: [10,20,30],
123
+ key_3: {
124
+ test_1_2_1: {
125
+ key_1: 50
126
+ }
127
+ }
128
+ }
129
+ },
130
+ test_2: 10,
131
+ test_3: :Blee,
132
+ test_4: %w[hello world],
133
+ test_5: [{a:1,b:2}, {c:3,d:4}]
134
+ }
135
+ )
136
+ end
137
+
138
+ it "reads a simple number correctly" do
139
+ @fb.child( :test_2 ).read.to_i.should == 10
140
+ end
141
+
142
+ it "reads a string correctly" do
143
+ @fb.child( :test_3 ).read.should == "Blee"
144
+ end
145
+
146
+ it "reads a simple array correctly" do
147
+ @fb.child( :test_4 ).read.should == %w[hello world]
148
+ end
149
+
150
+ it "reads an array of hash correctly" do
151
+ @fb.child( 'test_5/0' ).read.a.should == 1
152
+ end
153
+
154
+ it "reads a deeply nested hash correctly" do
155
+ @fb.child( 'test_1/test_1_2/key_3').read.test_1_2_1.key_1.should == 50
156
+ end
157
+ end
158
+
159
+ describe '#push' do
160
+ before :each do
161
+ @fb.remove
162
+ end
163
+
164
+ it "makes up an empty ref if no data" do
165
+ resp = @fb.push()
166
+ resp.name.should_not be_nil
167
+ end
168
+
169
+ it "builds a list with values" do
170
+ resp = @fb.push( {a:1,b:2} )
171
+ resp.name.should_not be_nil
172
+ @fb.child( resp.name ).read.a.should == 1
173
+ @fb.child( resp.name ).read.b.should == 2
174
+ end
175
+ end
176
+
177
+ describe 'priority' do
178
+ before :each do
179
+ @fb.remove
180
+ end
181
+
182
+ it "sets priority with complex data correctly" do
183
+ @fb.set( c:{d:1} )
184
+ ref = @fb.child( :c )
185
+ ref.set_priority( 2.0 )
186
+ ref.get_priority.to_i.should == 2.0
187
+ end
188
+
189
+ it "unsets priority correctly" do
190
+ @fb.set( c:{d:1} )
191
+ ref = @fb.child( :c )
192
+ ref.set_priority( 2.0 )
193
+ ref.get_priority.to_i.should == 2.0
194
+ ref.set_priority( nil )
195
+ ref.get_priority.should == nil
196
+ end
197
+
198
+ it "sets priority for lists correctly" do
199
+ a_ref = @fb.push( {b:1, a:2} )
200
+ b_ref = @fb.push( {e:1, d:2} )
201
+ a_ref.set_priority( 20 )
202
+ b_ref.set_priority( 10 )
203
+ a_ref.get_priority.to_i.should == 20
204
+ b_ref.get_priority.to_i.should == 10
205
+ res = a_ref.parent.read
206
+ keys = [b_ref.name, a_ref.name]
207
+ index = 0
208
+ res.each_pair do |k,v|
209
+ k.should == keys[index]
210
+ index += 1
211
+ end
212
+ end
213
+
214
+ it "sets priority for lists correctly" do
215
+ a_ref = @fb.push
216
+ a1_ref = a_ref.push( a:1 )
217
+ a2_ref = a_ref.push( b:1 )
218
+ b_ref = @fb.push
219
+ b1_ref = b_ref.push( c:1 )
220
+ b2_ref = b_ref.push( d:1 )
221
+
222
+ a_ref.set_priority( 20 )
223
+ a1_ref.set_priority( 50 )
224
+ a2_ref.set_priority( 30 )
225
+ b_ref.set_priority( 10 )
226
+ b1_ref.set_priority( 50 )
227
+ b2_ref.set_priority( 30 )
228
+
229
+ a1_ref.get_priority.to_i.should == 50
230
+ a2_ref.get_priority.to_i.should == 30
231
+ b1_ref.get_priority.to_i.should == 50
232
+ b2_ref.get_priority.to_i.should == 30
233
+
234
+ res = a_ref.parent.read
235
+ keys = [b_ref.name, a_ref.name]
236
+ index = 0
237
+ res.each_pair do |k,v|
238
+ k.should == keys[index]
239
+ index += 1
240
+ end
241
+ end
242
+
243
+ end
244
+
245
+ it "reads a simple number correctly" do
246
+ @fb.update( {test_1: 20 } )
247
+ @fb.child( :test_1 ).read.to_i.should == 20
248
+ end
249
+
250
+ describe '#remove' do
251
+ before :each do
252
+ @fb.remove
253
+ end
254
+
255
+ it "removes data correctly" do
256
+ @fb.set( {fred: 10} )
257
+ @fb.child( :fred ).remove
258
+ lambda { @fb.child( :fred ).read }.should raise_error( /No data/ )
259
+ end
260
+ end
261
+
262
+ describe '#update' do
263
+ before :all do
264
+ @fb.remove
265
+ @fb.set( a:{b:1,c:2} )
266
+ @a_ref = @fb.child( :a )
267
+ end
268
+
269
+ describe 'oneshot' do
270
+ it "updates an integer correctly" do
271
+ @a_ref.update( c:5 )
272
+ @a_ref.child( :c ).read.should == 5
273
+ end
274
+
275
+ it "updates a float correctly" do
276
+ @a_ref.update( c:5.0 )
277
+ @a_ref.child( :c ).read.should == 5.0
278
+ end
279
+
280
+ it "updates a boolean correctly" do
281
+ @a_ref.update( c:true )
282
+ @a_ref.child( :c ).read.should be_true
283
+ end
284
+
285
+ it "updates a boolean correctly" do
286
+ @a_ref.update( c:true )
287
+ @a_ref.child( :c ).read.should be_true
288
+ end
289
+
290
+ it "updates an object correctly" do
291
+ @a_ref.update( c:{fred:'Hello', blee:'World'} )
292
+ @a_ref.child( :c ).read.should == {fred:'Hello', blee:'World'}
293
+ end
294
+
295
+ it "updates an array correctly" do
296
+ @a_ref.update( c:%w[Hello World] )
297
+ @a_ref.child( :c ).read.should == %w[Hello World]
298
+ end
299
+ end
300
+ end
301
+ end