wonkavision 0.5.11 → 0.6.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.
- 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
|