von 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,53 @@
1
+ require 'test_helper'
2
+
3
+ describe Von::Counters::Best do
4
+ BestCounter = Von::Counters::Best
5
+
6
+ before :each do
7
+ Timecop.freeze(Time.local(2013, 01, 01, 06))
8
+ Von.config.init!
9
+ @redis = Redis.new
10
+ @redis.flushall
11
+ end
12
+
13
+ it "increments the best counter for a period" do
14
+ counter = BestCounter.new('foo', [ Von::Period.new(:day) ])
15
+
16
+ counter.increment
17
+
18
+ Timecop.freeze(Time.local(2013, 01, 02))
19
+ 4.times { counter.increment }
20
+ Timecop.freeze(Time.local(2013, 01, 03))
21
+ 3.times { counter.increment }
22
+
23
+ @redis.hget('von:counters:bests:foo:day:current', 'timestamp').must_equal '2013-01-03'
24
+ @redis.hget('von:counters:bests:foo:day:current', 'total').must_equal '3'
25
+ @redis.hget('von:counters:bests:foo:day:best', 'timestamp').must_equal '2013-01-02'
26
+ @redis.hget('von:counters:bests:foo:day:best', 'total').must_equal '4'
27
+ end
28
+
29
+ it "increments the best counter for multiple periods" do
30
+ counter = BestCounter.new('foo', [
31
+ Von::Period.new(:minute),
32
+ Von::Period.new(:week),
33
+ ])
34
+
35
+ counter.increment
36
+
37
+ Timecop.freeze(Time.local(2013, 01, 13, 06, 05))
38
+ 4.times { counter.increment }
39
+ Timecop.freeze(Time.local(2013, 01, 20, 06, 10))
40
+ 3.times { counter.increment }
41
+
42
+ @redis.hget('von:counters:bests:foo:minute:current', 'timestamp').must_equal '2013-01-20 06:10'
43
+ @redis.hget('von:counters:bests:foo:minute:current', 'total').must_equal '3'
44
+ @redis.hget('von:counters:bests:foo:minute:best', 'timestamp').must_equal '2013-01-13 06:05'
45
+ @redis.hget('von:counters:bests:foo:minute:best', 'total').must_equal '4'
46
+
47
+ @redis.hget('von:counters:bests:foo:week:current', 'timestamp').must_equal '2013-01-14'
48
+ @redis.hget('von:counters:bests:foo:week:current', 'total').must_equal '3'
49
+ @redis.hget('von:counters:bests:foo:week:best', 'timestamp').must_equal '2013-01-07'
50
+ @redis.hget('von:counters:bests:foo:week:best', 'total').must_equal '4'
51
+ end
52
+
53
+ end
@@ -0,0 +1,55 @@
1
+ require 'test_helper'
2
+
3
+ describe Von::Counters::Current do
4
+ CurrentCounter = Von::Counters::Current
5
+
6
+ before :each do
7
+ Timecop.freeze(Time.local(2013, 01, 01, 06))
8
+ Von.config.init!
9
+ @redis = Redis.new
10
+ @redis.flushall
11
+ end
12
+
13
+ it "increments the current counter for a period" do
14
+ counter = CurrentCounter.new('foo', [ Von::Period.new(:day) ])
15
+
16
+ 4.times { counter.increment }
17
+ Timecop.freeze(Time.local(2013, 01, 02))
18
+ 3.times { counter.increment }
19
+
20
+ @redis.hget('von:counters:currents:foo:day', 'timestamp').must_equal '2013-01-02'
21
+ @redis.hget('von:counters:currents:foo:day', 'total').must_equal '3'
22
+ end
23
+
24
+ it "increments the current counter for multiple periods" do
25
+ counter = CurrentCounter.new('foo', [
26
+ Von::Period.new(:minute),
27
+ Von::Period.new(:week),
28
+ ])
29
+
30
+ 4.times { counter.increment }
31
+ Timecop.freeze(Time.local(2013, 01, 20, 06, 10))
32
+ 3.times { counter.increment }
33
+
34
+ @redis.hget('von:counters:currents:foo:minute', 'timestamp').must_equal '2013-01-20 06:10'
35
+ @redis.hget('von:counters:currents:foo:minute', 'total').must_equal '3'
36
+
37
+ @redis.hget('von:counters:currents:foo:week', 'timestamp').must_equal '2013-01-14'
38
+ @redis.hget('von:counters:currents:foo:week', 'total').must_equal '3'
39
+ end
40
+
41
+ it "counts acurrent counter for a period" do
42
+ counter = CurrentCounter.new('foo', [
43
+ Von::Period.new(:minute),
44
+ Von::Period.new(:day),
45
+ ])
46
+
47
+ 4.times { counter.increment }
48
+ Timecop.freeze(Time.local(2013, 01, 01, 06, 10))
49
+ 3.times { counter.increment }
50
+
51
+ counter.count(:minute).must_equal 3
52
+ counter.count(:day).must_equal 7
53
+ end
54
+
55
+ end
@@ -0,0 +1,78 @@
1
+ require 'test_helper'
2
+
3
+ describe Von::Counters::Period do
4
+ PeriodCounter = Von::Counters::Period
5
+
6
+ before :each do
7
+ Timecop.freeze(Time.local(2013, 01, 01, 01, 01))
8
+ Von.config.init!
9
+ @redis = Redis.new
10
+ @redis.flushall
11
+ end
12
+
13
+ it "increments a month counter" do
14
+ counter = PeriodCounter.new('foo', [
15
+ Von::Period.new(:monthly, 1)
16
+ ])
17
+
18
+ counter.increment
19
+ counter.increment
20
+
21
+ @redis.hget('von:counters:foo:month', '2013-01').must_equal '2'
22
+ @redis.lrange('von:lists:foo:month', 0, -1).size.must_equal 1
23
+ @redis.lrange('von:lists:foo:month', 0, -1).first.must_equal '2013-01'
24
+ end
25
+
26
+ it 'increments a minute counter' do
27
+ counter = PeriodCounter.new('foo', [
28
+ Von::Period.new(:minutely, 60)
29
+ ])
30
+
31
+ counter.increment
32
+ counter.increment
33
+
34
+ @redis.hget('von:counters:foo:minute', '2013-01-01 01:01').must_equal '2'
35
+ @redis.lrange('von:lists:foo:minute', 0, -1).size.must_equal 1
36
+ @redis.lrange('von:lists:foo:minute', 0, -1).first.must_equal '2013-01-01 01:01'
37
+ end
38
+
39
+ it "expires counters past the limit" do
40
+ counter = PeriodCounter.new('foo', [
41
+ Von::Period.new(:monthly, 1)
42
+ ])
43
+
44
+ counter.increment
45
+ Timecop.freeze(Time.local(2013, 02))
46
+ counter.increment
47
+
48
+ @redis.hget('von:counters:foo:month', '2013-02').must_equal '1'
49
+ @redis.lrange('von:lists:foo:month', 0, -1).size.must_equal 1
50
+ @redis.lrange('von:lists:foo:month', 0, -1).first.must_equal '2013-02'
51
+ end
52
+
53
+
54
+ it "gets a count for a time period and 0s missing entries" do
55
+ counter = PeriodCounter.new('foo', [
56
+ Von::Period.new(:monthly, 1),
57
+ Von::Period.new(:hourly, 6)
58
+ ])
59
+
60
+ counter.increment
61
+ counter.increment
62
+ Timecop.freeze(Time.local(2013, 02, 01, 7))
63
+ counter.increment
64
+ Timecop.freeze(Time.local(2013, 02, 01, 9))
65
+ counter.increment
66
+
67
+ counter.count(:month).must_equal [{:timestamp => "2013-02", :count => 2}]
68
+ counter.count(:hour).must_equal [
69
+ { :timestamp => "2013-02-01 04:00", :count => 0 },
70
+ { :timestamp => "2013-02-01 05:00", :count => 0 },
71
+ { :timestamp => "2013-02-01 06:00", :count => 0 },
72
+ { :timestamp => "2013-02-01 07:00", :count => 1 },
73
+ { :timestamp => "2013-02-01 08:00", :count => 0 },
74
+ { :timestamp => "2013-02-01 09:00", :count => 1 }
75
+ ]
76
+ end
77
+
78
+ end
@@ -0,0 +1,33 @@
1
+ require 'test_helper'
2
+
3
+ describe Von::Counters::Total do
4
+ TotalCounter = Von::Counters::Total
5
+
6
+ before :each do
7
+ Timecop.freeze(Time.local(2013, 01, 01, 01, 01))
8
+ Von.config.init!
9
+ @redis = Redis.new
10
+ @redis.flushall
11
+ end
12
+
13
+ it "increments the total counter if given a single key" do
14
+ counter = TotalCounter.new('foo')
15
+
16
+ counter.increment
17
+ @redis.hget('von:counters:foo', 'total').must_equal '1'
18
+
19
+ counter.increment
20
+ @redis.hget('von:counters:foo', 'total').must_equal '2'
21
+ end
22
+
23
+ it "gets a total count for a counter" do
24
+ counter = TotalCounter.new('foo')
25
+ counter.increment
26
+ counter.increment
27
+ counter.increment
28
+
29
+ counter.count.must_equal 3
30
+ end
31
+
32
+
33
+ end
@@ -1,65 +1,87 @@
1
+ require 'test_helper'
2
+
1
3
  describe Von::Period do
