diff options
Diffstat (limited to 'spec/unit/provider')
-rw-r--r-- | spec/unit/provider/cron/filetype_spec.rb | 144 | ||||
-rw-r--r-- | spec/unit/provider/cron/parsed_spec.rb | 29 |
2 files changed, 161 insertions, 12 deletions
diff --git a/spec/unit/provider/cron/filetype_spec.rb b/spec/unit/provider/cron/filetype_spec.rb new file mode 100644 index 0000000..bf96f91 --- /dev/null +++ b/spec/unit/provider/cron/filetype_spec.rb @@ -0,0 +1,144 @@ +require 'spec_helper' +require 'puppet/provider/cron/filetype' + +# rubocop:disable RSpec/FilePath +describe Puppet::Provider::Cron::FileType do + shared_examples_for 'crontab provider' do + let(:cron) { type.new('no_such_user') } + let(:crontab) { File.read(my_fixture(crontab_output)) } + let(:options) { { failonfail: true, combine: true } } + let(:uid) { 'no_such_user' } + let(:user_options) { options.merge(uid: uid) } + + it 'exists' do + expect(type).not_to be_nil + end + + # make Puppet::Util::SUIDManager return something deterministic, not the + # uid of the user running the tests, except where overridden below. + before :each do + Puppet::Util::SUIDManager.stubs(:uid).returns 1234 + end + + describe '#read' do + before(:each) do + Puppet::Util.stubs(:uid).with(uid).returns 9000 + end + + it 'runs crontab -l as the target user' do + Puppet::Util::Execution + .expects(:execute) + .with(['crontab', '-l'], user_options) + .returns(Puppet::Util::Execution::ProcessOutput.new(crontab, 0)) + + expect(cron.read).to eq(crontab) + end + + it 'does not switch user if current user is the target user' do + Puppet::Util.expects(:uid).with(uid).twice.returns 9000 + Puppet::Util::SUIDManager.expects(:uid).returns 9000 + Puppet::Util::Execution + .expects(:execute).with(['crontab', '-l'], options) + .returns(Puppet::Util::Execution::ProcessOutput.new(crontab, 0)) + expect(cron.read).to eq(crontab) + end + + it 'treats an absent crontab as empty' do + Puppet::Util::Execution.expects(:execute).with(['crontab', '-l'], user_options).raises(Puppet::ExecutionFailure, absent_crontab) + expect(cron.read).to eq('') + end + + it "treats a nonexistent user's crontab as empty" do + Puppet::Util.expects(:uid).with(uid).returns nil + + expect(cron.read).to eq('') + end + + it 'returns empty if the user is not authorized to use cron' do + Puppet::Util::Execution.expects(:execute).with(['crontab', '-l'], user_options).raises(Puppet::ExecutionFailure, unauthorized_crontab) + expect(cron.read).to eq('') + end + end + + describe '#remove' do + it 'runs crontab -r as the target user' do + Puppet::Util::Execution.expects(:execute).with(['crontab', '-r'], user_options) + cron.remove + end + + it 'does not switch user if current user is the target user' do + Puppet::Util.expects(:uid).with(uid).returns 9000 + Puppet::Util::SUIDManager.expects(:uid).returns 9000 + Puppet::Util::Execution.expects(:execute).with(['crontab', '-r'], options) + cron.remove + end + end + + describe '#write' do + let!(:tmp_cron) { Tempfile.new('puppet_crontab_spec') } + let!(:tmp_cron_path) { tmp_cron.path } + + before :each do + Puppet::Util.stubs(:uid).with(uid).returns 9000 + Tempfile.expects(:new).with("puppet_#{name}", encoding: Encoding.default_external).returns tmp_cron + end + + after :each do + File.unstub(:chown) + end + + it 'runs crontab as the target user on a temporary file' do + File.expects(:chown).with(9000, nil, tmp_cron_path) + Puppet::Util::Execution.expects(:execute).with(['crontab', tmp_cron_path], user_options) + + tmp_cron.expects(:print).with("foo\n") + cron.write "foo\n" + + expect(Puppet::FileSystem).not_to exist(tmp_cron_path) + end + + it 'does not switch user if current user is the target user' do + Puppet::Util::SUIDManager.expects(:uid).returns 9000 + File.expects(:chown).with(9000, nil, tmp_cron_path) + Puppet::Util::Execution.expects(:execute).with(['crontab', tmp_cron_path], options) + + tmp_cron.expects(:print).with("foo\n") + cron.write "foo\n" + + expect(Puppet::FileSystem).not_to exist(tmp_cron_path) + end + end + end + + describe 'the suntab filetype', unless: Puppet::Util::Platform.windows? do + let(:type) { described_class.filetype(:suntab) } + let(:name) { type.name } + let(:crontab_output) { 'suntab_output' } + + # possible crontab output was taken from here: + # https://docs.oracle.com/cd/E19082-01/819-2380/sysrescron-60/index.html + let(:absent_crontab) do + 'crontab: can\'t open your crontab file' + end + let(:unauthorized_crontab) do + 'crontab: you are not authorized to use cron. Sorry.' + end + + it_behaves_like 'crontab provider' + end + + describe 'the aixtab filetype', unless: Puppet::Util::Platform.windows? do + let(:type) { described_class.filetype(:aixtab) } + let(:name) { type.name } + let(:crontab_output) { 'aixtab_output' } + + let(:absent_crontab) do + '0481-103 Cannot open a file in the /var/spool/cron/crontabs directory.' + end + let(:unauthorized_crontab) do + '0481-109 You are not authorized to use the cron command.' + end + + it_behaves_like 'crontab provider' + end +end diff --git a/spec/unit/provider/cron/parsed_spec.rb b/spec/unit/provider/cron/parsed_spec.rb index d54129c..b115f9d 100644 --- a/spec/unit/provider/cron/parsed_spec.rb +++ b/spec/unit/provider/cron/parsed_spec.rb @@ -64,17 +64,17 @@ describe Puppet::Type.type(:cron).provider(:crontab) do describe 'when determining the correct filetype' do it 'uses the suntab filetype on Solaris' do Facter.stubs(:value).with(:osfamily).returns 'Solaris' - expect(described_class.filetype).to eq(Puppet::Util::FileType::FileTypeSuntab) + expect(described_class.filetype).to eq(Puppet::Provider::Cron::FileType::FileTypeSuntab) end it 'uses the aixtab filetype on AIX' do Facter.stubs(:value).with(:osfamily).returns 'AIX' - expect(described_class.filetype).to eq(Puppet::Util::FileType::FileTypeAixtab) + expect(described_class.filetype).to eq(Puppet::Provider::Cron::FileType::FileTypeAixtab) end it 'uses the crontab filetype on other platforms' do Facter.stubs(:value).with(:osfamily).returns 'Not a real operating system family' - expect(described_class.filetype).to eq(Puppet::Util::FileType::FileTypeCrontab) + expect(described_class.filetype).to eq(Puppet::Provider::Cron::FileType::FileTypeCrontab) end end @@ -194,20 +194,25 @@ describe Puppet::Type.type(:cron).provider(:crontab) do Facter.stubs(:value).with(:operatingsystem) end - it 'contains no resources for a user who has no crontab, or for a user that is absent' do - if Puppet.version.to_f < 5.0 - described_class.target_object('foobar').expects(:`).with('crontab -u foobar -l 2>/dev/null').returns '' - else - Puppet::Util::Execution - .expects(:execute) - .with('crontab -u foobar -l', failonfail: true, combine: true) - .returns('') - end + it 'contains no resources for a user who has no crontab' do + Puppet::Util.stubs(:uid).returns(10) + + Puppet::Util::Execution + .expects(:execute) + .with('crontab -u foobar -l', failonfail: true, combine: true) + .returns('') + expect(described_class.instances.select do |resource| resource.get('target') == 'foobar' end).to be_empty end + it 'contains no resources for a user who is absent' do + Puppet::Util.stubs(:uid).returns(nil) + + expect(described_class.instances).to be_empty + end + it 'is able to create records from not-managed records' do described_class.stubs(:target_object).returns File.new(my_fixture('simple')) parameters = described_class.instances.map do |p| |