require 'test_helper' context 'class methods without setup' do teardown do AllSeeingEye.redis.flushall end test 'models know their own name' do assert_equal 'model', AllSeeingEye::Model.model_name end test 'models correctly find their next ID' do id = AllSeeingEye::Model.next_id (id + 1..(id + 11)).each {|n|assert_equal AllSeeingEye::Model.next_id, n} end test 'models should get fields' do assert_equal AllSeeingEye::Model.fields, {"uri"=>{"method"=>".request_uri", "object"=>"request"}, "action"=>{"method"=>"[:action]", "object"=>"params"}, "ip"=>{"method"=>".remote_ip", "object"=>"request"}, "controller"=>{"method"=>"[:controller]", "params"=>nil, "object"=>"params"}, "browser"=>{"method"=>".env[\"HTTP_USER_AGENT\"]", "object"=>"request"}, "status"=>{"method"=>".status", "object"=>"response"}} end test 'models should get field names' do assert_equal ["uri", "action", "ip", "controller", "browser", "status", "created_at", "time_spent"], AllSeeingEye::Model.field_names end test 'return a new model object' do time = Time.now obj = AllSeeingEye::Model.create(:uri => '/test/', :ip => '127.0.0.1', :created_at => time) assert_equal '/test/', obj.uri assert_equal '127.0.0.1', obj.ip assert_equal time, obj.created_at assert_equal nil, obj.action end test 'create a model object' do obj = AllSeeingEye::Model.create(:uri => '/test/', :ip => '127.0.0.1') assert_equal '/test/', obj.uri assert_equal '127.0.0.1', obj.ip assert_equal Marshal.dump(obj), AllSeeingEye.redis["allseeingeye:model:#{AllSeeingEye::Model.next_id - 1}"] assert_equal '1', AllSeeingEye.redis.zscore("allseeingeye:model:fields:uri", '/test/') assert_equal '1', AllSeeingEye.redis.zscore("allseeingeye:model:fields:ip", '127.0.0.1') assert_equal [obj.id.to_s], AllSeeingEye.redis.sort("allseeingeye:model:fields:uri:/test/", :by => 'nosort') assert_equal [obj.id.to_s], AllSeeingEye.redis.sort("allseeingeye:model:fields:ip:127.0.0.1", :by => 'nosort') end test 'unmarshal an object with load' do time = Time.now raw = AllSeeingEye::Model.create(:uri => '/test/', :ip => '127.0.0.1', :created_at => time) dump = Marshal.dump(raw) obj = AllSeeingEye::Model.load(dump) assert_equal '/test/', obj.uri assert_equal '127.0.0.1', obj.ip assert_equal time, obj.created_at assert_equal raw.id, obj.id end test 'find an object by its ID' do time = Time.now obj = AllSeeingEye::Model.create(:uri => '/test/', :ip => '127.0.0.1', :created_at => time) found = AllSeeingEye::Model.find(obj.id) [:uri, :ip, :created_at].each {|f| assert_equal obj.send(f), found.send(f)} end test 'find all objects' do obj1 = AllSeeingEye::Model.create(:uri => '/test/', :ip => '127.0.0.1', :created_at => Time.now) obj2 = AllSeeingEye::Model.create(:uri => '/test/', :ip => '127.0.0.1', :created_at => Time.now) obj3 = AllSeeingEye::Model.create(:uri => '/test/', :ip => '127.0.0.1', :created_at => Time.now) assert_equal [obj1.id, obj2.id, obj3.id], AllSeeingEye::Model.all.collect(&:id) end test 'find the count of all objects' do obj1 = AllSeeingEye::Model.create(:uri => '/test/', :ip => '127.0.0.1', :created_at => Time.now) obj2 = AllSeeingEye::Model.create(:uri => '/test/', :ip => '127.0.0.1', :created_at => Time.now) obj3 = AllSeeingEye::Model.create(:uri => '/test/', :ip => '127.0.0.1', :created_at => Time.now) assert_equal 3, AllSeeingEye::Model.count end end context 'class methods with setup' do setup do @time = Time.now @obj1 = AllSeeingEye::Model.create(:uri => '/', :ip => '127.0.0.1', :created_at => @time - 10 * 60) @obj2 = AllSeeingEye::Model.create(:uri => '/test/', :ip => '127.0.0.1', :created_at => @time - 5 * 60) @obj3 = AllSeeingEye::Model.create(:uri => '/test/', :ip => '127.0.0.1', :created_at => @time - 3 * 60) @obj4 = AllSeeingEye::Model.create(:uri => '/test/', :ip => '192.168.0.1', :created_at => @time - 1 * 60) @obj5 = AllSeeingEye::Model.create(:uri => '/test/', :ip => '127.0.0.1', :created_at => @time + 2 * 60) @obj6 = AllSeeingEye::Model.create(:uri => '/test/', :ip => '192.168.0.1', :created_at => @time + 2 * 60) end teardown do AllSeeingEye.redis.flushall end test 'find all objects in a date range with a start and a stop' do results = AllSeeingEye::Model.all(:start => @time - 11 * 60, :stop => @time - 4 * 60) assert_equal 2, results.count assert_equal @obj1.id, results[0].id assert_equal @obj2.id, results[1].id end test 'find all objects in a date range with only a start' do results = AllSeeingEye::Model.all(:start => @time) assert_equal 2, results.count assert_equal @obj5.id, results[0].id assert_equal @obj6.id, results[1].id end test 'find all objects in a date range with only a stop' do results = AllSeeingEye::Model.all(:stop => @time) assert_equal 4, results.count assert_equal @obj1.id, results[0].id assert_equal @obj2.id, results[1].id assert_equal @obj3.id, results[2].id assert_equal @obj4.id, results[3].id end test 'find model objects by a string field' do results = AllSeeingEye::Model.find_by_field('uri', :value => '/test/') assert_equal 5, results.count assert results.collect(&:id).include?(@obj2.id) assert results.collect(&:id).include?(@obj3.id) assert results.collect(&:id).include?(@obj4.id) assert results.collect(&:id).include?(@obj5.id) assert results.collect(&:id).include?(@obj6.id) end test 'find model objects by a string field with a start' do results = AllSeeingEye::Model.find_by_field('uri', :value => '/test/', :start => @time - 4 * 60) assert_equal 4, results.count assert results.collect(&:id).include?(@obj3.id) assert results.collect(&:id).include?(@obj4.id) assert results.collect(&:id).include?(@obj5.id) assert results.collect(&:id).include?(@obj6.id) end test 'find model objects by a string field with a stop' do results = AllSeeingEye::Model.find_by_field('uri', :value => '/test/', :stop => @time) assert_equal 3, results.count assert results.collect(&:id).include?(@obj2.id) assert results.collect(&:id).include?(@obj3.id) assert results.collect(&:id).include?(@obj4.id) end test 'find model objects by a string field with a start and a stop' do results = AllSeeingEye::Model.find_by_field('uri', :value => '/test/', :start => @time - 4 * 60, :stop => @time) assert_equal 2, results.count assert results.collect(&:id).include?(@obj3.id) assert results.collect(&:id).include?(@obj4.id) end test 'find model objects by a date field' do results = AllSeeingEye::Model.find_by_field('created_at', :start => @obj1.created_at, :stop => @obj4.created_at) assert_equal 4, results.count assert_equal results.first.id, @obj1.id assert_equal results.last.id, @obj4.id end test 'count model objects' do assert_equal 2, AllSeeingEye::Model.count(:start => @time - 11 * 60, :stop => @time - 4 * 60) assert_equal 2, AllSeeingEye::Model.count(:start => @time + 2 * 60, :stop => @time + 2 * 60) assert_equal 4, AllSeeingEye::Model.count(:stop => @time) assert_equal 2, AllSeeingEye::Model.count(:start => @time) assert_equal 6, AllSeeingEye::Model.count end test 'return the first object' do assert_equal @obj1.id, AllSeeingEye::Model.first.id end test 'return the last object' do assert_equal @obj6.id, AllSeeingEye::Model.last.id end test 'return count in a field' do counts = AllSeeingEye::Model.count_by_field('uri') assert_equal '/test/', counts.first.first assert_equal 5, counts.first.last assert_equal '/', counts.last.first assert_equal 1, counts.last.last end test 'search with Chronic' do results = AllSeeingEye::Model.search('last friday to five minutes ago') assert_equal 2, results.size assert_equal @obj1.id, results[0].id assert_equal @obj2.id, results[1].id end test 'search by a specific field' do results = AllSeeingEye::Model.search('uri:/test/') assert_equal 5, results.count assert results.collect(&:id).include?(@obj2.id) assert results.collect(&:id).include?(@obj3.id) assert results.collect(&:id).include?(@obj4.id) assert results.collect(&:id).include?(@obj5.id) assert results.collect(&:id).include?(@obj6.id) end test 'search without a specific field' do results = AllSeeingEye::Model.search('192.168.0.1') assert_equal 2, results.count assert results.collect(&:id).include?(@obj4.id) assert results.collect(&:id).include?(@obj6.id) end end context 'many objects' do setup do @time = Time.now 2000.times do |n| instance_variable_set("@obj#{n}".to_sym, AllSeeingEye::Model.create(:uri => '/', :ip => '127.0.0.1', :created_at => @time - (n * (1999 - n)).minutes)) end end test 'conglomerate an array successfully' do results = AllSeeingEye::Model.all counts = AllSeeingEye::Model.conglomerate(results) assert_equal 500, counts.count assert_equal 2000, counts.inject(0) {|sum, k| sum + k.last} assert_equal @obj999.created_at.to_i, counts.first.first end end context 'instance methods' do teardown do AllSeeingEye.redis.flushall end test 'assign all attr_accessors from fields at initialization' do obj = AllSeeingEye::Model.new AllSeeingEye::Model.field_names.each {|f| assert obj.respond_to?(f.to_sym); assert obj.respond_to?("#{f}=".to_sym)} end test 'assign an object an ID if it does not have one' do obj = AllSeeingEye::Model.new assert_equal nil, obj.instance_variable_get(:@id) assert_equal 1, obj.id assert_equal 1, obj.instance_variable_get(:@id) end test 'save a new model object' do obj = AllSeeingEye::Model.new(:uri => '/test/', :ip => '127.0.0.1') assert obj.save assert_equal '/test/', obj.uri assert_equal '127.0.0.1', obj.ip assert_equal Marshal.dump(obj), AllSeeingEye.redis["allseeingeye:model:#{AllSeeingEye::Model.next_id - 1}"] assert_equal '1', AllSeeingEye.redis.zscore("allseeingeye:model:fields:uri", '/test/') assert_equal '1', AllSeeingEye.redis.zscore("allseeingeye:model:fields:ip", '127.0.0.1') assert_equal [obj.id.to_s], AllSeeingEye.redis.sort("allseeingeye:model:fields:uri:/test/", :by => 'nosort') end test 'save a new model object with date attributes' do time = Time.now obj = AllSeeingEye::Model.new(:created_at => time) assert obj.save assert_equal time, obj.created_at assert_equal Marshal.dump(obj), AllSeeingEye.redis["allseeingeye:model:#{AllSeeingEye::Model.next_id - 1}"] assert_equal time.to_i.to_s, AllSeeingEye.redis.zscore("allseeingeye:model:fields:created_at", obj.id) end test 'ignore empty and nil attributes in model object creation' do time = Time.now obj = AllSeeingEye::Model.new(:created_at => time, :uri => '/test/', :ip => nil, :action => '') assert obj.save assert_equal time, obj.created_at assert_equal '/test/', obj.uri assert_equal nil, obj.ip assert_equal '', obj.action assert_equal Marshal.dump(obj), AllSeeingEye.redis["allseeingeye:model:#{AllSeeingEye::Model.next_id - 1}"] assert_equal time.to_i.to_s, AllSeeingEye.redis.zscore("allseeingeye:model:fields:created_at", obj.id) assert_equal '1', AllSeeingEye.redis.zscore("allseeingeye:model:fields:uri", '/test/') assert_equal nil, AllSeeingEye.redis.zscore("allseeingeye:model:fields:ip", nil) assert_equal nil, AllSeeingEye.redis.zscore("allseeingeye:model:fields:action", '') assert_equal [obj.id.to_s], AllSeeingEye.redis.sort("allseeingeye:model:fields:uri:/test/", :by => 'nosort') assert_equal [], AllSeeingEye.redis.sort("allseeingeye:model:fields:ip:", :by => 'nosort') assert_equal [], AllSeeingEye.redis.sort("allseeingeye:model:fields:action:", :by => 'nosort') end end