summaryrefslogtreecommitdiffstats
path: root/spec/unit/util/collection_spec.rb
blob: 86b602f32b343da399bd28fa84772e5b6e957f08 (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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
#!/usr/bin/env ruby

require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')

require 'facter/util/collection'

describe Facter::Util::Collection do
    it "should have a method for adding facts" do
        Facter::Util::Collection.new.should respond_to(:add)
    end

    it "should have a method for returning a loader" do
        Facter::Util::Collection.new.should respond_to(:loader)
    end

    it "should use an instance of the Loader class as its loader" do
        Facter::Util::Collection.new.loader.should be_instance_of(Facter::Util::Loader)
    end

    it "should cache its loader" do
        coll = Facter::Util::Collection.new
        coll.loader.should equal(coll.loader)
    end

    it "should have a method for loading all facts" do
        Facter::Util::Collection.new.should respond_to(:load_all)
    end

    it "should delegate its load_all method to its loader" do
        coll = Facter::Util::Collection.new
        coll.loader.expects(:load_all)
        coll.load_all
    end

    describe "when adding facts" do
        before do
            @coll = Facter::Util::Collection.new
        end

        it "should create a new fact if no fact with the same name already exists" do
            fact = mock 'fact'
            Facter::Util::Fact.expects(:new).with { |name, *args| name == :myname }.returns fact

            @coll.add(:myname)
        end

        it "should accept options" do
            @coll.add(:myname, :ldapname => "whatever") { }
        end

        it "should set any appropriate options on the fact instances" do
            # Use a real fact instance, because we're using respond_to?
            fact = Facter::Util::Fact.new(:myname)
            fact.expects(:ldapname=).with("testing")
            Facter::Util::Fact.expects(:new).with(:myname).returns fact

            @coll.add(:myname, :ldapname => "testing")
        end

        it "should set appropriate options on the resolution instance" do
            fact = Facter::Util::Fact.new(:myname)
            Facter::Util::Fact.expects(:new).with(:myname).returns fact

            resolve = Facter::Util::Resolution.new(:myname) {}
            fact.expects(:add).returns resolve

            @coll.add(:myname, :timeout => "myval") {}
        end

        it "should not pass fact-specific options to resolutions" do
            fact = Facter::Util::Fact.new(:myname)
            Facter::Util::Fact.expects(:new).with(:myname).returns fact

            resolve = Facter::Util::Resolution.new(:myname) {}
            fact.expects(:add).returns resolve

            fact.expects(:ldapname=).with("foo")
            resolve.expects(:timeout=).with("myval")

            @coll.add(:myname, :timeout => "myval", :ldapname => "foo") {}
        end

        it "should fail if invalid options are provided" do
            lambda { @coll.add(:myname, :foo => :bar) }.should raise_error(ArgumentError)
        end

        describe "and a block is provided" do
            it "should use the block to add a resolution to the fact" do
                fact = mock 'fact'
                Facter::Util::Fact.expects(:new).returns fact

                fact.expects(:add)

                @coll.add(:myname) {}
            end
        end
    end

    it "should have a method for retrieving facts by name" do
        Facter::Util::Collection.new.should respond_to(:fact)
    end

    describe "when retrieving facts" do
        before do
            @coll = Facter::Util::Collection.new

            @fact = @coll.add("YayNess")
        end

        it "should return the fact instance specified by the name" do
            @coll.fact("YayNess").should equal(@fact)
        end

        it "should be case-insensitive" do
            @coll.fact("yayness").should equal(@fact)
        end

        it "should treat strings and symbols equivalently" do
            @coll.fact(:yayness).should equal(@fact)
        end

        it "should use its loader to try to load the fact if no fact can be found" do
            @coll.loader.expects(:load).with(:testing)
            @coll.fact("testing")
        end

        it "should return nil if it cannot find or load the fact" do
            @coll.loader.expects(:load).with(:testing)
            @coll.fact("testing").should be_nil
        end
    end

    it "should have a method for returning a fact's value" do
        Facter::Util::Collection.new.should respond_to(:value)
    end

    describe "when returning a fact's value" do
        before do
            @coll = Facter::Util::Collection.new
            @fact = @coll.add("YayNess")

            @fact.stubs(:value).returns "result"
        end

        it "should use the 'fact' method to retrieve the fact" do
            @coll.expects(:fact).with(:yayness).returns @fact
            @coll.value(:yayness)
        end

        it "should return the result of calling :value on the fact" do
            @fact.expects(:value).returns "result"

            @coll.value("YayNess").should == "result"
        end

        it "should be case-insensitive" do
            @coll.value("yayness").should_not be_nil
        end

        it "should treat strings and symbols equivalently" do
            @coll.value(:yayness).should_not be_nil
        end
    end

    it "should return the fact's value when the array index method is used" do
        @coll = Facter::Util::Collection.new
        @coll.expects(:value).with("myfact").returns "foo"
        @coll["myfact"].should == "foo"
    end

    it "should have a method for flushing all facts" do
        @coll = Facter::Util::Collection.new
        @fact = @coll.add("YayNess")

        @fact.expects(:flush)

        @coll.flush
    end

    it "should have a method that returns all fact names" do
        @coll = Facter::Util::Collection.new
        @coll.add(:one)
        @coll.add(:two)

        @coll.list.sort { |a,b| a.to_s <=> b.to_s }.should == [:one, :two]
    end

    it "should have a method for returning a hash of fact values" do
        Facter::Util::Collection.new.should respond_to(:to_hash)
    end

    describe "when returning a hash of values" do
        before do
            @coll = Facter::Util::Collection.new
            @fact = @coll.add(:one)
            @fact.stubs(:value).returns "me"
        end

        it "should return a hash of fact names and values with the fact names as strings" do
            @coll.to_hash.should == {"one" => "me"}
        end

        it "should not include facts that did not return a value" do
            f = @coll.add(:two)
            f.stubs(:value).returns nil
            @coll.to_hash.should_not be_include(:two)
        end
    end

    it "should have a method for iterating over all facts" do
        Facter::Util::Collection.new.should respond_to(:each)
    end

    it "should include Enumerable" do
        Facter::Util::Collection.ancestors.should be_include(Enumerable)
    end

    describe "when iterating over facts" do
        before do
            @coll = Facter::Util::Collection.new
            @one = @coll.add(:one)
            @two = @coll.add(:two)
        end

        it "should yield each fact name and the fact value" do
            @one.stubs(:value).returns "ONE"
            @two.stubs(:value).returns "TWO"
            facts = {}
            @coll.each do |fact, value|
                facts[fact] = value
            end
            facts.should == {"one" => "ONE", "two" => "TWO"}
        end

        it "should convert the fact name to a string" do
            @one.stubs(:value).returns "ONE"
            @two.stubs(:value).returns "TWO"
            facts = {}
            @coll.each do |fact, value|
                fact.should be_instance_of(String)
            end
        end

        it "should only yield facts that have values" do
            @one.stubs(:value).returns "ONE"
            @two.stubs(:value).returns nil
            facts = {}
            @coll.each do |fact, value|
                facts[fact] = value
            end

            facts.should_not be_include("two")
        end
    end
end