require File.join( File.dirname(__FILE__), 'spec_helper' ) describe Trigga::Cache::FileCache do describe "file_path" do before(:each) do @opts = {:blart=>'flange', :cache_key=>'cache_key'} end context "when not given a cache_key" do it "should raise an ArgumentError" do lambda{ Trigga::Cache::FileCache.file_path(:blart=>'flange') }.should raise_error(ArgumentError) end end context "when given a cache_key" do it "should not raise an ArgumentError" do lambda{ Trigga::Cache::FileCache.file_path(@opts) }.should_not raise_error(ArgumentError) end context "when not given a cache_dir" do it "should default cache_dir to the module's attribute" do Trigga::Cache::FileCache.cache_dir = "/blart/flange/foo/bar/" Trigga::Cache::FileCache.file_path(@opts) @opts[:cache_dir].should == "/blart/flange/foo/bar/" end end it "should expand the cache_dir plus cache_key" do File.should_receive(:expand_path).with( "/blart/flange/foo/bar/baz.cache" ).and_return("blart") Trigga::Cache::FileCache.file_path( :cache_dir=> "/blart/flange/foo/bar", :cache_key => "baz.cache") end it "should return the expanded path" do File.stub!(:expand_path).and_return("blart") Trigga::Cache::FileCache.file_path( :cache_dir=> "/blart/flange/foo/bar", :cache_key => "baz.cache").should == "blart" end end end describe "expired?" do before(:each) do Trigga::Cache::FileCache.stub!(:file_path).and_return('/foo/bar/baz.txt') File.stub!(:mtime).and_return(Time.now - 10) @opts = {} end context "when not given :timeout_seconds" do it "should default :timeout_seconds to the module's attribute" do Trigga::Cache::FileCache.timeout_seconds = 345 Trigga::Cache::FileCache.expired?(@opts) @opts[:timeout_seconds].should == 345 end end it "should get the file_path for the given opts" do Trigga::Cache::FileCache.should_receive(:file_path).with(hash_including( {:blart=>'flange'} )).and_return('/foo/bar/baz.txt') Trigga::Cache::FileCache.expired?( :blart=>'flange' ) end it "should get the mtime of the file_path" do File.should_receive(:mtime).with('/foo/bar/baz.txt').and_return(Time.now - 10) Trigga::Cache::FileCache.expired? end context "when the file is dated more than timeout_seconds ago" do it "should return true" do Trigga::Cache::FileCache.expired?(:timeout_seconds=>9).should == true end end context "when the file is dated less than timeout_seconds ago" do it "should return false" do Trigga::Cache::FileCache.expired?(:timeout_seconds=>11).should == false end end end describe "is_in_cache?" do before(:each) do Trigga::Cache::FileCache.stub!(:file_path).and_return('/foo/bar/baz.txt') end it "should get the file_path for the given opts" do Trigga::Cache::FileCache.should_receive(:file_path).with(hash_including( {:blart=>'flange'} )).and_return('/foo/bar/baz.txt') Trigga::Cache::FileCache.is_in_cache?( :blart=>'flange' ) end context "when the file_path exists" do before(:each) do File.stub!(:exists?).with('/foo/bar/baz.txt').and_return(true) end it "should return true" do Trigga::Cache::FileCache.is_in_cache?.should == true end end context "when the file_path does not exist" do before(:each) do File.stub!(:exists?).with('/foo/bar/baz.txt').and_return(false) end it "should return false" do Trigga::Cache::FileCache.is_in_cache?.should == false end end end describe "with_cache" do context "when the entry is in cache" do before(:each) do Trigga::Cache::FileCache.stub!(:is_in_cache?).and_return(true) end context "and has not expired" do before(:each) do Trigga::Cache::FileCache.stub!(:expired?).and_return(false) Trigga::Cache::FileCache.stub!(:get).and_return('result') end it "should get the entry" do Trigga::Cache::FileCache.should_receive(:get).with( :blart=>'flange' ).and_return('result') Trigga::Cache::FileCache.with_cache(:blart=>'flange') end it "should return the results of the get call" do Trigga::Cache::FileCache.with_cache.should == 'result' end it "should not call the given block" do @called = false Trigga::Cache::FileCache.with_cache{ @called = true } @called.should_not == true end end context "but has expired" do before(:each) do Trigga::Cache::FileCache.stub!(:expired?).and_return(true) Trigga::Cache::FileCache.stub!(:delete) Trigga::Cache::FileCache.stub!(:put) end it "should delete the existing entry" do Trigga::Cache::FileCache.should_receive(:delete).with(:blart=>'flange') Trigga::Cache::FileCache.with_cache(:blart=>'flange') {} end it "should call the given block" do @called = false Trigga::Cache::FileCache.with_cache{ @called = true } @called.should == true end it "should return the result of the block call" do Trigga::Cache::FileCache.with_cache{ 'donkeys' }.should == 'donkeys' end it "should put the result to the cache" do Trigga::Cache::FileCache.should_receive(:put).with( {:blart=>'flange'}, 'cheese' ) Trigga::Cache::FileCache.with_cache(:blart=>'flange'){ 'cheese' } end end end end describe "get" do before(:each) do Trigga::Cache::FileCache.stub!(:file_path).and_return('/foo/bar/baz.txt') File.stub!(:open).and_yield(@mock_file = mock('file')) @mock_file.stub!(:read).and_return("contents") end it "should get the file_path for the given opts" do Trigga::Cache::FileCache.should_receive(:file_path).with(hash_including( {:blart=>'flange'} )).and_return('/foo/bar/baz.txt') Trigga::Cache::FileCache.get( :blart=>'flange' ) end it "should open the file in read-only mode" do File.should_receive(:open).with('/foo/bar/baz.txt','r').and_return(@mock_file) Trigga::Cache::FileCache.get( :blart=>'flange' ) end it "should read the file" do @mock_file.should_receive(:read).and_return("contents") Trigga::Cache::FileCache.get( :blart=>'flange' ) end it "should return the file contents" do Trigga::Cache::FileCache.get( :blart=>'flange' ).should == 'contents' end end describe "delete" do before(:each) do Trigga::Cache::FileCache.stub!(:file_path).and_return('/foo/bar/baz.txt') Trigga::Cache::FileCache.stub!(:exists?).and_return(true) File.stub!(:delete).and_return(@mock_file = mock('file')) end it "should get the file_path for the given opts" do Trigga::Cache::FileCache.should_receive(:file_path).with(hash_including( {:blart=>'flange'} )).and_return('/foo/bar/baz.txt') Trigga::Cache::FileCache.delete( :blart=>'flange' ) end context "when the file is_in_cache" do before(:each) do Trigga::Cache::FileCache.stub!(:is_in_cache?).and_return(true) end it "should delete the file" do File.should_receive(:delete).with('/foo/bar/baz.txt') Trigga::Cache::FileCache.delete( :blart=>'flange' ) end end context "when the file is not in cache" do before(:each) do Trigga::Cache::FileCache.stub!(:is_in_cache?).and_return(false) end it "should not delete the file" do File.should_not_receive(:delete) Trigga::Cache::FileCache.delete( :blart=>'flange' ) end end end describe "put" do before(:each) do Trigga::Cache::FileCache.stub!(:file_path).and_return('/foo/bar/baz.txt') File.stub!(:open).and_yield( @mock_file = mock('file') ) @mock_file.stub!(:write) end it "should get the file_path for the given opts" do Trigga::Cache::FileCache.should_receive(:file_path).with(hash_including( {:blart=>'flange'} )).and_return('/foo/bar/baz.txt') Trigga::Cache::FileCache.put( {:blart=>'flange'}, 'content' ) end it "should open the file for writing" do File.should_receive(:open).with('/foo/bar/baz.txt', 'w') Trigga::Cache::FileCache.put( {:blart=>'flange'}, 'content' ) end it "should write the given content to the file" do @mock_file.should_receive(:write).with('content') Trigga::Cache::FileCache.put( {:blart=>'flange'}, 'content' ) end end end