summaryrefslogtreecommitdiffstats
path: root/spec/unit/util/autoload/file_cache_spec.rb
blob: cdde9bb482373b5200792966102b8217fc3b4a89 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#!/usr/bin/env rspec
require 'spec_helper'
require 'puppet/util/autoload/file_cache'

class FileCacheTester
  include Puppet::Util::Autoload::FileCache
end

describe Puppet::Util::Autoload::FileCache do
  before do
    @cacher = FileCacheTester.new
  end

  after do
    Puppet::Util::Autoload::FileCache.clear
  end

  describe "when checking whether files exist" do
    it "should have a method for testing whether a file exists" do
      @cacher.should respond_to(:file_exist?)
    end

    it "should use lstat to determine whether a file exists" do
      File.expects(:lstat).with("/my/file")
      @cacher.file_exist?("/my/file")
    end

    it "should consider a file as absent if its lstat fails" do
      File.expects(:lstat).with("/my/file").raises Errno::ENOENT
      @cacher.should_not be_file_exist("/my/file")
    end

    it "should consider a file as absent if the directory is absent" do
      File.expects(:lstat).with("/my/file").raises Errno::ENOTDIR
      @cacher.should_not be_file_exist("/my/file")
    end

    it "should consider a file as absent permissions are missing" do
      File.expects(:lstat).with("/my/file").raises Errno::EACCES
      @cacher.should_not be_file_exist("/my/file")
    end

    it "should raise non-fs exceptions" do
      File.expects(:lstat).with("/my/file").raises ArgumentError
      lambda { @cacher.file_exist?("/my/file") }.should raise_error(ArgumentError)
    end

    it "should consider a file as present if its lstat succeeds" do
      File.expects(:lstat).with("/my/file").returns mock("stat")
      @cacher.should be_file_exist("/my/file")
    end

    it "should not stat a file twice in quick succession when the file is missing" do
      File.expects(:lstat).with("/my/file").once.raises Errno::ENOENT
      @cacher.should_not be_file_exist("/my/file")
      @cacher.should_not be_file_exist("/my/file")
    end

    it "should not stat a file twice in quick succession when the file is present" do
      File.expects(:lstat).with("/my/file").once.returns mock("stat")
      @cacher.should be_file_exist("/my/file")
      @cacher.should be_file_exist("/my/file")
    end

    it "should expire cached data after 15 seconds" do
      now = Time.now

      later = now + 16

      Time.expects(:now).times(3).returns(now).then.returns(later).then.returns(later)
      File.expects(:lstat).with("/my/file").times(2).returns(mock("stat")).then.raises Errno::ENOENT
      @cacher.should be_file_exist("/my/file")
      @cacher.should_not be_file_exist("/my/file")
    end

    it "should share cached data across autoload instances" do
      File.expects(:lstat).with("/my/file").once.returns mock("stat")
      other = Puppet::Util::Autoload.new("bar", "tmp")

      @cacher.should be_file_exist("/my/file")
      other.should be_file_exist("/my/file")
    end
  end

  describe "when checking whether files exist" do
    before do
      @stat = stub 'stat', :directory? => true
    end

    it "should have a method for determining whether a directory exists" do
      @cacher.should respond_to(:directory_exist?)
    end

    it "should use lstat to determine whether a directory exists" do
      File.expects(:lstat).with("/my/file").returns @stat
      @cacher.directory_exist?("/my/file")
    end

    it "should consider a directory as absent if its lstat fails" do
      File.expects(:lstat).with("/my/file").raises Errno::ENOENT
      @cacher.should_not be_directory_exist("/my/file")
    end

    it "should consider a file as absent if the directory is absent" do
      File.expects(:lstat).with("/my/file").raises Errno::ENOTDIR
      @cacher.should_not be_directory_exist("/my/file")
    end

    it "should consider a file as absent permissions are missing" do
      File.expects(:lstat).with("/my/file").raises Errno::EACCES
      @cacher.should_not be_directory_exist("/my/file")
    end

    it "should raise non-fs exceptions" do
      File.expects(:lstat).with("/my/file").raises ArgumentError
      lambda { @cacher.directory_exist?("/my/file") }.should raise_error(ArgumentError)
    end

    it "should consider a directory as present if its lstat succeeds and the stat is of a directory" do
      @stat.expects(:directory?).returns true
      File.expects(:lstat).with("/my/file").returns @stat
      @cacher.should be_directory_exist("/my/file")
    end

    it "should consider a directory as absent if its lstat succeeds and the stat is not of a directory" do
      @stat.expects(:directory?).returns false
      File.expects(:lstat).with("/my/file").returns @stat
      @cacher.should_not be_directory_exist("/my/file")
    end

    it "should not stat a directory twice in quick succession when the file is missing" do
      File.expects(:lstat).with("/my/file").once.raises Errno::ENOENT
      @cacher.should_not be_directory_exist("/my/file")
      @cacher.should_not be_directory_exist("/my/file")
    end

    it "should not stat a directory twice in quick succession when the file is present" do
      File.expects(:lstat).with("/my/file").once.returns @stat
      @cacher.should be_directory_exist("/my/file")
      @cacher.should be_directory_exist("/my/file")
    end

    it "should not consider a file to be a directory based on cached data" do
      @stat.stubs(:directory?).returns false
      File.stubs(:lstat).with("/my/file").returns @stat
      @cacher.file_exist?("/my/file")
      @cacher.should_not be_directory_exist("/my/file")
    end

    it "should share cached data across autoload instances" do
      File.expects(:lstat).with("/my/file").once.returns @stat
      other = Puppet::Util::Autoload.new("bar", "tmp")

      @cacher.should be_directory_exist("/my/file")
      other.should be_directory_exist("/my/file")
    end
  end
end