dcca4a4ccd5184d3eaa87d2a48799c6b01132e06
[mirror/dsa-puppet.git] / 3rdparty / modules / stdlib / spec / unit / puppet / provider / file_line / ruby_spec.rb
1 #! /usr/bin/env ruby -S rspec
2 require 'spec_helper'
3 require 'tempfile'
4 provider_class = Puppet::Type.type(:file_line).provider(:ruby)
5 # These tests fail on windows when run as part of the rake task. Individually they pass
6 describe provider_class, :unless => Puppet::Util::Platform.windows? do
7   context "when adding" do
8     let :tmpfile do
9       tmp = Tempfile.new('tmp')
10       path = tmp.path
11       tmp.close!
12       path
13     end
14     let :resource do
15       Puppet::Type::File_line.new(
16         {:name => 'foo', :path => tmpfile, :line => 'foo'}
17       )
18     end
19     let :provider do
20       provider_class.new(resource)
21     end
22
23     it 'should detect if the line exists in the file' do
24       File.open(tmpfile, 'w') do |fh|
25         fh.write('foo')
26       end
27       expect(provider.exists?).to be_truthy
28     end
29     it 'should detect if the line does not exist in the file' do
30       File.open(tmpfile, 'w') do |fh|
31         fh.write('foo1')
32       end
33       expect(provider.exists?).to eql (false)
34     end
35     it 'should append to an existing file when creating' do
36       provider.create
37       expect(File.read(tmpfile).chomp).to eq('foo')
38     end
39   end
40   context 'when using replace' do
41     before :each do
42       # TODO: these should be ported over to use the PuppetLabs spec_helper
43       #  file fixtures once the following pull request has been merged:
44       # https://github.com/puppetlabs/puppetlabs-stdlib/pull/73/files
45       tmp = Tempfile.new('tmp')
46       @tmpfile = tmp.path
47       tmp.close!
48       @resource = Puppet::Type::File_line.new(
49         {
50           :name    => 'foo',
51           :path    => @tmpfile,
52           :line    => 'foo = bar',
53           :match   => '^foo\s*=.*$',
54           :replace => false,
55         }
56       )
57       @provider = provider_class.new(@resource)
58     end
59
60     it 'should not replace the matching line' do
61       File.open(@tmpfile, 'w') do |fh|
62         fh.write("foo1\nfoo=blah\nfoo2\nfoo3")
63       end
64       expect(@provider.exists?).to be_truthy
65       @provider.create
66       expect(File.read(@tmpfile).chomp).to eql("foo1\nfoo=blah\nfoo2\nfoo3")
67     end
68
69     it 'should append the line if no matches are found' do
70       File.open(@tmpfile, 'w') do |fh|
71         fh.write("foo1\nfoo2")
72       end
73       expect(@provider.exists?).to eql (false)
74       @provider.create
75       expect(File.read(@tmpfile).chomp).to eql("foo1\nfoo2\nfoo = bar")
76     end
77
78     it 'should raise an error with invalid values' do
79       expect {
80         @resource = Puppet::Type::File_line.new(
81           {
82             :name     => 'foo',
83             :path     => @tmpfile,
84             :line     => 'foo = bar',
85             :match    => '^foo\s*=.*$',
86             :replace  => 'asgadga',
87           }
88         )
89       }.to raise_error(Puppet::Error, /Invalid value "asgadga"\. Valid values are true, false\./)
90     end
91   end
92   context "when matching" do
93     before :each do
94       # TODO: these should be ported over to use the PuppetLabs spec_helper
95       #  file fixtures once the following pull request has been merged:
96       # https://github.com/puppetlabs/puppetlabs-stdlib/pull/73/files
97       tmp = Tempfile.new('tmp')
98       @tmpfile = tmp.path
99       tmp.close!
100       @resource = Puppet::Type::File_line.new(
101         {
102           :name  => 'foo',
103           :path  => @tmpfile,
104           :line  => 'foo = bar',
105           :match => '^foo\s*=.*$',
106         }
107       )
108       @provider = provider_class.new(@resource)
109     end
110
111     describe 'using match' do
112       it 'should raise an error if more than one line matches, and should not have modified the file' do
113         File.open(@tmpfile, 'w') do |fh|
114           fh.write("foo1\nfoo=blah\nfoo2\nfoo=baz")
115         end
116         expect(@provider.exists?).to eql(false)
117         expect { @provider.create }.to raise_error(Puppet::Error, /More than one line.*matches/)
118         expect(File.read(@tmpfile)).to eql("foo1\nfoo=blah\nfoo2\nfoo=baz")
119       end
120
121       it 'should replace all lines that matches' do
122         @resource = Puppet::Type::File_line.new(
123           {
124             :name     => 'foo',
125             :path     => @tmpfile,
126             :line     => 'foo = bar',
127             :match    => '^foo\s*=.*$',
128             :multiple => true,
129           }
130         )
131         @provider = provider_class.new(@resource)
132         File.open(@tmpfile, 'w') do |fh|
133           fh.write("foo1\nfoo=blah\nfoo2\nfoo=baz")
134         end
135         expect(@provider.exists?).to eql(false)
136         @provider.create
137         expect(File.read(@tmpfile).chomp).to eql("foo1\nfoo = bar\nfoo2\nfoo = bar")
138       end
139
140       it 'should replace all lines that match, even when some lines are correct' do
141         @resource = Puppet::Type::File_line.new(
142           {
143             :name     => 'neil',
144             :path     => @tmpfile,
145             :line     => "\thard\tcore\t0\n",
146             :match    => '^[ \t]hard[ \t]+core[ \t]+.*',
147             :multiple => true,
148           }
149         )
150         @provider = provider_class.new(@resource)
151         File.open(@tmpfile, 'w') do |fh|
152           fh.write("\thard\tcore\t90\n\thard\tcore\t0\n")
153         end
154         expect(@provider.exists?).to eql(false)
155         @provider.create
156         expect(File.read(@tmpfile).chomp).to eql("\thard\tcore\t0\n\thard\tcore\t0")
157       end
158
159       it 'should raise an error with invalid values' do
160         expect {
161           @resource = Puppet::Type::File_line.new(
162             {
163               :name     => 'foo',
164               :path     => @tmpfile,
165               :line     => 'foo = bar',
166               :match    => '^foo\s*=.*$',
167               :multiple => 'asgadga',
168             }
169           )
170         }.to raise_error(Puppet::Error, /Invalid value "asgadga"\. Valid values are true, false\./)
171       end
172
173       it 'should replace a line that matches' do
174         File.open(@tmpfile, 'w') do |fh|
175           fh.write("foo1\nfoo=blah\nfoo2")
176         end
177         expect(@provider.exists?).to eql(false)
178         @provider.create
179         expect(File.read(@tmpfile).chomp).to eql("foo1\nfoo = bar\nfoo2")
180       end
181       it 'should add a new line if no lines match' do
182         File.open(@tmpfile, 'w') do |fh|
183           fh.write("foo1\nfoo2")
184         end
185         expect(@provider.exists?).to eql(false)
186         @provider.create
187         expect(File.read(@tmpfile)).to eql("foo1\nfoo2\nfoo = bar\n")
188       end
189       it 'should do nothing if the exact line already exists' do
190         File.open(@tmpfile, 'w') do |fh|
191           fh.write("foo1\nfoo = bar\nfoo2")
192         end
193         expect(@provider.exists?).to eql(true)
194         @provider.create
195         expect(File.read(@tmpfile).chomp).to eql("foo1\nfoo = bar\nfoo2")
196       end
197
198       it 'should not add line after no matches found' do
199         @resource = Puppet::Type::File_line.new(
200           {
201             :name               => 'foo',
202             :path               => @tmpfile,
203             :line               => 'inserted = line',
204             :match              => '^foo3$',
205             :append_on_no_match => false,
206           }
207         )
208         @provider = provider_class.new(@resource)
209         File.open(@tmpfile, 'w') do |fh|
210           fh.write("foo1\nfoo = blah\nfoo2\nfoo = baz")
211         end
212         expect(@provider.exists?).to be true
213         expect(File.read(@tmpfile).chomp).to eql("foo1\nfoo = blah\nfoo2\nfoo = baz")
214       end
215     end
216
217     describe 'using after' do
218       let :resource do
219         Puppet::Type::File_line.new(
220           {
221             :name  => 'foo',
222             :path  => @tmpfile,
223             :line  => 'inserted = line',
224             :after => '^foo1',
225           }
226         )
227       end
228
229       let :provider do
230         provider_class.new(resource)
231       end
232       context 'match and after set' do
233         shared_context 'resource_create' do
234           let(:match) { '^foo2$' }
235           let(:after) { '^foo1$' }
236           let(:resource) {
237             Puppet::Type::File_line.new(
238               {
239                 :name  => 'foo',
240                 :path  => @tmpfile,
241                 :line  => 'inserted = line',
242                 :after => after,
243                 :match => match,
244               }
245             )
246           }
247         end
248         before :each do
249           File.open(@tmpfile, 'w') do |fh|
250             fh.write("foo1\nfoo2\nfoo = baz")
251           end
252         end
253         describe 'inserts at match' do
254           include_context 'resource_create'
255           it {
256             provider.create
257             expect(File.read(@tmpfile).chomp).to eq("foo1\ninserted = line\nfoo = baz")
258           }
259         end
260         describe 'inserts a new line after when no match' do
261           include_context 'resource_create' do
262             let(:match) { '^nevergoingtomatch$' }
263           end
264           it {
265             provider.create
266             expect(File.read(@tmpfile).chomp).to eq("foo1\ninserted = line\nfoo2\nfoo = baz")
267           }
268         end
269         describe 'append to end of file if no match for both after and match' do
270           include_context 'resource_create' do
271             let(:match) { '^nevergoingtomatch$' }
272             let(:after) { '^stillneverafter' }
273           end
274           it {
275             provider.create
276             expect(File.read(@tmpfile).chomp).to eq("foo1\nfoo2\nfoo = baz\ninserted = line")
277           }
278         end
279       end
280       context 'with one line matching the after expression' do
281         before :each do
282           File.open(@tmpfile, 'w') do |fh|
283             fh.write("foo1\nfoo = blah\nfoo2\nfoo = baz")
284           end
285         end
286
287         it 'inserts the specified line after the line matching the "after" expression' do
288           provider.create
289           expect(File.read(@tmpfile).chomp).to eql("foo1\ninserted = line\nfoo = blah\nfoo2\nfoo = baz")
290         end
291       end
292
293       context 'with multiple lines matching the after expression' do
294         before :each do
295           File.open(@tmpfile, 'w') do |fh|
296             fh.write("foo1\nfoo = blah\nfoo2\nfoo1\nfoo = baz")
297           end
298         end
299
300         it 'errors out stating "One or no line must match the pattern"' do
301           expect { provider.create }.to raise_error(Puppet::Error, /One or no line must match the pattern/)
302         end
303
304         it 'adds the line after all lines matching the after expression' do
305           @resource = Puppet::Type::File_line.new(
306             {
307               :name     => 'foo',
308               :path     => @tmpfile,
309               :line     => 'inserted = line',
310               :after    => '^foo1$',
311               :multiple => true,
312             }
313           )
314           @provider = provider_class.new(@resource)
315           expect(@provider.exists?).to eql (false) 
316           @provider.create
317           expect(File.read(@tmpfile).chomp).to eql("foo1\ninserted = line\nfoo = blah\nfoo2\nfoo1\ninserted = line\nfoo = baz")
318         end
319       end
320
321       context 'with no lines matching the after expression' do
322         let :content do
323           "foo3\nfoo = blah\nfoo2\nfoo = baz\n"
324         end
325
326         before :each do
327           File.open(@tmpfile, 'w') do |fh|
328             fh.write(content)
329           end
330         end
331
332         it 'appends the specified line to the file' do
333           provider.create
334           expect(File.read(@tmpfile)).to eq(content << resource[:line] << "\n")
335         end
336       end
337     end
338   end
339
340   context "when removing" do
341     before :each do
342       # TODO: these should be ported over to use the PuppetLabs spec_helper
343       #  file fixtures once the following pull request has been merged:
344       # https://github.com/puppetlabs/puppetlabs-stdlib/pull/73/files
345       tmp = Tempfile.new('tmp')
346       @tmpfile = tmp.path
347       tmp.close!
348       @resource = Puppet::Type::File_line.new(
349         {
350           :name   => 'foo',
351           :path   => @tmpfile,
352           :line   => 'foo',
353           :ensure => 'absent',
354         }
355       )
356       @provider = provider_class.new(@resource)
357     end
358     it 'should remove the line if it exists' do
359       File.open(@tmpfile, 'w') do |fh|
360         fh.write("foo1\nfoo\nfoo2")
361       end
362       @provider.destroy
363       expect(File.read(@tmpfile)).to eql("foo1\nfoo2")
364     end
365
366     it 'should remove the line without touching the last new line' do
367       File.open(@tmpfile, 'w') do |fh|
368         fh.write("foo1\nfoo\nfoo2\n")
369       end
370       @provider.destroy
371       expect(File.read(@tmpfile)).to eql("foo1\nfoo2\n")
372     end
373
374     it 'should remove any occurence of the line' do
375       File.open(@tmpfile, 'w') do |fh|
376         fh.write("foo1\nfoo\nfoo2\nfoo\nfoo")
377       end
378       @provider.destroy
379       expect(File.read(@tmpfile)).to eql("foo1\nfoo2\n")
380     end
381   end
382
383   context "when removing with a match" do
384     before :each do
385       # TODO: these should be ported over to use the PuppetLabs spec_helper
386       #  file fixtures once the following pull request has been merged:
387       # https://github.com/puppetlabs/puppetlabs-stdlib/pull/73/files
388       tmp = Tempfile.new('tmp')
389       @tmpfile = tmp.path
390       tmp.close!
391       @resource = Puppet::Type::File_line.new(
392         {
393           :name              => 'foo',
394           :path              => @tmpfile,
395           :line              => 'foo2',
396           :ensure            => 'absent',
397           :match             => 'o$',
398           :match_for_absence => true,
399         }
400       )
401       @provider = provider_class.new(@resource)
402     end
403
404     it 'should find a line to match' do
405       File.open(@tmpfile, 'w') do |fh|
406         fh.write("foo1\nfoo\nfoo2")
407       end
408       expect(@provider.exists?).to eql (true)
409     end
410
411     it 'should remove one line if it matches' do
412       File.open(@tmpfile, 'w') do |fh|
413         fh.write("foo1\nfoo\nfoo2")
414       end
415       @provider.destroy
416       expect(File.read(@tmpfile)).to eql("foo1\nfoo2")
417     end
418
419     it 'should raise an error if more than one line matches' do
420       File.open(@tmpfile, 'w') do |fh|
421         fh.write("foo1\nfoo\nfoo2\nfoo\nfoo")
422       end
423       expect { @provider.destroy }.to raise_error(Puppet::Error, /More than one line/)
424     end
425
426     it 'should remove multiple lines if :multiple is true' do
427       @resource = Puppet::Type::File_line.new(
428         {
429           :name              => 'foo',
430           :path              => @tmpfile,
431           :line              => 'foo2',
432           :ensure            => 'absent',
433           :match             => 'o$',
434           :multiple          => true,
435           :match_for_absence => true,
436         }
437       )
438       @provider = provider_class.new(@resource)
439       File.open(@tmpfile, 'w') do |fh|
440         fh.write("foo1\nfoo\nfoo2\nfoo\nfoo")
441       end
442       @provider.destroy
443       expect(File.read(@tmpfile)).to eql("foo1\nfoo2\n")
444     end
445
446     it 'should ignore the match if match_for_absence is not specified' do
447       @resource = Puppet::Type::File_line.new(
448         {
449           :name     => 'foo',
450           :path     => @tmpfile,
451           :line     => 'foo2',
452           :ensure   => 'absent',
453           :match    => 'o$',
454         }
455       )
456       @provider = provider_class.new(@resource)
457       File.open(@tmpfile, 'w') do |fh|
458         fh.write("foo1\nfoo\nfoo2")
459       end
460       @provider.destroy
461       expect(File.read(@tmpfile)).to eql("foo1\nfoo\n")
462     end
463
464     it 'should ignore the match if match_for_absence is false' do
465       @resource = Puppet::Type::File_line.new(
466         {
467           :name              => 'foo',
468           :path              => @tmpfile,
469           :line              => 'foo2',
470           :ensure            => 'absent',
471           :match             => 'o$',
472           :match_for_absence => false,
473         }
474       )
475       @provider = provider_class.new(@resource)
476       File.open(@tmpfile, 'w') do |fh|
477         fh.write("foo1\nfoo\nfoo2")
478       end
479       @provider.destroy
480       expect(File.read(@tmpfile)).to eql("foo1\nfoo\n")
481     end
482
483   end
484
485 end