2
4
  Period = Von::Period
3
5
 
4
6
  before :each do
5
7
  @config = Von::Config
6
8
  @config.init!
9
+ Timecop.freeze(Time.local(2013, 01, 02, 03, 04))
7
10
  end
8
11
 
9
- it "intiializes given a counter, period, and length" do
10
- period = Period.new('foo', :monthly, 6)
11
- period.counter_key.must_equal 'foo'
12
- period.length.must_equal 6
12
+ it "intiializes given a period" do
13
+ period = Period.new(:monthly)
14
+ period.name.must_equal :monthly
15
+ period.length.must_be_nil
13
16
  period.format.must_equal '%Y-%m'
14
17
  end
15
18
 
16
- it "checks if the period is an hourly period" do
17
- Period.new('foo', :hourly, 6).must_be :hours?
18
- Period.new('foo', :daily, 6).wont_be :hours?
19
- Period.new('foo', :weekly, 6).wont_be :hours?
20
- Period.new('foo', :monthly, 6).wont_be :hours?
21
- Period.new('foo', :yearly, 6).wont_be :hours?
19
+ it "intiializes given a time unit" do
20
+ period = Period.new(:month)
21
+ period.name.must_equal :monthly
22
+ period.length.must_be_nil
23
+ period.format.must_equal '%Y-%m'
22
24
  end
