Clean up whitespace

This commit is contained in:
2012-04-17 13:03:38 +01:00
parent 4d5998af91
commit 7b14b9b5ab
43 changed files with 594 additions and 607 deletions

View File

@@ -61,7 +61,7 @@ Store page view on product #44 from Chrome 11:
```ruby
ViewStats.store('views/product/44', {'count/chrome/11' => 1})
```
Fetch product #44 stats:
```ruby
@@ -184,7 +184,7 @@ ViewStats.store('views/product/44', {'count/chrome/11' => 1})
```ruby
{ 'count' => 1, 'count/chrome' => 1, 'count/chrome/11' => 1 }
```
...to all 12 of these Redis hash keys...
ViewStats/views:2011
@@ -237,7 +237,7 @@ Buffering tries to fold together multiple `store` calls into as few as possible
## Note on Patches/Pull Requests ##
* Fork the project.
* Make your feature addition or bug fix.
* Add tests for it. This is important so I don't break it in a

View File

@@ -39,58 +39,58 @@ require 'redistat/core_ext'
module Redistat
KEY_NEXT_ID = ".next_id"
KEY_EVENT = ".event:"
KEY_LABELS = "Redistat.labels:" # used for reverse label hash lookup
KEY_EVENT_IDS = ".event_ids"
LABEL_INDEX = ".label_index:"
GROUP_SEPARATOR = "/"
class InvalidOptions < ArgumentError; end
class RedisServerIsTooOld < Exception; end
class << self
def buffer
Buffer.instance
end
def buffer_size
buffer.size
end
def buffer_size=(size)
buffer.size = size
end
def thread_safe
Synchronize.thread_safe
end
def thread_safe=(value)
Synchronize.thread_safe = value
end
def connection(ref = nil)
Connection.get(ref)
end
alias :redis :connection
def connection=(connection)
Connection.add(connection)
end
alias :redis= :connection=
def connect(options)
Connection.create(options)
end
def flush
puts "WARNING: Redistat.flush is deprecated. Use Redistat.redis.flushdb instead."
connection.flushdb
end
end
end

View File

@@ -3,33 +3,33 @@ require 'redistat/core_ext/hash'
module Redistat
class Buffer
include Synchronize
def self.instance
@instance ||= self.new
end
def size
synchronize do
@size ||= 0
end
end
def size=(value)
synchronize do
@size = value
end
end
def count
@count ||= 0
end
def store(key, stats, depth_limit, opts)
return false unless should_buffer?
to_flush = {}
buffkey = buffer_key(key, opts)
synchronize do
if !queue.has_key?(buffkey)
queue[buffkey] = { :key => key,
@@ -37,19 +37,19 @@ module Redistat
:depth_limit => depth_limit,
:opts => opts }
end
queue[buffkey][:stats].merge_and_incr!(stats)
incr_count
# return items to be flushed if buffer size limit has been reached
to_flush = reset_queue
end
# flush any data that's been cleared from the queue
flush_data(to_flush)
true
end
def flush(force = false)
to_flush = {}
synchronize do
@@ -57,28 +57,28 @@ module Redistat
end
flush_data(to_flush)
end
private
# should always be called from within a synchronize block
def incr_count
@count ||= 0
@count += 1
end
def queue
@queue ||= {}
end
def should_buffer?
size > 1 # buffer size of 1 would be equal to not using buffer
end
# should always be called from within a synchronize block
def should_flush?
(!queue.blank? && count >= size)
end
# returns items to be flushed if buffer size limit has been reached
# should always be called from within a synchronize block
def reset_queue(force = false)
@@ -88,13 +88,13 @@ module Redistat
@count = 0
data
end
def flush_data(buffer_data)
buffer_data.each do |k, item|
Summary.update(item[:key], item[:stats], item[:depth_limit], item[:opts])
end
end
def buffer_key(key, opts)
# depth_limit is not needed as it's evident in key.to_s
opts_index = Summary.default_options.keys.sort { |a,b| a.to_s <=> b.to_s }.map do |k|
@@ -102,6 +102,6 @@ module Redistat
end
"#{key.to_s}:#{opts_index.join(':')}"
end
end
end

View File

@@ -1,20 +1,20 @@
module Redistat
class Collection < ::Array
attr_accessor :from
attr_accessor :till
attr_accessor :depth
attr_accessor :total
def initialize(options = {})
@from = options[:from] ||= nil
@till = options[:till] ||= nil
@depth = options[:depth] ||= nil
end
def total
@total ||= {}
end
end
end
end

View File

@@ -2,22 +2,22 @@ require 'monitor'
module Redistat
module Connection
REQUIRED_SERVER_VERSION = "1.3.10"
# TODO: Create a ConnectionPool instance object using Sychronize mixin to replace Connection class
class << self
# TODO: clean/remove all ref-less connections
def get(ref = nil)
ref ||= :default
synchronize do
connections[references[ref]] || create
end
end
def add(conn, ref = nil)
ref ||= :default
synchronize do
@@ -26,7 +26,7 @@ module Redistat
connections[conn.client.id] = conn
end
end
def create(options = {})
synchronize do
options = options.clone
@@ -37,39 +37,39 @@ module Redistat
conn
end
end
def connections
@connections ||= {}
end
def references
@references ||= {}
end
private
def monitor
@monitor ||= Monitor.new
end
def synchronize(&block)
monitor.synchronize(&block)
end
def connection(options)
check_redis_version(Redis.new(options))
end
def connection_id(options = {})
options = options.reverse_merge(default_options)
"redis://#{options[:host]}:#{options[:port]}/#{options[:db]}"
end
def check_redis_version(conn)
raise RedisServerIsTooOld if conn.info["redis_version"] < REQUIRED_SERVER_VERSION
conn
end
def default_options
{
:host => '127.0.0.1',
@@ -78,7 +78,7 @@ module Redistat
:timeout => 5
}
end
end
end
end
end

View File

@@ -2,4 +2,4 @@ require 'redistat/core_ext/bignum'
require 'redistat/core_ext/date'
require 'redistat/core_ext/fixnum'
require 'redistat/core_ext/hash'
require 'redistat/core_ext/time'
require 'redistat/core_ext/time'

View File

@@ -1,8 +1,8 @@
class Bignum
include Redistat::DateHelper
def to_time
Time.at(self)
end
end

View File

@@ -1,8 +1,8 @@
class Date
include Redistat::DateHelper
def to_time
Time.parse(self.to_s)
end
end

View File

@@ -1,8 +1,8 @@
class Fixnum
include Redistat::DateHelper
def to_time
Time.at(self)
end
end

View File

@@ -1,9 +1,9 @@
class Hash
def merge_and_incr(hash)
self.clone.merge_and_incr!(hash)
end
def merge_and_incr!(hash)
raise ArgumentError unless hash.is_a?(Hash)
hash.each do |key, value|
@@ -11,7 +11,7 @@ class Hash
end
self
end
def set_or_incr(key, value)
return false unless value.is_a?(Numeric)
self[key] = 0 unless self.has_key?(key)
@@ -19,5 +19,5 @@ class Hash
self[key] += value
true
end
end

View File

@@ -1,6 +1,6 @@
module Redistat
class Date
attr_accessor :year
attr_accessor :month
attr_accessor :day
@@ -9,9 +9,9 @@ module Redistat
attr_accessor :sec
attr_accessor :usec
attr_accessor :depth
DEPTHS = [:year, :month, :day, :hour, :min, :sec, :usec]
def initialize(input, depth = nil)
@depth = depth
if input.is_a?(::Time)
@@ -26,12 +26,12 @@ module Redistat
from_integer(input)
end
end
def to_t
::Time.local(@year, @month, @day, @hour, @min, @sec, @usec)
end
alias :to_time :to_t
def to_d
::Date.civil(@year, @month, @day)
end
@@ -41,7 +41,7 @@ module Redistat
to_time.to_i
end
alias :to_integer :to_i
def to_s(depth = nil)
depth ||= @depth ||= :sec
output = ""
@@ -57,9 +57,9 @@ module Redistat
output
end
alias :to_string :to_s
private
def from_time(input)
DEPTHS.each do |k|
send("#{k}=", input.send(k))
@@ -74,15 +74,15 @@ module Redistat
send("#{k}=", 0)
end
end
def from_integer(input)
from_time(::Time.at(input))
end
def from_string(input)
input += "19700101000000"[input.size..-1] if input =~ /^\d\d\d[\d]+$/i
from_time(::Time.parse(input))
end
end
end

View File

@@ -2,13 +2,13 @@ module Redistat
class Event
include Database
include Options
attr_reader :id
attr_reader :key
attr_accessor :stats
attr_accessor :meta
def default_options
{ :depth => :hour,
:store_event => false,
@@ -16,7 +16,7 @@ module Redistat
:enable_grouping => true,
:label_indexing => true }
end
def initialize(scope, label = nil, date = nil, stats = {}, opts = {}, meta = {}, is_new = true)
parse_options(opts)
@key = Key.new(scope, label, date, @options)
@@ -24,35 +24,35 @@ module Redistat
@meta = meta ||= {}
@new = is_new
end
def new?
@new
end
def date
@key.date
end
def date=(input)
@key.date = input
end
def scope
@key.scope
end
def scope=(input)
@key.scope = input
end
def label
@key.label
end
def label_hash
@key.label_hash
end
def label=(input)
@key.label = input
end
@@ -60,7 +60,7 @@ module Redistat
def next_id
db.incr("#{self.scope}#{KEY_NEXT_ID}")
end
def save
return false if !self.new?
Summary.update_all(@key, @stats, depth_limit, @options)
@@ -78,21 +78,21 @@ module Redistat
@new = false
self
end
def depth_limit
@options[:depth] ||= @key.depth
end
def self.create(*args)
self.new(*args).save
end
def self.find(scope, id)
event = db.hgetall "#{scope}#{KEY_EVENT}#{id}"
return nil if event.size == 0
self.new( event["scope"], event["label"], event["date"], JSON.parse(event["stats"]),
JSON.parse(event["options"]), JSON.parse(event["meta"]), false )
end
end
end
end

View File

@@ -3,117 +3,117 @@ require 'redistat/finder/date_set'
module Redistat
class Finder
include Database
class << self
def find(*args)
new.find(*args)
end
def scope(scope)
new.scope(scope)
end
def label(label)
new.label(label)
end
def dates(from, till)
new.dates(from, till)
end
alias :date :dates
def from(date)
new.from(date)
end
def till(date)
new.till(date)
end
alias :untill :till
def depth(unit)
new.depth(unit)
end
def interval(unit)
new.interval(unit)
end
end
attr_reader :options
def initialize(opts = {})
set_options(opts)
end
def options
@options ||= {}
end
def all(reload = false)
@result = nil if reload
@result ||= find
end
def total
all.total
end
def each(&block)
all.each(&block)
end
def map(&block)
all.map(&block)
end
def each_with_index(&block)
all.each_with_index(&block)
end
def parent
@parent ||= self.class.new(options.merge(:label => options[:label].parent)) unless options[:label].nil?
end
def children
build_key.children.map { |key|
self.class.new(options.merge(:label => key.label.to_s))
}
end
def connection_ref(ref = nil)
return options[:connection_ref] if ref.nil?
reset! if options[:connection_ref] != ref
options[:connection_ref] = ref
self
end
def scope(input = nil)
return options[:scope] if input.nil?
reset! if !options[:scope].nil? && options[:scope].to_s != input.to_s
options[:scope] = Scope.new(input)
self
end
def label(input = nil)
return options[:label] if input.nil?
reset! if options.has_key?(:label) && options[:label].to_s != input.to_s
options[:label] = (!input.nil?) ? Label.new(input) : nil
self
end
def dates(start, finish)
from(start).till(finish)
end
alias :date :dates
def from(date = nil)
return options[:from] if date.nil?
reset! if options[:from] != date
options[:from] = date
self
end
def till(date = nil)
return options[:till] if date.nil?
reset! if options[:till] != date
@@ -121,21 +121,21 @@ module Redistat
self
end
alias :until :till
def depth(unit = nil)
return options[:depth] if unit.nil?
reset! if options[:depth] != unit
options[:depth] = unit
self
end
def interval(unit = nil)
return options[:interval] if unit.nil?
reset! if options[:interval] != unit
options[:interval] = unit
self
end
def find(opts = {})
set_options(opts)
raise InvalidOptions.new if !valid_options?
@@ -145,9 +145,9 @@ module Redistat
find_by_interval
end
end
private
def set_options(opts = {})
opts = opts.clone
opts.each do |key, value|
@@ -155,7 +155,7 @@ module Redistat
end
self.options.merge!(opts)
end
def find_by_interval
raise InvalidOptions.new if !valid_options?
key = build_key
@@ -174,7 +174,7 @@ module Redistat
end
col
end
def find_by_magic
raise InvalidOptions.new if !valid_options?
key = build_key
@@ -196,20 +196,20 @@ module Redistat
@result = nil
@parent = nil
end
def valid_options?
return true if !options[:scope].blank? && !options[:label].blank? && !options[:from].blank? && !options[:till].blank?
false
end
def build_date_sets
Finder::DateSet.new(options[:from], options[:till], options[:depth], options[:interval])
end
def build_key
Key.new(options[:scope], options[:label])
end
def summarize_add_keys(sets, key, sum)
sets.each do |date|
db.hgetall("#{key.prefix}#{date}").each do |k, v|
@@ -218,7 +218,7 @@ module Redistat
end
sum
end
def summarize_rem_keys(sets, key, sum)
sets.each do |date|
db.hgetall("#{key.prefix}#{date}").each do |k, v|
@@ -227,10 +227,10 @@ module Redistat
end
sum
end
def db
super(options[:connection_ref])
end
end
end
end

View File

@@ -1,7 +1,7 @@
module Redistat
class Finder
class DateSet < Array
def initialize(start_date = nil, end_date = nil, depth = nil, interval = false)
if !start_date.nil? && !end_date.nil?
find_date_sets(start_date, end_date, depth, interval)
@@ -71,7 +71,7 @@ module Redistat
end
{ :add => add, :rem => [] }
elsif has_nunit
{ :add => [end_date.beginning_of(nunit).to_rs.to_s(nunit)],
{ :add => [end_date.beginning_of(nunit).to_rs.to_s(nunit)],
:rem => end_date.map_beginning_of_each(unit, :include_start => !lowest_depth).until(end_date.end_of(nunit)) { |t| t.to_rs.to_s(unit) } }
else
{ :add => [], :rem => [] }
@@ -93,7 +93,7 @@ module Redistat
{ :add => [], :rem => [] }
end
end
end
end
end
end

View File

@@ -2,56 +2,56 @@ module Redistat
class Key
include Database
include Options
def default_options
{ :depth => :hour }
end
def initialize(scope, label_name = nil, time_stamp = nil, opts = {})
parse_options(opts)
self.scope = scope
self.label = label_name if !label_name.nil?
self.date = time_stamp ||= Time.now
end
def prefix
key = "#{@scope}"
key << "/#{label.name}" if !label.nil?
key << ":"
key
end
def date=(input)
@date = (input.instance_of?(Redistat::Date)) ? input : Date.new(input) # Redistat::Date, not ::Date
end
attr_reader :date
def depth
options[:depth]
end
# def scope
# @scope.to_s
# end
def scope=(input)
@scope = (input.instance_of?(Redistat::Scope)) ? input : Scope.new(input)
end
attr_reader :scope
def label=(input)
@label = (input.instance_of?(Redistat::Label)) ? input : Label.create(input, @options)
end
attr_reader :label
def label_hash
@label.hash
end
def parent
@parent ||= self.class.new(self.scope, @label.parent, self.date, @options) unless @label.parent.nil?
end
def children
members = db.smembers("#{scope}#{LABEL_INDEX}#{@label}") || [] # older versions of Redis returns nil
members.map { |member|
@@ -59,26 +59,26 @@ module Redistat
self.class.new(self.scope, child_label.join(GROUP_SEPARATOR), self.date, @options)
}
end
def update_index
@label.groups.each do |label|
parent = (label.parent || "")
db.sadd("#{scope}#{LABEL_INDEX}#{parent}", label.me)
end
end
def groups
@groups ||= @label.groups.map do |label|
self.class.new(@scope, label, self.date, @options)
end
end
def to_s(depth = nil)
depth ||= @options[:depth]
key = self.prefix
key << @date.to_s(depth)
key
end
end
end
end

View File

@@ -2,55 +2,55 @@ module Redistat
class Label
include Database
include Options
def default_options
{ :hashed_label => false }
end
def self.create(name, opts = {})
self.new(name, opts).save
end
def self.join(*args)
args = args.map {|i| i.to_s}
self.new(args.reject {|i| i.blank? }.join(GROUP_SEPARATOR))
end
def initialize(str, opts = {})
parse_options(opts)
@raw = str.to_s
end
def to_s
@raw
end
def name
@options[:hashed_label] ? hash : self.to_s
end
def hash
@hash ||= Digest::SHA1.hexdigest(self.to_s)
end
def save
@saved = db.hset(KEY_LABELS, hash, self.to_s) if @options[:hashed_label]
self
end
def saved?
return true unless @options[:hashed_label]
@saved ||= false
end
def parent
@parent ||= groups[1] if groups.size > 1
end
def me
self.to_s.split(GROUP_SEPARATOR).last
end
def groups
return @groups unless @groups.nil?
@groups = []
@@ -64,6 +64,6 @@ module Redistat
end
@groups.reverse!
end
end
end
end

View File

@@ -8,4 +8,4 @@ module Redistat
Redistat.connection(ref)
end
end
end
end

View File

@@ -5,4 +5,4 @@ module Redistat
end
alias :to_rs :to_redistat
end
end
end

View File

@@ -1,10 +1,10 @@
module Redistat
module Options
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def option_accessor(*opts)
opts.each do |option|
@@ -18,24 +18,24 @@ module Redistat
end
end
end
def parse_options(opts)
opts ||= {}
@raw_options = opts
@options = default_options.merge(opts.reject { |k,v| v.nil? })
end
def default_options
{}
end
def options
@options ||= {}
end
def raw_options
@raw_options ||= {}
end
end
end
end

View File

@@ -2,42 +2,42 @@ require 'monitor'
module Redistat
module Synchronize
class << self
def included(base)
base.send(:include, InstanceMethods)
end
def monitor
@monitor ||= Monitor.new
end
def thread_safe
monitor.synchronize do
@thread_safe ||= false
end
end
def thread_safe=(value)
monitor.synchronize do
@thread_safe = value
end
end
end # << self
module InstanceMethods
def thread_safe
Synchronize.thread_safe
end
def thread_safe=(value)
Synchronize.thread_safe = value
end
def monitor
Synchronize.monitor
end
def synchronize(&block)
if thread_safe
monitor.synchronize(&block)
@@ -46,6 +46,6 @@ module Redistat
end
end
end # InstanceMethods
end
end
end

View File

@@ -2,16 +2,16 @@ module Redistat
module Model
include Database
include Options
def self.included(base)
base.extend(self)
end
#
# statistics store/fetch methods
#
#
def store(label, stats = {}, date = nil, opts = {}, meta = {})
Event.new(self.name, label, date, stats, options.merge(opts), meta).save
end
@@ -28,42 +28,42 @@ module Redistat
:from => from,
:till => till }.merge(options.merge(opts)) )
end
def find_event(event_id)
Event.find(self.name, event_id)
end
#
# options methods
#
option_accessor :depth
option_accessor :scope
option_accessor :store_event
option_accessor :hashed_label
option_accessor :label_indexing
alias :class_name :scope
def connect_to(opts = {})
Connection.create(opts.merge(:ref => name))
options[:connection_ref] = name
end
#
# resource access methods
#
def connection
db(options[:connection_ref])
end
alias :redis :connection
def name
options[:scope] || (@name ||= self.to_s)
end
end
end
end

View File

@@ -2,17 +2,17 @@ require 'active_support/core_ext/hash/indifferent_access'
module Redistat
class Result < HashWithIndifferentAccess
attr_accessor :from
attr_accessor :till
alias :date :from
alias :date= :from=
def initialize(options = {})
@from = options[:from] ||= nil
@till = options[:till] ||= nil
end
end
end

View File

@@ -1,18 +1,18 @@
module Redistat
class Scope
include Database
def initialize(name)
@name = name.to_s
end
def to_s
@name
end
def next_id
db.incr("#{@name}#{KEY_NEXT_ID}")
end
end
end
end

View File

@@ -1,34 +1,34 @@
module Redistat
class Summary
include Database
class << self
def default_options
{ :enable_grouping => true,
:label_indexing => true,
:connection_ref => nil }
end
def buffer
Redistat.buffer
end
def update_all(key, stats = {}, depth_limit = nil, opts = {})
stats ||= {}
return if stats.empty?
options = default_options.merge((opts || {}).reject { |k,v| v.nil? })
depth_limit ||= key.depth
update_through_buffer(key, stats, depth_limit, options)
end
def update_through_buffer(*args)
update(*args) unless buffer.store(*args)
end
def update(key, stats, depth_limit, opts)
if opts[:enable_grouping]
stats = inject_group_summaries(stats)
@@ -40,22 +40,22 @@ module Redistat
update_key(key, stats, depth_limit, opts[:connection_ref])
end
end
private
def update_key(key, stats, depth_limit, connection_ref)
Date::DEPTHS.each do |depth|
update_fields(key, stats, depth, connection_ref)
break if depth == depth_limit
end
end
def update_fields(key, stats, depth, connection_ref = nil)
stats.each do |field, value|
db(connection_ref).hincrby key.to_s(depth), field, value
end
end
def inject_group_summaries!(stats)
summaries = {}
stats.each do |key, value|
@@ -72,11 +72,11 @@ module Redistat
end
stats.merge_and_incr!(summaries)
end
def inject_group_summaries(stats)
inject_group_summaries!(stats.clone)
end
end
end
end
end

View File

@@ -1,7 +1,7 @@
require "spec_helper"
describe Redistat::Buffer do
before(:each) do
@class = Redistat::Buffer
@buffer = Redistat::Buffer.instance
@@ -10,17 +10,17 @@ describe Redistat::Buffer do
@depth_limit = :hour
@opts = {:enable_grouping => true}
end
# let's cleanup after ourselves for the other specs
after(:each) do
@class.instance_variable_set("@instance", nil)
@buffer.size = 0
end
it "should provide instance of itself" do
@buffer.should be_a(@class)
end
it "should only buffer if buffer size setting is greater than 1" do
@buffer.size.should == 0
@buffer.send(:should_buffer?).should be_false
@@ -31,7 +31,7 @@ describe Redistat::Buffer do
@buffer.size.should == 2
@buffer.send(:should_buffer?).should be_true
end
it "should only flush buffer if buffer size is greater than or equal to buffer size setting" do
@buffer.size.should == 0
@buffer.send(:queue).size.should == 0
@@ -50,7 +50,7 @@ describe Redistat::Buffer do
@buffer.send(:incr_count)
@buffer.send(:should_flush?).should be_true
end
it "should force flush queue irregardless of result of #should_flush? when #reset_queue is called with true" do
@buffer.send(:queue)[:hello] = 'world'
@buffer.send(:incr_count)
@@ -62,7 +62,7 @@ describe Redistat::Buffer do
@buffer.send(:reset_queue, true).should == {:hello => 'world'}
@buffer.instance_variable_get("@count").should == 0
end
it "should #flush_data into Summary.update properly" do
# the root level key value doesn't actually matter, but it's something like this...
data = {'ScopeName/label/goes/here:2011::true:true' => {
@@ -75,14 +75,14 @@ describe Redistat::Buffer do
Redistat::Summary.should_receive(:update).with(@key, @stats, @depth_limit, @opts)
@buffer.send(:flush_data, data)
end
it "should build #buffer_key correctly" do
opts = {:enable_grouping => true, :label_indexing => false, :connection_ref => nil}
@buffer.send(:buffer_key, @key, opts).should == "#{@key.to_s}::true:false"
opts = {:enable_grouping => false, :label_indexing => true, :connection_ref => :omg}
@buffer.send(:buffer_key, @key, opts).should == "#{@key.to_s}:omg:false:true"
end
describe "Buffering" do
it "should store items on buffer queue" do
@buffer.store(@key, @stats, @depth_limit, @opts).should be_false
@@ -96,7 +96,7 @@ describe Redistat::Buffer do
@buffer.send(:queue)[@buffer.send(:queue).keys.first][:stats][:count].should == 2
@buffer.send(:queue)[@buffer.send(:queue).keys.first][:stats][:views].should == 6
end
it "should flush buffer queue when size is reached" do
key = mock('Key', :to_s => "Scope/labelx:2011")
@buffer.size = 10
@@ -115,18 +115,18 @@ describe Redistat::Buffer do
4.times { @buffer.store(key, @stats, @depth_limit, @opts).should be_true }
end
end
describe "Thread-Safety" do
it "should read/write to buffer queue in a thread-safe manner" do
# Setting thread_safe to false only makes the spec fail with
# JRuby. 1.8.x and 1.9.x both pass fine for some reason
# regardless of what the thread_safe option is set to.
Redistat.thread_safe = true
key = mock('Key', :to_s => "Scope/labelx:2011")
@buffer.size = 100
Redistat::Summary.should_receive(:update).exactly(2).times.and_return do |k, stats, depth_limit, opts|
depth_limit.should == @depth_limit
opts.should == @opts
@@ -138,7 +138,7 @@ describe Redistat::Buffer do
stats[:views].should == 120
end
end
threads = []
10.times do
threads << Thread.new {
@@ -146,12 +146,12 @@ describe Redistat::Buffer do
4.times { @buffer.store(key, @stats, @depth_limit, @opts).should be_true }
}
end
threads.each { |t| t.join }
end
it "should have specs that fail on 1.8.x/1.9.x when thread_safe is disabled"
end
end

View File

@@ -1,7 +1,7 @@
require "spec_helper"
describe Redistat::Collection do
it "should initialize properly" do
options = {:from => "from", :till => "till", :depth => "depth"}
result = Redistat::Collection.new(options)
@@ -9,12 +9,12 @@ describe Redistat::Collection do
result.till.should == options[:till]
result.depth.should == options[:depth]
end
it "should have a total property" do
col = Redistat::Collection.new()
col.total.should == {}
col.total = {:foo => "bar"}
col.total.should == {:foo => "bar"}
end
end
end

View File

@@ -2,11 +2,11 @@ require "spec_helper"
include Redistat
describe Redistat::Connection do
before(:each) do
@redis = Redistat.redis
end
it "should have a valid Redis client instance" do
Redistat.redis.should_not be_nil
end
@@ -16,13 +16,13 @@ describe Redistat::Connection do
@redis.client.port.should == 8379
@redis.client.db.should == 15
end
it "should be able to set and get data" do
@redis.set("hello", "world")
@redis.get("hello").should == "world"
@redis.del("hello").should be_true
end
it "should be able to store hashes to Redis" do
@redis.hset("hash", "field", "1")
@redis.hget("hash", "field").should == "1"
@@ -32,36 +32,36 @@ describe Redistat::Connection do
@redis.hget("hash", "field").should == "1"
@redis.del("hash")
end
it "should be accessible from Redistat module" do
Redistat.redis.should == Connection.get
Redistat.redis.should == Redistat.connection
end
it "should handle multiple connections with refs" do
Redistat.redis.client.db.should == 15
Redistat.connect(:port => 8379, :db => 14, :ref => "Custom")
Redistat.redis.client.db.should == 15
Redistat.redis("Custom").client.db.should == 14
end
it "should be able to overwrite default and custom refs" do
Redistat.redis.client.db.should == 15
Redistat.connect(:port => 8379, :db => 14)
Redistat.redis.client.db.should == 14
Redistat.redis("Custom").client.db.should == 14
Redistat.connect(:port => 8379, :db => 15, :ref => "Custom")
Redistat.redis("Custom").client.db.should == 15
# Reset the default connection to the testing server or all hell
# might brake loose from the rest of the specs
Redistat.connect(:port => 8379, :db => 15)
end
# TODO: Test thread-safety
it "should be thread-safe" do
pending("need to figure out a way to test thread-safety")
end
end
end

View File

@@ -1,7 +1,7 @@
require "spec_helper"
describe Hash do
it "should #set_or_incr values" do
hash = {:count => 1}
hash.set_or_incr(:sum, 3).should be_true
@@ -14,17 +14,17 @@ describe Hash do
hash[:view] = 'test'
hash.set_or_incr(:view, 3).should be_false
end
it "should #merge_and_incr hashes" do
hash = { :count => 1, :city => 'hell', :sum => 3, :name => 'john' }
new_hash = { :count => 3, :city => 'slum', :views => 2 }
hash.clone.merge_and_incr(new_hash).should == { :count => 4, :city => 'slum', :views => 2,
:sum => 3, :name => 'john' }
new_hash = { :count => 'six', :city => 'slum', :views => 2, :time => 'late' }
hash.clone.merge_and_incr(new_hash).should == { :count => 'six', :city => 'slum', :views => 2,
:sum => 3, :name => 'john', :time => 'late' }
end
end

View File

@@ -2,9 +2,9 @@ require "spec_helper"
describe Redistat::Database do
include Redistat::Database
it "should make #db method available when included" do
db.should == Redistat.redis
end
end
end

View File

@@ -1,14 +1,14 @@
require "spec_helper"
describe Redistat::Date do
it "should initialize from Time object" do
now = Time.now
[Redistat::Date.new(now), now.to_rs].each do |rdate|
Redistat::Date::DEPTHS.each { |k| rdate.send(k).should == now.send(k) }
end
end
it "should initialize from Date object" do
today = Date.today
[Redistat::Date.new(today), today.to_rs].each do |rdate|
@@ -16,7 +16,7 @@ describe Redistat::Date do
[:hour, :min, :sec, :usec].each { |k| rdate.send(k).should == 0 }
end
end
it "should initialize from Fixnum object (UNIX Timestamp)" do
now = Time.now.to_i
time = Time.at(now)
@@ -24,13 +24,13 @@ describe Redistat::Date do
[:year, :month, :day, :hour, :min, :sec].each { |k| rdate.send(k).should == time.send(k) }
end
end
it "should initialize from String object" do
now = Time.now
rdate = Redistat::Date.new(now.to_s)
[:year, :month, :day, :hour, :min, :sec].each { |k| rdate.send(k).should == now.send(k) }
end
it "should initialize from Redistat date String" do
now = Time.now
rdate = Redistat::Date.new(now.to_s)
@@ -38,25 +38,25 @@ describe Redistat::Date do
rdate.to_s(k).should == Redistat::Date.new(rdate.to_s(k)).to_s(k)
}
end
it "should convert to Time object" do
now = Time.now
rdate = Redistat::Date.new(now)
rdate.to_time.to_s.should == now.to_s
end
it "should convert to Date object" do
today = Date.today
rdate = Redistat::Date.new(today)
rdate.to_date.to_s.should == today.to_s
end
it "should convert to Fixnum object (UNIX Timestamp)" do
now = Time.now
rdate = Redistat::Date.new(now)
rdate.to_i.should == now.to_i
end
it "should convert to string with correct depths" do
today = Date.today
now = Time.now
@@ -71,25 +71,25 @@ describe Redistat::Date do
end
end
end
it "should add helper methods to Date, Time and Fixnum classes" do
Date.today.to_time.should == Time.parse(Date.today.to_s)
Time.now.to_i.to_time.should == Time.at(Time.now.to_i)
Date.today.to_rs.to_date.should == Date.today
end
it "should have a depth property" do
now = Time.now
date = Redistat::Date.new(now)
date.depth.should be_nil
date.to_s.should == now.to_rs(:sec).to_s
date.to_s.should == now.to_rs.to_s(:sec)
date = Redistat::Date.new(now, :hour)
date.depth.should == :hour
date.to_s.should == now.to_rs(:hour).to_s
date.to_s.should == now.to_rs.to_s(:hour)
end
end
end

View File

@@ -2,7 +2,7 @@ require "spec_helper"
describe Redistat::Event do
include Redistat::Database
before(:each) do
db.flushdb
@scope = "PageViews"
@@ -14,7 +14,7 @@ describe Redistat::Event do
@date = Time.now
@event = Redistat::Event.new(@scope, @label, @date, @stats, @options, @meta)
end
it "should initialize properly" do
@event.id.should be_nil
@event.scope.to_s.should == @scope
@@ -41,7 +41,7 @@ describe Redistat::Event do
@event.label.to_s.should == @label
@event.label_hash.should == @label_hash
end
it "should increment next_id" do
event = Redistat::Event.new("VisitorCount", @label, @date, @stats, @options, @meta)
@event.next_id.should == 1
@@ -49,7 +49,7 @@ describe Redistat::Event do
@event.next_id.should == 2
event.next_id.should == 2
end
it "should store event properly" do
@event = Redistat::Event.new(@scope, @label, @date, @stats, @options.merge({:store_event => true}), @meta)
@event.new?.should be_true
@@ -59,7 +59,7 @@ describe Redistat::Event do
keys.should include("#{@event.scope}#{Redistat::KEY_EVENT}#{@event.id}")
keys.should include("#{@event.scope}#{Redistat::KEY_EVENT_IDS}")
end
it "should find event by id" do
@event = Redistat::Event.new(@scope, @label, @date, @stats, @options.merge({:store_event => true}), @meta).save
fetched = Redistat::Event.find(@scope, @event.id)
@@ -69,7 +69,7 @@ describe Redistat::Event do
@event.stats.should == fetched.stats
@event.meta.should == fetched.meta
end
it "should store summarized statistics" do
2.times do |i|
@event = Redistat::Event.new(@scope, @label, @date, @stats, @options, @meta).save
@@ -81,5 +81,5 @@ describe Redistat::Event do
end
end
end
end
end

View File

@@ -1,11 +1,11 @@
require "spec_helper"
describe Redistat::Finder::DateSet do
before(:all) do
@finder = Redistat::Finder::DateSet.new
end
it "should initialize properly" do
t_start = Time.utc(2010, 8, 28, 22, 54, 57)
t_end = Time.utc(2013, 12, 4, 22, 52, 3)
@@ -20,508 +20,508 @@ describe Redistat::Finder::DateSet do
{ :add => ["2011", "2012"], :rem => [] }
]
end
it "should find date sets by interval" do
t_start = Time.utc(2010, 8, 28, 18, 54, 57)
t_end = t_start + 4.hours
result = Redistat::Finder::DateSet.new.find_date_sets(t_start, t_end, :hour, true)
result[0][:add].should == ["2010082818", "2010082819", "2010082820", "2010082821", "2010082822"]
result[0][:rem].should == []
result.should == Redistat::Finder::DateSet.new(t_start, t_end, nil, :hour)
t_end = t_start + 4.days
result = Redistat::Finder::DateSet.new.find_date_sets(t_start, t_end, :day, true)
result[0][:add].should == ["20100828", "20100829", "20100830", "20100831", "20100901"]
result[0][:rem].should == []
result.should == Redistat::Finder::DateSet.new(t_start, t_end, nil, :day)
end
it "should find start keys properly" do
#
# Simple fetching
# Dates: 22:54, 26th August, 2010 --> 22:52, 14th December, 2010
#
t_start = Time.utc(2010, 8, 26, 22, 54, 57)
t_end = Time.utc(2013, 12, 14, 22, 52, 3)
result = @finder.send(:find_start_keys_for, :sec, t_start, t_end)
result[:add].should == ["20100826225458", "20100826225459"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :min, t_start, t_end)
result[:add].should == ["201008262255", "201008262256", "201008262257", "201008262258", "201008262259"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :hour, t_start, t_end)
result[:add].should == ["2010082623"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :day, t_start, t_end)
result[:add].should == ["20100827", "20100828", "20100829", "20100830", "20100831"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :month, t_start, t_end)
result[:add].should == ["201009", "201010", "201011", "201012"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :year, t_start, t_end)
result[:add].should == ["2011", "2012"]
result[:rem].should == []
#
# Reverse / Inteligent fetching
# Dates: 5:06, 4th April, 2010 --> 22:52, 14th February, 2011
#
t_start = Time.utc(2010, 4, 4, 5, 6, 4)
t_end = Time.utc(2011, 2, 14, 22, 52, 3)
result = @finder.send(:find_start_keys_for, :sec, t_start, t_end)
result[:add].should == ["201004040506"]
result[:rem].should == ["20100404050600", "20100404050601", "20100404050602", "20100404050603", "20100404050604"]
result = @finder.send(:find_start_keys_for, :min, t_start, t_end)
result[:add].should == ["2010040405"]
result[:rem].should == ["201004040500", "201004040501", "201004040502", "201004040503", "201004040504", "201004040505", "201004040506"]
result = @finder.send(:find_start_keys_for, :hour, t_start, t_end)
result[:add].should == ["20100404"]
result[:rem].should == ["2010040400", "2010040401", "2010040402", "2010040403", "2010040404", "2010040405"]
result = @finder.send(:find_start_keys_for, :day, t_start, t_end)
result[:add].should == ["201004"]
result[:rem].should == ["20100401", "20100402", "20100403", "20100404"]
result = @finder.send(:find_start_keys_for, :month, t_start, t_end)
result[:add].should == ["2010"]
result[:rem].should == ["201001", "201002", "201003", "201004"]
result = @finder.send(:find_start_keys_for, :year, t_start, t_end)
result[:add].should == []
result[:rem].should == []
end
it "should find end keys properly" do
#
# Simple fetching
# Dates: 22:04, 26th December, 2007 --> 5:06, 7th May, 2010
#
t_start = Time.utc(2007, 12, 26, 22, 4, 4)
t_end = Time.utc(2010, 5, 7, 5, 6, 3)
result = @finder.send(:find_end_keys_for, :sec, t_start, t_end)
result[:add].should == ["20100507050600", "20100507050601", "20100507050602"]
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :min, t_start, t_end)
result[:add].should == ["201005070500", "201005070501", "201005070502", "201005070503", "201005070504", "201005070505"]
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :hour, t_start, t_end)
result[:add].should == ["2010050700", "2010050701", "2010050702", "2010050703", "2010050704"]
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :day, t_start, t_end)
result[:add].should == ["20100501", "20100502", "20100503", "20100504", "20100505", "20100506"]
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :month, t_start, t_end)
result[:add].should == ["201001", "201002", "201003", "201004"]
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :year, t_start, t_end)
result[:add].should == []
result[:rem].should == []
#
# Reverse / Inteligent fetching
# Dates: 22:04, 26th December, 2009 --> 22:56, 27th October, 2010
#
t_start = Time.utc(2009, 12, 26, 22, 4, 4)
t_end = Time.utc(2010, 10, 27, 22, 56, 57)
result = @finder.send(:find_end_keys_for, :sec, t_start, t_end)
result[:add].should == ["201010272256"]
result[:rem].should == ["20101027225657", "20101027225658", "20101027225659"]
result = @finder.send(:find_end_keys_for, :min, t_start, t_end)
result[:add].should == ["2010102722"]
result[:rem].should == ["201010272256", "201010272257", "201010272258", "201010272259"]
result = @finder.send(:find_end_keys_for, :hour, t_start, t_end)
result[:add].should == ["20101027"]
result[:rem].should == ["2010102722", "2010102723"]
result = @finder.send(:find_end_keys_for, :day, t_start, t_end)
result[:add].should == ["201010"]
result[:rem].should == ["20101027", "20101028", "20101029", "20101030", "20101031"]
result = @finder.send(:find_end_keys_for, :month, t_start, t_end)
result[:add].should == ["2010"]
result[:rem].should == ["201010", "201011", "201012"]
result = @finder.send(:find_end_keys_for, :year, t_start, t_end)
result[:add].should == []
result[:rem].should == []
end
it "should fetch start/end keys with limits" do
#
# Simple fetching with Limits
#
# seconds
t_start = Time.utc(2010, 8, 26, 20, 54, 45)
t_end = t_start + 4.seconds
result = @finder.send(:find_start_keys_for, :sec, t_start, t_end)
result[:add].should == ["20100826205446", "20100826205447", "20100826205448"]
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :sec, t_start, t_end)
result[:add].should == []
result[:rem].should == []
t_start = Time.utc(2010, 8, 26, 20, 54, 4)
t_end = t_start + 4.seconds
result = @finder.send(:find_start_keys_for, :sec, t_start, t_end)
result[:add].should == ["20100826205405", "20100826205406", "20100826205407"]
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :sec, t_start, t_end)
result[:add].should == []
result[:rem].should == []
# minutes
t_start = Time.utc(2010, 8, 26, 20, 54)
t_end = t_start + 4.minutes
result = @finder.send(:find_start_keys_for, :min, t_start, t_end)
result[:add].should == ["201008262055", "201008262056", "201008262057"]
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :min, t_start, t_end)
result[:add].should == []
result[:rem].should == []
t_start = Time.utc(2010, 8, 26, 20, 4)
t_end = t_start + 4.minutes
result = @finder.send(:find_start_keys_for, :min, t_start, t_end)
result[:add].should == ["201008262005", "201008262006", "201008262007"]
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :min, t_start, t_end)
result[:add].should == []
result[:rem].should == []
# hours
t_start = Time.utc(2010, 8, 26, 20, 54)
t_end = t_start + 2.hours
result = @finder.send(:find_start_keys_for, :min, t_start, t_end)
result[:add].should == ["201008262055", "201008262056", "201008262057", "201008262058", "201008262059"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :hour, t_start, t_end)
result[:add].should == ["2010082621"]
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :hour, t_start, t_end)
result[:add].should == []
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :min, t_start, t_end)
result[:add].should == ["2010082622"]
result[:rem].should == ["201008262254", "201008262255", "201008262256", "201008262257", "201008262258", "201008262259"]
t_start = Time.utc(2010, 8, 26, 4, 54)
t_end = t_start + 5.hours
result = @finder.send(:find_start_keys_for, :min, t_start, t_end)
result[:add].should == ["201008260455", "201008260456", "201008260457", "201008260458", "201008260459"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :hour, t_start, t_end)
result[:add].should == ["2010082605", "2010082606", "2010082607", "2010082608"]
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :hour, t_start, t_end)
result[:add].should == []
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :min, t_start, t_end)
result[:add].should == ["2010082609"]
result[:rem].should == ["201008260954", "201008260955", "201008260956", "201008260957", "201008260958", "201008260959"]
# days
t_start = Time.utc(2010, 8, 26, 20, 54)
t_end = t_start + 2.day
result = @finder.send(:find_start_keys_for, :min, t_start, t_end)
result[:add].should == ["201008262055", "201008262056", "201008262057", "201008262058", "201008262059"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :hour, t_start, t_end)
result[:add].should == ["2010082621", "2010082622", "2010082623"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :day, t_start, t_end)
result[:add].should == ["20100827"]
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :day, t_start, t_end)
result[:add].should == []
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :hour, t_start, t_end)
result[:add].should == ["20100828"]
result[:rem].should == ["2010082820", "2010082821", "2010082822", "2010082823"]
result = @finder.send(:find_end_keys_for, :min, t_start, t_end)
result[:add].should == ["2010082820"]
result[:rem].should == ["201008282054", "201008282055", "201008282056", "201008282057", "201008282058", "201008282059"]
t_start = Time.utc(2010, 8, 6, 20, 54)
t_end = t_start + 2.day
result = @finder.send(:find_start_keys_for, :min, t_start, t_end)
result[:add].should == ["201008062055", "201008062056", "201008062057", "201008062058", "201008062059"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :hour, t_start, t_end)
result[:add].should == ["2010080621", "2010080622", "2010080623"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :day, t_start, t_end)
result[:add].should == ["20100807"]
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :day, t_start, t_end)
result[:add].should == []
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :hour, t_start, t_end)
result[:add].should == ["20100808"]
result[:rem].should == ["2010080820", "2010080821", "2010080822", "2010080823"]
result = @finder.send(:find_end_keys_for, :min, t_start, t_end)
result[:add].should == ["2010080820"]
result[:rem].should == ["201008082054", "201008082055", "201008082056", "201008082057", "201008082058", "201008082059"]
# months
t_start = Time.utc(2010, 8, 26, 20, 54)
t_end = t_start + 3.months
result = @finder.send(:find_start_keys_for, :min, t_start, t_end)
result[:add].should == ["201008262055", "201008262056", "201008262057", "201008262058", "201008262059"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :hour, t_start, t_end)
result[:add].should == ["2010082621", "2010082622", "2010082623"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :day, t_start, t_end)
result[:add].should == ["20100827", "20100828", "20100829", "20100830", "20100831"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :month, t_start, t_end)
result[:add].should == ["201009", "201010"]
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :month, t_start, t_end)
result[:add].should == []
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :day, t_start, t_end)
result[:add].should == ["201011"]
result[:rem].should == ["20101126", "20101127", "20101128", "20101129", "20101130"]
result = @finder.send(:find_end_keys_for, :hour, t_start, t_end)
result[:add].should == ["20101126"]
result[:rem].should == ["2010112620", "2010112621", "2010112622", "2010112623"]
result = @finder.send(:find_end_keys_for, :min, t_start, t_end)
result[:add].should == ["2010112620"]
result[:rem].should == ["201011262054", "201011262055", "201011262056", "201011262057", "201011262058", "201011262059"]
t_start = Time.utc(2010, 4, 26, 20, 54)
t_end = t_start + 3.months
result = @finder.send(:find_start_keys_for, :min, t_start, t_end)
result[:add].should == ["201004262055", "201004262056", "201004262057", "201004262058", "201004262059"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :hour, t_start, t_end)
result[:add].should == ["2010042621", "2010042622", "2010042623"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :day, t_start, t_end)
result[:add].should == ["20100427", "20100428", "20100429", "20100430"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :month, t_start, t_end)
result[:add].should == ["201005", "201006"]
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :month, t_start, t_end)
result[:add].should == []
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :day, t_start, t_end)
result[:add].should == ["201007"]
result[:rem].should == ["20100726", "20100727", "20100728", "20100729", "20100730", "20100731"]
result = @finder.send(:find_end_keys_for, :hour, t_start, t_end)
result[:add].should == ["20100726"]
result[:rem].should == ["2010072620", "2010072621", "2010072622", "2010072623"]
result = @finder.send(:find_end_keys_for, :min, t_start, t_end)
result[:add].should == ["2010072620"]
result[:rem].should == ["201007262054", "201007262055", "201007262056", "201007262057", "201007262058", "201007262059"]
end
it "should find inclusive keys on lowest depth" do
#
# Simple start fetching
# Dates: 22:54, 26th August, 2010 --> 22:52, 14th December, 2010
#
t_start = Time.utc(2010, 8, 26, 22, 54, 57)
t_end = Time.utc(2013, 12, 14, 22, 52, 3)
result = @finder.send(:find_start_keys_for, :sec, t_start, t_end, true)
result[:add].should == ["20100826225457", "20100826225458", "20100826225459"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :min, t_start, t_end, true)
result[:add].should == ["201008262254", "201008262255", "201008262256", "201008262257", "201008262258", "201008262259"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :hour, t_start, t_end, true)
result[:add].should == ["2010082622", "2010082623"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :day, t_start, t_end, true)
result[:add].should == ["20100826", "20100827", "20100828", "20100829", "20100830", "20100831"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :month, t_start, t_end, true)
result[:add].should == ["201008", "201009", "201010", "201011", "201012"]
result[:rem].should == []
result = @finder.send(:find_start_keys_for, :year, t_start, t_end, true)
result[:add].should == ["2011", "2012", "2013"]
result[:rem].should == []
#
# Reverse / Inteligent start fetching
# Dates: 5:06, 4th April, 2010 --> 22:52, 14th February, 2011
#
t_start = Time.utc(2010, 4, 4, 5, 6, 4)
t_end = Time.utc(2013, 2, 14, 22, 52, 3)
result = @finder.send(:find_start_keys_for, :sec, t_start, t_end, true)
result[:add].should == ["201004040506"]
result[:rem].should == ["20100404050600", "20100404050601", "20100404050602", "20100404050603"]
result = @finder.send(:find_start_keys_for, :min, t_start, t_end, true)
result[:add].should == ["2010040405"]
result[:rem].should == ["201004040500", "201004040501", "201004040502", "201004040503", "201004040504", "201004040505"]
result = @finder.send(:find_start_keys_for, :hour, t_start, t_end, true)
result[:add].should == ["20100404"]
result[:rem].should == ["2010040400", "2010040401", "2010040402", "2010040403", "2010040404"]
result = @finder.send(:find_start_keys_for, :day, t_start, t_end, true)
result[:add].should == ["201004"]
result[:rem].should == ["20100401", "20100402", "20100403"]
result = @finder.send(:find_start_keys_for, :month, t_start, t_end, true)
result[:add].should == ["2010"]
result[:rem].should == ["201001", "201002", "201003"]
result = @finder.send(:find_start_keys_for, :year, t_start, t_end, true)
result[:add].should == ["2011", "2012", "2013"]
result[:rem].should == []
#
# Simple fetching
# Dates: 22:04, 26th December, 2007 --> 5:06, 7th May, 2010
#
t_start = Time.utc(2007, 12, 26, 22, 4, 4)
t_end = Time.utc(2010, 5, 7, 5, 6, 3)
result = @finder.send(:find_end_keys_for, :sec, t_start, t_end, true)
result[:add].should == ["20100507050600", "20100507050601", "20100507050602", "20100507050603"]
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :min, t_start, t_end, true)
result[:add].should == ["201005070500", "201005070501", "201005070502", "201005070503", "201005070504", "201005070505", "201005070506"]
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :hour, t_start, t_end, true)
result[:add].should == ["2010050700", "2010050701", "2010050702", "2010050703", "2010050704", "2010050705"]
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :day, t_start, t_end, true)
result[:add].should == ["20100501", "20100502", "20100503", "20100504", "20100505", "20100506", "20100507"]
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :month, t_start, t_end, true)
result[:add].should == ["201001", "201002", "201003", "201004", "201005"]
result[:rem].should == []
result = @finder.send(:find_end_keys_for, :year, t_start, t_end, true)
result[:add].should == ["2010"]
result[:rem].should == []
#
# Reverse / Inteligent fetching
# Dates: 22:04, 26th December, 2009 --> 22:56, 27th October, 2010
#
t_start = Time.utc(2009, 12, 26, 22, 4, 4)
t_end = Time.utc(2010, 10, 27, 22, 56, 57)
result = @finder.send(:find_end_keys_for, :sec, t_start, t_end, true)
result[:add].should == ["201010272256"]
result[:rem].should == ["20101027225658", "20101027225659"]
result = @finder.send(:find_end_keys_for, :min, t_start, t_end, true)
result[:add].should == ["2010102722"]
result[:rem].should == ["201010272257", "201010272258", "201010272259"]
result = @finder.send(:find_end_keys_for, :hour, t_start, t_end, true)
result[:add].should == ["20101027"]
result[:rem].should == ["2010102723"]
result = @finder.send(:find_end_keys_for, :day, t_start, t_end, true)
result[:add].should == ["201010"]
result[:rem].should == ["20101028", "20101029", "20101030", "20101031"]
result = @finder.send(:find_end_keys_for, :month, t_start, t_end, true)
result[:add].should == ["2010"]
result[:rem].should == ["201011", "201012"]
result = @finder.send(:find_end_keys_for, :year, t_start, t_end, true)
result[:add].should == ["2010"]
result[:rem].should == []
end
end
end

View File

@@ -2,21 +2,21 @@ require "spec_helper"
describe Redistat::Finder do
include Redistat::Database
before(:each) do
db.flushdb
@scope = "PageViews"
@label = "about_us"
@date = Time.now
@key = Redistat::Key.new(@scope, @label, @date, {:depth => :day})
@stats = {"views" => 3, "visitors" => 2}
@stats = {"views" => 3, "visitors" => 2}
@two_hours_ago = 2.hours.ago
@one_hour_ago = 1.hour.ago
end
it "should initialize properly" do
options = {:scope => "PageViews", :label => "Label", :from => @two_hours_ago, :till => @one_hour_ago, :depth => :hour, :interval => :hour}
finder = Redistat::Finder.new
finder.send(:set_options, options)
finder.options[:scope].should be_a(Redistat::Scope)
@@ -24,31 +24,31 @@ describe Redistat::Finder do
finder.options[:label].should be_a(Redistat::Label)
finder.options[:label].to_s.should == options[:label]
finder.options.should == options.merge(:scope => finder.options[:scope], :label => finder.options[:label])
finder = Redistat::Finder.scope("hello")
finder.options[:scope].to_s.should == "hello"
finder.scope.to_s.should == "hello"
finder = Redistat::Finder.label("hello")
finder.options[:label].to_s.should == "hello"
finder.label.to_s.should == "hello"
finder = Redistat::Finder.dates(@two_hours_ago, @one_hour_ago)
finder.options[:from].should == @two_hours_ago
finder.options[:till].should == @one_hour_ago
finder = Redistat::Finder.from(@two_hours_ago)
finder.options[:from].should == @two_hours_ago
finder.from.should == @two_hours_ago
finder = Redistat::Finder.till(@one_hour_ago)
finder.options[:till].should == @one_hour_ago
finder.till.should == @one_hour_ago
finder = Redistat::Finder.depth(:hour)
finder.options[:depth].should == :hour
finder.depth.should == :hour
finder = Redistat::Finder.interval(true)
finder.options[:interval].should be_true
finder.interval.should be_true
@@ -56,24 +56,24 @@ describe Redistat::Finder do
finder.options[:interval].should be_false
finder.interval.should be_false
end
it "should fetch stats properly" do
first_stat, last_stat = create_example_stats
stats = Redistat::Finder.find({:from => first_stat, :till => last_stat, :scope => @scope, :label => @label, :depth => :hour})
stats.from.should == first_stat
stats.till.should == last_stat
stats.depth.should == :hour
stats.total.should == { "views" => 12, "visitors" => 8 }
stats.total.from.should == first_stat
stats.total.till.should == last_stat
stats.first.should == stats.total
end
it "should fetch data per unit when interval option is specified" do
first_stat, last_stat = create_example_stats
stats = Redistat::Finder.find(:from => first_stat, :till => last_stat, :scope => @scope, :label => @label, :depth => :hour, :interval => :hour)
stats.from.should == first_stat
stats.till.should == last_stat
@@ -89,22 +89,22 @@ describe Redistat::Finder do
stats[4].should == {}
stats[4].date.should == Time.parse("2010-05-14 16:00")
end
it "should return empty hash when attempting to fetch non-existent results" do
stats = Redistat::Finder.find({:from => 3.hours.ago, :till => 2.hours.from_now, :scope => @scope, :label => @label, :depth => :hour})
stats.total.should == {}
end
it "should throw error on invalid options" do
lambda { Redistat::Finder.find(:from => 3.hours.ago) }.should raise_error(Redistat::InvalidOptions)
end
describe "Grouping" do
before(:each) do
@options = {:scope => "PageViews", :label => "message/public", :from => @two_hours_ago, :till => @one_hour_ago, :depth => :hour, :interval => :hour}
@finder = Redistat::Finder.new(@options)
end
it "should return parent finder" do
@finder.instance_variable_get("@parent").should be_nil
@finder.parent.should be_a(Redistat::Finder)
@@ -116,7 +116,7 @@ describe Redistat::Finder do
@finder.parent.options[:label].should be_nil
@finder.parent.parent.should be_nil
end
it "should find children" do
Redistat::Key.new("PageViews", "message/public/die").update_index
Redistat::Key.new("PageViews", "message/public/live").update_index
@@ -130,25 +130,25 @@ describe Redistat::Finder do
subs.should include('fester')
end
end
describe "Lazy-Loading" do
before(:each) do
@first_stat, @last_stat = create_example_stats
@finder = Redistat::Finder.new
@finder.from(@first_stat).till(@last_stat).scope(@scope).label(@label).depth(:hour)
@match = [{}, {"visitors"=>"4", "views"=>"6"},
{"visitors"=>"2", "views"=>"3"},
{"visitors"=>"2", "views"=>"3"}, {}]
end
it "should lazy-load" do
@finder.instance_variable_get("@result").should be_nil
stats = @finder.all
@finder.instance_variable_get("@result").should_not be_nil
stats.should == @finder.find # find method directly fetches results
stats.total.should == @finder.total
stats.total.should == { "views" => 12, "visitors" => 8 }
@@ -163,35 +163,35 @@ describe Redistat::Finder do
stats = @finder.all
stats.total.should == { "views" => 6, "visitors" => 4 }
end
it "should handle #map" do
@finder.interval(:hour)
@finder.map { |r| r }.should == @match
end
it "should handle #each" do
@finder.interval(:hour)
res = []
@finder.each { |r| res << r }
res.should == @match
end
it "should handle #each_with_index" do
@finder.interval(:hour)
res = {}
match = {}
@finder.each_with_index { |r, i| res[i] = r }
@match.each_with_index { |r, i| match[i] = r }
res.should == match
end
end # "Lazy-Loading"
# helper methods
def create_example_stats
key = Redistat::Key.new(@scope, @label, (first = Time.parse("2010-05-14 13:43")))
Redistat::Summary.send(:update_fields, key, @stats, :hour)
@@ -203,5 +203,5 @@ describe Redistat::Finder do
Redistat::Summary.send(:update_fields, key, @stats, :hour)
[first - 1.hour, last + 1.hour]
end
end

View File

@@ -2,7 +2,7 @@ require "spec_helper"
describe Redistat::Key do
include Redistat::Database
before(:each) do
db.flushdb
@scope = "PageViews"
@@ -11,7 +11,7 @@ describe Redistat::Key do
@date = Time.now
@key = Redistat::Key.new(@scope, @label, @date, {:depth => :hour})
end
it "should initialize properly" do
@key.scope.to_s.should == @scope
@key.label.to_s.should == @label
@@ -20,7 +20,7 @@ describe Redistat::Key do
@key.date.should be_instance_of(Redistat::Date)
@key.date.to_time.to_s.should == @date.to_s
end
it "should convert to string properly" do
@key.to_s.should == "#{@scope}/#{@label}:#{@key.date.to_s(:hour)}"
props = [:year, :month, :day, :hour, :min, :sec]
@@ -31,19 +31,19 @@ describe Redistat::Key do
key = Redistat::Key.new(@scope, nil, @date, {:depth => :hour})
key.to_s.should == "#{@scope}:#{key.date.to_s(:hour)}"
end
it "should abide to hashed_label option" do
@key = Redistat::Key.new(@scope, @label, @date, {:depth => :hour, :hashed_label => true})
@key.to_s.should == "#{@scope}/#{@label_hash}:#{@key.date.to_s(:hour)}"
@key = Redistat::Key.new(@scope, @label, @date, {:depth => :hour, :hashed_label => false})
@key.to_s.should == "#{@scope}/#{@label}:#{@key.date.to_s(:hour)}"
end
it "should have default depth option" do
@key = Redistat::Key.new(@scope, @label, @date)
@key.depth.should == :hour
end
it "should allow changing attributes" do
# scope
@key.scope.to_s.should == @scope
@@ -64,13 +64,13 @@ describe Redistat::Key do
@key.label.to_s.should == @label
@key.label_hash == @label_hash
end
describe "Grouping" do
before(:each) do
@label = "message/public/offensive"
@key = Redistat::Key.new(@scope, @label, @date, {:depth => :hour})
end
it "should create a group of keys from label group" do
label = 'message/public/offensive'
result = [ "message/public/offensive",
@@ -81,49 +81,49 @@ describe Redistat::Key do
key.groups.map { |k| k.label.to_s }.should == result
end
it "should know it's parent" do
@key.parent.should be_a(Redistat::Key)
@key.parent.label.to_s.should == 'message/public'
Redistat::Key.new(@scope, 'hello', @date).parent.should be_nil
end
it "should update label index and return children" do
db.smembers("#{@scope}#{Redistat::LABEL_INDEX}#{@key.label.parent}").should == []
@key.children.should have(0).items
@key.update_index # indexing 'message/publish/offensive'
Redistat::Key.new("PageViews", "message/public/die").update_index # indexing 'message/publish/die'
Redistat::Key.new("PageViews", "message/public/live").update_index # indexing 'message/publish/live'
members = db.smembers("#{@scope}#{Redistat::LABEL_INDEX}#{@key.label.parent}") # checking 'message/public'
members.should have(3).item
members.should include('offensive')
members.should include('live')
members.should include('die')
key = @key.parent
key.children.first.should be_a(Redistat::Key)
key.children.should have(3).item
key.children.map { |k| k.label.me }.should == members
members = db.smembers("#{@scope}#{Redistat::LABEL_INDEX}#{key.label.parent}") # checking 'message'
members.should have(1).item
members.should include('public')
key = key.parent
key.children.should have(1).item
key.children.map { |k| k.label.me }.should == members
members = db.smembers("#{@scope}#{Redistat::LABEL_INDEX}") # checking ''
members.should have(1).item
members.should include('message')
key.parent.should be_nil
key = Redistat::Key.new("PageViews")
key.children.should have(1).item
key.children.map { |k| k.label.me }.should include('message')
end
end
end
end

View File

@@ -2,29 +2,29 @@ require "spec_helper"
describe Redistat::Label do
include Redistat::Database
before(:each) do
db.flushdb
@name = "about_us"
@label = Redistat::Label.new(@name)
end
it "should initialize properly and SHA1 hash the label name" do
@label.name.should == @name
@label.hash.should == Digest::SHA1.hexdigest(@name)
end
it "should store a label hash lookup key" do
label = Redistat::Label.new(@name, {:hashed_label => true}).save
label.saved?.should be_true
db.hget(Redistat::KEY_LABELS, label.hash).should == @name
name = "contact_us"
label = Redistat::Label.create(name, {:hashed_label => true})
label.saved?.should be_true
db.hget(Redistat::KEY_LABELS, label.hash).should == name
end
it "should join labels" do
include Redistat
label = Label.join('email', 'message', 'public')
@@ -37,18 +37,18 @@ describe Redistat::Label do
label.should be_a(Label)
label.to_s.should == 'email/message/public'
end
describe "Grouping" do
before(:each) do
@name = "message/public/offensive"
@label = Redistat::Label.new(@name)
end
it "should know it's parent label group" do
@label.parent.to_s.should == 'message/public'
Redistat::Label.new('hello').parent.should be_nil
end
it "should separate label names into groups" do
@label.name.should == @name
@label.groups.map { |l| l.to_s }.should == [ "message/public/offensive",
@@ -67,5 +67,5 @@ describe Redistat::Label do
@label.groups.map { |l| l.to_s }.should == [ "message" ]
end
end
end
end

View File

@@ -2,29 +2,29 @@ require "redistat"
class ModelHelper1
include Redistat::Model
end
class ModelHelper2
include Redistat::Model
depth :day
store_event true
hashed_label true
end
class ModelHelper3
include Redistat::Model
connect_to :port => 8379, :db => 14
end
class ModelHelper4
include Redistat::Model
scope "FancyHelper"
end
end

View File

@@ -3,7 +3,7 @@ require "model_helper"
describe Redistat::Model do
include Redistat::Database
before(:each) do
@time = Time.utc(2010, 8, 28, 12, 0, 0)
ModelHelper1.redis.flushdb
@@ -11,12 +11,12 @@ describe Redistat::Model do
ModelHelper3.redis.flushdb
ModelHelper4.redis.flushdb
end
it "should should name itself correctly" do
ModelHelper1.send(:name).should == "ModelHelper1"
ModelHelper2.send(:name).should == "ModelHelper2"
end
it "should return a Finder" do
two_hours_ago = 2.hours.ago
one_hour_ago = 1.hour.ago
@@ -27,18 +27,18 @@ describe Redistat::Model do
finder.options[:from].should == two_hours_ago
finder.options[:till].should == one_hour_ago
end
it "should #find_event" do
Redistat::Event.should_receive(:find).with('ModelHelper1', 1)
ModelHelper1.find_event(1)
end
it "should listen to model-defined options" do
ModelHelper2.depth.should == :day
ModelHelper2.store_event.should == true
ModelHelper2.hashed_label.should == true
ModelHelper2.scope.should be_nil
ModelHelper1.depth.should == nil
ModelHelper1.store_event.should == nil
ModelHelper1.hashed_label.should == nil
@@ -54,134 +54,134 @@ describe Redistat::Model do
ModelHelper1.depth.should == nil
ModelHelper1.store_event.should == nil
ModelHelper1.hashed_label.should == nil
ModelHelper4.scope.should == "FancyHelper"
ModelHelper4.send(:name).should == "FancyHelper"
end
it "should store and fetch stats" do
ModelHelper1.store("sheep.black", {:count => 6, :weight => 461}, @time.hours_ago(4))
ModelHelper1.store("sheep.black", {:count => 2, :weight => 156}, @time)
stats = ModelHelper1.fetch("sheep.black", @time.hours_ago(2), @time.hours_since(1))
stats.total["count"].should == 2
stats.total["weight"].should == 156
stats.first.should == stats.total
stats = ModelHelper1.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1))
stats.total[:count].should == 8
stats.total[:weight].should == 617
stats.first.should == stats.total
ModelHelper1.store("sheep.white", {:count => 5, :weight => 393}, @time.hours_ago(4))
ModelHelper1.store("sheep.white", {:count => 4, :weight => 316}, @time)
stats = ModelHelper1.fetch("sheep.white", @time.hours_ago(2), @time.hours_since(1))
stats.total[:count].should == 4
stats.total[:weight].should == 316
stats.first.should == stats.total
stats = ModelHelper1.fetch("sheep.white", @time.hours_ago(5), @time.hours_since(1))
stats.total[:count].should == 9
stats.total[:weight].should == 709
stats.first.should == stats.total
end
it "should store and fetch grouping enabled stats" do
ModelHelper1.store("sheep/black", {:count => 6, :weight => 461}, @time.hours_ago(4))
ModelHelper1.store("sheep/black", {:count => 2, :weight => 156}, @time)
ModelHelper1.store("sheep/white", {:count => 5, :weight => 393}, @time.hours_ago(4))
ModelHelper1.store("sheep/white", {:count => 4, :weight => 316}, @time)
stats = ModelHelper1.fetch("sheep/black", @time.hours_ago(2), @time.hours_since(1))
stats.total["count"].should == 2
stats.total["weight"].should == 156
stats.first.should == stats.total
stats = ModelHelper1.fetch("sheep/black", @time.hours_ago(5), @time.hours_since(1))
stats.total[:count].should == 8
stats.total[:weight].should == 617
stats.first.should == stats.total
stats = ModelHelper1.fetch("sheep/white", @time.hours_ago(2), @time.hours_since(1))
stats.total[:count].should == 4
stats.total[:weight].should == 316
stats.first.should == stats.total
stats = ModelHelper1.fetch("sheep/white", @time.hours_ago(5), @time.hours_since(1))
stats.total[:count].should == 9
stats.total[:weight].should == 709
stats.first.should == stats.total
stats = ModelHelper1.fetch("sheep", @time.hours_ago(2), @time.hours_since(1))
stats.total[:count].should == 6
stats.total[:weight].should == 472
stats.first.should == stats.total
stats = ModelHelper1.fetch("sheep", @time.hours_ago(5), @time.hours_since(1))
stats.total[:count].should == 17
stats.total[:weight].should == 1326
stats.first.should == stats.total
end
it "should connect to different Redis servers on a per-model basis" do
ModelHelper3.redis.client.db.should == 14
ModelHelper3.store("sheep.black", {:count => 6, :weight => 461}, @time.hours_ago(4), :label_indexing => false)
ModelHelper3.store("sheep.black", {:count => 2, :weight => 156}, @time, :label_indexing => false)
db.keys("*").should be_empty
ModelHelper1.redis.keys("*").should be_empty
db("ModelHelper3").keys("*").should have(5).items
ModelHelper3.redis.keys("*").should have(5).items
stats = ModelHelper3.fetch("sheep.black", @time.hours_ago(2), @time.hours_since(1), :label_indexing => false)
stats.total["count"].should == 2
stats.total["weight"].should == 156
stats = ModelHelper3.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1), :label_indexing => false)
stats.total[:count].should == 8
stats.total[:weight].should == 617
ModelHelper3.connect_to(:port => 8379, :db => 13)
ModelHelper3.redis.client.db.should == 13
stats = ModelHelper3.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1), :label_indexing => false)
stats.total.should == {}
ModelHelper3.connect_to(:port => 8379, :db => 14)
ModelHelper3.redis.client.db.should == 14
stats = ModelHelper3.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1), :label_indexing => false)
stats.total[:count].should == 8
stats.total[:weight].should == 617
end
describe "Write Buffer" do
before(:each) do
Redistat.buffer_size = 20
end
after(:each) do
Redistat.buffer_size = 0
end
it "should buffer calls in memory before committing to Redis" do
14.times do
ModelHelper1.store("sheep.black", {:count => 1, :weight => 461}, @time.hours_ago(4))
end
ModelHelper1.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1)).total.should == {}
5.times do
ModelHelper1.store("sheep.black", {:count => 1, :weight => 156}, @time)
end
ModelHelper1.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1)).total.should == {}
ModelHelper1.store("sheep.black", {:count => 1, :weight => 156}, @time)
stats = ModelHelper1.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1))
stats.total["count"].should == 20
stats.total["weight"].should == 7390
end
it "should force flush buffer when #flush(true) is called" do
ModelHelper1.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1)).total.should == {}
14.times do
@@ -189,16 +189,11 @@ describe Redistat::Model do
end
ModelHelper1.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1)).total.should == {}
Redistat.buffer.flush(true)
stats = ModelHelper1.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1))
stats.total["count"].should == 14
stats.total["weight"].should == 6454
end
end
end

View File

@@ -1,36 +1,36 @@
require "spec_helper"
describe Redistat::Options do
before(:each) do
@helper = OptionsHelper.new
@helper.parse_options(:wtf => 'dude', :foo => 'booze')
end
it "should #parse_options" do
@helper.options[:hello].should == 'world'
@helper.options[:foo].should == 'booze'
@helper.options[:wtf].should == 'dude'
@helper.raw_options.should_not have_key(:hello)
end
it "should create option_accessors" do
@helper.hello.should == 'world'
@helper.hello('woooo')
@helper.hello.should == 'woooo'
end
end
class OptionsHelper
include Redistat::Options
option_accessor :hello
def default_options
{ :hello => 'world',
:foo => 'bar' }
end
end
end

View File

@@ -1,14 +1,14 @@
require "spec_helper"
describe Redistat::Result do
it "should should initialize properly" do
options = {:from => "from", :till => "till"}
result = Redistat::Result.new(options)
result.from.should == "from"
result.till.should == "till"
end
it "should have set_or_incr method" do
result = Redistat::Result.new
result[:world].should be_nil
@@ -17,5 +17,5 @@ describe Redistat::Result do
result.set_or_incr(:world, 8)
result[:world].should == 11
end
end
end

View File

@@ -2,20 +2,20 @@ require "spec_helper"
describe Redistat::Scope do
include Redistat::Database
before(:all) do
db.flushdb
end
before(:each) do
@name = "PageViews"
@scope = Redistat::Scope.new(@name)
end
it "should initialize properly" do
@scope.to_s.should == @name
end
it "should increment next_id" do
scope = Redistat::Scope.new("Visitors")
@scope.next_id.should == 1
@@ -23,5 +23,5 @@ describe Redistat::Scope do
@scope.next_id.should == 2
scope.next_id.should == 2
end
end
end

View File

@@ -2,7 +2,7 @@ require "spec_helper"
describe Redistat::Summary do
include Redistat::Database
before(:each) do
db.flushdb
@scope = "PageViews"
@@ -11,27 +11,27 @@ describe Redistat::Summary do
@key = Redistat::Key.new(@scope, @label, @date, {:depth => :day})
@stats = {"views" => 3, "visitors" => 2}
end
it "should update a single summary properly" do
Redistat::Summary.send(:update_fields, @key, @stats, :hour)
summary = db.hgetall(@key.to_s(:hour))
summary.should have(2).items
summary["views"].should == "3"
summary["visitors"].should == "2"
Redistat::Summary.send(:update_fields, @key, @stats, :hour)
summary = db.hgetall(@key.to_s(:hour))
summary.should have(2).items
summary["views"].should == "6"
summary["visitors"].should == "4"
Redistat::Summary.send(:update_fields, @key, {"views" => -4, "visitors" => -3}, :hour)
summary = db.hgetall(@key.to_s(:hour))
summary.should have(2).items
summary["views"].should == "2"
summary["visitors"].should == "1"
end
it "should update all summaries properly" do
Redistat::Summary.update_all(@key, @stats, :sec)
[:year, :month, :day, :hour, :min, :sec, :usec].each do |depth|
@@ -45,7 +45,7 @@ describe Redistat::Summary do
end
end
end
it "should update summaries even if no label is set" do
key = Redistat::Key.new(@scope, nil, @date, {:depth => :day})
Redistat::Summary.send(:update_fields, key, @stats, :hour)
@@ -54,7 +54,7 @@ describe Redistat::Summary do
summary["views"].should == "3"
summary["visitors"].should == "2"
end
it "should inject stats key grouping summaries" do
hash = { "count/hello" => 3, "count/world" => 7,
"death/bomb" => 4, "death/unicorn" => 3,
@@ -64,7 +64,7 @@ describe Redistat::Summary do
"death" => 7, "death/bomb" => 4, "death/unicorn" => 3,
"od" => 15, :"od/sugar" => 7, :"od/meth" => 8 }
end
it "should properly store key group summaries" do
stats = {"views" => 3, "visitors/eu" => 2, "visitors/us" => 4}
Redistat::Summary.update_all(@key, stats, :hour)
@@ -75,7 +75,7 @@ describe Redistat::Summary do
summary["visitors/eu"].should == "2"
summary["visitors/us"].should == "4"
end
it "should not store key group summaries when option is disabled" do
stats = {"views" => 3, "visitors/eu" => 2, "visitors/us" => 4}
Redistat::Summary.update_all(@key, stats, :hour, {:enable_grouping => false})
@@ -85,7 +85,7 @@ describe Redistat::Summary do
summary["visitors/eu"].should == "2"
summary["visitors/us"].should == "4"
end
it "should store label-based grouping enabled stats" do
stats = {"views" => 3, "visitors/eu" => 2, "visitors/us" => 4}
label = "views/about_us"
@@ -96,37 +96,29 @@ describe Redistat::Summary do
key.groups[1].label.to_s.should == "views"
child1 = key.groups[0]
parent = key.groups[1]
label = "views/contact"
key = Redistat::Key.new(@scope, label, @date)
Redistat::Summary.update_all(key, stats, :hour)
key.groups[0].label.to_s.should == "views/contact"
key.groups[1].label.to_s.should == "views"
child2 = key.groups[0]
summary = db.hgetall(child1.to_s(:hour))
summary["views"].should == "3"
summary["visitors/eu"].should == "2"
summary["visitors/us"].should == "4"
summary = db.hgetall(child2.to_s(:hour))
summary["views"].should == "3"
summary["visitors/eu"].should == "2"
summary["visitors/us"].should == "4"
summary = db.hgetall(parent.to_s(:hour))
summary["views"].should == "6"
summary["visitors/eu"].should == "4"
summary["visitors/us"].should == "8"
end
end

View File

@@ -4,27 +4,27 @@ describe Redistat::Synchronize do
it { should respond_to(:monitor) }
it { should respond_to(:thread_safe) }
it { should respond_to(:thread_safe=) }
describe "instanciated class with Redistat::Synchronize included" do
subject { SynchronizeSpecHelper.new }
it { should respond_to(:monitor) }
it { should respond_to(:thread_safe) }
it { should respond_to(:thread_safe=) }
it { should respond_to(:synchronize) }
end
describe "#synchronize method" do
before(:each) do
Redistat::Synchronize.instance_variable_set("@thread_safe", nil)
@obj = SynchronizeSpecHelper.new
end
it "should share single Monitor object across all objects" do
@obj.monitor.should == Redistat::Synchronize.monitor
end
it "should share thread_safe option across all objects" do
obj2 = SynchronizeSpecHelper.new
Redistat::Synchronize.thread_safe.should be_false
@@ -35,14 +35,14 @@ describe Redistat::Synchronize do
@obj.thread_safe.should be_true
obj2.thread_safe.should be_true
end
it "should not synchronize when thread_safe is disabled" do
# monitor receives :synchronize twice cause #thread_safe is _always_ synchronized
Redistat::Synchronize.monitor.should_receive(:synchronize).twice
@obj.thread_safe.should be_false # first #synchronize call
@obj.synchronize { 'foo' } # one #synchronize call while checking #thread_safe
end
it "should synchronize when thread_safe is enabled" do
Monitor.class_eval {
# we're stubbing synchronize to ensure it's being called correctly, but still need it :P
@@ -56,7 +56,7 @@ describe Redistat::Synchronize do
@obj.synchronize { 'foo' } # two synchronize calls, once while checking thread_safe, once to call black
end
end
end
class SynchronizeSpecHelper

View File

@@ -2,13 +2,13 @@ require "spec_helper"
describe "Thread-Safety" do
include Redistat::Database
before(:each) do
db.flushdb
end
#TODO should have more comprehensive thread-safe tests
it "should incr in multiple threads" do
threads = []
50.times do
@@ -19,7 +19,7 @@ describe "Thread-Safety" do
threads.each { |t| t.join }
db.get("spec:incr").should == "50"
end
it "should store event in multiple threads" do
class ThreadSafetySpec
include Redistat::Model
@@ -35,5 +35,5 @@ describe "Thread-Safety" do
result.total[:count].should == 50
result.total[:rand].should <= 250
end
end
end