require File.expand_path(File.dirname(__FILE__) + '/spec_helper') class TriggaCacheTestClass include Itrigga::Cache end unless defined?(ActionController::Base) # for testing outside rails module ActionController class Base def render_to_string; "content"; end end end end class TriggaCacheControllerTestClass < ActionController::Base include Itrigga::Cache end describe Itrigga::Cache do before do Itrigga::Cache.setup!(:backend=>:filecache) @klass = TriggaCacheTestClass.new @klass.stub!(:cache_log) # stub out the logging method in tests end describe "included" do it "should include InstanceMethods" do TriggaCacheTestClass.should include Itrigga::Cache::InstanceMethods TriggaCacheControllerTestClass.should include Itrigga::Cache::InstanceMethods end it "should include ParamFu" do TriggaCacheTestClass.should include Trigga::ParamFu end it "should not include the controller methods" do TriggaCacheTestClass.should_not include Itrigga::Cache::ControllerMethods end it "should include the controller methods" do TriggaCacheControllerTestClass.should include Itrigga::Cache::ControllerMethods end end describe "setup" do before do end it "should initialize the memcache client" do @opts = {:abc => 123, :backend => :memcached} Itrigga::Cache::Memcache.should_receive(:setup!).with(@opts) Itrigga::Cache.setup!(@opts) end it "should initialize the filecache client" do @opts = {:abc => 123, :backend => :filecached} Itrigga::Cache::Filecache.should_receive(:setup!).with(@opts) Itrigga::Cache.setup!(@opts) end end describe "instance" do before(:each) do Itrigga::Cache.setup!(:backend=>:filecache) end it "should initialize the memcache client" do Itrigga::Cache::Memcache.should_receive(:instance).and_return(@instance = mock("Instance")) Itrigga::Cache.instance(:backend => :memcached).should == @instance end it "should initialize the filecache client" do Itrigga::Cache::Filecache.should_receive(:instance).and_return(@instance = mock("Instance")) Itrigga::Cache.instance(:backend => :filecache).should == @instance end context "when no backend given" do it "should call instance on the default @@ITRIGGA_CACHE_TYPE" do Itrigga::Cache::Filecache.should_receive(:instance).and_return(@instance = mock("Instance", :cache => "a cache")) Itrigga::Cache.instance() end end it "should return the subclass instance" do Itrigga::Cache::Filecache.stub!(:instance).and_return(@instance = mock("Instance", :cache => "a cache")) Itrigga::Cache.instance().should == @instance end end describe "with_cache" do before do @klass.class.stub!(:get_from_cache) @klass.class.stub!(:set_to_cache) @klass.stub!(:require_param) @opts = {:key => "monkeys"} end it "should call require_param" do @klass.class.should_receive(:require_param).with(@opts, :key) @klass.with_cache(@opts){ nil } end describe "when caching not enabled" do before do @klass.class.stub!(:caching_enabled?).and_return(false) end it "should not call get_from_cache" do @klass.class.should_not_receive(:get_from_cache) @klass.with_cache(@opts){ nil } end it "should return the block output" do @klass.with_cache(@opts){ "blart" }.should == "blart" end end describe "with cache enabled" do before do @klass.class.stub!(:caching_enabled?).and_return(true) end describe "when key no in cache" do it "should call get_from_cache" do @klass.class.should_receive(:get_from_cache).with("monkeys",@opts) @klass.with_cache(@opts){ nil } end it "should call the block" do value = 1 @klass.with_cache(@opts){ value = 2 } value.should == 2 end it "should call set_to_cache" do @klass.class.should_receive(:set_to_cache).with("monkeys",2,{}) @klass.with_cache(@opts){ 2 } end it "should return the value" do @klass.with_cache(@opts){ 2 }.should == 2 end end describe "when key is already in cache" do before do @klass.class.stub!(:get_from_cache).and_return("funkiness") end it "should not call the block" do value = 1 @klass.with_cache(@opts){ value = 2 } value.should == 1 end it "should not call set_to_cache" do @klass.class.should_not_receive(:set_to_cache) @klass.with_cache(@opts){ 2 } end it "should return the original value" do @klass.with_cache(@opts){ 2 }.should == "funkiness" end end end end describe "get_from_cache" do before do Itrigga::Cache.stub!(:instance).and_return(@cache = mock("Cache")) @cache.stub!(:get).and_return("funky") @cache.stub!(:enabled).and_return(true) end context "if caching disabled" do before(:each) do @cache.stub!(:enabled).and_return(false) end it "should return nil" do @klass.class.send("get_from_cache","monkeys").should == nil end end it "should call get with the key" do @cache.should_receive(:get).with("monkeys") @klass.class.send("get_from_cache","monkeys") end it "should return the value" do @klass.class.send("get_from_cache","monkeys").should == "funky" end it "should catch Memcached::NotFound and return nil" do @cache.stub!(:get).and_raise(Memcached::NotFound) lambda { @klass.class.send("get_from_cache","monkeys") }.should_not raise_error @klass.class.send("get_from_cache","monkeys").should == nil end end describe "set_to_cache" do before do Itrigga::Cache.stub!(:instance).and_return(@cache = mock("Cache")) @cache.stub!(:set) @cache.stub!(:enabled).and_return(true) end describe "when no timeout" do before do @opts = {} end it "should call $cache.set" do @cache.should_receive(:set).with("monky","funky",@opts) @klass.class.send("set_to_cache","monky","funky", @opts) end it "should return the value" do @klass.class.send("set_to_cache","monky","funky").should == "funky" end end describe "when given a timeout" do before do @opts = {:timeout => 42} end it "should call $cache.set" do @cache.should_receive(:set).with("monky","funky",@opts) @klass.class.send("set_to_cache","monky","funky",@opts) end it "should return the value" do @klass.class.send("set_to_cache","monky","funky", @opts).should == "funky" end end end describe "delete_from_cache" do before do Itrigga::Cache.stub!(:instance).and_return(@cache = mock("Cache")) @cache.stub!(:delete) @klass.class.stub!(:caching_enabled?).and_return(true) end it "should return nil if caching disabled" do @klass.class.stub!(:caching_enabled?).and_return(false) @klass.class.send("delete_from_cache","monkeys").should == nil end it "should call delete with the key" do @cache.should_receive(:delete).with("monkeys") @klass.class.send("delete_from_cache","monkeys") end it "should catch Memcached::NotFound and return nil" do @cache.stub!(:delete).and_raise(Memcached::NotFound) lambda { @klass.class.send("delete_from_cache","monkeys") }.should_not raise_error @klass.class.send("delete_from_cache","monkeys").should == nil end end describe "with_controller_cache" do before do @controller = TriggaCacheControllerTestClass.new @controller.stub!(:delete_from_cache) @controller.stub!(:with_cache) @controller.stub!(:cache_log) # stub out the logging method in tests @controller.stub!(:render) @controller.stub!(:performed?).and_return(false) @controller.stub!(:request => mock("Request", :format => mock("Format", :html? => true))) @controller.stub!(:params).and_return({}) @controller.stub!(:caching_enabled?).and_return(true) @abc = 1 end describe "when caching disabled" do before do @controller.stub!(:caching_enabled?).and_return(false) end it "should log a message" do @controller.should_receive(:cache_log).with("Cache not enabled!",{}) @controller.with_controller_cache(){ @abc = 2 } end it "should call the block" do @controller.with_controller_cache(){ @abc = 2 } @abc.should == 2 end it "should save the output from the block into the @content instance variable" do @controller.with_controller_cache(){ @abc = 2 } @controller.instance_variable_get("@content").should == 2 end describe "when performed? is false" do it "should not call render_to_string" do @controller.stub!(:performed?).and_return(false) @controller.should_receive(:render_to_string) @controller.with_controller_cache(){ nil } end end describe "when performed? is true" do it "should not call render_to_string" do @controller.stub!(:performed?).and_return(true) @controller.should_not_receive(:render_to_string) @controller.with_controller_cache(){ nil } end end end describe "when caching enabled" do before do @controller.stub!(:caching_enabled?).and_return(true) @opts = {:key => "key"} end it "should raise an error if :key not given" do expect{ @controller.with_controller_cache(){ nil } }.to raise_error end it "should call delete_from_cache if the freshen key is given" do @controller.should_receive(:delete_from_cache).with("key", @opts) @controller.stub!(:params).and_return("freshen" => true) @controller.with_controller_cache(@opts){ nil } end it "should not call delete_from_cache" do @controller.should_not_receive(:delete_from_cache) @controller.with_controller_cache(@opts.merge("freshen" => true)){ nil } end it "should call with_cache" do @controller.should_receive(:with_cache).and_return("content") @controller.with_controller_cache(@opts) { "content" } end it "should call render_to_string" do @controller.should_receive(:render_to_string).and_return("content") @controller.stub!(:performed?).and_return(false) @controller.with_controller_cache(@opts) { nil } end it "should call not render_to_string" do @controller.should_not_receive(:render_to_string).and_return("content") @controller.stub!(:performed?).and_return(true) @controller.with_controller_cache(@opts) { "content" } end it "should call not render_to_string" do @controller.should_not_receive(:render_to_string).and_return("content") @controller.stub!(:performed?).and_return(true) @controller.with_controller_cache(@opts) { nil } end it "should call render" do @controller.should_receive(:render).with(hash_including(:text => "content", :content_type => "text/html")) @controller.with_controller_cache(@opts) { "content" } end it "should call render with status set from the instance variable @status" do @controller.should_receive(:render).with(hash_including(:status => 418)) @controller.send(:instance_variable_set, "@status", 418) @controller.with_controller_cache(@opts) { "content" } end it "should return the content" do @controller.with_controller_cache(@opts) { "content" }.should == "content" end describe "when an error occurs" do before do @controller.stub!(:with_cache).and_raise("An error") end it "should handle the error" do lambda { @controller.with_controller_cache(@opts) { "content" } }.should_not raise_error end it "should log the error" do @controller.should_receive(:cache_log).with("Error when rendering cache block: An error", {:key=>"key"}) @controller.with_controller_cache(@opts) { "content" } end it "should call the block and set the output into @content" do @controller.with_controller_cache(@opts) { "content" } @controller.instance_variable_get("@content").should == "content" end it "should call render_to_string" do @controller.stub!(:performed?).and_return(false) @controller.should_receive(:render_to_string).and_return("string") @controller.with_controller_cache(@opts) { nil } end it "should not call render_to_string" do @controller.stub!(:performed?).and_return(true) @controller.should_not_receive(:render_to_string).and_return("string") @controller.with_controller_cache(@opts) { nil } end it "should not call render_to_string" do @controller.stub!(:performed?).and_return(false) @controller.should_not_receive(:render_to_string).and_return("string") @controller.with_controller_cache(@opts) { "content" } end end end end end