23
25
 
24
- it "knows what time unit it is" do
25
- Period.new('foo', :hourly, 6).time_unit.must_equal :hour
26
- Period.new('foo', :daily, 6).time_unit.must_equal :day
27
- Period.new('foo', :weekly, 6).time_unit.must_equal :week
28
- Period.new('foo', :monthly, 6).time_unit.must_equal :month
29
- Period.new('foo', :yearly, 6).time_unit.must_equal :year
26
+ it "intiializes given a period and length" do
27
+ period = Period.new(:monthly, 3)
28
+ period.name.must_equal :monthly
29
+ period.length.must_equal 3
30
+ period.format.must_equal '%Y-%m'
30
31
  end
31
32
 
32
- it "pulls a time format from config options" do
33
- Period.new('foo', :hourly, 6).format.must_equal Von.config.hourly_format
34
- Period.new('foo', :daily, 6).format.must_equal Von.config.daily_format
35
- Period.new('foo', :weekly, 6).format.must_equal Von.config.weekly_format
36
- Period.new('foo', :monthly, 6).format.must_equal Von.config.monthly_format
37
- Period.new('foo', :yearly, 6).format.must_equal Von.config.yearly_format
33
+ it "generates a timestamp for now" do
34
+ Period.new(:minutely).timestamp.must_equal '2013-01-02 03:04'
35
+ Period.new(:hourly).timestamp.must_equal '2013-01-02 03:00'
36
+ Period.new(:daily).timestamp.must_equal '2013-01-02'
37
+ Period.new(:weekly).timestamp.must_equal '2012-12-31'
38
+ Period.new(:monthly).timestamp.must_equal '2013-01'
39
+ Period.new(:yearly).timestamp.must_equal '2013'
38
40
  end
