diff options
Diffstat (limited to 'test/ral/type/cron.rb')
-rwxr-xr-x | test/ral/type/cron.rb | 499 |
1 files changed, 499 insertions, 0 deletions
diff --git a/test/ral/type/cron.rb b/test/ral/type/cron.rb new file mode 100755 index 000000000..73e941894 --- /dev/null +++ b/test/ral/type/cron.rb @@ -0,0 +1,499 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../lib/puppettest' + +require 'puppettest' + +# Test cron job creation, modification, and destruction + +class TestCron < Test::Unit::TestCase + include PuppetTest + + def setup + super + + setme() + + @crontype = Puppet::Type.type(:cron) + @provider = @crontype.defaultprovider + if @provider.respond_to?(:filetype=) + @provider.stubs(:filetype).returns(Puppet::Util::FileType.filetype(:ram)) + end + @crontype = Puppet::Type.type(:cron) + end + + def teardown + super + @crontype.defaultprovider = nil + Puppet::Util::FileType.filetype(:ram).clear + end + + def eachprovider + @crontype.suitableprovider.each do |provider| + yield provider + end + end + + # Back up the user's existing cron tab if they have one. + def cronback + tab = nil + assert_nothing_raised { + tab = Puppet.type(:cron).filetype.read(@me) + } + + if $? == 0 + @currenttab = tab + else + @currenttab = nil + end + end + + # Restore the cron tab to its original form. + def cronrestore + assert_nothing_raised { + if @currenttab + @crontype.filetype.new(@me).write(@currenttab) + else + @crontype.filetype.new(@me).remove + end + } + end + + # Create a cron job with all fields filled in. + def mkcron(name, addargs = true) + cron = nil + command = "date > %s/crontest%s" % [tmpdir(), name] + args = nil + if addargs + args = { + :command => command, + :name => name, + :user => @me, + :minute => rand(59), + :month => "1", + :monthday => "1", + :hour => "1" + } + else + args = {:command => command, :name => name} + end + assert_nothing_raised { + cron = @crontype.create(args) + } + + return cron + end + + # Run the cron through its paces -- install it then remove it. + def cyclecron(cron) + obj = Puppet::Type::Cron.cronobj(@me) + + text = obj.read + name = cron.name + comp = mk_catalog(name, cron) + + assert_events([:cron_created], comp) + cron.provider.class.prefetch + currentvalue = cron.retrieve + + assert(cron.insync?(currentvalue), "Cron is not in sync") + + assert_events([], comp) + + curtext = obj.read + text.split("\n").each do |line| + assert(curtext.include?(line), "Missing '%s'" % line) + end + obj = Puppet::Type::Cron.cronobj(@me) + + cron[:ensure] = :absent + + assert_events([:cron_removed], comp) + + cron.provider.class.prefetch + currentvalue = cron.retrieve + + assert(cron.insync?(currentvalue), "Cron is not in sync") + assert_events([], comp) + end + + # Test that a cron job with spaces at the end doesn't get rewritten + def test_trailingspaces + eachprovider do |provider| + cron = nil + # make the cron + name = "yaytest" + command = "date > /dev/null " + assert_nothing_raised { + cron = @crontype.create( + :name => name, + :command => "date > /dev/null ", + :month => "May", + :user => @me + ) + } + property = cron.send(:property, :command) + cron.provider.command = command + cron.provider.ensure = :present + cron.provider.user = @me + cron.provider.month = ["4"] + cron.provider.class.prefetch + currentvalue = cron.retrieve + + currentvalue.each do |prop, value| + # We're only interested in comparing the command. + next unless prop.name.to_s == "command" + assert(prop.insync?(value), "Property %s is not considered in sync with value %s" % [prop.name, value.inspect]) + end + + @crontype.clear + end + end + + def test_makeandretrievecron + %w{storeandretrieve a-name another-name more_naming SomeName}.each do |name| + cron = mkcron(name) + comp = mk_catalog(name, cron) + trans = assert_events([:cron_created], comp, name) + + cron.provider.class.prefetch + cron = nil + + assert(cron = Puppet.type(:cron)[name], "Could not retrieve named cron") + assert_instance_of(Puppet.type(:cron), cron) + end + end + + # Do input validation testing on all of the parameters. + def test_arguments + values = { + :monthday => { + :valid => [ 1, 13, "1" ], + :invalid => [ -1, 0, 32 ] + }, + :weekday => { + :valid => [ 0, 3, 6, "1", "tue", "wed", + "Wed", "MOnday", "SaTurday" ], + :invalid => [ -1, 7, "13", "tues", "teusday", "thurs" ] + }, + :hour => { + :valid => [ 0, 21, 23 ], + :invalid => [ -1, 24 ] + }, + :minute => { + :valid => [ 0, 34, 59 ], + :invalid => [ -1, 60 ] + }, + :month => { + :valid => [ 1, 11, 12, "mar", "March", "apr", "October", "DeCeMbEr" ], + :invalid => [ -1, 0, 13, "marc", "sept" ] + } + } + + cron = mkcron("valtesting") + values.each { |param, hash| + # We have to test the valid ones first, because otherwise the + # property will fail to create at all. + [:valid, :invalid].each { |type| + hash[type].each { |value| + case type + when :valid: + assert_nothing_raised { + cron[param] = value + } + + if value.is_a?(Integer) + assert_equal([value.to_s], cron.should(param), + "Cron value was not set correctly") + end + when :invalid: + assert_raise(Puppet::Error, "%s is incorrectly a valid %s" % + [value, param]) { + cron[param] = value + } + end + + if value.is_a?(Integer) + value = value.to_s + redo + end + } + } + } + end + + # Verify that comma-separated numbers are not resulting in rewrites + def test_comma_separated_vals_work + eachprovider do |provider| + cron = nil + assert_nothing_raised { + cron = @crontype.create( + :command => "/bin/date > /dev/null", + :minute => [0, 30], + :name => "crontest", + :provider => provider.name + ) + } + + + cron.provider.ensure = :present + cron.provider.command = '/bin/date > /dev/null' + cron.provider.minute = %w{0 30} + cron.provider.class.prefetch + currentvalue = cron.retrieve + + currentvalue.each do |prop, value| + # We're only interested in comparing minutes. + next unless prop.name.to_s == "minute" + assert(prop.insync?(value), "Property %s is not considered in sync with value %s" % [prop.name, value.inspect]) + end + @crontype.clear + end + end + + def test_fieldremoval + cron = nil + assert_nothing_raised { + cron = @crontype.create( + :command => "/bin/date > /dev/null", + :minute => [0, 30], + :name => "crontest", + :provider => :crontab + ) + } + + assert_events([:cron_created], cron) + cron.provider.class.prefetch + + cron[:minute] = :absent + assert_events([:cron_changed], cron) + + current_values = nil + assert_nothing_raised { + cron.provider.class.prefetch + current_values = cron.retrieve + } + assert_equal(:absent, current_values[cron.property(:minute)]) + end + + def test_listing + # Make a crontab cron for testing + provider = @crontype.provider(:crontab) + return unless provider.suitable? + + ft = provider.filetype + provider.filetype = :ram + cleanup { provider.filetype = ft } + + setme + cron = @crontype.create(:name => "testing", + :minute => [0, 30], + :command => "/bin/testing", + :user => @me + ) + # Write it to our file + assert_apply(cron) + + @crontype.clear + + crons = [] + assert_nothing_raised { + @crontype.instances.each do |cron| + crons << cron + end + } + + crons.each do |cron| + assert_instance_of(@crontype, cron, "Did not receive a real cron object") + assert_instance_of(String, cron.value(:user), + "Cron user is not a string") + end + end + + def verify_failonnouser + assert_raise(Puppet::Error) do + @crontype.retrieve("nosuchuser") + end + end + + def test_divisionnumbers + cron = mkcron("divtest") + cron[:minute] = "*/5" + + assert_apply(cron) + + cron.provider.class.prefetch + currentvalue = cron.retrieve + + assert_equal(["*/5"], currentvalue[cron.property(:minute)]) + end + + def test_ranges + cron = mkcron("rangetest") + cron[:minute] = "2-4" + + assert_apply(cron) + + current_values = nil + assert_nothing_raised { + cron.provider.class.prefetch + current_values = cron.retrieve + } + + assert_equal(["2-4"], current_values[cron.property(:minute)]) + end + + + def provider_set(cron, param, value) + unless param =~ /=$/ + param = "%s=" % param + end + + cron.provider.send(param, value) + end + + def test_value + cron = mkcron("valuetesting", false) + + # First, test the normal properties + [:minute, :hour, :month].each do |param| + cron.newattr(param) + property = cron.property(param) + + assert(property, "Did not get %s property" % param) + + assert_nothing_raised { +# property.is = :absent + provider_set(cron, param, :absent) + } + + val = "*" + assert_equal(val, cron.value(param)) + + # Make sure arrays work, too + provider_set(cron, param, ["1"]) + assert_equal(%w{1}, cron.value(param)) + + # Make sure values get comma-joined + provider_set(cron, param, %w{2 3}) + assert_equal(%w{2 3}, cron.value(param)) + + # Make sure "should" values work, too + cron[param] = "4" + assert_equal(%w{4}, cron.value(param)) + + cron[param] = ["4"] + assert_equal(%w{4}, cron.value(param)) + + cron[param] = ["4", "5"] + assert_equal(%w{4 5}, cron.value(param)) + + provider_set(cron, param, :absent) + assert_equal(%w{4 5}, cron.value(param)) + end + + Puppet[:trace] = false + + # Now make sure that :command works correctly + cron.delete(:command) + cron.newattr(:command) + property = cron.property(:command) + + assert_nothing_raised { + provider_set(cron, :command, :absent) + } + + param = :command + # Make sure arrays work, too + provider_set(cron, param, ["/bin/echo"]) + assert_equal("/bin/echo", cron.value(param)) + + # Make sure values are not comma-joined + provider_set(cron, param, %w{/bin/echo /bin/test}) + assert_equal("/bin/echo", cron.value(param)) + + # Make sure "should" values work, too + cron[param] = "/bin/echo" + assert_equal("/bin/echo", cron.value(param)) + + cron[param] = ["/bin/echo"] + assert_equal("/bin/echo", cron.value(param)) + + cron[param] = %w{/bin/echo /bin/test} + assert_equal("/bin/echo", cron.value(param)) + + provider_set(cron, param, :absent) + assert_equal("/bin/echo", cron.value(param)) + end + + def test_multiple_users + crons = [] + users = ["root", nonrootuser.name] + users.each do |user| + cron = Puppet::Type.type(:cron).create( + :name => "testcron-#{user}", + :user => user, + :command => "/bin/echo", + :minute => [0,30] + ) + crons << cron + + assert_equal(cron.should(:user), cron.should(:target), + "Target was not set correctly for %s" % user) + end + provider = crons[0].provider.class + + assert_apply(*crons) + + users.each do |user| + users.each do |other| + next if user == other + text = provider.target_object(other).read + + assert(text !~ /testcron-#{user}/, + "%s's cron job is in %s's tab" % + [user, other]) + end + end + end + + # Make sure the user stuff defaults correctly. + def test_default_user + crontab = @crontype.provider(:crontab) + if crontab.suitable? + inst = @crontype.create( + :name => "something", :command => "/some/thing", + :provider => :crontab) + assert_equal(Etc.getpwuid(Process.uid).name, inst.should(:user), + "user did not default to current user with crontab") + assert_equal(Etc.getpwuid(Process.uid).name, inst.should(:target), + "target did not default to current user with crontab") + + # Now make a new cron with a user, and make sure it gets copied + # over + inst = @crontype.create(:name => "yay", :command => "/some/thing", + :user => "bin", :provider => :crontab) + assert_equal("bin", inst.should(:target), + "target did not default to user with crontab") + end + end + + # #705 - make sure extra spaces don't screw things up + def test_spaces_in_command + string = "echo multiple spaces" + cron = @crontype.create(:name => "space testing", :command => string) + assert_apply(cron) + + cron.class.clear + cron = @crontype.create(:name => "space testing", :command => string) + + # Now make sure that it's correctly in sync + cron.provider.class.prefetch("testing" => cron) + properties = cron.retrieve + command, result = properties.find { |prop, value| prop.name == :command } + assert_equal(string, result, "Cron did not pick up extra spaces in command") + assert(command.insync?(string), "Command changed with multiple spaces") + end +end + + |