File: defined_spec.rb

package info (click to toggle)
puppet 5.5.22-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 21,316 kB
  • sloc: ruby: 254,925; sh: 1,608; xml: 219; makefile: 153; sql: 103
file content (288 lines) | stat: -rw-r--r-- 10,535 bytes parent folder | download | duplicates (3)
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
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
require 'spec_helper'
require 'puppet/pops'
require 'puppet/loaders'

describe "the 'defined' function" do
  after(:all) { Puppet::Pops::Loaders.clear }

  # This loads the function once and makes it easy to call it
  # It does not matter that it is not bound to the env used later since the function
  # looks up everything via the scope that is given to it.
  # The individual tests needs to have a fresh env/catalog set up
  #
  let(:loaders) { Puppet::Pops::Loaders.new(Puppet::Node::Environment.create(:testing, [])) }
  let(:func) { loaders.puppet_system_loader.load(:function, 'defined') }

  before :each do
    # A fresh environment is needed for each test since tests creates types and resources
    environment = Puppet::Node::Environment.create(:testing, [])
    @node = Puppet::Node.new('yaynode', :environment => environment)
    @known_resource_types = environment.known_resource_types
    @compiler = Puppet::Parser::Compiler.new(@node)
    @scope = Puppet::Parser::Scope.new(@compiler)
  end

  def newclass(name)
    @known_resource_types.add Puppet::Resource::Type.new(:hostclass, name)
  end

  def newdefine(name)
    @known_resource_types.add Puppet::Resource::Type.new(:definition, name)
  end

  def newresource(type, title)
    resource = Puppet::Resource.new(type, title)
    @compiler.add_resource(@scope, resource)
    resource
  end

  #--- CLASS
  #
  context 'can determine if a class' do
    context 'is defined' do

      it 'by using the class name in string form' do
        newclass 'yayness'
        expect(func.call(@scope, 'yayness')).to be_truthy
      end

      it 'by using a Type[Class[name]] type reference' do
        name = 'yayness'
        newclass name
        class_type = Puppet::Pops::Types::TypeFactory.host_class(name)
        type_type = Puppet::Pops::Types::TypeFactory.type_type(class_type)
        expect(func.call(@scope, type_type)).to be_truthy
      end
    end

    context 'is not defined' do
      it 'by using the class name in string form' do
        expect(func.call(@scope, 'yayness')).to be_falsey
      end

      it 'even if there is a define, by using a Type[Class[name]] type reference' do
        name = 'yayness'
        newdefine name
        class_type = Puppet::Pops::Types::TypeFactory.host_class(name)
        type_type = Puppet::Pops::Types::TypeFactory.type_type(class_type)
        expect(func.call(@scope, type_type)).to be_falsey
      end
    end

    context 'is defined and realized' do
      it 'by using a Class[name] reference' do
        name = 'cowabunga'
        newclass name
        newresource(:class, name)
        class_type = Puppet::Pops::Types::TypeFactory.host_class(name)
        expect(func.call(@scope, class_type)).to be_truthy
      end
    end

    context 'is not realized' do
      it '(although defined) by using a Class[name] reference' do
        name = 'cowabunga'
        newclass name
        class_type = Puppet::Pops::Types::TypeFactory.host_class(name)
        expect(func.call(@scope, class_type)).to be_falsey
      end

      it '(and not defined) by using a Class[name] reference' do
        name = 'cowabunga'
        class_type = Puppet::Pops::Types::TypeFactory.host_class(name)
        expect(func.call(@scope, class_type)).to be_falsey
      end
    end
  end

  #---RESOURCE TYPE
  #
  context 'can determine if a resource type' do
    context 'is defined' do

      it 'by using the type name (of a built in type) in string form' do
        expect(func.call(@scope, 'file')).to be_truthy
      end

      it 'by using the type name (of a resource type) in string form' do
        newdefine 'yayness'
        expect(func.call(@scope, 'yayness')).to be_truthy
      end

      it 'by using a File type reference (built in type)' do
        resource_type = Puppet::Pops::Types::TypeFactory.resource('file')
        type_type = Puppet::Pops::Types::TypeFactory.type_type(resource_type)
        expect(func.call(@scope, type_type)).to be_truthy
      end

      it 'by using a Type[File] type reference' do
        resource_type = Puppet::Pops::Types::TypeFactory.resource('file')
        type_type = Puppet::Pops::Types::TypeFactory.type_type(resource_type)
        expect(func.call(@scope, type_type)).to be_truthy
      end

      it 'by using a Resource[T] type reference (defined type)' do
        name = 'yayness'
        newdefine name
        resource_type = Puppet::Pops::Types::TypeFactory.resource(name)
        expect(func.call(@scope, resource_type)).to be_truthy
      end

      it 'by using a Type[Resource[T]] type reference (defined type)' do
        name = 'yayness'
        newdefine name
        resource_type = Puppet::Pops::Types::TypeFactory.resource(name)
        type_type = Puppet::Pops::Types::TypeFactory.type_type(resource_type)
        expect(func.call(@scope, type_type)).to be_truthy
      end
    end

    context 'is not defined' do
      it 'by using the resource name in string form' do
        expect(func.call(@scope, 'notatype')).to be_falsey
      end

      it 'even if there is a class with the same name, by using a Type[Resource[T]] type reference' do
        name = 'yayness'
        newclass name
        resource_type = Puppet::Pops::Types::TypeFactory.resource(name)
        type_type = Puppet::Pops::Types::TypeFactory.type_type(resource_type)
        expect(func.call(@scope, type_type)).to be_falsey
      end
    end

    context 'is defined and instance realized' do
      it 'by using a Resource[T, title] reference for a built in type' do
        type_name = 'file'
        title = '/tmp/myfile'
        newdefine type_name
        newresource(type_name, title)
        class_type = Puppet::Pops::Types::TypeFactory.resource(type_name, title)
        expect(func.call(@scope, class_type)).to be_truthy
      end

      it 'by using a Resource[T, title] reference for a defined type' do
        type_name = 'meme'
        title = 'cowabunga'
        newdefine type_name
        newresource(type_name, title)
        class_type = Puppet::Pops::Types::TypeFactory.resource(type_name, title)
        expect(func.call(@scope, class_type)).to be_truthy
      end
    end

    context 'is not realized' do
      it '(although defined) by using a Resource[T, title] reference or Type[Resource[T, title]] reference' do
        type_name = 'meme'
        title = 'cowabunga'
        newdefine type_name
        resource_type = Puppet::Pops::Types::TypeFactory.resource(type_name, title)
        expect(func.call(@scope, resource_type)).to be_falsey

        type_type = Puppet::Pops::Types::TypeFactory.type_type(resource_type)
        expect(func.call(@scope, type_type)).to be_falsey
      end

      it '(and not defined) by using a Resource[T, title] reference or Type[Resource[T, title]] reference' do
        type_name = 'meme'
        title = 'cowabunga'
        resource_type = Puppet::Pops::Types::TypeFactory.resource(type_name, title)
        expect(func.call(@scope, resource_type)).to be_falsey

        type_type = Puppet::Pops::Types::TypeFactory.type_type(resource_type)
        expect(func.call(@scope, type_type)).to be_falsey
      end
    end
  end

  #---VARIABLES
  #
  context 'can determine if a variable' do
    context 'is defined' do
      it 'by giving the variable in string form' do
        @scope['x'] = 'something'
        expect(func.call(@scope, '$x')).to be_truthy
      end

      it 'by giving a :: prefixed variable in string form' do
        @compiler.topscope['x'] = 'something'
        expect(func.call(@scope, '$::x')).to be_truthy
      end

      it 'by giving a numeric variable in string form (when there is a match scope)' do
        # with no match scope, there are no numeric variables defined
        expect(func.call(@scope, '$0')).to be_falsey
        expect(func.call(@scope, '$42')).to be_falsey
        pattern = Regexp.new('.*')
        @scope.new_match_scope(pattern.match('anything'))

        # with a match scope, all numeric variables are set (the match defines if they have a value or not, but they are defined)
        # even if their value is undef.
        expect(func.call(@scope, '$0')).to be_truthy
        expect(func.call(@scope, '$42')).to be_truthy
      end
    end

    context 'is undefined' do
      it 'by giving a :: prefixed or regular variable in string form' do
        expect(func.call(@scope, '$x')).to be_falsey
        expect(func.call(@scope, '$::x')).to be_falsey
      end
    end
  end

  context 'has any? semantics when given multiple arguments' do
    it 'and one of the names is a defined user defined type' do
      newdefine 'yayness'
      expect(func.call(@scope, 'meh', 'yayness', 'booness')).to be_truthy
    end

    it 'and one of the names is a built type' do
      expect(func.call(@scope, 'meh', 'file', 'booness')).to be_truthy
    end

    it 'and one of the names is a defined class' do
      newclass 'yayness'
      expect(func.call(@scope, 'meh', 'yayness', 'booness')).to be_truthy
    end

    it 'is true when at least one variable exists in scope' do
      @scope['x'] = 'something'
      expect(func.call(@scope, '$y', '$x', '$z')).to be_truthy
    end

    it 'is false when none of the names are defined' do
      expect(func.call(@scope, 'meh', 'yayness', 'booness')).to be_falsey
    end
  end

  it 'raises an argument error when asking if Resource type is defined' do
    resource_type = Puppet::Pops::Types::TypeFactory.resource
    expect { func.call(@scope, resource_type)}.to raise_error(ArgumentError, /reference to all.*type/)
  end

  it 'raises an argument error if you ask if Class is defined' do
    class_type = Puppet::Pops::Types::TypeFactory.host_class
    expect { func.call(@scope, class_type) }.to raise_error(ArgumentError, /reference to all.*class/)
  end

  it 'raises error if referencing undef' do
    expect{func.call(@scope, nil)}.to raise_error(ArgumentError, /'defined' parameter 'vals' expects a value of type String, Type\[CatalogEntry\], or Type\[Type\], got Undef/)
  end

  it 'raises error if referencing a number' do
    expect{func.call(@scope, 42)}.to raise_error(ArgumentError, /'defined' parameter 'vals' expects a value of type String, Type\[CatalogEntry\], or Type\[Type\], got Integer/)
  end

  it 'is false if referencing empty string' do
    expect(func.call(@scope, '')).to be_falsey
  end

  it "is true if referencing 'main'" do
    # mimic what compiler does with "main" in intial import
    newclass ''
    newresource :class, ''
    expect(func.call(@scope, 'main')).to be_truthy
  end

end