39
41
 
40
- it "builds a redis hash key string" do
41
- field = 'foo'
42
- period = :hourly
43
- period_obj = Period.new(field, period, 6)
42
+ it "knows the prev time period" do
43
+ Period.new(:minutely).prev.must_equal '2013-01-02 03:03'
44
+ Period.new(:hourly).prev.must_equal '2013-01-02 02:00'
45
+ Period.new(:daily).prev.must_equal '2013-01-01'
46
+ Period.new(:weekly).prev.must_equal '2012-12-24'
47
+ Period.new(:monthly).prev.must_equal '2012-12'
48
+ Period.new(:yearly).prev.must_equal '2012'
49
+ end
44
50
 
45
- period_obj.hash_key.must_equal "#{@config.namespace}:counters:#{field}:#{period}"
51
+ it "checks if the period is an hourly period" do
52
+ Period.new(:minutely).wont_be :hours?
53
+ Period.new(:hourly).must_be :hours?
54
+ Period.new(:daily).wont_be :hours?
55
+ Period.new(:weekly).wont_be :hours?
56
+ Period.new(:monthly).wont_be :hours?
57
+ Period.new(:yearly).wont_be :hours?
46
58
  end
47
59
 
48
- it "builds a redis list key string" do
49
- field = 'foo'
50
- period = :hourly
51
- period_obj = Period.new(field, period, 6)
60
+ it "checks if the period is an hourly period" do
61
+ Period.new(:minutely).must_be :minutes?
62
+ Period.new(:hourly).wont_be :minutes?
63
+ Period.new(:daily).wont_be :minutes?
64
+ Period.new(:weekly).wont_be :minutes?
65
+ Period.new(:monthly).wont_be :minutes?
66
+ Period.new(:yearly).wont_be :minutes?
67
+ end
52
68
 
53
- period_obj.list_key.must_equal "#{@config.namespace}:lists:#{field}:#{period}"
69
+ it "knows what time unit it is" do
70
+ Period.new(:minutely).time_unit.must_equal :minute
71
+ Period.new(:hourly).time_unit.must_equal :hour
72
+ Period.new(:daily).time_unit.must_equal :day
73
+ Period.new(:weekly).time_unit.must_equal :week
74
+ Period.new(:monthly).time_unit.must_equal :month
75
+ Period.new(:yearly).time_unit.must_equal :year
54
76
  end
55
77
 
56
- it "builds a redis field for the given period and current time" do
57
- Timecop.freeze(Time.local(2013, 02, 01, 05))
58
- Period.new('foo', :hourly, 6).field.must_equal '2013-02-01 05:00'
59
- Period.new('foo', :daily, 6).field.must_equal '2013-02-01'
60
- Period.new('foo', :weekly, 6).field.must_equal '2013-02-01'
61
- Period.new('foo', :monthly, 6).field.must_equal '2013-02'
62
- Period.new('foo', :yearly, 6).field.must_equal '2013'
78
+ it "gets a time format from config" do
79
+ Period.new(:minutely).format.must_equal Von.config.minutely_format
80
+ Period.new(:hourly).format.must_equal Von.config.hourly_format
81
+ Period.new(:daily).format.must_equal Von.config.daily_format
82
+ Period.new(:weekly).format.must_equal Von.config.weekly_format
83
+ Period.new(:monthly).format.must_equal Von.config.monthly_format
84
+ Period.new(:yearly).format.must_equal Von.config.yearly_format
63
85
  end
