wonkavision 0.5.11 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +3 -0
- data/lib/wonkavision.rb +28 -1
- data/lib/wonkavision/aggregation.rb +21 -0
- data/lib/wonkavision/event_coordinator.rb +19 -7
- data/lib/wonkavision/extensions/symbol.rb +55 -0
- data/lib/wonkavision/facts.rb +27 -0
- data/lib/wonkavision/local_job_queue.rb +28 -0
- data/lib/wonkavision/message_mapper.rb +2 -2
- data/lib/wonkavision/message_mapper/map.rb +60 -8
- data/lib/wonkavision/persistence/mongo.rb +95 -0
- data/lib/wonkavision/plugins.rb +2 -1
- data/lib/wonkavision/plugins/analytics/aggregation.rb +139 -0
- data/lib/wonkavision/plugins/analytics/aggregation/aggregation_spec.rb +53 -0
- data/lib/wonkavision/plugins/analytics/aggregation/attribute.rb +22 -0
- data/lib/wonkavision/plugins/analytics/aggregation/dimension.rb +64 -0
- data/lib/wonkavision/plugins/analytics/aggregation/measure.rb +240 -0
- data/lib/wonkavision/plugins/analytics/cellset.rb +171 -0
- data/lib/wonkavision/plugins/analytics/facts.rb +106 -0
- data/lib/wonkavision/plugins/analytics/handlers/apply_aggregation.rb +35 -0
- data/lib/wonkavision/plugins/analytics/handlers/split_by_aggregation.rb +60 -0
- data/lib/wonkavision/plugins/analytics/member_filter.rb +106 -0
- data/lib/wonkavision/plugins/analytics/mongo.rb +6 -0
- data/lib/wonkavision/plugins/analytics/persistence/hash_store.rb +59 -0
- data/lib/wonkavision/plugins/analytics/persistence/mongo_store.rb +85 -0
- data/lib/wonkavision/plugins/analytics/persistence/store.rb +105 -0
- data/lib/wonkavision/plugins/analytics/query.rb +76 -0
- data/lib/wonkavision/plugins/event_handling.rb +15 -3
- data/lib/wonkavision/version.rb +1 -1
- data/test/aggregation_spec_test.rb +99 -0
- data/test/aggregation_test.rb +170 -0
- data/test/analytics/test_aggregation.rb +78 -0
- data/test/apply_aggregation_test.rb +92 -0
- data/test/attribute_test.rb +26 -0
- data/test/cellset_test.rb +200 -0
- data/test/dimension_test.rb +186 -0
- data/test/facts_test.rb +146 -0
- data/test/hash_store_test.rb +112 -0
- data/test/log/test.log +96844 -0
- data/test/map_test.rb +48 -1
- data/test/measure_test.rb +146 -0
- data/test/member_filter_test.rb +143 -0
- data/test/mongo_store_test.rb +115 -0
- data/test/query_test.rb +106 -0
- data/test/split_by_aggregation_test.rb +114 -0
- data/test/store_test.rb +71 -0
- data/test/symbol_test.rb +62 -0
- data/test/test_activity_models.rb +1 -1
- data/test/test_aggregation.rb +42 -0
- data/test/test_data.tuples +100 -0
- data/test/test_helper.rb +7 -0
- metadata +57 -5
data/test/map_test.rb
CHANGED
@@ -112,7 +112,7 @@ class MapTest < ActiveSupport::TestCase
|
|
112
112
|
should "accept a time unmolested" do
|
113
113
|
time = Time.now
|
114
114
|
m = Wonkavision::MessageMapper::Map.new(:a=>time)
|
115
|
-
m.
|
115
|
+
m.time :a
|
116
116
|
assert_equal time, m.a
|
117
117
|
end
|
118
118
|
end
|
@@ -311,5 +311,52 @@ class MapTest < ActiveSupport::TestCase
|
|
311
311
|
assert_equal 4, m.new_collection[1].b
|
312
312
|
end
|
313
313
|
end
|
314
|
+
|
315
|
+
context "Map.duration" do
|
316
|
+
should "return nil if no :from or :to value is available" do
|
317
|
+
m = Wonkavision::MessageMapper::Map.new
|
318
|
+
m.duration :a_duration
|
319
|
+
assert_nil m.a_duration
|
320
|
+
end
|
321
|
+
should "return time from Time.now if only to is supplied" do
|
322
|
+
m = Wonkavision::MessageMapper::Map.new({ :a => "1/1/2001" })
|
323
|
+
m.time :a
|
324
|
+
m.duration :a_duration, :to => m.a
|
325
|
+
assert m.a_duration < 0
|
326
|
+
end
|
327
|
+
should "return time to Time.now if only from is supplied" do
|
328
|
+
m = Wonkavision::MessageMapper::Map.new({ :a=>"1/1/2001"})
|
329
|
+
m.time :a
|
330
|
+
m.duration :a_duration, :from => m.a
|
331
|
+
assert m.a_duration > 0
|
332
|
+
end
|
333
|
+
should "convert the duration to the desired time unit" do
|
334
|
+
m = Wonkavision::MessageMapper::Map.new
|
335
|
+
m.expects(:convert_seconds).with(1,:months)
|
336
|
+
m.time :a=>"1/1/2001 00:00:00"
|
337
|
+
m.time :b=>"1/1/2001 00:00:01"
|
338
|
+
m.duration :a_duration, :from=>m.a, :to=>m.b, :in=>:months
|
339
|
+
end
|
340
|
+
end
|
341
|
+
context "Map.convert_seconds" do
|
342
|
+
setup do
|
343
|
+
@m = Wonkavision::MessageMapper::Map.new
|
344
|
+
end
|
345
|
+
should "raise an exception for an invalid unit" do
|
346
|
+
assert_raise(RuntimeError) { @m.send(:convert_seconds,1,:wakka)}
|
347
|
+
end
|
348
|
+
should "should correctly calculate proper units" do
|
349
|
+
assert_equal 100, @m.send(:convert_seconds,100,:seconds)
|
350
|
+
assert_equal 1, @m.send(:convert_seconds,60,:minutes)
|
351
|
+
assert_equal 1, @m.send(:convert_seconds,60*60,:hours)
|
352
|
+
assert_equal 1, @m.send(:convert_seconds,60*60*24,:days)
|
353
|
+
assert_equal 1, @m.send(:convert_seconds,60*60*24*7,:weeks)
|
354
|
+
assert_equal 1, @m.send(:convert_seconds,60*60*24*30,:months)
|
355
|
+
assert_equal 1, @m.send(:convert_seconds,60*60*24*365,:years)
|
356
|
+
end
|
357
|
+
|
358
|
+
end
|
359
|
+
|
360
|
+
|
314
361
|
end
|
315
362
|
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class MeasureTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@stats = Wonkavision::Plugins::Aggregation::Measure.new(:log_buckets => 128)
|
7
|
+
|
8
|
+
@@DATA.each do |x|
|
9
|
+
@stats << x
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_stats_count
|
14
|
+
assert_equal @@DATA.length, @stats.count
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_stats_min_max
|
18
|
+
sorted_data = @@DATA.sort
|
19
|
+
|
20
|
+
assert_equal sorted_data[0], @stats.min
|
21
|
+
assert_equal sorted_data.last, @stats.max
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_stats_mean
|
25
|
+
sum = 0
|
26
|
+
@@DATA.each do |x|
|
27
|
+
sum += x
|
28
|
+
end
|
29
|
+
|
30
|
+
assert_equal sum.to_f/@@DATA.length.to_f, @stats.mean
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_bucket_counts
|
34
|
+
|
35
|
+
#Test each iterator
|
36
|
+
total_bucket_sum = 0
|
37
|
+
i = 0
|
38
|
+
@stats.each do |bucket, count|
|
39
|
+
assert_equal 2**i, bucket
|
40
|
+
|
41
|
+
total_bucket_sum += count
|
42
|
+
i += 1
|
43
|
+
end
|
44
|
+
|
45
|
+
assert_equal @@DATA.length, total_bucket_sum
|
46
|
+
|
47
|
+
#Test each_nonzero iterator
|
48
|
+
prev_bucket = 0
|
49
|
+
total_bucket_sum = 0
|
50
|
+
@stats.each_nonzero do |bucket, count|
|
51
|
+
assert bucket > prev_bucket
|
52
|
+
assert_not_equal count, 0
|
53
|
+
|
54
|
+
total_bucket_sum += count
|
55
|
+
end
|
56
|
+
|
57
|
+
assert_equal total_bucket_sum, @@DATA.length
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
#XXX: Update test_bucket_contents() if you muck with @@DATA
|
62
|
+
@@DATA = [ 1, 5, 4, 6, 1028, 1972, 16384, 16385, 16383]
|
63
|
+
def test_bucket_contents
|
64
|
+
#XXX: This is the only test so far that cares about the actual contents
|
65
|
+
# of @@DATA, so if you update that array ... update this method too
|
66
|
+
expected_buckets = [1, 4, 1024, 8192, 16384]
|
67
|
+
expected_counts = [1, 3, 2, 1, 2]
|
68
|
+
|
69
|
+
i = 0
|
70
|
+
@stats.each_nonzero do |bucket, count|
|
71
|
+
assert_equal expected_buckets[i], bucket
|
72
|
+
assert_equal expected_counts[i], count
|
73
|
+
# Increment for the next test
|
74
|
+
i += 1
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_outlier
|
79
|
+
assert_equal 0, @stats.outliers_low
|
80
|
+
assert_equal 0, @stats.outliers_high
|
81
|
+
|
82
|
+
@stats << -1
|
83
|
+
@stats << -2
|
84
|
+
@stats << 0
|
85
|
+
|
86
|
+
@stats << 2**128
|
87
|
+
|
88
|
+
# This should be the last value in the last bucket, but Ruby's native
|
89
|
+
# floats are not precise enough. Somewhere past 2^32 the log(x)/log(2)
|
90
|
+
# breaks down. So it shows up as 128 (outlier) instead of 127
|
91
|
+
#@stats << (2**128) - 1
|
92
|
+
|
93
|
+
assert_equal 3, @stats.outliers_low
|
94
|
+
assert_equal 1, @stats.outliers_high
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_std_dev
|
98
|
+
@stats.std_dev
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
class LinearHistogramTest < Test::Unit::TestCase
|
103
|
+
def setup
|
104
|
+
@stats = Wonkavision::Plugins::Aggregation::Measure.new(:low => 0, :high => 32768, :width => 1024)
|
105
|
+
|
106
|
+
@@DATA.each do |x|
|
107
|
+
@stats << x
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_validation
|
112
|
+
|
113
|
+
# Range cannot be 0
|
114
|
+
assert_raise(ArgumentError) {bad_stats = Wonkavision::Plugins::Aggregation::Measure.new(:low => 32,:high => 32, :width => 4)}
|
115
|
+
|
116
|
+
# Range cannot be negative
|
117
|
+
assert_raise(ArgumentError) {bad_stats = Wonkavision::Plugins::Aggregation::Measure.new(:low => 32, :high => 16, :width => 4)}
|
118
|
+
|
119
|
+
# Range cannot be < single bucket
|
120
|
+
assert_raise(ArgumentError) {bad_stats = Wonkavision::Plugins::Aggregation::Measure.new(:low => 16, :high => 32, :width => 17)}
|
121
|
+
|
122
|
+
# Range % width must equal 0 (for now)
|
123
|
+
assert_raise(ArgumentError) {bad_stats = Wonkavision::Plugins::Aggregation::Measure.new(:low => 1, :high => 16384, :width => 1024)}
|
124
|
+
end
|
125
|
+
|
126
|
+
#XXX: Update test_bucket_contents() if you muck with @@DATA
|
127
|
+
# 32768 is an outlier
|
128
|
+
@@DATA = [ 0, 1, 5, 4, 6, 1028, 1972, 16384, 16385, 16383, 32768]
|
129
|
+
def test_bucket_contents
|
130
|
+
#XXX: This is the only test so far that cares about the actual contents
|
131
|
+
# of @@DATA, so if you update that array ... update this method too
|
132
|
+
expected_buckets = [0, 1024, 15360, 16384]
|
133
|
+
expected_counts = [5, 2, 1, 2]
|
134
|
+
|
135
|
+
i = 0
|
136
|
+
@stats.each_nonzero do |bucket, count|
|
137
|
+
assert_equal expected_buckets[i], bucket
|
138
|
+
assert_equal expected_counts[i], count
|
139
|
+
# Increment for the next test
|
140
|
+
i += 1
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
|
146
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class MemberFilterTest < ActiveSupport::TestCase
|
4
|
+
context "MemberFilter" do
|
5
|
+
setup do
|
6
|
+
@dimension = Wonkavision::Analytics::MemberFilter.new(:a_dim, :member_type=>:dimension)
|
7
|
+
@measure = Wonkavision::Analytics::MemberFilter.new(:a_measure, :member_type=>:measure)
|
8
|
+
end
|
9
|
+
context "#attribute_name" do
|
10
|
+
should "default to key for dimension" do
|
11
|
+
assert_equal :key, @dimension.attribute_name
|
12
|
+
end
|
13
|
+
should "default to count for measure" do
|
14
|
+
assert_equal :count, @measure.attribute_name
|
15
|
+
end
|
16
|
+
end
|
17
|
+
context "#dimension?" do
|
18
|
+
should "be true for dimension" do
|
19
|
+
assert @dimension.dimension?
|
20
|
+
end
|
21
|
+
should "not be true for measure" do
|
22
|
+
assert !@measure.dimension?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
context "#measure?" do
|
26
|
+
should "be true for measure" do
|
27
|
+
assert @measure.measure?
|
28
|
+
end
|
29
|
+
should "not be true for dimension" do
|
30
|
+
assert !@dimension.measure?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
context "#operators" do
|
34
|
+
should "set the operator property appropriately" do
|
35
|
+
[:gt, :lt, :gte, :lte, :ne, :in, :nin].each do |op|
|
36
|
+
assert_equal op, @dimension.send(op).operator
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
context "#matches" do
|
43
|
+
setup do
|
44
|
+
@tuple = {
|
45
|
+
"measures" => { "a_measure" => { "sum" => 2.0, "count" => 5 } }
|
46
|
+
}
|
47
|
+
@aggregation = {}
|
48
|
+
@dimension = {}
|
49
|
+
@filter = Wonkavision::Analytics::MemberFilter.new(:a_measure, :member_type=>:measure,:value=>1)
|
50
|
+
end
|
51
|
+
should "return false for gt, lt, gte, lte if the data is nil" do
|
52
|
+
@tuple["measures"]["a_measure"]["count"] = nil
|
53
|
+
[:gt, :lt, :gte, :lte].each do |op|
|
54
|
+
@filter.send(op)
|
55
|
+
assert_equal false, @filter.matches(@aggregation, @tuple)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
should "evaluate gt, gte" do
|
59
|
+
[:gt, :gte].each do |op|
|
60
|
+
@filter.send(op,4)
|
61
|
+
assert @filter.matches(@aggregation, @tuple)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
should "evaluate lt, lte" do
|
65
|
+
[:lt, :lte].each do |op|
|
66
|
+
@filter.send(op,6)
|
67
|
+
assert @filter.matches(@aggregation, @tuple)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
should "evaluate in" do
|
71
|
+
@filter.in([4,5,6])
|
72
|
+
assert @filter.matches(@aggregation, @tuple)
|
73
|
+
end
|
74
|
+
should "evalute nin" do
|
75
|
+
@filter.nin([6,7,8])
|
76
|
+
assert @filter.matches(@aggregation, @tuple)
|
77
|
+
end
|
78
|
+
should "evaluate eq" do
|
79
|
+
@filter.eq(5)
|
80
|
+
assert @filter.matches(@aggregation, @tuple)
|
81
|
+
end
|
82
|
+
should "evaluate ne" do
|
83
|
+
@filter.ne(6)
|
84
|
+
assert @filter.matches(@aggregation, @tuple)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context "#extract_attribute_value_from_tuple" do
|
89
|
+
setup do
|
90
|
+
@tuple = {
|
91
|
+
"dimensions" => { "a_dimension" => { "akey" => "abc" } },
|
92
|
+
"measures" => { "a_measure" => { "sum" => 2.0, "count" => 5 } }
|
93
|
+
}
|
94
|
+
@aggregation = {}
|
95
|
+
@dimension = {}
|
96
|
+
end
|
97
|
+
context "for a dimension filter" do
|
98
|
+
setup do
|
99
|
+
@filter = Wonkavision::Analytics::MemberFilter.new(:a_dimension)
|
100
|
+
@aggregation.expects(:dimensions).returns( { :a_dimension => @dimension } )
|
101
|
+
end
|
102
|
+
should "extract a dimension value from a tuple message" do
|
103
|
+
@dimension.expects(:key).returns(:akey)
|
104
|
+
assert_equal "abc", @filter.send(:extract_attribute_value_from_tuple,@aggregation,@tuple)
|
105
|
+
end
|
106
|
+
should "extract a dimension value with a custom attribute" do
|
107
|
+
@filter.instance_variable_set("@attribute_name","akey")
|
108
|
+
assert_equal "abc", @filter.send(:extract_attribute_value_from_tuple,@aggregation,@tuple)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
context "for a measure filter" do
|
112
|
+
setup do
|
113
|
+
@filter = Wonkavision::Analytics::MemberFilter.new(:a_measure, :member_type=>:measure)
|
114
|
+
end
|
115
|
+
should "extract a measure value" do
|
116
|
+
assert_equal 5, @filter.send(:extract_attribute_value_from_tuple,@aggregation,@tuple)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context "#assert_operator_matches_value" do
|
122
|
+
should "raise an exception if inappropriately nil" do
|
123
|
+
filter = Wonkavision::Analytics::MemberFilter.new(:hi)
|
124
|
+
[:gt, :lt, :gte, :lte, :in, :nin].each do |op|
|
125
|
+
filter.send(op)
|
126
|
+
assert_raise(RuntimeError) { filter.send :assert_operator_matches_value }
|
127
|
+
end
|
128
|
+
end
|
129
|
+
should "raise an exception if 'in' and 'nin' are not given an array" do
|
130
|
+
filter = Wonkavision::Analytics::MemberFilter.new(:hi, :value=>:ho)
|
131
|
+
[:in,:nin].each do |op|
|
132
|
+
filter.send(op)
|
133
|
+
assert_raise(RuntimeError) { filter.send :assert_operator_matches_value }
|
134
|
+
end
|
135
|
+
end
|
136
|
+
should "not raise an exception otherwise" do
|
137
|
+
filter = Wonkavision::Analytics::MemberFilter.new(:hi, :operator=>:gt, :value=>1)
|
138
|
+
filter.send(:assert_operator_matches_value)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class MongoStoreTest < ActiveSupport::TestCase
|
4
|
+
MongoStore = Wonkavision::Analytics::Persistence::MongoStore
|
5
|
+
|
6
|
+
context "MongoStore" do
|
7
|
+
setup do
|
8
|
+
@facts = Class.new
|
9
|
+
@facts.class_eval do
|
10
|
+
def self.name; "TestFacts"; end
|
11
|
+
include Wonkavision::Facts
|
12
|
+
record_id :tada
|
13
|
+
end
|
14
|
+
@store = MongoStore.new(@facts)
|
15
|
+
end
|
16
|
+
|
17
|
+
should "provide access to the underlying facts specification" do
|
18
|
+
assert_equal @facts, @store.owner
|
19
|
+
end
|
20
|
+
|
21
|
+
should "create a collection name based on the facts class name" do
|
22
|
+
assert_equal "wv.test_facts.facts", @store.facts_collection_name
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
context "Facts persistence" do
|
27
|
+
setup do
|
28
|
+
@doc_id = 123
|
29
|
+
@store.facts_collection.insert( {"_id" => @doc_id,
|
30
|
+
"tada" => @doc_id,
|
31
|
+
"todo" => "hoho",
|
32
|
+
"canttouchthis"=>"yo"} )
|
33
|
+
end
|
34
|
+
context "#update_facts_record" do
|
35
|
+
setup do
|
36
|
+
@prev,@cur = @store.send( :update_facts_record,
|
37
|
+
@doc_id, "tada"=>@doc_id, "todo"=>"heehee", "more"=>"4me?" )
|
38
|
+
end
|
39
|
+
should "return the previous version of the facts record" do
|
40
|
+
assert_equal( { "tada" => @doc_id, "todo" => "hoho", "canttouchthis"=>"yo"}, @prev )
|
41
|
+
end
|
42
|
+
should "return the updated version of the facts record" do
|
43
|
+
assert_equal({ "tada" => @doc_id, "todo" => "heehee", "canttouchthis"=>"yo","more"=>"4me?"},
|
44
|
+
@cur)
|
45
|
+
end
|
46
|
+
should "contain the upated version in the storage" do
|
47
|
+
assert_equal({ "_id"=>@doc_id, "tada" => @doc_id, "todo" => "heehee", "canttouchthis"=>"yo","more"=>"4me?"},
|
48
|
+
@store[@doc_id])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
context "#insert_facts_record" do
|
52
|
+
setup do
|
53
|
+
@cur = @store.send(:insert_facts_record,@doc_id,{ "tada"=>@doc_id,"i is"=>"new"})
|
54
|
+
end
|
55
|
+
should "return the current version of the facts record" do
|
56
|
+
assert_equal( { "tada"=>@doc_id,"i is"=>"new"}, @cur )
|
57
|
+
end
|
58
|
+
should "add the record to the storage" do
|
59
|
+
assert_equal @cur.merge("_id"=>@doc_id), @store[@doc_id]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
context "#delete_facts_record" do
|
63
|
+
setup do
|
64
|
+
@prev = @store.send(:delete_facts_record,@doc_id,{"tada"=>@doc_id})
|
65
|
+
end
|
66
|
+
should "return the previous version of the facts record" do
|
67
|
+
assert_equal( { "tada" => @doc_id, "todo" => "hoho", "canttouchthis"=>"yo"}, @prev )
|
68
|
+
end
|
69
|
+
should "remove the facts record from the storage" do
|
70
|
+
assert_nil @store[@doc_id]
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
context "Aggregations persistence" do
|
77
|
+
setup do
|
78
|
+
@tuple = { :dimension_keys=>[1,2,3],
|
79
|
+
:dimension_names=>[:a,:b,:c],
|
80
|
+
:dimensions=>{"dims"=>"doms"},
|
81
|
+
:measures=>{ "measures.one"=>1} }
|
82
|
+
end
|
83
|
+
context "#update_tuple" do
|
84
|
+
should "insert a new tuple if not present" do
|
85
|
+
@store.send(:update_tuple, @tuple)
|
86
|
+
added = @store.aggregations_collection.find({ :dimension_names=>[:a,:b,:c] }).to_a[0]
|
87
|
+
added.delete("_id") #isn't present on the original, we know its there
|
88
|
+
assert_equal @tuple.merge({:measures=>{ "one" => 1}}).stringify_keys!, added
|
89
|
+
end
|
90
|
+
end
|
91
|
+
context "#append_filters" do
|
92
|
+
setup do
|
93
|
+
@dim_filter = Wonkavision::Analytics::MemberFilter.new("tada",:value=>[1,2,3])
|
94
|
+
@measure_filter = Wonkavision::Analytics::MemberFilter.new("haha",
|
95
|
+
:member_type=>:measure,
|
96
|
+
:op=>:gte,
|
97
|
+
:value=>100.0)
|
98
|
+
@criteria = {}
|
99
|
+
@dim_filter.expects(:attribute_key).returns "tada_key"
|
100
|
+
@store.send(:append_filters,@criteria,[@dim_filter,@measure_filter])
|
101
|
+
end
|
102
|
+
should "prepare the dimension filter for mongodb" do
|
103
|
+
assert_equal( [1,2,3], @criteria["dimensions.tada.tada_key"] )
|
104
|
+
end
|
105
|
+
should "prepare the measure filter for mongodb" do
|
106
|
+
assert_equal( { "$gte" => 100.0 }, @criteria["measures.haha.count"] )
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|