64
86
 
65
- end
87
+ end
@@ -6,68 +6,8 @@ Bundler.setup
6
6
 
7
7
  require 'minitest/autorun'
8
8
  require 'minitest/pride'
9
+ require 'fakeredis'
9
10
  require 'mocha'
10
11
  require 'timecop'
11
12
 
12
- require 'von'
13
-
14
- module Von
15
- class TestConnection
16
- attr_reader :store
17
-
18
- def initialize
19
- @store = {}
20
- end
21
-
22
- def hincrby(hash, key, counter)
23
- @store[hash] ||= {}
24
-
25
- if @store[hash].has_key?(key)
26
- @store[hash][key] += counter
27
- else
28
- @store[hash][key] = counter
29
- end
30
-
31
- @store[hash][key]
32
- end
33
-
34
- def hget(hash, key)
35
- @store[hash][key]
36
- end
37
-
38
- def hgetall(hash)
39
- @store.fetch(hash, {})
40
- end
41
-
42
- def hdel(hash, key)
43
- @store[hash].delete(key)
44
- end
45
-
46
- def rpush(list, member)
47
- @store[list] ||= []
48
- @store[list] << member
49
- end
50
-
51
- def lpop(list)
52
- @store[list].shift
53
- end
54
-
55
- def lrange(list, start, stop)
56
- @store[list] ||= []
57
- @store[list][start..stop]
58
- end
59
-
60
- def llen(list)
61
- @store[list].length
62
- end
63
-
64
- end
65
- end
66
-
67
- module MiniTest::Expectations
68
- def mock_connection!
69
- connection = Von::TestConnection.new
70
- @store = connection.store
71
- Von.expects(:connection).returns(connection).at_least_once
72
- end
73
- end
13
+ require 'von'
@@ -3,20 +3,42 @@ require 'test_helper'
3
3
  describe Von do
4
4
 
5
5
  before :each do
6
+ Timecop.freeze(Time.local(2013, 01, 01, 01, 01))
6
7
  Von.config.init!
8
+ @redis = Redis.new
9
+ @redis.flushall
7
10
  end
8
11
 
9
12
  it "increments a counter and counts it" do
10
- mock_connection!
13
+ 3.times { Von.increment('foo') }
14
+ Von.count('foo').total.must_equal 3
15
+ end
16
+
17
+ it "increments a counter and parent counters and counts them" do
18
+ 3.times { Von.increment('foo:bar') }
19
+ Von.count('foo').total.must_equal 3
20
+ Von.count('foo:bar').total.must_equal 3
21
+ end
22
+
23
+ it "increments period/best counters and counts them" do
24
+ Von.configure do |config|
25
+ config.counter 'foo', :monthly => 2, :best => :day
26
+ end
11
27
 
12
28
  Von.increment('foo')
29
+ Timecop.freeze(Time.local(2013, 02, 03))
13
30
  Von.increment('foo')
14
- Von.count('foo').must_equal 2
31
+ Von.increment('foo')
32
+ Timecop.freeze(Time.local(2013, 03, 04))
33
+ Von.increment('foo')
34
+
35
+ Von.count('foo').best(:day).must_equal({:timestamp => "2013-02-03", :count => 2})
36
+ Von.count('foo').per(:month).must_equal [{:timestamp => "2013-02", :count => 2}, {:timestamp => "2013-03", :count => 1}]
15
37
  end
16
38
 
17
39
  it "raises a Redis connection errors if raise_connection_errors is true" do
18
40
  Von.config.raise_connection_errors = true
19
- Redis.expects(:new).raises(Redis::CannotConnectError)
41
+ Von.expects(:increment).raises(Redis::CannotConnectError)
20
42
 
21
43
  lambda { Von.increment('foo') }.must_raise Redis::CannotConnectError
22
44
  end