diff options
author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-10-04 18:24:24 +0000 |
---|---|---|
committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-10-04 18:24:24 +0000 |
commit | 28cee40689440388994a4768bd301ae32c8ecc05 (patch) | |
tree | c865ab44f4c9247052cf83de16ffc8ebe8b15e54 /test | |
parent | e0e291332bd4676962a28c7b220ae5c5e9651c0a (diff) | |
download | puppet-28cee40689440388994a4768bd301ae32c8ecc05.tar.gz puppet-28cee40689440388994a4768bd301ae32c8ecc05.tar.xz puppet-28cee40689440388994a4768bd301ae32c8ecc05.zip |
Merging the changes from the override-refactor branch. This is a significant rewrite of the parser, but it has little affect on the rest of the code tree.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@1726 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'test')
57 files changed, 3035 insertions, 1883 deletions
diff --git a/test/data/failers/badclassnoparam b/test/data/failers/badclassnoparam new file mode 100644 index 000000000..a0397aacc --- /dev/null +++ b/test/data/failers/badclassnoparam @@ -0,0 +1,10 @@ +class comp() { + file { "/etc/passwd": + mode => 644 + } +} + +# this argument is invalid, thus we should get a falure +comp { + fakearg => "yay" +} diff --git a/test/data/failers/badclassparam b/test/data/failers/badclassparam new file mode 100644 index 000000000..4c9ff6199 --- /dev/null +++ b/test/data/failers/badclassparam @@ -0,0 +1,10 @@ +class comp(arg1) { + file { "/etc/passwd": + mode => 644 + } +} + +# i've specified an arg but it's an invalid one +comp { + fakearg => "yay" +} diff --git a/test/data/failers/badcompnoparam b/test/data/failers/badcompnoparam new file mode 100644 index 000000000..fd25c9445 --- /dev/null +++ b/test/data/failers/badcompnoparam @@ -0,0 +1,9 @@ +define comp() { + file { "/etc/passwd": + mode => 644 + } +} + +comp { + fakearg => "yay" +} diff --git a/test/data/failers/badcompparam b/test/data/failers/badcompparam new file mode 100644 index 000000000..346e64b25 --- /dev/null +++ b/test/data/failers/badcompparam @@ -0,0 +1,9 @@ +define comp($arg1) { + file { "/etc/passwd": + mode => 644 + } +} + +comp { + fakearg => "yay" +} diff --git a/test/data/failers/badtypeparam b/test/data/failers/badtypeparam new file mode 100644 index 000000000..4634f2052 --- /dev/null +++ b/test/data/failers/badtypeparam @@ -0,0 +1,3 @@ +file { "/etc/passwd": + fakeparam => 644 +} diff --git a/test/data/failers/noobjectrvalue b/test/data/failers/noobjectrvalue new file mode 100644 index 000000000..ef6064740 --- /dev/null +++ b/test/data/failers/noobjectrvalue @@ -0,0 +1 @@ +$variable = file { "/etc/passwd": owner => root } diff --git a/test/data/snippets/aliastest.pp b/test/data/snippets/aliastest.pp new file mode 100644 index 000000000..2a8fc9cb9 --- /dev/null +++ b/test/data/snippets/aliastest.pp @@ -0,0 +1,16 @@ +file { "a file": + path => "/tmp/aliastest", + ensure => file +} + +file { "another": + path => "/tmp/aliastest2", + ensure => file, + require => file["a file"] +} + +file { "a third": + path => "/tmp/aliastest3", + ensure => file, + require => file["/tmp/aliastest"] +} diff --git a/test/data/snippets/argumentdefaults b/test/data/snippets/argumentdefaults new file mode 100644 index 000000000..eac9dd757 --- /dev/null +++ b/test/data/snippets/argumentdefaults @@ -0,0 +1,14 @@ +# $Id$ + +define testargs($file, $mode = 755) { + file { $file: ensure => file, mode => $mode } +} + +testargs { "testingname": + file => "/tmp/argumenttest1" +} + +testargs { "testingother": + file => "/tmp/argumenttest2", + mode => 644 +} diff --git a/test/data/snippets/casestatement.pp b/test/data/snippets/casestatement.pp new file mode 100644 index 000000000..4fcf2e408 --- /dev/null +++ b/test/data/snippets/casestatement.pp @@ -0,0 +1,58 @@ +# $Id$ + +$var = "value" + +case $var { + "nope": { + file { "/tmp/fakefile": mode => 644, ensure => file } + } + "value": { + file { "/tmp/existsfile": mode => 755, ensure => file } + } +} + +$ovar = "yayness" + +case $ovar { + "fooness": { + file { "/tmp/nostillexistsfile": mode => 644, ensure => file } + } + "booness", "yayness": { + case $var { + "nep": { + file { "/tmp/noexistsfile": mode => 644, ensure => file } + } + "value": { + file { "/tmp/existsfile2": mode => 755, ensure => file } + } + } + } +} + +case $ovar { + "fooness": { + file { "/tmp/nostillexistsfile": mode => 644, ensure => file } + } + default: { + file { "/tmp/existsfile3": mode => 755, ensure => file } + } +} + +$bool = true + +case $bool { + true: { + file { "/tmp/existsfile4": mode => 755, ensure => file } + } +} + +$yay = yay +$a = yay +$b = boo + +case $yay { + $a: { file { "/tmp/existsfile5": mode => 755, ensure => file } } + $b: { file { "/tmp/existsfile5": mode => 644, ensure => file } } + default: { file { "/tmp/existsfile5": mode => 711, ensure => file } } + +} diff --git a/test/data/snippets/classheirarchy.pp b/test/data/snippets/classheirarchy.pp new file mode 100644 index 000000000..36619d8b9 --- /dev/null +++ b/test/data/snippets/classheirarchy.pp @@ -0,0 +1,15 @@ +# $Id$ + +class base { + file { "/tmp/classheir1": ensure => file, mode => 755 } +} + +class sub1 inherits base { + file { "/tmp/classheir2": ensure => file, mode => 755 } +} + +class sub2 inherits base { + file { "/tmp/classheir3": ensure => file, mode => 755 } +} + +include sub1, sub2 diff --git a/test/data/snippets/classincludes.pp b/test/data/snippets/classincludes.pp new file mode 100644 index 000000000..927800599 --- /dev/null +++ b/test/data/snippets/classincludes.pp @@ -0,0 +1,17 @@ +# $Id$ + +class base { + file { "/tmp/classincludes1": ensure => file, mode => 755 } +} + +class sub1 inherits base { + file { "/tmp/classincludes2": ensure => file, mode => 755 } +} + +class sub2 inherits base { + file { "/tmp/classincludes3": ensure => file, mode => 755 } +} + +$sub = "sub2" + +include sub1, $sub diff --git a/test/data/snippets/classpathtest b/test/data/snippets/classpathtest new file mode 100644 index 000000000..68610958b --- /dev/null +++ b/test/data/snippets/classpathtest @@ -0,0 +1,11 @@ +# $Id$ + +define component { + file { "/tmp/classtest": ensure => file, mode => 755 } +} + +class testing { + component { "componentname": } +} + +include testing diff --git a/test/data/snippets/componentmetaparams.pp b/test/data/snippets/componentmetaparams.pp new file mode 100644 index 000000000..7d9f0c2c1 --- /dev/null +++ b/test/data/snippets/componentmetaparams.pp @@ -0,0 +1,11 @@ +file { "/tmp/component1": + ensure => file +} + +define thing { + file { $name: ensure => file } +} + +thing { "/tmp/component2": + require => File["/tmp/component1"] +} diff --git a/test/data/snippets/deepclassheirarchy.pp b/test/data/snippets/deepclassheirarchy.pp new file mode 100644 index 000000000..249e6334d --- /dev/null +++ b/test/data/snippets/deepclassheirarchy.pp @@ -0,0 +1,23 @@ +# $Id$ + +class base { + file { "/tmp/deepclassheir1": ensure => file, mode => 755 } +} + +class sub1 inherits base { + file { "/tmp/deepclassheir2": ensure => file, mode => 755 } +} + +class sub2 inherits sub1 { + file { "/tmp/deepclassheir3": ensure => file, mode => 755 } +} + +class sub3 inherits sub2 { + file { "/tmp/deepclassheir4": ensure => file, mode => 755 } +} + +class sub4 inherits sub3 { + file { "/tmp/deepclassheir5": ensure => file, mode => 755 } +} + +include sub4 diff --git a/test/data/snippets/defineoverrides.pp b/test/data/snippets/defineoverrides.pp new file mode 100644 index 000000000..a87573a57 --- /dev/null +++ b/test/data/snippets/defineoverrides.pp @@ -0,0 +1,17 @@ +# $Id$ + +$file = "/tmp/defineoverrides1" + +define myfile($mode) { + file { $name: ensure => file, mode => $mode } +} + +class base { + myfile { $file: mode => 644 } +} + +class sub inherits base { + Myfile[$file] { mode => 755 } +} + +include sub diff --git a/test/data/snippets/dirchmod b/test/data/snippets/dirchmod new file mode 100644 index 000000000..dc2cc8949 --- /dev/null +++ b/test/data/snippets/dirchmod @@ -0,0 +1,19 @@ +# $Id$ + +file { + "/tmp/dirchmodtesta": ensure => directory; + "/tmp/dirchmodtesta/testing": ensure => file +} + +file { "/tmp/dirchmodtesta": + mode => 644, recurse => true +} + +file { + "/tmp/dirchmodtestb": ensure => directory; + "/tmp/dirchmodtestb/testing": ensure => file +} + +file { "/tmp/dirchmodtestb": + mode => 600, recurse => true +} diff --git a/test/data/snippets/emptyclass.pp b/test/data/snippets/emptyclass.pp new file mode 100644 index 000000000..48047e748 --- /dev/null +++ b/test/data/snippets/emptyclass.pp @@ -0,0 +1,9 @@ +# $Id$ + +define component { +} + +class testing { +} + +include testing diff --git a/test/data/snippets/emptyexec.pp b/test/data/snippets/emptyexec.pp new file mode 100644 index 000000000..847a30d18 --- /dev/null +++ b/test/data/snippets/emptyexec.pp @@ -0,0 +1,3 @@ +exec { "touch /tmp/emptyexectest": + path => "/usr/bin:/bin" +} diff --git a/test/data/snippets/failmissingexecpath.pp b/test/data/snippets/failmissingexecpath.pp new file mode 100644 index 000000000..aae1a09fa --- /dev/null +++ b/test/data/snippets/failmissingexecpath.pp @@ -0,0 +1,13 @@ +define distloc($path) { + file { "/tmp/exectesting1": + ensure => file + } + exec { "touch $path": + subscribe => File["/tmp/exectesting1"], + refreshonly => true + } +} + +distloc { yay: + path => "/tmp/execdisttesting", +} diff --git a/test/data/snippets/falsevalues.pp b/test/data/snippets/falsevalues.pp new file mode 100644 index 000000000..2143b79a7 --- /dev/null +++ b/test/data/snippets/falsevalues.pp @@ -0,0 +1,3 @@ +$value = false + +file { "/tmp/falsevalues$value": ensure => file } diff --git a/test/data/snippets/filecreate b/test/data/snippets/filecreate new file mode 100644 index 000000000..d7972c234 --- /dev/null +++ b/test/data/snippets/filecreate @@ -0,0 +1,11 @@ +# $Id$ + +file { + "/tmp/createatest": ensure => file, mode => 755; + "/tmp/createbtest": ensure => file, mode => 755 +} + +file { + "/tmp/createctest": ensure => file; + "/tmp/createdtest": ensure => file; +} diff --git a/test/data/snippets/implicititeration b/test/data/snippets/implicititeration new file mode 100644 index 000000000..6f34cb29c --- /dev/null +++ b/test/data/snippets/implicititeration @@ -0,0 +1,15 @@ +# $Id$ + +$files = ["/tmp/iterationatest", "/tmp/iterationbtest"] + +file { $files: ensure => file, mode => 755 } + +file { ["/tmp/iterationctest", "/tmp/iterationdtest"]: + ensure => file, + mode => 755 +} + +file { + ["/tmp/iterationetest", "/tmp/iterationftest"]: ensure => file, mode => 755; + ["/tmp/iterationgtest", "/tmp/iterationhtest"]: ensure => file, mode => 755; +} diff --git a/test/data/snippets/multipleinstances b/test/data/snippets/multipleinstances new file mode 100644 index 000000000..2f9b3c2e8 --- /dev/null +++ b/test/data/snippets/multipleinstances @@ -0,0 +1,7 @@ +# $Id$ + +file { + "/tmp/multipleinstancesa": ensure => file, mode => 755; + "/tmp/multipleinstancesb": ensure => file, mode => 755; + "/tmp/multipleinstancesc": ensure => file, mode => 755; +} diff --git a/test/data/snippets/multisubs.pp b/test/data/snippets/multisubs.pp new file mode 100644 index 000000000..bcec69e2a --- /dev/null +++ b/test/data/snippets/multisubs.pp @@ -0,0 +1,13 @@ +class base { + file { "/tmp/multisubtest": content => "base", mode => 644 } +} + +class sub1 inherits base { + File["/tmp/multisubtest"] { mode => 755 } +} + +class sub2 inherits base { + File["/tmp/multisubtest"] { content => sub2 } +} + +include sub1, sub2 diff --git a/test/data/snippets/namevartest b/test/data/snippets/namevartest new file mode 100644 index 000000000..dbee1c356 --- /dev/null +++ b/test/data/snippets/namevartest @@ -0,0 +1,9 @@ +define filetest($mode, $ensure = file) { + file { $name: + mode => $mode, + ensure => $ensure + } +} + +filetest { "/tmp/testfiletest": mode => 644} +filetest { "/tmp/testdirtest": mode => 755, ensure => directory} diff --git a/test/data/snippets/scopetest b/test/data/snippets/scopetest new file mode 100644 index 000000000..331491766 --- /dev/null +++ b/test/data/snippets/scopetest @@ -0,0 +1,13 @@ + +$mode = 640 + +define thing { + file { "/tmp/$name": ensure => file, mode => $mode } +} + +class testing { + $mode = 755 + thing {scopetest: } +} + +include testing diff --git a/test/data/snippets/selectorvalues.pp b/test/data/snippets/selectorvalues.pp new file mode 100644 index 000000000..cd8cf77a7 --- /dev/null +++ b/test/data/snippets/selectorvalues.pp @@ -0,0 +1,42 @@ +$value1 = "" +$value2 = true +$value3 = false +$value4 = yay + +$test = "yay" + +$mode1 = $value1 ? { + "" => 755, + default => 644 +} + +$mode2 = $value2 ? { + true => 755, + default => 644 +} + +$mode3 = $value3 ? { + false => 755, + default => 644 +} + +$mode4 = $value4 ? { + $test => 755, + default => 644 +} + +$mode5 = yay ? { + $test => 755, + default => 644 +} + +$mode6 = $mode5 ? { + 755 => 755 +} + +file { "/tmp/selectorvalues1": ensure => file, mode => $mode1 } +file { "/tmp/selectorvalues2": ensure => file, mode => $mode2 } +file { "/tmp/selectorvalues3": ensure => file, mode => $mode3 } +file { "/tmp/selectorvalues4": ensure => file, mode => $mode4 } +file { "/tmp/selectorvalues5": ensure => file, mode => $mode5 } +file { "/tmp/selectorvalues6": ensure => file, mode => $mode6 } diff --git a/test/data/snippets/simpledefaults b/test/data/snippets/simpledefaults new file mode 100644 index 000000000..63d199a68 --- /dev/null +++ b/test/data/snippets/simpledefaults @@ -0,0 +1,5 @@ +# $Id$ + +File { mode => 755 } + +file { "/tmp/defaulttest": ensure => file } diff --git a/test/data/snippets/simpleselector b/test/data/snippets/simpleselector new file mode 100644 index 000000000..8b9bc7292 --- /dev/null +++ b/test/data/snippets/simpleselector @@ -0,0 +1,38 @@ +# $Id$ + +$var = "value" + +file { "/tmp/snippetselectatest": + ensure => file, + mode => $var ? { + nottrue => 641, + value => 755 + } +} + +file { "/tmp/snippetselectbtest": + ensure => file, + mode => $var ? { + nottrue => 644, + default => 755 + } +} + +$othervar = "complex value" + +file { "/tmp/snippetselectctest": + ensure => file, + mode => $othervar ? { + "complex value" => 755, + default => 644 + } +} +$anothervar = Yayness + +file { "/tmp/snippetselectdtest": + ensure => file, + mode => $anothervar ? { + Yayness => 755, + default => 644 + } +} diff --git a/test/data/snippets/singleary.pp b/test/data/snippets/singleary.pp new file mode 100644 index 000000000..9ce56dd89 --- /dev/null +++ b/test/data/snippets/singleary.pp @@ -0,0 +1,19 @@ +# $Id$ + +file { "/tmp/singleary1": + ensure => file +} + +file { "/tmp/singleary2": + ensure => file +} + +file { "/tmp/singleary3": + ensure => file, + require => [File["/tmp/singleary1"], File["/tmp/singleary2"]] +} + +file { "/tmp/singleary4": + ensure => file, + require => [File["/tmp/singleary1"]] +} diff --git a/test/data/snippets/singlequote.pp b/test/data/snippets/singlequote.pp new file mode 100644 index 000000000..dc876a2f8 --- /dev/null +++ b/test/data/snippets/singlequote.pp @@ -0,0 +1,11 @@ +# $Id$ + +file { "/tmp/singlequote1": + ensure => file, + content => 'a $quote' +} + +file { "/tmp/singlequote2": + ensure => file, + content => 'some "\yayness\"' +} diff --git a/test/data/snippets/singleselector.pp b/test/data/snippets/singleselector.pp new file mode 100644 index 000000000..520a14017 --- /dev/null +++ b/test/data/snippets/singleselector.pp @@ -0,0 +1,22 @@ +$value1 = "" +$value2 = true +$value3 = false +$value4 = yay + +$test = "yay" + +$mode1 = $value1 ? { + "" => 755 +} + +$mode2 = $value2 ? { + true => 755 +} + +$mode3 = $value3 ? { + default => 755 +} + +file { "/tmp/singleselector1": ensure => file, mode => $mode1 } +file { "/tmp/singleselector2": ensure => file, mode => $mode2 } +file { "/tmp/singleselector3": ensure => file, mode => $mode3 } diff --git a/test/data/snippets/tag.pp b/test/data/snippets/tag.pp new file mode 100644 index 000000000..e6e770dd9 --- /dev/null +++ b/test/data/snippets/tag.pp @@ -0,0 +1,9 @@ +# $Id$ + +$variable = value + +tag yayness, rahness + +tag booness, $variable + +file { "/tmp/settestingness": ensure => file } diff --git a/test/data/snippets/tagged.pp b/test/data/snippets/tagged.pp new file mode 100644 index 000000000..7bf90a645 --- /dev/null +++ b/test/data/snippets/tagged.pp @@ -0,0 +1,35 @@ +# $Id$ + +tag testing +tag(funtest) + +class tagdefine { + $path = tagged(tagdefine) ? { + true => "true", false => "false" + } + + file { "/tmp/taggeddefine$path": ensure => file } +} + +include tagdefine + +$yayness = tagged(yayness) ? { + true => "true", false => "false" +} + +$funtest = tagged(testing) ? { + true => "true", false => "false" +} + +$both = tagged(testing, yayness) ? { + true => "true", false => "false" +} + +$bothtrue = tagged(testing, testing) ? { + true => "true", false => "false" +} + +file { "/tmp/taggedyayness$yayness": ensure => file } +file { "/tmp/taggedtesting$funtest": ensure => file } +file { "/tmp/taggedboth$both": ensure => file } +file { "/tmp/taggedbothtrue$bothtrue": ensure => file } diff --git a/test/executables/puppetmodule.rb b/test/executables/puppetmodule.rb index 0752fed14..6ffd84be3 100755 --- a/test/executables/puppetmodule.rb +++ b/test/executables/puppetmodule.rb @@ -34,16 +34,19 @@ class TestPuppetModule < Test::Unit::TestCase if Puppet[:debug] cmd += " --logdest %s" % "console" cmd += " --debug" + cmd += " --trace" else cmd += " --logdest %s" % "/dev/null" end ENV["CFALLCLASSES"] = "yaytest:all" + libsetup + out = nil assert_nothing_raised { - %x{#{cmd + " " + file} 2>&1} + out = %x{#{cmd + " " + file} 2>&1} } - assert($? == 0, "Puppet module exited with code %s" % $?.to_i) + assert($? == 0, "Puppet module exited with code %s: %s" % [$?.to_i, out]) assert(FileTest.exists?(createdfile), "Failed to create config'ed file") end diff --git a/test/language/ast.rb b/test/language/ast.rb index ab528a49d..731b37cb8 100755 --- a/test/language/ast.rb +++ b/test/language/ast.rb @@ -1,13 +1,19 @@ #!/usr/bin/ruby require 'puppet' +require 'puppet/rails' require 'puppet/parser/interpreter' require 'puppet/parser/parser' require 'puppet/client' require 'puppettest' +require 'puppettest/resourcetesting' +require 'puppettest/parsertesting' +require 'puppettest/railstesting' class TestAST < Test::Unit::TestCase + include PuppetTest::RailsTesting include PuppetTest::ParserTesting + include PuppetTest::ResourceTesting # A fake class that we can use for testing evaluation. class FakeAST @@ -28,910 +34,465 @@ class TestAST < Test::Unit::TestCase end end - # Test that classes behave like singletons - def test_classsingleton - parent = child1 = child2 = nil - children = [] - - # create the parent class - children << classobj("parent") - - # Create child class one - children << classobj("child1", :parentclass => nameobj("parent")) + if defined? ActiveRecord + # Verify that our collection stuff works. + def test_collection + collectable = [] + non = [] + # First put some objects into the database. + bucket = mk_transtree do |object, depth, width| + # and mark some of them collectable + if width % 2 == 1 + object.collectable = true + collectable << object + else + non << object + end + end - # Create child class two - children << classobj("child2", :parentclass => nameobj("parent")) - classes = %w{parent child1 child2} + # Now collect our facts + facts = {} + Facter.each do |fact, value| facts[fact] = value end - # Now call the two classes - assert_nothing_raised("Could not add AST nodes for calling") { - children << AST::ObjectDef.new( - :type => nameobj("child1"), - :name => nameobj("yayness"), - :params => astarray() - ) - children << AST::ObjectDef.new( - :type => nameobj("child2"), - :name => nameobj("booness"), - :params => astarray() - ) + assert_nothing_raised { + Puppet::Rails.init } - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => children + # Now try storing our crap + assert_nothing_raised { + host = Puppet::Rails::Host.store( + :objects => bucket, + :facts => facts, + :host => facts["hostname"] ) } - scope = nil - objects = nil - assert_nothing_raised("Could not evaluate") { - scope = Puppet::Parser::Scope.new() - objects = scope.evaluate(:ast => top) + # Now create an ast tree that collects that. They should all be files. + coll = nil + assert_nothing_raised { + coll = AST::Collection.new( + :type => nameobj("file") + ) } - assert_instance_of(Puppet::TransBucket, objects) - - assert_equal(1, scope.find_all { |child| - if child.is_a? Puppet::Parser::Scope - child.lookupobject(:name => "/parent", :type => "file") - else - nil - end - }.length, "Found incorrect number of '/parent' objects") - - assert_equal(classes.sort, scope.classlist.sort) - end - - # Test that 'tagobject' collects all of an object's parameters and stores - # them in one TransObject, rather than many. This is probably a bad idea. - def test_tagobject top = nil - children = [ - fileobj("/etc", "owner" => "root"), - fileobj("/etc", "group" => "root") - ] assert_nothing_raised("Could not create top object") { top = AST::ASTArray.new( - :children => children + :children => [coll] ) } - scope = Puppet::Parser::Scope.new() + objects = nil assert_nothing_raised("Could not evaluate") { - top.evaluate(:scope => scope) - } - - obj = nil - assert_nothing_raised("Could not retrieve file object") { - obj = scope.lookupobject(:name => "/etc", :type => "file") - } - - assert(obj, "could not retrieve file object") - - %w{owner group}.each { |param| - assert(obj.include?(param), "Object did not include %s" % param) + scope = mkscope + objects = scope.evaluate(:ast => top).flatten } + assert(objects.length > 0, "Did not receive any collected objects") + end + else + $stderr.puts "No ActiveRecord -- skipping collection tests" end - # Verify that objects can only have parents of the same type. - def test_validparent - parent = child1 = nil - children = [] - - # create the parent class - children << compobj("parent", :args => AST::ASTArray.new(:children => [])) - - # Create child class one - children << classobj("child1", :parentclass => nameobj("parent")) + def test_if + astif = nil + astelse = nil + fakeelse = FakeAST.new(:else) + faketest = FakeAST.new(true) + fakeif = FakeAST.new(:if) - # Now call the two classes - assert_nothing_raised("Could not add AST nodes for calling") { - children << AST::ObjectDef.new( - :type => nameobj("child1"), - :name => nameobj("yayness"), - :params => astarray() - ) + assert_nothing_raised { + astelse = AST::Else.new(:statements => fakeelse) } - - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => children + assert_nothing_raised { + astif = AST::IfStatement.new( + :test => faketest, + :statements => fakeif, + :else => astelse ) } - scope = nil - assert_raise(Puppet::ParseError, "Invalid parent type was allowed") { - scope = Puppet::Parser::Scope.new() - objects = scope.evaluate(:ast => top) + # We initialized it to true, so we should get that first + ret = nil + assert_nothing_raised { + ret = astif.evaluate(:scope => "yay") } - end - - # Verify that nodes don't evaluate code in other node scopes but that their - # facts work outside their scopes. - def test_nodescopes - parent = child1 = nil - topchildren = [] - - # create the parent class - topchildren << classobj("everyone") - - topchildren << classobj("parent") - - - classes = %w{everyone parent} + assert_equal(:if, ret) - # And a variable, so we verify the facts get set at the top + # Now set it to false and check that + faketest.evaluate = false assert_nothing_raised { - children = [] - children << varobj("yaytest", "$hostname") + ret = astif.evaluate(:scope => "yay") } + assert_equal(:else, ret) + end - nodes = [] - - 3.times do |i| - children = [] - - # Create a child class - topchildren << classobj("perchild#{i}", :parentclass => nameobj("parent")) - classes << "perchild%s" - - # Create a child class - children << classobj("child", :parentclass => nameobj("parent")) - - classes << "child" - - ["child", "everyone", "perchild#{i}"].each do |name| - # Now call our child class - assert_nothing_raised { - children << AST::ObjectDef.new( - :type => nameobj(name), - :params => astarray() - ) - } - end + # Make sure our override object behaves "correctly" + def test_override + interp, scope, source = mkclassframing - # and another variable - assert_nothing_raised { - children << varobj("rahtest", "$hostname") - } - - # create the node - nodename = "node#{i}" - nodes << nodename - assert_nothing_raised("Could not create parent object") { - topchildren << AST::NodeDef.new( - :names => nameobj(nodename), - :code => AST::ASTArray.new( - :children => children - ) - ) - } + ref = nil + assert_nothing_raised do + ref = resourceoverride("resource", "yaytest", "one" => "yay", "two" => "boo") end - # Create the wrapper object - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => topchildren - ) - } - - nodes.each_with_index do |node, i| - # Evaluate the parse tree - scope = Puppet::Parser::Scope.new() - args = {:names => [node], :facts => {"hostname" => node}, :ast => top} + ret = nil + assert_nothing_raised do + ret = ref.evaluate :scope => scope + end - # verify that we can evaluate it okay - trans = nil - assert_nothing_raised("Could not retrieve node definition") { - trans = scope.evaluate(args) - } + assert_instance_of(Puppet::Parser::Resource, ret) - assert_equal(node, scope.lookupvar("hostname")) + assert(ret.override?, "Resource was not an override resource") - assert(trans, "Could not retrieve trans objects") + assert(scope.overridetable[ret.ref].include?(ret), + "Was not stored in the override table") + end - # and that we can convert them to type objects - objects = nil - assert_nothing_raised("Could not retrieve node definition") { - objects = trans.to_type - } + # make sure our resourcedefaults ast object works correctly. + def test_resourcedefaults + interp, scope, source = mkclassframing - assert(objects, "Could not retrieve trans objects") + # Now make some defaults for files + args = {:source => "/yay/ness", :group => "yayness"} + assert_nothing_raised do + obj = defaultobj "file", args + obj.evaluate :scope => scope + end - count = 0 - # Make sure the node name gets into the path correctly. - Puppet.type(:file).each { |obj| - count += 1 - assert(obj.path !~ /#{node}\[#{node}\]/, - "Node name appears twice") - } + hash = nil + assert_nothing_raised do + hash = scope.lookupdefaults("file") + end - assert(count > 0, "Did not create any files") + hash.each do |name, value| + assert_instance_of(Symbol, name) # params always convert + assert_instance_of(Puppet::Parser::Resource::Param, value) + end - classes.each do |name| - if name =~ /%s/ - name = name % i - end - assert(Puppet::Type.type(:file)["/#{name}"], "Could not find '#{name}'") - end - Puppet::Type.allclear + args.each do |name, value| + assert(hash[name], "Did not get default %s" % name) + assert_equal(value, hash[name].value) end end - # Verify that classes are correctly defined in node scopes. - def disabled_test_nodeclasslookup - parent = child1 = nil - children = [] - - # create the parent class - children << classobj("parent") - - # Create child class one - children << classobj("child1", :parentclass => nameobj("parent")) - - # Now call the two classes - assert_nothing_raised("Could not add AST nodes for calling") { - children << AST::ObjectDef.new( - :type => nameobj("child1"), - :name => nameobj("yayness"), - :params => astarray() - ) - } - - # create the node - nodename = "mynodename" - node = nil - assert_nothing_raised("Could not create parent object") { - node = AST::NodeDef.new( - :names => nameobj(nodename), - :code => AST::ASTArray.new( - :children => children - ) - ) - } + def test_hostclass + interp, scope, source = mkclassframing - # Create the wrapper object - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => [node] + # Create the class we're testing, first with no parent + klass = interp.newclass "first", + :code => AST::ASTArray.new( + :children => [resourcedef("file", "/tmp", + "owner" => "nobody", "mode" => "755")] ) - } - - # Evaluate the parse tree - scope = nil - assert_nothing_raised("Could not evaluate node") { - scope = Puppet::Parser::Scope.new() - top.evaluate(:scope => scope) - } - - # Verify that, well, nothing really happened, and especially verify - # that the top scope is not a node scope - assert(scope.topscope?, "Scope is not top scope") - assert(! scope.nodescope?, "Scope is mistakenly node scope") - assert(! scope.lookupclass("parent"), "Found parent class in top scope") - # verify we can find our node - assert(scope.node(nodename), "Could not find node") - - # And verify that we can evaluate it okay - objects = nil - assert_nothing_raised("Could not retrieve node definition") { - objects = scope.evalnode(:name => [nodename], :facts => {}) - } - - assert(objects, "Could not retrieve node definition") - - # Because node scopes are temporary (i.e., they get destroyed after the node's - # config is returned) we should not be able to find the node scope. - nodescope = nil - assert_nothing_raised { - nodescope = scope.find { |child| - child.nodescope? - } - } - - assert_nil(nodescope, "Found nodescope") - - # And now verify again that the top scope cannot find the node's definition - # of the parent class - assert(! scope.lookupclass("parent"), "Found parent class in top scope") - - trans = nil - # Verify that we can evaluate the node twice - assert_nothing_raised("Could not retrieve node definition") { - trans = scope.evalnode(:name => [nodename], :facts => {}) - } - - objects = nil - assert_nothing_raised("Could not convert to objects") { - objects = trans.to_type - } - - Puppet.type(:file).each { |obj| - assert(obj.path !~ /#{nodename}\[#{nodename}\]/, - "Node name appears twice") - } - - assert(Puppet::Type.type(:file)["/child1"], "Could not find child") - assert(Puppet::Type.type(:file)["/parent"], "Could not find parent") - end + assert_nothing_raised do + klass.evaluate(:scope => scope) + end - # Test that you can look a host up using multiple names, e.g., an FQDN and - # a short name - def test_multiplenodenames - children = [] + # Then try it again + assert_nothing_raised do + klass.evaluate(:scope => scope) + end - # create a short-name node - shortname = "mynodename" - children << nodedef(shortname) + assert(scope.setclass?(klass), "Class was not considered evaluated") - # And a long-name node - longname = "node.domain.com" - children << nodedef(longname) + tmp = scope.findresource("file[/tmp]") + assert(tmp, "Could not find file /tmp") + assert_equal("nobody", tmp[:owner]) + assert_equal("755", tmp[:mode]) - # Create the wrapper object - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => children - ) - } - - # Evaluate the parse tree - scope = Puppet::Parser::Scope.new() - - # Verify we can find the node via a search list - objects = nil - assert_nothing_raised("Could not retrieve short node definition") { - objects = scope.evaluate( - :names => ["%s.domain.com" % shortname, shortname], :facts => {}, - :ast => top + # Now create a couple more classes. + newbase = interp.newclass "newbase", + :code => AST::ASTArray.new( + :children => [resourcedef("file", "/tmp/other", + "owner" => "nobody", "mode" => "644")] ) - } - assert(objects, "Could not retrieve short node definition") - - scope = Puppet::Parser::Scope.new() - # and then look for the long name - assert_nothing_raised("Could not retrieve long node definition") { - objects = scope.evaluate( - :names => [longname.sub(/\..+/, ''), longname], :facts => {}, - :ast => top + newsub = interp.newclass "newsub", + :parent => "newbase", + :code => AST::ASTArray.new( + :children => [resourcedef("file", "/tmp/yay", + "owner" => "nobody", "mode" => "755"), + resourceoverride("file", "/tmp/other", + "owner" => "daemon") + ] ) - } - assert(objects, "Could not retrieve long node definition") - end - - # Test that a node gets the entire configuration except for work meant for - # another node - def test_fullconfigwithnodes - children = [] - - children << fileobj("/testing") - # create a short-name node - name = "mynodename" - children << nodedef(name) - - # Create the wrapper object - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => children + # Override a different variable in the top scope. + moresub = interp.newclass "moresub", + :parent => "newbase", + :code => AST::ASTArray.new( + :children => [resourceoverride("file", "/tmp/other", + "mode" => "755")] ) - } - scope = Puppet::Parser::Scope.new() - - # Verify we can find the node via a search list - objects = nil - assert_nothing_raised("Could not retrieve short node definition") { - objects = scope.evaluate(:names => [name], :facts => {}, :ast => top) - } - assert(objects, "Could not retrieve short node definition") - assert_instance_of(Puppet::TransBucket, objects) - - # And now verify that we got both the top and node objects - assert_nothing_raised("Could not find top-declared object") { - assert_equal("/testing", objects[0].name) - } - - assert_nothing_raised("Could not find node-declared object %s" % - "/%s" % name - ) { - assert_equal("/%s" % name, objects[1][0].name) - } - end - - # Test that we can 'include' variables, not just normal strings. - def test_includevars - children = [] - classes = [] - - # Create our class for testin - klassname = "include" - children << classobj(klassname) - classes << klassname - - # Then add our variable assignment - children << varobj("klassvar", klassname) - - # And finally add our calling of the variable - children << AST::ObjectDef.new( - :type => AST::Variable.new(:value => "klassvar"), - :params => astarray - ) - - # And then create our top object - top = AST::ASTArray.new( - :children => children - ) + assert_nothing_raised do + newsub.evaluate(:scope => scope) + end - # Evaluate the parse tree - scope = nil - objects = nil - assert_nothing_raised("Could not evaluate node") { - scope = Puppet::Parser::Scope.new() - objects = scope.evaluate(:ast => top) - } + assert_nothing_raised do + moresub.evaluate(:scope => scope) + end - # Verify we get the right classlist back - assert_equal(classes.sort, scope.classlist.sort) + assert(scope.setclass?(newbase), "Did not eval newbase") + assert(scope.setclass?(newsub), "Did not eval newsub") - # Verify we can find the node via a search list - #assert_nothing_raised("Could not retrieve objects") { - # objects = scope.to_trans - #} - assert(objects, "Could not retrieve objects") + yay = scope.findresource("file[/tmp/yay]") + assert(yay, "Did not find file /tmp/yay") + assert_equal("nobody", yay[:owner]) + assert_equal("755", yay[:mode]) - assert_nothing_raised("Could not find top-declared object") { - assert_equal("/%s" % klassname, objects[0][0].name) - } + other = scope.findresource("file[/tmp/other]") + assert(other, "Did not find file /tmp/other") + assert_equal("daemon", other[:owner]) + assert_equal("755", other[:mode]) end - # Test that node inheritance works correctly - def test_nodeinheritance - children = [] + def test_component + interp, scope, source = mkclassframing - # create the base node - name = "basenode" - children << nodedef(name) - - # and the sub node - name = "subnode" - children << AST::NodeDef.new( - :names => nameobj(name), - :parentclass => nameobj("basenode"), + # Create a new definition + klass = interp.newdefine "yayness", + :arguments => [["owner", stringobj("nobody")], %w{mode}], :code => AST::ASTArray.new( - :children => [ - varobj("%svar" % name, "%svalue" % name), - fileobj("/%s" % name) - ] + :children => [resourcedef("file", "/tmp/$name", + "owner" => varref("owner"), "mode" => varref("mode"))] ) - ) - #subnode = nodedef(name) - #subnode.parentclass = "basenode" - #children << subnode + # Test validattr? a couple different ways + [:owner, "owner", :schedule, "schedule"].each do |var| + assert(klass.validattr?(var), "%s was not considered valid" % var.inspect) + end - # and the top object - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => children + [:random, "random"].each do |var| + assert(! klass.validattr?(var), "%s was considered valid" % var.inspect) + end + # Now call it a couple of times + # First try it without a required param + assert_raise(Puppet::ParseError) do + klass.evaluate(:scope => scope, + :name => "bad", + :arguments => {"owner" => "nobody"} ) - } + end - # Evaluate the parse tree - scope = Puppet::Parser::Scope.new() + # And make sure it didn't create the file + assert_nil(scope.findresource("file[/tmp/bad]"), + "Made file with invalid params") - # Verify we can find the node via a search list - objects = nil - assert_nothing_raised("Could not evaluate node") { - objects = scope.evaluate(:names => [name], :facts => {}, :ast => top) - } - assert(objects, "Could not retrieve node definition") - - assert_nothing_raised { - inner = objects[0] - - # And now verify that we got the subnode file - assert_nothing_raised("Could not find basenode file") { - base = inner[0] - assert_equal("/basenode", base.name) - } - - # and the parent node file - assert_nothing_raised("Could not find subnode file") { - sub = inner[1] - assert_equal("/subnode", sub.name) - } - - inner.each { |obj| - %w{basenode subnode}.each { |tag| - assert(obj.tags.include?(tag), - "%s did not include %s tag" % [obj.name, tag] - ) - } - } - } - end - - def test_typechecking - object = nil - children = [] - type = "deftype" - assert_nothing_raised("Could not add AST nodes for calling") { - object = AST::ObjectDef.new( - :type => nameobj(type), - :name => nameobj("yayness"), - :params => astarray() + assert_nothing_raised do + klass.evaluate(:scope => scope, + :name => "first", + :arguments => {"mode" => "755"} ) - } - - assert_nothing_raised("Typecheck failed") { - object.typecheck(type) - } - - # Add a scope, which makes it think it's evaluating - assert_nothing_raised { - scope = Puppet::Parser::Scope.new() - object.scope = scope - } + end - # Verify an error is thrown when it can't find the type - assert_raise(Puppet::ParseError) { - object.typecheck(type) - } + firstobj = scope.findresource("file[/tmp/first]") + assert(firstobj, "Did not create /tmp/first obj") - # Create child class one - children << classobj(type) - children << object + assert_equal("file", firstobj.type) + assert_equal("/tmp/first", firstobj.title) + assert_equal("nobody", firstobj[:owner]) + assert_equal("755", firstobj[:mode]) - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => children + # Make sure we can't evaluate it with the same args + assert_raise(Puppet::ParseError) do + klass.evaluate(:scope => scope, + :name => "first", + :arguments => {"mode" => "755"} ) - } - - scope = nil - assert_nothing_raised("Could not evaluate") { - scope = Puppet::Parser::Scope.new() - objects = top.evaluate(:scope => scope) - } - end + end - def disabled_test_paramcheck - object = nil - children = [] - type = "deftype" - params = %w{param1 param2} - - comp = compobj(type, { - :args => astarray( - argobj("param1", "yay"), - argobj("param2", "rah") - ), - :code => AST::ASTArray.new( - :children => [ - varobj("%svar" % name, "%svalue" % name), - fileobj("/%s" % name) - ] + # Now create another with different args + assert_nothing_raised do + klass.evaluate(:scope => scope, + :name => "second", + :arguments => {"mode" => "755", "owner" => "daemon"} ) - }) - assert_nothing_raised("Could not add AST nodes for calling") { - object = AST::ObjectDef.new( - :type => nameobj(type), - :name => nameobj("yayness"), - :params => astarray( - astarray(stringobj("param1"), stringobj("value1")), - astarray(stringobj("param2"), stringobj("value2")) - ) - ) - } - - # Add a scope, which makes it think it's evaluating - assert_nothing_raised { - scope = Puppet::Parser::Scope.new() - object.scope = scope - } - - # Verify an error is thrown when it can't find the type - assert_raise(Puppet::ParseError) { - object.paramcheck(false, comp) - } + end - # Create child class one - children << classobj(type) - children << object + secondobj = scope.findresource("file[/tmp/second]") + assert(secondobj, "Did not create /tmp/second obj") - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => children - ) - } - - scope = nil - assert_nothing_raised("Could not evaluate") { - scope = Puppet::Parser::Scope.new() - objects = top.evaluate(:scope => scope) - } + assert_equal("file", secondobj.type) + assert_equal("/tmp/second", secondobj.title) + assert_equal("daemon", secondobj[:owner]) + assert_equal("755", secondobj[:mode]) end - def test_setclass - type = "yay" - classes = [type] - children = [] - # Create child class one - children << varobj("variable", "aclass") - children << tagobj(type, varref("variable")) - children << tagobj(type) + def test_node + interp = mkinterp + scope = mkscope(:interp => interp) - classes << "aclass" + # Define a base node + basenode = interp.newnode "basenode", :code => AST::ASTArray.new(:children => [ + resourcedef("file", "/tmp/base", "owner" => "root") + ]) - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => children - ) - } + # Now define a subnode + nodes = interp.newnode ["mynode", "othernode"], + :code => AST::ASTArray.new(:children => [ + resourcedef("file", "/tmp/mynode", "owner" => "root"), + resourcedef("file", "/tmp/basenode", "owner" => "daemon") + ]) - scope = nil - assert_nothing_raised("Could not evaluate") { - scope = Puppet::Parser::Scope.new() - objects = top.evaluate(:scope => scope) - } + assert_instance_of(Array, nodes) + # Make sure we can find them all. + %w{mynode othernode}.each do |node| + assert(interp.nodesearch_code(node), "Could not find %s" % node) + end + mynode = interp.nodesearch_code("mynode") - classes.each do |tag| - assert(scope.classlist.include?(tag), "Did not set class %s" % tag) + # Now try evaluating the node + assert_nothing_raised do + mynode.evaluate :scope => scope end - end + # Make sure that we can find each of the files + myfile = scope.findresource "file[/tmp/mynode]" + assert(myfile, "Could not find file from node") + assert_equal("root", myfile[:owner]) - # Test that we strip the domain off of host names before they are set as classes - def test_nodenamestrip - children = [] + basefile = scope.findresource "file[/tmp/basenode]" + assert(basefile, "Could not find file from base node") + assert_equal("daemon", basefile[:owner]) - longname = "node.domain.com" - children << nodedef(longname) + # Now make sure we can evaluate nodes with parents + child = interp.newnode(%w{child}, :parent => "basenode").shift - # Create the wrapper object - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => children - ) - } - - scope = Puppet::Parser::Scope.new() - - assert_nothing_raised("Could not evaluate node") { - objects = scope.evaluate(:names => [longname], :facts => {}, :ast => top) - } + newscope = mkscope :interp => interp + assert_nothing_raised do + child.evaluate :scope => newscope + end - assert(!scope.classlist.include?("node.domain.com"), - "Node's long name got set") - assert(scope.classlist.include?("node"), "Node's name did not get set") + assert(newscope.findresource("file[/tmp/base]"), + "Could not find base resource") end - # Make sure that deep class parentage works - def test_classparentage - children = [] - files = [] - base = classobj("base") - files << "/base" + def test_collection + interp = mkinterp + scope = mkscope(:interp => interp) - children << base + coll = nil + assert_nothing_raised do + coll = AST::Collection.new(:type => "file", :form => :virtual) + end - parent = "base" - 5.times { |i| - name = "child%s" % i - files << "/%s" % name - children << classobj(name, :parentclass => nameobj(parent)) + assert_instance_of(AST::Collection, coll) - parent = name - } + ret = nil + assert_nothing_raised do + ret = coll.evaluate :scope => scope + end - children << functionobj("include", parent) + assert_instance_of(Puppet::Parser::Collector, ret) - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => children - ) - } + # Now make sure we get it back from the scope + assert_equal([ret], scope.collections) + end - objects = nil - assert_nothing_raised("Could not evaluate") { - scope = Puppet::Parser::Scope.new() - objects = scope.evaluate(:ast => top) - } + def test_virtual_collexp + @interp, @scope, @source = mkclassframing - objects = objects.flatten + # make a resource + resource = mkresource(:type => "file", :title => "/tmp/testing", + :params => {:owner => "root", :group => "bin", :mode => "644"}) - files.each do |file| - assert(objects.find { |o| o.name == file }, - "Could not find file %s" % file) + run_collection_queries(:virtual) do |string, result, query| + code = nil + assert_nothing_raised do + str, code = query.evaluate :scope => @scope + end + + assert_instance_of(Proc, code) + assert_nothing_raised do + assert_equal(result, code.call(resource), + "'#{string}' failed") + end end end - # Make sure we catch names that are specified like parameters. - def test_name_or_param - obj = nil - assert_nothing_raised { - obj = AST::ObjectDef.new( - :type => nameobj("file"), - :params => astarray(AST::ObjectParam.new( - :param => stringobj("name"), - :value => stringobj("yayness") - )) - ) - } - - scope = Puppet::Parser::Scope.new + if defined? ActiveRecord::Base + def test_exported_collexp + railsinit + Puppet[:storeconfigs] = true + @interp, @scope, @source = mkclassframing + + # make a rails resource + railsresource "file", "/tmp/testing", :owner => "root", :group => "bin", + :mode => "644" + + run_collection_queries(:exported) do |string, result, query| + code = nil + str = nil + + # We don't support anything but the title in rails right now + retval = nil + bad = false + # Figure out if the search is for anything rails will ignore + string.scan(/(\w+) [!=]= \w+/) do |s| + unless s[0] == "title" + bad = true + break + end + end - trans = nil - assert_nothing_raised { - trans = scope.evaluate(:ast => obj, :facts => {}) - } + # And if it is, make sure we throw an error. + if bad + assert_raise(Puppet::ParseError, "Evaluated '#{string}'") do + str, code = query.evaluate :scope => @scope + end + next + else + assert_nothing_raised("Could not evaluate '#{string}'") do + str, code = query.evaluate :scope => @scope + end + end + assert_nothing_raised("Could not find resource") do + retval = Puppet::Rails::RailsResource.find(:all, + :include => :rails_parameters, + :conditions => str) + end - transobj = trans.shift - assert(transobj.name, "Name did not convert from param to name") - end + if result + assert_equal(1, retval.length, "Did not find resource with '#{string}'") + res = retval.shift - if defined? ActiveRecord - # Verify that our collection stuff works. - def test_collection - collectable = [] - non = [] - # First put some objects into the database. - bucket = mk_transtree do |object, depth, width| - # and mark some of them collectable - if width % 2 == 1 - object.collectable = true - collectable << object + assert_equal("file", res.restype) + assert_equal("/tmp/testing", res.title) else - non << object + assert_equal(0, retval.length, "found a resource with '#{string}'") end end - - # Now collect our facts - facts = {} - Facter.each do |fact, value| facts[fact] = value end - - assert_nothing_raised { - Puppet::Rails.init - } - - # Now try storing our crap - assert_nothing_raised { - host = Puppet::Rails::Host.store( - :objects => bucket, - :facts => facts, - :host => facts["hostname"] - ) - } - - # Now create an ast tree that collects that. They should all be files. - coll = nil - assert_nothing_raised { - coll = AST::Collection.new( - :type => nameobj("file") - ) - } - - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => [coll] - ) - } - - objects = nil - assert_nothing_raised("Could not evaluate") { - scope = Puppet::Parser::Scope.new() - objects = scope.evaluate(:ast => top).flatten - } - - assert(objects.length > 0, "Did not receive any collected objects") end - else - $stderr.puts "No ActiveRecord -- skipping collection tests" end - # To fix #140. Currently non-functional. - def disabled_test_classreuse - children = [] - - # Create the parent class, with a definition in it. - children << classobj("parent", :code => AST::ASTArray.new( - :file => __FILE__, - :line => __LINE__, - :children => [ - compobj("foo", :args => AST::ASTArray.new( - :children => [nameobj("arg")] - ), - :code => AST::ASTArray.new( - :file => __FILE__, - :line => __LINE__, - :children => [fileobj("/$arg")] - ) - ), - objectdef("foo", "ptest", {"arg" => "parentfoo"}) - ] - )) - - # Create child class, also trying to use that definition - children << classobj("child1", :parentclass => nameobj("parent"), - :code => AST::ASTArray.new( - :file => __FILE__, - :line => __LINE__, - :children => [ - objectdef("foo", "ctest", {"arg" => "childfoo"}) - ] - ) - ) - - # Call the parent first - children << functionobj("include", "parent") - - # Then call the child, and make sure it can look up the definition - children << functionobj("include", "child1") - - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => children - ) - } - - objects = nil - assert_nothing_raised("Could not evaluate") { - scope = Puppet::Parser::Scope.new() - objects = scope.evaluate(:ast => top) - } - end - - def test_if - astif = nil - astelse = nil - fakeelse = FakeAST.new(:else) - faketest = FakeAST.new(true) - fakeif = FakeAST.new(:if) - - assert_nothing_raised { - astelse = AST::Else.new(:statements => fakeelse) - } - assert_nothing_raised { - astif = AST::IfStatement.new( - :test => faketest, - :statements => fakeif, - :else => astelse - ) - } + def run_collection_queries(form) + {true => [%{title == "/tmp/testing"}, %{(title == "/tmp/testing")}, + %{title == "/tmp/testing" and group == bin}, %{title == bin or group == bin}, + %{title == "/tmp/testing" or title == bin}, %{title == "/tmp/testing"}, + %{(title == "/tmp/testing" or title == bin) and group == bin}], + false => [%{title == bin}, %{title == bin or (title == bin and group == bin)}, + %{title != "/tmp/testing"}, %{title != "/tmp/testing" and group != bin}] + }.each do |res, ary| + ary.each do |str| + if form == :virtual + code = "File <| #{str} |>" + else + code = "File <<| #{str} |>>" + end + parser = mkparser + query = nil - # We initialized it to true, so we should get that first - ret = nil - assert_nothing_raised { - ret = astif.evaluate(:scope => "yay") - } - assert_equal(:if, ret) + assert_nothing_raised("Could not parse '#{str}'") do + query = parser.parse(code)[0].query + end - # Now set it to false and check that - faketest.evaluate = false - assert_nothing_raised { - ret = astif.evaluate(:scope => "yay") - } - assert_equal(:else, ret) + yield str, res, query + end + end end end diff --git a/test/language/collector.rb b/test/language/collector.rb new file mode 100755 index 000000000..d7ac059fa --- /dev/null +++ b/test/language/collector.rb @@ -0,0 +1,206 @@ +#!/usr/bin/ruby + +require 'puppet/rails' +require 'puppettest' +require 'puppettest/parsertesting' +require 'puppettest/resourcetesting' +require 'puppettest/railstesting' + +class TestCollector < Test::Unit::TestCase + include PuppetTest + include PuppetTest::ParserTesting + include PuppetTest::ResourceTesting + include PuppetTest::RailsTesting + Parser = Puppet::Parser + AST = Parser::AST + + def setup + super + Puppet[:trace] = false + @interp, @scope, @source = mkclassframing + end + + def test_virtual + # Make a virtual resource + virtual = mkresource(:type => "file", :title => "/tmp/virtual", + :virtual => true, :params => {:owner => "root"}) + @scope.setresource virtual + + # And a non-virtual + real = mkresource(:type => "file", :title => "/tmp/real", + :params => {:owner => "root"}) + @scope.setresource real + + # Now make a collector + coll = nil + assert_nothing_raised do + coll = Puppet::Parser::Collector.new(@scope, "file", nil, :virtual) + end + + # Set it in our scope + @scope.newcollection(coll) + + # Make sure it's in the collections + assert_equal([coll], @scope.collections) + + # And try to collect the virtual resources. + ret = nil + assert_nothing_raised do + ret = coll.collect_virtual + end + + assert_equal([virtual], ret) + + # Now make sure evaluate does the right thing. + assert_nothing_raised do + ret = coll.evaluate + end + + # Make sure it got deleted from the collection list + assert_equal([], @scope.collections) + + # And make sure our virtual object is no longer virtual + assert(! virtual.virtual?, "Virtual object did not get realized") + + # Now make a new collector of a different type and make sure it + # finds nothing. + assert_nothing_raised do + coll = Puppet::Parser::Collector.new(@scope, "exec", nil, :virtual) + end + + # Remark this as virtual + virtual.virtual = true + + assert_nothing_raised do + ret = coll.evaluate + end + + assert_equal([], ret) + end + + if defined? ActiveRecord::Base + def test_collect_exported + railsinit + # make an exported resource + exported = mkresource(:type => "file", :title => "/tmp/exported", + :exported => true, :params => {:owner => "root"}) + @scope.setresource exported + + assert(exported.exported?, "Object was not marked exported") + assert(exported.virtual?, "Object was not marked virtual") + + # And a non-exported + real = mkresource(:type => "file", :title => "/tmp/real", + :params => {:owner => "root"}) + @scope.setresource real + + # Now make a collector + coll = nil + assert_nothing_raised do + coll = Puppet::Parser::Collector.new(@scope, "file", nil, :exported) + end + + # Set it in our scope + @scope.newcollection(coll) + + # Make sure it's in the collections + assert_equal([coll], @scope.collections) + + # And try to collect the virtual resources. + ret = nil + assert_nothing_raised do + ret = coll.collect_exported + end + + assert_equal([exported], ret) + + # Now make sure evaluate does the right thing. + assert_nothing_raised do + ret = coll.evaluate + end + + # Make sure it got deleted from the collection list + assert_equal([], @scope.collections) + + # And make sure our exported object is no longer exported + assert(! exported.virtual?, "Virtual object did not get realized") + + # But it should still be marked exported. + assert(exported.exported?, "Resource got un-exported") + + # Now make a new collector of a different type and make sure it + # finds nothing. + assert_nothing_raised do + coll = Puppet::Parser::Collector.new(@scope, "exec", nil, :exported) + end + + # Remark this as virtual + exported.virtual = true + + assert_nothing_raised do + ret = coll.evaluate + end + + assert_equal([], ret) + end + + def test_collection_conflicts + railsinit + + # First make a railshost we can conflict with + host = Puppet::Rails::Host.new(:name => "myhost") + + host.rails_resources.build(:title => "/tmp/conflicttest", :restype => "file", + :exported => true) + + host.save + + # Now make a normal resource + normal = mkresource(:type => "file", :title => "/tmp/conflicttest", + :params => {:owner => "root"}) + @scope.setresource normal + + # Now make a collector + coll = nil + assert_nothing_raised do + coll = Puppet::Parser::Collector.new(@scope, "file", nil, :exported) + end + + # And try to collect the virtual resources. + assert_raise(Puppet::ParseError) do + ret = coll.collect_exported + end + end + + # Make sure we do not collect resources from the host we're on + def test_no_resources_from_me + railsinit + + # Make our configuration + host = Puppet::Rails::Host.new(:name => "myhost") + + host.rails_resources.build(:title => "/tmp/hosttest", :restype => "file", + :exported => true) + + host.save + + @scope.host = "myhost" + + # Now make a collector + coll = nil + assert_nothing_raised do + coll = Puppet::Parser::Collector.new(@scope, "file", nil, :exported) + end + + # And make sure we get nada back + ret = nil + assert_nothing_raised do + ret = coll.collect_exported + end + + assert(ret.empty?, "Found exports from our own host") + end + end +end + +# $Id$ diff --git a/test/language/functions.rb b/test/language/functions.rb index 2c3246e6a..062971bf1 100755 --- a/test/language/functions.rb +++ b/test/language/functions.rb @@ -35,7 +35,7 @@ class TestLangFunctions < Test::Unit::TestCase ) end - scope = Puppet::Parser::Scope.new() + scope = mkscope val = nil assert_nothing_raised do val = func.evaluate(:scope => scope) @@ -45,10 +45,10 @@ class TestLangFunctions < Test::Unit::TestCase end def test_taggedfunction - scope = Puppet::Parser::Scope.new() + scope = mkscope tag = "yayness" - scope.setclass(tag.object_id, tag) + scope.tag(tag) {"yayness" => true, "booness" => false}.each do |tag, retval| func = taggedobj(tag, :rvalue) @@ -75,7 +75,7 @@ class TestLangFunctions < Test::Unit::TestCase ) end - scope = Puppet::Parser::Scope.new() + scope = mkscope val = nil assert_raise(Puppet::ParseError) do val = func.evaluate(:scope => scope) @@ -107,7 +107,7 @@ class TestLangFunctions < Test::Unit::TestCase end ast = varobj("output", func) - scope = Puppet::Parser::Scope.new() + scope = mkscope assert_raise(Puppet::ParseError) do ast.evaluate(:scope => scope) end @@ -145,7 +145,7 @@ class TestLangFunctions < Test::Unit::TestCase end ast = varobj("output", func) - scope = Puppet::Parser::Scope.new() + scope = mkscope assert_raise(Puppet::ParseError) do ast.evaluate(:scope => scope) end @@ -180,7 +180,7 @@ class TestLangFunctions < Test::Unit::TestCase end ast = varobj("output", func) - scope = Puppet::Parser::Scope.new() + scope = mkscope scope.setvar("myvar", "this is yayness") assert_raise(Puppet::ParseError) do ast.evaluate(:scope => scope) @@ -257,7 +257,7 @@ class TestLangFunctions < Test::Unit::TestCase "" => "", false => "false", }.each do |string, value| - scope = Puppet::Parser::Scope.new() + scope = mkscope assert_raise(Puppet::ParseError) do ast.evaluate(:scope => scope) end diff --git a/test/language/interpreter.rb b/test/language/interpreter.rb index c127ab517..e195e28b3 100755 --- a/test/language/interpreter.rb +++ b/test/language/interpreter.rb @@ -8,10 +8,18 @@ require 'puppet/parser/parser' require 'puppet/client' require 'puppet/rails' require 'puppettest' +require 'puppettest/resourcetesting' +require 'puppettest/parsertesting' +require 'puppettest/servertest' +require 'puppettest/railstesting' +require 'timeout' class TestInterpreter < Test::Unit::TestCase include PuppetTest include PuppetTest::ServerTest + include PuppetTest::ParserTesting + include PuppetTest::ResourceTesting + include PuppetTest::RailsTesting AST = Puppet::Parser::AST # create a simple manifest that uses nodes to create a file @@ -135,81 +143,48 @@ class TestInterpreter < Test::Unit::TestCase return parent, classes end - def test_ldapnodes + def test_ldapsearch Puppet[:ldapbase] = "ou=hosts, dc=madstop, dc=com" Puppet[:ldapnodes] = true ldapconnect() - file = tempfile() - files = [] - parentfile = tempfile() + "-parent" - files << parentfile - hostname = Facter["hostname"].value - lparent, lclasses = ldaphost(Facter["hostname"].value) - assert(lclasses, "Did not retrieve info from ldap") - File.open(file, "w") { |f| - f.puts "node #{lparent} { - file { \"#{parentfile}\": ensure => file } -}" - - lclasses.each { |klass| - kfile = tempfile() + "-klass" - files << kfile - f.puts "class #{klass} { file { \"#{kfile}\": ensure => file } }" - } - } - interp = nil - assert_nothing_raised { - interp = Puppet::Parser::Interpreter.new( - :Manifest => file - ) - } - parent = nil - classes = nil - # First make sure we get the default node for unknown hosts - dparent, dclasses = ldaphost("default") + interp = mkinterp :NodeSources => [:ldap, :code] - assert_nothing_raised { - parent, classes = interp.nodesearch("nosuchhostokay") - } + # Make sure we can find 'culain' in ldap + parent, classes = nil + assert_nothing_raised do + parent, classes = interp.ldapsearch("culain") + end - assert_equal(dparent, parent, "Default parent node did not match") - assert_equal(dclasses, classes, "Default parent class list did not match") + realparent, realclasses = ldaphost("culain") + assert_equal(realparent, parent) + assert_equal(realclasses, classes) + end - # Look for a host we know doesn't have a parent - npparent, npclasses = ldaphost("noparent") - assert_nothing_raised { - #parent, classes = interp.nodesearch_ldap("noparent") - parent, classes = interp.nodesearch("noparent") - } + def test_ldapnodes + Puppet[:ldapbase] = "ou=hosts, dc=madstop, dc=com" + Puppet[:ldapnodes] = true - assert_equal(npparent, parent, "Parent node did not match") - assert_equal(npclasses, classes, "Class list did not match") + ldapconnect() - # Now look for our normal host - assert_nothing_raised { - parent, classes = interp.nodesearch_ldap(hostname) - } + interp = mkinterp :NodeSources => [:ldap, :code] - assert_equal(lparent, parent, "Parent node did not match") - assert_equal(lclasses, classes, "Class list did not match") + # culain uses basenode, so create that + basenode = interp.newnode([:basenode])[0] - objects = nil - assert_nothing_raised { - objects = interp.run(hostname, Puppet::Client::MasterClient.facts) - } + # Make sure we can find 'culain' in ldap + culain = nil + assert_nothing_raised do + culain = interp.nodesearch_ldap("culain") + end - comp = nil - assert_nothing_raised { - comp = objects.to_type - } + assert(culain, "Did not find culain in ldap") - assert_apply(comp) - files.each { |cfile| - @@tmpfiles << cfile - assert(FileTest.exists?(cfile), "Did not make %s" % cfile) - } + assert_nothing_raised do + assert_equal(basenode.fqname.to_s, culain.parentclass.fqname.to_s, + "Did not get parent class") + end end if Puppet::SUIDManager.uid == 0 and Facter["hostname"].value == "culain" @@ -260,87 +235,32 @@ class TestInterpreter < Test::Unit::TestCase # Make sure searchnode behaves as we expect. def test_nodesearch - # First create a fake nodesearch algorithm - i = 0 - bucket = [] - Puppet::Parser::Interpreter.send(:define_method, "nodesearch_fake") do |node| - return nil, nil if node == "default" - - return bucket[0], bucket[1] - end - text = %{ -node nodeparent {} -node othernodeparent {} -class nodeclass {} -class nothernode {} -} - manifest = tempfile() - File.open(manifest, "w") do |f| f.puts text end - interp = nil - assert_nothing_raised { - interp = Puppet::Parser::Interpreter.new( - :Manifest => manifest, - :NodeSources => [:fake] - ) - } - # Make sure it behaves correctly for all forms - [[nil, nil], - ["nodeparent", nil], - [nil, ["nodeclass"]], - [nil, ["nodeclass", "nothernode"]], - ["othernodeparent", ["nodeclass", "nothernode"]],].each do |ary| - # Set the return values - bucket = ary - - # Look them back up - parent, classes = interp.nodesearch("mynode") - - # Basically, just make sure that if we have either or both, - # we get a result back. - assert_equal(ary[0], parent, - "Parent is not %s" % parent) - assert_equal(ary[1], classes, - "Parent is not %s" % parent) - - next if ary == [nil, nil] - # Now make sure we actually get the configuration. This will throw - # an exception if we don't. - assert_nothing_raised do - interp.run("mynode", {}) - end - end - end - - # Make sure nodesearch uses all names, not just one. - def test_nodesearch_multiple_names - bucket = {} - Puppet::Parser::Interpreter.send(:define_method, "nodesearch_multifake") do |node| - if bucket[node] - return *bucket[node] - else - return nil, nil - end + interp = mkinterp + + # Make some nodes + names = %w{node1 node2 node2.domain.com} + interp.newnode names + + nodes = {} + # Make sure we can find them all, using the direct method + names.each do |name| + nodes[name] = interp.nodesearch_code(name) + assert(nodes[name], "Could not find %s" % name) + nodes[name].file = __FILE__ end - manifest = tempfile() - File.open(manifest, "w") do |f| f.puts "" end - interp = nil - assert_nothing_raised { - interp = Puppet::Parser::Interpreter.new( - :Manifest => manifest, - :NodeSources => [:multifake] - ) - } - bucket["name.domain.com"] = [:parent, [:classes]] - - ret = nil - - assert_nothing_raised do - assert_equal bucket["name.domain.com"], - interp.nodesearch("name", "name.domain.com") + # Now let's try it with the nodesearch method + names.each do |name| + node = interp.nodesearch(name) + assert(node, "Could not find #{name} via nodesearch") end + # Now make sure the longest match always wins + node = interp.nodesearch(*%w{node2 node2.domain.com}) + assert(node, "Did not find node2") + assert_equal("node2.domain.com", node.fqname, + "Did not get longest match") end def test_parsedate @@ -389,4 +309,519 @@ class nothernode {} newdate = interp.parsedate assert(date != newdate, "Parsedate was not updated") end + + # Make sure our node gets added to the node table. + def test_newnode + interp = mkinterp + + # First just try calling it directly + assert_nothing_raised { + interp.newnode("mynode", :code => :yay) + } + + assert_equal(:yay, interp.nodesearch_code("mynode").code) + + # Now make sure that trying to redefine it throws an error. + assert_raise(Puppet::ParseError) { + interp.newnode("mynode", {}) + } + + # Now try one with no code + assert_nothing_raised { + interp.newnode("simplenode", :parent => :foo) + } + + # Make sure trying to get the parentclass throws an error + assert_raise(Puppet::ParseError) do + interp.nodesearch_code("simplenode").parentclass + end + + # Now define the parent node + interp.newnode(:foo) + + # And make sure we get things back correctly + assert_equal("foo", interp.nodesearch_code("simplenode").parentclass.fqname) + assert_nil(interp.nodesearch_code("simplenode").code) + + # Now make sure that trying to redefine it throws an error. + assert_raise(Puppet::ParseError) { + interp.newnode("mynode", {}) + } + + # Test multiple names + names = ["one", "two", "three"] + assert_nothing_raised { + interp.newnode(names, {:code => :yay, :parent => :foo}) + } + + names.each do |name| + assert_equal(:yay, interp.nodesearch_code(name).code) + assert_equal("foo", interp.nodesearch_code(name).parentclass.name) + # Now make sure that trying to redefine it throws an error. + assert_raise(Puppet::ParseError) { + interp.newnode(name, {}) + } + end + end + + # Make sure we're correctly generating a node definition. + def test_gennode + interp = mkinterp + + node = nil + assert_nothing_raised { + node = interp.gennode("nodeA", :classes => %w{classA classB}) + } + + assert_instance_of(Puppet::Parser::AST::Node, node) + + assert_equal("nodeA", node.name) + end + + def test_fqfind + interp = mkinterp + + table = {} + # Define a bunch of things. + %w{a c a::b a::b::c a::c a::b::c::d a::b::c::d::e::f c::d}.each do |string| + table[string] = string + end + + check = proc do |namespace, hash| + hash.each do |thing, result| + assert_equal(result, interp.fqfind(namespace, thing, table), + "Could not find %s in %s" % [thing, namespace]) + end + end + + # Now let's do some test lookups. + + # First do something really simple + check.call "a", "b" => "a::b", "b::c" => "a::b::c", "d" => nil, "::c" => "c" + + check.call "a::b", "c" => "a::b::c", "b" => "a::b", "a" => "a" + + check.call "a::b::c::d::e", "c" => "a::b::c", "::c" => "c", + "c::d" => "a::b::c::d", "::c::d" => "c::d" + + check.call "", "a" => "a", "a::c" => "a::c" + end + + def test_newdefine + interp = mkinterp + + assert_nothing_raised { + interp.newdefine("mydefine", :code => :yay, + :arguments => ["a", stringobj("b")]) + } + + mydefine = interp.finddefine("", "mydefine") + assert(mydefine, "Could not find definition") + assert_equal("mydefine", interp.finddefine("", "mydefine").type) + assert_equal("", mydefine.namespace) + assert_equal("mydefine", mydefine.type) + + assert_raise(Puppet::ParseError) do + interp.newdefine("mydefine", :code => :yay, + :arguments => ["a", stringobj("b")]) + end + + # Now define the same thing in a different scope + assert_nothing_raised { + interp.newdefine("other::mydefine", :code => :other, + :arguments => ["a", stringobj("b")]) + } + other = interp.finddefine("other", "mydefine") + assert(other, "Could not find definition") + assert(interp.finddefine("", "other::mydefine"), + "Could not find other::mydefine") + assert_equal(:other, other.code) + assert_equal("other", other.namespace) + assert_equal("mydefine", other.type) + assert_equal("other::mydefine", other.fqname) + end + + def test_newclass + interp = mkinterp + + mkcode = proc do |ary| + classes = ary.collect do |string| + AST::FlatString.new(:value => string) + end + AST::ASTArray.new(:children => classes) + end + scope = Puppet::Parser::Scope.new(:interp => interp) + + # First make sure that code is being appended + code = mkcode.call(%w{original code}) + + klass = nil + assert_nothing_raised { + klass = interp.newclass("myclass", :code => code) + } + + assert(klass, "Did not return class") + + assert(interp.findclass("", "myclass"), "Could not find definition") + assert_equal("myclass", interp.findclass("", "myclass").type) + assert_equal(%w{original code}, + interp.findclass("", "myclass").code.evaluate(:scope => scope)) + + # Now create the same class name in a different scope + assert_nothing_raised { + klass = interp.newclass("other::myclass", + :code => mkcode.call(%w{something diff})) + } + assert(klass, "Did not return class") + other = interp.findclass("other", "myclass") + assert(other, "Could not find class") + assert(interp.findclass("", "other::myclass"), "Could not find class") + assert_equal("other::myclass", other.fqname) + assert_equal("other", other.namespace) + assert_equal("myclass", other.type) + assert_equal(%w{something diff}, + interp.findclass("other", "myclass").code.evaluate(:scope => scope)) + + # Newclass behaves differently than the others -- it just appends + # the code to the existing class. + code = mkcode.call(%w{something new}) + assert_nothing_raised do + klass = interp.newclass("myclass", :code => code) + end + assert(klass, "Did not return class when appending") + assert_equal(%w{original code something new}, + interp.findclass("", "myclass").code.evaluate(:scope => scope)) + + # Make sure newclass deals correctly with nodes with no code + klass = interp.newclass("nocode") + assert(klass, "Did not return class") + + assert_nothing_raised do + klass = interp.newclass("nocode", :code => mkcode.call(%w{yay test})) + end + assert(klass, "Did not return class with no code") + assert_equal(%w{yay test}, + interp.findclass("", "nocode").code.evaluate(:scope => scope)) + + # Then try merging something into nothing + interp.newclass("nocode2", :code => mkcode.call(%w{foo test})) + assert(klass, "Did not return class with no code") + + assert_nothing_raised do + klass = interp.newclass("nocode2") + end + assert(klass, "Did not return class with no code") + assert_equal(%w{foo test}, + interp.findclass("", "nocode2").code.evaluate(:scope => scope)) + + # And lastly, nothing and nothing + klass = interp.newclass("nocode3") + assert(klass, "Did not return class with no code") + + assert_nothing_raised do + klass = interp.newclass("nocode3") + end + assert(klass, "Did not return class with no code") + assert_nil(interp.findclass("", "nocode3").code) + + end + + # Now make sure we get appropriate behaviour with parent class conflicts. + def test_newclass_parentage + interp = mkinterp + interp.newclass("base1") + interp.newclass("one::two::three") + + # First create it with no parentclass. + assert_nothing_raised { + interp.newclass("sub") + } + assert(interp.findclass("", "sub"), "Could not find definition") + assert_nil(interp.findclass("", "sub").parentclass) + + # Make sure we can't set the parent class to ourself. + assert_raise(Puppet::ParseError) { + interp.newclass("sub", :parent => "sub") + } + + # Now create another one, with a parentclass. + assert_nothing_raised { + interp.newclass("sub", :parent => "base1") + } + + # Make sure we get the right parent class, and make sure it's an object. + assert_equal(interp.findclass("", "base1"), + interp.findclass("", "sub").parentclass) + + # Now make sure we get a failure if we try to conflict. + assert_raise(Puppet::ParseError) { + interp.newclass("sub", :parent => "one::two::three") + } + + # Make sure that failure didn't screw us up in any way. + assert_equal(interp.findclass("", "base1"), + interp.findclass("", "sub").parentclass) + # But make sure we can create a class with a fq parent + assert_nothing_raised { + interp.newclass("another", :parent => "one::two::three") + } + assert_equal(interp.findclass("", "one::two::three"), + interp.findclass("", "another").parentclass) + + end + + def test_namesplit + interp = mkinterp + + assert_nothing_raised do + {"base::sub" => %w{base sub}, + "main" => ["", "main"], + "one::two::three::four" => ["one::two::three", "four"], + }.each do |name, ary| + result = interp.namesplit(name) + assert_equal(ary, result, "%s split to %s" % [name, result]) + end + end + end + + # Make sure you can't have classes and defines with the same name in the + # same scope. + def test_classes_beat_defines + interp = mkinterp + + assert_nothing_raised { + interp.newclass("yay::funtest") + } + + assert_raise(Puppet::ParseError) do + interp.newdefine("yay::funtest") + end + + assert_nothing_raised { + interp.newdefine("yay::yaytest") + } + + assert_raise(Puppet::ParseError) do + interp.newclass("yay::yaytest") + end + end + + # Make sure our whole chain works. + def test_evaluate + interp, scope, source = mkclassframing + + # Create a define that we'll be using + interp.newdefine("wrapper", :code => AST::ASTArray.new(:children => [ + resourcedef("file", varref("name"), "owner" => "root") + ])) + + # Now create a resource that uses that define + define = mkresource(:type => "wrapper", :title => "/tmp/testing", + :scope => scope, :source => source, :params => :none) + + scope.setresource define + + # And a normal resource + scope.setresource mkresource(:type => "file", :title => "/tmp/rahness", + :scope => scope, :source => source, + :params => {:owner => "root"}) + + # Now evaluate everything + objects = nil + interp.usenodes = false + assert_nothing_raised do + objects = interp.evaluate(nil, {}) + end + + assert_instance_of(Puppet::TransBucket, objects) + end + + def test_evaliterate + interp, scope, source = mkclassframing + + # Create a top-level definition that creates a builtin object + interp.newdefine("one", :arguments => [%w{owner}], + :code => AST::ASTArray.new(:children => [ + resourcedef("file", varref("name"), + "owner" => varref("owner") + ) + ]) + ) + + # Create another definition to call that one + interp.newdefine("two", :arguments => [%w{owner}], + :code => AST::ASTArray.new(:children => [ + resourcedef("one", varref("name"), + "owner" => varref("owner") + ) + ]) + ) + + # And then a third + interp.newdefine("three", :arguments => [%w{owner}], + :code => AST::ASTArray.new(:children => [ + resourcedef("two", varref("name"), + "owner" => varref("owner") + ) + ]) + ) + + three = Puppet::Parser::Resource.new( + :type => "three", :title => "/tmp/yayness", + :scope => scope, :source => source, + :params => paramify(source, :owner => "root") + ) + + scope.setresource(three) + + ret = nil + assert_nothing_raised do + ret = scope.unevaluated + end + + + assert_instance_of(Array, ret) + assert(1, ret.length) + assert_equal([three], ret) + + assert(ret.detect { |r| r.ref == "three[/tmp/yayness]"}, + "Did not get three back as unevaluated") + + # Now translate the whole tree + assert_nothing_raised do + interp.evaliterate(scope) + end + + # Now make sure we've got our file + file = scope.findresource "file[/tmp/yayness]" + assert(file, "Could not find file") + + assert_equal("root", file[:owner]) + end + + # Make sure we fail if there are any leftover overrides to perform. + # This would normally mean that someone is trying to override an object + # that does not exist. + def test_failonleftovers + interp, scope, source = mkclassframing + + # Make sure we don't fail, since there are no overrides + assert_nothing_raised do + interp.failonleftovers(scope) + end + + # Add an override, and make sure it causes a failure + over1 = mkresource :scope => scope, :source => source, + :params => {:one => "yay"} + + scope.setoverride(over1) + + assert_raise(Puppet::ParseError) do + interp.failonleftovers(scope) + end + + end + + def test_evalnode + interp = mkinterp + interp.usenodes = false + scope = Parser::Scope.new(:interp => interp) + facts = Facter.to_hash + + # First make sure we get no failures when client is nil + assert_nothing_raised do + interp.evalnode(nil, scope, facts) + end + + # Now define a node + interp.newnode "mynode", :code => AST::ASTArray.new(:children => [ + resourcedef("file", "/tmp/testing", "owner" => "root") + ]) + + # Eval again, and make sure it does nothing + assert_nothing_raised do + interp.evalnode("mynode", scope, facts) + end + + assert_nil(scope.findresource("file[/tmp/testing]"), + "Eval'ed node with nodes off") + + # Now enable usenodes and make sure it works. + interp.usenodes = true + assert_nothing_raised do + interp.evalnode("mynode", scope, facts) + end + file = scope.findresource("file[/tmp/testing]") + + assert_instance_of(Puppet::Parser::Resource, file, + "Could not find file") + end + + # This is mostly used for the cfengine module + def test_specificclasses + interp = mkinterp :Classes => %w{klass1 klass2}, :UseNodes => false + + # Make sure it's not a failure to be missing classes, since + # we're using the cfengine class list, which is huge. + assert_nothing_raised do + interp.evaluate(nil, {}) + end + + interp.newclass("klass1", :code => AST::ASTArray.new(:children => [ + resourcedef("file", "/tmp/klass1", "owner" => "root") + ])) + interp.newclass("klass2", :code => AST::ASTArray.new(:children => [ + resourcedef("file", "/tmp/klass2", "owner" => "root") + ])) + + ret = nil + assert_nothing_raised do + ret = interp.evaluate(nil, {}) + end + + found = ret.flatten.collect do |res| res.name end + + assert(found.include?("/tmp/klass1"), "Did not evaluate klass1") + assert(found.include?("/tmp/klass2"), "Did not evaluate klass2") + end + + if defined? ActiveRecord::Base + # We need to make sure finished objects are stored in the db. + def test_finish_before_store + railsinit + interp = mkinterp + + node = interp.newnode ["myhost"], :code => AST::ASTArray.new(:children => [ + resourcedef("file", "/tmp/yay", :group => "root"), + defaultobj("file", :owner => "root") + ]) + + interp.newclass "myclass", :code => AST::ASTArray.new(:children => [ + ]) + + interp.newclass "sub", :parent => "myclass", + :code => AST::ASTArray.new(:children => [ + resourceoverride("file", "/tmp/yay", :owner => "root") + ] + ) + + # Now do the rails crap + Puppet[:storeconfigs] = true + + interp.evaluate("myhost", {}) + + # And then retrieve the object from rails + res = Puppet::Rails::RailsResource.find_by_restype_and_title("file", "/tmp/yay") + + assert(res, "Did not get resource from rails") + + param = res.rails_parameters.find_by_name("owner") + + assert(param, "Did not find owner param") + + assert_equal("root", param[:value]) + end + end end + +# $Id$ diff --git a/test/language/lexer.rb b/test/language/lexer.rb index 496087ba2..26b85b3b7 100644 --- a/test/language/lexer.rb +++ b/test/language/lexer.rb @@ -13,6 +13,10 @@ class TestLexer < Test::Unit::TestCase include PuppetTest def setup super + mklexer + end + + def mklexer @lexer = Puppet::Parser::Lexer.new() end @@ -79,9 +83,10 @@ class TestLexer < Test::Unit::TestCase def test_files textfiles() { |file| - @lexer.file = file + lexer = Puppet::Parser::Lexer.new() + lexer.file = file assert_nothing_raised() { - @lexer.fullscan() + lexer.fullscan() } Puppet::Type.allclear } @@ -149,6 +154,75 @@ class TestLexer < Test::Unit::TestCase assert_equal([[:AT, "@"], [:NAME, "type"], [:LBRACE, "{"], [false,false]],ret) end + + def test_namespace + @lexer.string = %{class myclass} + + assert_nothing_raised { + @lexer.fullscan + } + + assert_equal("myclass", @lexer.namespace) + + assert_nothing_raised do + @lexer.namepop + end + + assert_equal("", @lexer.namespace) + + @lexer.string = "class base { class sub { class more" + + assert_nothing_raised { + @lexer.fullscan + } + + assert_equal("base::sub::more", @lexer.namespace) + + assert_nothing_raised do + @lexer.namepop + end + + assert_equal("base::sub", @lexer.namespace) + + # Now try it with some fq names + mklexer + + @lexer.string = "class base { class sub::more {" + + assert_nothing_raised { + @lexer.fullscan + } + + assert_equal("base::sub::more", @lexer.namespace) + + assert_nothing_raised do + @lexer.namepop + end + + assert_equal("base", @lexer.namespace) + end + + def test_indefine + @lexer.string = %{define me} + + assert_nothing_raised { + @lexer.fullscan + } + + assert(@lexer.indefine?, "Lexer not considered in define") + + # Now make sure we throw an error when trying to nest defines. + assert_raise(Puppet::ParseError) do + @lexer.string = %{define another} + @lexer.fullscan + end + + assert_nothing_raised do + @lexer.indefine = false + end + + assert(! @lexer.indefine?, "Lexer still considered in define") + end end # $Id$ diff --git a/test/language/node.rb b/test/language/node.rb index 791c44874..251e4c4aa 100644 --- a/test/language/node.rb +++ b/test/language/node.rb @@ -8,7 +8,6 @@ class TestParser < Test::Unit::TestCase def setup super Puppet[:parseonly] = true - @parser = Puppet::Parser::Parser.new() end def test_simple_hostname @@ -41,48 +40,40 @@ class TestParser < Test::Unit::TestCase unless hostnames.is_a?(Array) hostnames = [ hostnames ] end + interp = nil assert_nothing_raised { - @parser.string = "node #{hostnames.join(", ")} { }" + interp = mkinterp :Code => "node #{hostnames.join(", ")} { }" } # Strip quotes hostnames.map! { |s| s.sub(/^'(.*)'$/, "\\1") } - ast = nil + + # parse assert_nothing_raised { - ast = @parser.parse + interp.send(:parsefiles) } - # Verify that the AST has the expected structure - # and that the leaves have the right hostnames in them - assert_kind_of(AST::ASTArray, ast) - assert_equal(1, ast.children.size) - nodedef = ast.children[0] - assert_kind_of(AST::NodeDef, nodedef) - assert_kind_of(AST::ASTArray, nodedef.names) - assert_equal(hostnames.size, nodedef.names.children.size) - hostnames.size.times do |i| - hostnode = nodedef.names.children[i] - assert_kind_of(AST::HostName, hostnode) - assert_equal(hostnames[i], hostnode.value) + + # Now make sure we can look up each of the names + hostnames.each do |name| + assert(interp.nodesearch_code(name), + "Could not find node %s" % name) end end def check_nonparseable(hostname) - assert_nothing_raised { - @parser.string = "node #{hostname} { }" - } - - assert_raise(Puppet::DevError, Puppet::ParseError) { - @parser.parse + interp = nil + assert_raise(Puppet::DevError, Puppet::ParseError, "#{hostname} passed") { + interp = mkinterp :Code => "node #{hostname} { }" + interp.send(:parsefiles) } end # Make sure we can find default nodes if there's no other entry def test_default_node Puppet[:parseonly] = false - @parser = Puppet::Parser::Parser.new() fileA = tempfile() fileB = tempfile() - @parser.string = %{ + code = %{ node mynode { file { "#{fileA}": ensure => file } } @@ -91,34 +82,25 @@ node default { file { "#{fileB}": ensure => file } } } - - # First make sure it parses - ast = nil + interp = nil assert_nothing_raised { - ast = @parser.parse - } - - args = { - :ast => ast, - :facts => {}, - :names => ["mynode"] + interp = mkinterp :Code => code } - # Make sure we get a config for "mynode" - trans = nil + # First make sure it parses assert_nothing_raised { - trans = Puppet::Parser::Scope.new.evaluate(args) + interp.send(:parsefiles) } - assert(trans, "Did not get config for mynode") + # Make sure we find our normal node + assert(interp.nodesearch("mynode"), + "Did not find normal node") - args[:names] = ["othernode"] - # Now make sure the default node is used - trans = nil - assert_nothing_raised { - trans = Puppet::Parser::Scope.new.evaluate(args) - } + # Now look for the default node + default = interp.nodesearch("someother") + assert(default, + "Did not find default node") - assert(trans, "Did not get config for default node") + assert_equal("default", default.fqname) end end diff --git a/test/language/parser.rb b/test/language/parser.rb index d6e176870..dbe48616a 100644 --- a/test/language/parser.rb +++ b/test/language/parser.rb @@ -8,15 +8,15 @@ class TestParser < Test::Unit::TestCase super Puppet[:parseonly] = true #@lexer = Puppet::Parser::Lexer.new() - @parser = Puppet::Parser::Parser.new() end def test_each_file textfiles { |file| + parser = mkparser Puppet.debug("parsing %s" % file) if __FILE__ == $0 assert_nothing_raised() { - @parser.file = file - @parser.parse + parser.file = file + parser.parse } Puppet::Type.eachtype { |type| @@ -32,18 +32,20 @@ class TestParser < Test::Unit::TestCase def test_failers failers { |file| + parser = mkparser Puppet.debug("parsing failer %s" % file) if __FILE__ == $0 assert_raise(Puppet::ParseError) { - @parser.file = file - ast = @parser.parse - Puppet::Parser::Scope.new.evaluate(:ast => ast) + parser.file = file + ast = parser.parse + scope = mkscope :interp => parser.interp + ast.evaluate :scope => scope } Puppet::Type.allclear } end def test_arrayrvalues - parser = Puppet::Parser::Parser.new() + parser = mkparser ret = nil file = tempfile() assert_nothing_raised { @@ -83,7 +85,7 @@ class TestParser < Test::Unit::TestCase } assert_nothing_raised("Could not parse multiple files") { - parser = Puppet::Parser::Parser.new() + parser = mkparser parser.file = manifest parser.parse } @@ -98,103 +100,18 @@ class TestParser < Test::Unit::TestCase f.puts "import \" no such file \"" end assert_raise(Puppet::ParseError) { - parser = Puppet::Parser::Parser.new() + parser = mkparser parser.file = manifest parser.parse } end - def test_defaults - basedir = File.join(tmpdir(), "defaulttesting") - @@tmpfiles << basedir - Dir.mkdir(basedir) - - defs1 = { - "testing" => "value" - } - - defs2 = { - "one" => "two", - "three" => "four", - "five" => false, - "seven" => "eight", - "nine" => true, - "eleven" => "twelve" - } - - mkdef = proc { |hash| - hash.collect { |arg, value| - "$%s = %s" % [arg, value] - }.join(", ") - } - manifest = File.join(basedir, "manifest") - File.open(manifest, "w") { |f| - f.puts " - define method(#{mkdef.call(defs1)}, $other) { - $variable = $testing - } - - define othermethod(#{mkdef.call(defs2)}, $goodness) { - $more = less - } - - method { - other => yayness - } - - othermethod { - goodness => rahness - } -" - - } - - ast = nil - assert_nothing_raised("Could not parse multiple files") { - parser = Puppet::Parser::Parser.new() - parser.file = manifest - ast = parser.parse - } - - assert(ast, "Did not receive AST while parsing defaults") - - scope = nil - assert_nothing_raised("Could not evaluate defaults parse tree") { - scope = Puppet::Parser::Scope.new() - scope.name = "parsetest" - scope.type = "parsetest" - objects = scope.evaluate(:ast => ast) - } - - method = nil - othermethod = nil - assert_nothing_raised { - method = scope.find { |child| - child.is_a?(Puppet::Parser::Scope) and child.type == "method" - } - defs1.each { |var, value| - curval = method.lookupvar(var) - assert_equal(value, curval, "Did not get default") - } - } - - assert_nothing_raised { - method = scope.find { |child| - child.is_a?(Puppet::Parser::Scope) and child.type == "othermethod" - } - defs2.each { |var, value| - curval = method.lookupvar(var) - assert_equal(value, curval, "Did not get default") - } - } - end - def test_trailingcomma path = tempfile() str = %{file { "#{path}": ensure => file, } } - parser = Puppet::Parser::Parser.new + parser = mkparser parser.string = str assert_nothing_raised("Could not parse trailing comma") { @@ -216,7 +133,7 @@ class TestParser < Test::Unit::TestCase f.puts %{import "#{imported}"\ninclude foo} end - parser = Puppet::Parser::Parser.new + parser = mkparser parser.file = importer # Make sure it parses fine @@ -256,7 +173,7 @@ class TestParser < Test::Unit::TestCase f.puts %{class local { file { "#{localmaker}": ensure => file }}} end - parser = Puppet::Parser::Parser.new + parser = mkparser parser.file = importer # Make sure it parses @@ -288,7 +205,7 @@ class TestParser < Test::Unit::TestCase f.puts %{class local { file { "#{file}": ensure => file }}} end - parser = Puppet::Parser::Parser.new + parser = mkparser parser.file = importer assert_nothing_raised { @@ -325,7 +242,7 @@ class TestParser < Test::Unit::TestCase f.puts %{import "subdir/subtwo"} end - parser = Puppet::Parser::Parser.new + parser = mkparser parser.file = top assert_nothing_raised { @@ -333,46 +250,21 @@ class TestParser < Test::Unit::TestCase } end - # Verify that collectable objects are marked that way. - def test_collectable - Puppet[:storeconfigs] = true - ["@port { ssh: protocols => tcp, number => 22 }", - "@port { ssh: protocols => tcp, number => 22; - smtp: protocols => tcp, number => 25 }"].each do |text| - parser = Puppet::Parser::Parser.new - parser.string = text - - ret = nil - assert_nothing_raised { - ret = parser.parse - } - - assert_instance_of(AST::ASTArray, ret) - - ret.each do |obj| - assert_instance_of(AST::ObjectDef, obj) - assert(obj.collectable, "Object was not marked collectable") - end - end - end - # Defaults are purely syntactical, so it doesn't make sense to be able to # collect them. def test_uncollectabledefaults string = "@Port { protocols => tcp }" - parser = Puppet::Parser::Parser.new - parser.string = string assert_raise(Puppet::ParseError) { - parser.parse + mkparser.parse(string) } end # Verify that we can parse collections def test_collecting Puppet[:storeconfigs] = true - text = "port <| |>" - parser = Puppet::Parser::Parser.new + text = "Port <| |>" + parser = mkparser parser.string = text ret = nil @@ -392,7 +284,7 @@ class TestParser < Test::Unit::TestCase File.open(file, "w") do |f| f.puts %{} end - parser = Puppet::Parser::Parser.new + parser = mkparser parser.file = file assert_nothing_raised { parser.parse @@ -412,7 +304,7 @@ node nodeA, nodeB { } end - parser = Puppet::Parser::Parser.new + parser = mkparser parser.file = file ast = nil assert_nothing_raised { @@ -423,7 +315,7 @@ node nodeA, nodeB { def test_emptyarrays str = %{$var = []\n} - parser = Puppet::Parser::Parser.new + parser = mkparser parser.string = str # Make sure it parses fine @@ -442,7 +334,7 @@ file { "/tmp/yayness": ensure => exists } } - parser = Puppet::Parser::Parser.new + parser = mkparser parser.string = str # Make sure it parses fine @@ -452,32 +344,21 @@ file { "/tmp/yayness": end def test_metaparams_in_definition_prototypes - parser = Puppet::Parser::Parser.new - - str1 = %{define mydef($schedule) {}} - parser.string = str1 + parser = mkparser - assert_raise(Puppet::ParseError) { - parser.parse - } - - str2 = %{define mydef($schedule = false) {}} - parser.string = str2 assert_raise(Puppet::ParseError) { - parser.parse + parser.parse %{define mydef($schedule) {}} } - str3 = %{define mydef($schedule = daily) {}} - parser.string = str3 - assert_nothing_raised { - parser.parse + parser.parse %{define adef($schedule = false) {}} + parser.parse %{define mydef($schedule = daily) {}} } end def test_parsingif - parser = Puppet::Parser::Parser.new() + parser = mkparser exec = proc do |val| %{exec { "/bin/echo #{val}": logoutput => true }} end @@ -494,6 +375,208 @@ file { "/tmp/yayness": assert_instance_of(Puppet::Parser::AST::IfStatement, ret) assert_instance_of(Puppet::Parser::AST::Else, ret.else) end + + def test_hostclass + parser = mkparser + interp = parser.interp + + assert_nothing_raised { + parser.parse %{class myclass { class other {} }} + } + assert(interp.findclass("", "myclass"), "Could not find myclass") + assert(interp.findclass("", "myclass::other"), "Could not find myclass::other") + + assert_nothing_raised { + parser.parse "class base {} + class container { + class deep::sub inherits base {} + }" + } + sub = interp.findclass("", "container::deep::sub") + assert(sub, "Could not find sub") + assert_equal("base", sub.parentclass.type) + end + + def test_topnamespace + parser = mkparser + parser.interp.clear + + # Make sure we put the top-level code into a class called "" in + # the "" namespace + assert_nothing_raised do + out = parser.parse "" + + assert_nil(out) + assert_nil(parser.interp.findclass("", "")) + end + + # Now try something a touch more complicated + parser.interp.clear + assert_nothing_raised do + out = parser.parse "Exec { path => '/usr/bin:/usr/sbin' }" + assert_instance_of(AST::ASTArray, out) + assert_equal("", parser.interp.findclass("", "").type) + assert_equal("", parser.interp.findclass("", "").namespace) + assert_equal(out.object_id, parser.interp.findclass("", "").code.object_id) + end + end + + # Make sure virtual and exported resources work appropriately. + def test_virtualresources + Puppet[:storeconfigs] = true + [:virtual, :exported].each do |form| + parser = mkparser + + if form == :virtual + at = "@" + else + at = "@@" + end + + check = proc do |res| + # Real resources get marked virtual when exported + if form == :virtual or res.is_a?(Puppet::Parser::Resource) + assert(res.virtual, "Resource #{res.class} is not virtual") + end + if form == :virtual + assert(! res.exported, "Resource #{res.type} is exported") + else + assert(res.exported, "Resource #{res.type} is not exported") + end + end + + ret = nil + assert_nothing_raised do + ret = parser.parse("#{at}file { '/tmp/testing': owner => root }") + end + + assert_equal("/tmp/testing", ret[0].title.value) + # We always get an astarray back, so... + assert_instance_of(AST::ResourceDef, ret[0]) + check.call(ret[0]) + + # Now let's try it with multiple resources in the same spec + assert_nothing_raised do + ret = parser.parse("#{at}file { ['/tmp/1', '/tmp/2']: owner => root }") + end + + assert_instance_of(AST::ASTArray, ret) + ret.each do |res| + assert_instance_of(AST::ResourceDef, res) + check.call(res) + end + + # Now evaluate these + scope = mkscope + + klass = scope.interp.newclass "" + scope.source = klass + + assert_nothing_raised do + ret.evaluate :scope => scope + end + + # Make sure we can find both of them + %w{/tmp/1 /tmp/2}.each do |title| + res = scope.findresource("file[#{title}]") + assert(res, "Could not find %s" % title) + check.call(res) + end + end + end + + def test_collections + Puppet[:storeconfigs] = true + [:virtual, :exported].each do |form| + parser = mkparser + + if form == :virtual + arrow = "<||>" + else + arrow = "<<||>>" + end + + check = proc do |coll| + assert_instance_of(AST::Collection, coll) + assert_equal(form, coll.form) + end + + ret = nil + assert_nothing_raised do + ret = parser.parse("File #{arrow}") + end + check.call(ret[0]) + end + end + + def test_collectionexpressions + %w{== !=}.each do |oper| + str = "File <| title #{oper} '/tmp/testing' |>" + + parser = mkparser + + res = nil + assert_nothing_raised do + res = parser.parse(str)[0] + end + + assert_instance_of(AST::Collection, res) + + query = res.query + assert_instance_of(AST::CollExpr, query) + + assert_equal(:virtual, query.form) + assert_equal("title", query.test1.value) + assert_equal("/tmp/testing", query.test2.value) + assert_equal(oper, query.oper) + end + end + + def test_collectionstatements + %w{and or}.each do |joiner| + str = "File <| title == '/tmp/testing' #{joiner} owner == root |>" + + parser = mkparser + + res = nil + assert_nothing_raised do + res = parser.parse(str)[0] + end + + assert_instance_of(AST::Collection, res) + + query = res.query + assert_instance_of(AST::CollExpr, query) + + assert_equal(joiner, query.oper) + assert_instance_of(AST::CollExpr, query.test1) + assert_instance_of(AST::CollExpr, query.test2) + end + end + + def test_collectionstatements_with_parens + [ + "(title == '/tmp/testing' and owner == root) or owner == wheel", + "(title == '/tmp/testing')" + ].each do |test| + str = "File <| #{test} |>" + parser = mkparser + + res = nil + assert_nothing_raised("Could not parse '#{test}'") do + res = parser.parse(str)[0] + end + + assert_instance_of(AST::Collection, res) + + query = res.query + assert_instance_of(AST::CollExpr, query) + + #assert_equal(joiner, query.oper) + #assert_instance_of(AST::CollExpr, query.test1) + #assert_instance_of(AST::CollExpr, query.test2) + end + end end # $Id$ diff --git a/test/language/rails.rb b/test/language/rails.rb deleted file mode 100755 index ada4e0915..000000000 --- a/test/language/rails.rb +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/ruby - -require 'puppet' -require 'puppet/rails' -require 'puppet/parser/interpreter' -require 'puppet/parser/parser' -require 'puppet/client' -require 'puppettest' - -class TestRails < Test::Unit::TestCase - include PuppetTest::ParserTesting - - def test_includerails - assert_nothing_raised { - require 'puppet/rails' - } - end - - # Don't do any tests w/out this class - if defined? ActiveRecord::Base - def test_hostcache - # First make some objects - bucket = mk_transtree do |object, depth, width| - # and mark some of them collectable - if width % 2 == 1 - object.collectable = true - end - end - - # Now collect our facts - facts = {} - Facter.each do |fact, value| facts[fact] = value end - - assert_nothing_raised { - Puppet::Rails.init - } - - # Now try storing our crap - host = nil - assert_nothing_raised { - host = Puppet::Rails::Host.store( - :objects => bucket, - :facts => facts, - :host => facts["hostname"] - ) - } - - assert(host, "Did not create host") - - host = nil - assert_nothing_raised { - host = Puppet::Rails::Host.find_by_name(facts["hostname"]) - } - assert(host, "Could not find host object") - - assert(host.rails_objects, "No objects on host") - - assert_equal(facts["hostname"], host.facts["hostname"], - "Did not retrieve facts") - - inline_test_objectcollection(host) - end - - # This is called from another test, it just makes sense to split it out some - def inline_test_objectcollection(host) - # XXX For some reason, find_all doesn't work here at all. - collectable = [] - host.rails_objects.each do |obj| - if obj.collectable? - collectable << obj - end - end - - assert(collectable.length > 0, "Found no collectable objects") - - collectable.each do |obj| - trans = nil - assert_nothing_raised { - trans = obj.to_trans - } - # Make sure that the objects do not retain their collectable - # nature. - assert(!trans.collectable, "Object from db was collectable") - end - - # Now find all collectable objects directly through database APIs - - list = Puppet::Rails::RailsObject.find_all_by_collectable(true) - - assert_equal(collectable.length, list.length, - "Did not get the right number of objects") - end - else - $stderr.puts "Install Rails for Rails and Caching tests" - end -end - -# $Id$ diff --git a/test/language/resource.rb b/test/language/resource.rb new file mode 100755 index 000000000..12b1e7d2a --- /dev/null +++ b/test/language/resource.rb @@ -0,0 +1,391 @@ +#!/usr/bin/ruby + +require 'puppettest' +require 'puppettest/resourcetesting' +require 'puppettest/railstesting' + +class TestResource < Test::Unit::TestCase + include PuppetTest + include PuppetTest::ParserTesting + include PuppetTest::ResourceTesting + include PuppetTest::RailsTesting + Parser = Puppet::Parser + AST = Parser::AST + + def setup + super + Puppet[:trace] = false + @interp, @scope, @source = mkclassframing + end + + def test_initialize + args = {:type => "resource", :title => "testing", + :source => @source, :scope => @scope} + # Check our arg requirements + args.each do |name, value| + try = args.dup.delete(name) + assert_raise(Puppet::DevError) do + Parser::Resource.new(try) + end + end + + args[:params] = paramify @source, :one => "yay", :three => "rah" + + res = nil + assert_nothing_raised do + res = Parser::Resource.new(args) + end + + # Make sure it got the parameters correctly. + assert_equal("yay", res[:one]) + assert_equal("rah", res[:three]) + + assert_equal({:one => "yay", :three => "rah"}, res.to_hash) + end + + def test_override + res = mkresource + + # Now verify we can't override with any random class + assert_raise(Puppet::ParseError) do + res.set paramify(@scope.findclass("other"), "one" => "boo").shift + end + + # And that we can with a subclass + assert_nothing_raised do + res.set paramify(@scope.findclass("sub1"), "one" => "boo").shift + end + + # And that a different subclass can override a different parameter + assert_nothing_raised do + res.set paramify(@scope.findclass("sub2"), "three" => "boo").shift + end + + # But not the same one + assert_raise(Puppet::ParseError) do + res.set paramify(@scope.findclass("sub2"), "one" => "something").shift + end + end + + def test_merge + # Start with the normal one + res = mkresource + + # Now create a resource from a different scope + other = mkresource :source => other, :params => {"one" => "boo"} + + # Make sure we can't merge it + assert_raise(Puppet::ParseError) do + res.merge(other) + end + + # Make one from a subscope + other = mkresource :source => "sub1", :params => {"one" => "boo"} + + # Make sure it merges + assert_nothing_raised do + res.merge(other) + end + + assert_equal("boo", res["one"]) + end + + def test_paramcheck + # First make a builtin resource + res = nil + assert_nothing_raised do + res = Parser::Resource.new :type => "file", :title => tempfile(), + :source => @source, :scope => @scope + end + + %w{path group source schedule subscribe}.each do |param| + assert_nothing_raised("Param %s was considered invalid" % param) do + res.paramcheck(param) + end + end + + %w{this bad noness}.each do |param| + assert_raise(Puppet::ParseError, "%s was considered valid" % param) do + res.paramcheck(param) + end + end + + # Now create a defined resource + assert_nothing_raised do + res = Parser::Resource.new :type => "resource", :title => "yay", + :source => @source, :scope => @scope + end + + %w{one two three schedule subscribe}.each do |param| + assert_nothing_raised("Param %s was considered invalid" % param) do + res.paramcheck(param) + end + end + + %w{this bad noness}.each do |param| + assert_raise(Puppet::ParseError, "%s was considered valid" % param) do + res.paramcheck(param) + end + end + end + + def test_to_trans + # First try translating a builtin resource + res = Parser::Resource.new :type => "file", :title => "/tmp", + :source => @source, :scope => @scope, + :params => paramify(@source, :owner => "nobody", :mode => "644") + + obj = nil + assert_nothing_raised do + obj = res.to_trans + end + + assert_instance_of(Puppet::TransObject, obj) + + assert_equal(obj.type, res.type) + assert_equal(obj.name, res.title) + + # TransObjects use strings, resources use symbols + hash = obj.to_hash.inject({}) { |h,a| h[a[0].intern] = a[1]; h } + assert_equal(hash, res.to_hash) + end + + def test_adddefaults + # Set some defaults at the top level + top = {:one => "fun", :two => "shoe"} + + @scope.setdefaults("resource", paramify(@source, top)) + + # Make a resource at that level + res = Parser::Resource.new :type => "resource", :title => "yay", + :source => @source, :scope => @scope + + # Add the defaults + assert_nothing_raised do + res.adddefaults + end + + # And make sure we got them + top.each do |p, v| + assert_equal(v, res[p]) + end + + # Now got a bit lower + other = @scope.newscope + + # And create a resource + lowerres = Parser::Resource.new :type => "resource", :title => "funtest", + :source => @source, :scope => other + + assert_nothing_raised do + lowerres.adddefaults + end + + # And check + top.each do |p, v| + assert_equal(v, lowerres[p]) + end + + # Now add some of our own defaults + lower = {:one => "shun", :three => "free"} + other.setdefaults("resource", paramify(@source, lower)) + otherres = Parser::Resource.new :type => "resource", :title => "yaytest", + :source => @source, :scope => other + + should = top.dup + # Make sure the lower defaults beat the higher ones. + lower.each do |p, v| should[p] = v end + + otherres.adddefaults + + should.each do |p,v| + assert_equal(v, otherres[p]) + end + end + + def test_evaluate + # Make a definition that we know will, um, do something + @interp.newdefine "evaltest", + :arguments => [%w{one}, ["two", stringobj("755")]], + :code => resourcedef("file", "/tmp", + "owner" => varref("one"), "mode" => varref("two")) + + res = Parser::Resource.new :type => "evaltest", :title => "yay", + :source => @source, :scope => @scope, + :params => paramify(@source, :one => "nobody") + + # Now try evaluating + ret = nil + assert_nothing_raised do + ret = res.evaluate + end + + # Make sure we can find our object now + result = @scope.findresource("file[/tmp]") + + # Now make sure we got the code we expected. + assert_instance_of(Puppet::Parser::Resource, result) + + assert_equal("file", result.type) + assert_equal("/tmp", result.title) + assert_equal("nobody", result["owner"]) + assert_equal("755", result["mode"]) + + # And that we cannot find the old resource + assert_nil(@scope.findresource("evaltest[yay]"), + "Evaluated resource was not deleted") + end + + def test_addoverrides + # First create an override for an object that doesn't yet exist + over1 = mkresource :source => "sub1", :params => {:one => "yay"} + + assert_nothing_raised do + @scope.setoverride(over1) + end + + assert(over1.override, "Override was not marked so") + + # Now make the resource + res = mkresource :source => "base", :params => {:one => "rah", + :three => "foo"} + + # And add it to our scope + @scope.setresource(res) + + # And make sure over1 has not yet taken affect + assert_equal("foo", res[:three], "Lost value") + + # Now add an immediately binding override + over2 = mkresource :source => "sub1", :params => {:three => "yay"} + + assert_nothing_raised do + @scope.setoverride(over2) + end + + # And make sure it worked + assert_equal("yay", res[:three], "Override 2 was ignored") + + # Now add our late-binding override + assert_nothing_raised do + res.addoverrides + end + + # And make sure they're still around + assert_equal("yay", res[:one], "Override 1 lost") + assert_equal("yay", res[:three], "Override 2 lost") + + # And finally, make sure that there are no remaining overrides + assert_nothing_raised do + res.addoverrides + end + end + + def test_proxymethods + res = Parser::Resource.new :type => "evaltest", :title => "yay", + :source => @source, :scope => @scope + + assert_equal("evaltest", res.type) + assert_equal("yay", res.title) + assert_equal(false, res.builtin?) + end + + def test_addmetaparams + res = Parser::Resource.new :type => "evaltest", :title => "yay", + :source => @source, :scope => @scope + + assert_nil(res[:schedule], "Got schedule already") + @scope.setvar("schedule", "daily") + + assert_nothing_raised do + res.addmetaparams + end + + assert_equal("daily", res[:schedule], "Did not get metaparam") + assert_nil(res[:noop], "Got invalid metaparam") + end + + def test_reference_conversion + # First try it as a normal string + ref = Parser::Resource::Reference.new(:type => "file", :title => "/tmp/ref1") + + # Now create an obj that uses it + res = mkresource :type => "file", :title => "/tmp/resource", + :params => {:require => ref} + + trans = nil + assert_nothing_raised do + trans = res.to_trans + end + + assert_instance_of(Array, trans["require"]) + assert_equal(["file", "/tmp/ref1"], trans["require"]) + + # Now try it when using an array of references. + two = Parser::Resource::Reference.new(:type => "file", :title => "/tmp/ref2") + res = mkresource :type => "file", :title => "/tmp/resource2", + :params => {:require => [ref, two]} + + trans = nil + assert_nothing_raised do + trans = res.to_trans + end + + assert_instance_of(Array, trans["require"][0]) + trans["require"].each do |val| + assert_instance_of(Array, val) + assert_equal("file", val[0]) + assert(val[1] =~ /\/tmp\/ref[0-9]/, + "Was %s instead of the file name" % val[1]) + end + end + + # This is a bit of a weird one -- the user should not actually know + # that components exist, so we want references to act like they're not + # builtin + def test_components_are_not_builtin + ref = Parser::Resource::Reference.new(:type => "component", :title => "yay") + + assert_nil(ref.builtintype, "Component was considered builtin") + end + if defined? ActiveRecord::Base + def test_store + railsinit + res = mkresource :type => "file", :title => "/tmp/testing", + :source => @source, :scope => @scope, + :params => {:owner => "root", :mode => "755"} + + # We also need a Rails Host to store under + host = Puppet::Rails::Host.new(:name => Facter.hostname) + + obj = nil + assert_nothing_raised do + obj = res.store(host) + end + + assert_instance_of(Puppet::Rails::RailsResource, obj) + + assert_nothing_raised do + Puppet::Util.benchmark(:info, "Saved host") do + host.save + end + end + + # Now make sure we can find it again + assert_nothing_raised do + obj = Puppet::Rails::RailsResource.find_by_host_id_and_restype_and_title( + host.id, res.type, res.title + ) + end + assert_instance_of(Puppet::Rails::RailsResource, obj) + + # Make sure we get the parameters back + obj.rails_parameters.each do |param| + assert_equal(res[param[:name]], param[:value], + "%s was different" % param[:name]) + end + end + end +end + +# $Id$ diff --git a/test/language/scope.rb b/test/language/scope.rb index 85189627d..b9401e38b 100755 --- a/test/language/scope.rb +++ b/test/language/scope.rb @@ -5,6 +5,8 @@ require 'puppet/parser/interpreter' require 'puppet/parser/parser' require 'puppet/client' require 'puppettest' +require 'puppettest/parsertesting' +require 'puppettest/resourcetesting' # so, what kind of things do we want to test? @@ -17,6 +19,7 @@ require 'puppettest' class TestScope < Test::Unit::TestCase include PuppetTest::ParserTesting + include PuppetTest::ResourceTesting def to_ary(hash) hash.collect { |key,value| @@ -35,7 +38,7 @@ class TestScope < Test::Unit::TestCase 10.times { |index| # slap some recursion in there - scope = Puppet::Parser::Scope.new(:parent => scope) + scope = mkscope(:parent => scope) scopes.push scope var = "var%s" % index @@ -97,8 +100,8 @@ class TestScope < Test::Unit::TestCase def test_declarative # set to declarative - top = Puppet::Parser::Scope.new(:declarative => true) - sub = Puppet::Parser::Scope.new(:parent => top) + top = mkscope(:declarative => true) + sub = mkscope(:parent => top) assert_nothing_raised { top.setvar("test","value") @@ -116,8 +119,8 @@ class TestScope < Test::Unit::TestCase def test_notdeclarative # set to not declarative - top = Puppet::Parser::Scope.new(:declarative => false) - sub = Puppet::Parser::Scope.new(:parent => top) + top = mkscope(:declarative => false) + sub = mkscope(:parent => top) assert_nothing_raised { top.setvar("test","value") @@ -133,106 +136,65 @@ class TestScope < Test::Unit::TestCase } end - def test_defaults - scope = nil - over = "over" - - scopes = [] - vars = [] - values = {} - ovalues = [] + def test_setdefaults + interp, scope, source = mkclassframing - defs = Hash.new { |hash,key| - hash[key] = Hash.new(nil) - } - - prevdefs = Hash.new { |hash,key| - hash[key] = Hash.new(nil) - } - - params = %w{a list of parameters that could be used for defaults} + # The setdefaults method doesn't really check what we're doing, + # so we're just going to use fake defaults here. - types = %w{a set of types that could be used to set defaults} + # First do a simple local lookup + params = paramify(source, :one => "fun", :two => "shoe") + origshould = {} + params.each do |p| origshould[p.name] = p end + assert_nothing_raised do + scope.setdefaults(:file, params) + end - 10.times { |index| - scope = Puppet::Parser::Scope.new(:parent => scope) - scopes.push scope + ret = nil + assert_nothing_raised do + ret = scope.lookupdefaults(:file) + end - tmptypes = [] - - # randomly create defaults for a random set of types - tnum = rand(5) - tnum.times { |t| - # pick a type - #Puppet.debug "Type length is %s" % types.length - #s = rand(types.length) - #Puppet.debug "Type num is %s" % s - #type = types[s] - #Puppet.debug "Type is %s" % s - type = types[rand(types.length)] - if tmptypes.include?(type) - Puppet.debug "Duplicate type %s" % type - redo - else - tmptypes.push type - end + assert_equal(origshould, ret) - Puppet.debug "type is %s" % type + # Now create a subscope and add some more params. + newscope = scope.newscope - d = {} + newparams = paramify(source, :one => "shun", :three => "free") + assert_nothing_raised { + newscope.setdefaults(:file, newparams) + } - # randomly assign some parameters - num = rand(4) - num.times { |n| - param = params[rand(params.length)] - if d.include?(param) - Puppet.debug "Duplicate param %s" % param - redo - else - d[param] = rand(1000) - end - } + # And make sure we get the appropriate ones back + should = {} + params.each do |p| should[p.name] = p end + newparams.each do |p| should[p.name] = p end - # and then add a consistent type - d["always"] = rand(1000) + assert_nothing_raised do + ret = newscope.lookupdefaults(:file) + end - d.each { |var,val| - defs[type][var] = val - } + assert_equal(should, ret) - assert_nothing_raised { - scope.setdefaults(type,to_ary(d)) - } - fdefs = nil - assert_nothing_raised { - fdefs = scope.lookupdefaults(type) - } + # Make sure we still only get the originals from the top scope + assert_nothing_raised do + ret = scope.lookupdefaults(:file) + end - # now, make sure that reassignment fails if we're - # in declarative mode - assert_raise(Puppet::ParseError) { - scope.setdefaults(type,[%w{always funtest}]) - } + assert_equal(origshould, ret) - # assert that we have collected the same values - assert_equal(defs[type],fdefs) + # Now create another scope and make sure we only get the top defaults + otherscope = scope.newscope + assert_equal(origshould, otherscope.lookupdefaults(:file)) - # now assert that our parent still finds the same defaults - # it got last time - if parent = scope.parent - unless prevdefs[type].nil? - assert_equal(prevdefs[type],parent.lookupdefaults(type)) - end - end - d.each { |var,val| - prevdefs[type][var] = val - } - } - } + # And make sure none of the scopes has defaults for other types + [scope, newscope, otherscope].each do |sc| + assert_equal({}, sc.lookupdefaults(:exec)) + end end def test_strinterp - scope = Puppet::Parser::Scope.new() + scope = mkscope() assert_nothing_raised { scope.setvar("test","value") @@ -264,313 +226,61 @@ class TestScope < Test::Unit::TestCase assert_equal("$test string", val) end - # Test some of the host manipulations - def test_hostlookup - top = Puppet::Parser::Scope.new() - - # Create a deep scope tree, so that we know we're doing a deeply recursive - # search. - mid1 = Puppet::Parser::Scope.new(:parent => top) - mid2 = Puppet::Parser::Scope.new(:parent => mid1) - mid3 = Puppet::Parser::Scope.new(:parent => mid2) - child1 = Puppet::Parser::Scope.new(:parent => mid3) - mida = Puppet::Parser::Scope.new(:parent => top) - midb = Puppet::Parser::Scope.new(:parent => mida) - midc = Puppet::Parser::Scope.new(:parent => midb) - child2 = Puppet::Parser::Scope.new(:parent => midc) - - # verify we can set a host - assert_nothing_raised("Could not create host") { - child1.setnode("testing", AST::Node.new( - :type => "testing", - :code => :notused - ) - ) - } - - # Verify we cannot redefine it - assert_raise(Puppet::ParseError, "Duplicate host creation succeeded") { - child2.setnode("testing", AST::Node.new( - :type => "testing", - :code => :notused - ) - ) - } - - # Now verify we can find the host again - host = nil - assert_nothing_raised("Host lookup failed") { - hash = top.node("testing") - host = hash[:node] - } - - assert(host, "Could not find host") - assert(host.code == :notused, "Host is not what we stored") - end - - # Verify that two statements about a file within the same scope tree - # will cause a conflict. - def test_noconflicts - filename = tempfile() - children = [] - - # create the parent class - children << classobj("one", :code => AST::ASTArray.new( - :children => [ - fileobj(filename, "owner" => "root") - ] - )) - - # now create a child class with differ values - children << classobj("two", - :code => AST::ASTArray.new( - :children => [ - fileobj(filename, "owner" => "bin") - ] - )) - - # Now call the child class - assert_nothing_raised("Could not add AST nodes for calling") { - children << AST::ObjectDef.new( - :type => nameobj("two"), - :name => nameobj("yayness"), - :params => astarray() - ) << AST::ObjectDef.new( - :type => nameobj("one"), - :name => nameobj("yayness"), - :params => astarray() - ) - } - - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => children - ) - } - - objects = nil - scope = nil - - # Here's where we should encounter the failure. It should find that - # it has already created an object with that name, and this should result - # in some pukey-pukeyness. - assert_raise(Puppet::ParseError) { - scope = Puppet::Parser::Scope.new() - objects = scope.evaluate(:ast => top) - } - end - - # Verify that statements about the same element within the same scope - # cause a conflict. - def test_failonconflictinsamescope - filename = tempfile() - children = [] - - # Now call the child class - assert_nothing_raised("Could not add AST nodes for calling") { - children << fileobj(filename, "owner" => "root") - children << fileobj(filename, "owner" => "bin") - } - - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => children - ) - } - - objects = nil - scope = nil - - # Here's where we should encounter the failure. It should find that - # it has already created an object with that name, and this should result - # in some pukey-pukeyness. - assert_raise(Puppet::ParseError) { - scope = Puppet::Parser::Scope.new() - scope.top = true - objects = scope.evaluate(:ast => top) - } - end - - # Verify that we override statements that we find within our scope - def test_suboverrides - filename = tempfile() - children = [] - - # create the parent class - children << classobj("parent", :code => AST::ASTArray.new( - :children => [ - fileobj(filename, "owner" => "root") - ] - )) - - # now create a child class with differ values - children << classobj("child", :parentclass => nameobj("parent"), - :code => AST::ASTArray.new( - :children => [ - fileobj(filename, "owner" => "bin") - ] - )) - - # Now call the child class - assert_nothing_raised("Could not add AST nodes for calling") { - children << AST::ObjectDef.new( - :type => nameobj("child"), - :name => nameobj("yayness"), - :params => astarray() - ) - } - - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => children - ) - } - - objects = nil - scope = nil - assert_nothing_raised("Could not evaluate") { - scope = Puppet::Parser::Scope.new() - objects = scope.evaluate(:ast => top) - } - - assert_equal(1, objects.length, "Returned too many objects: %s" % - objects.inspect) - - assert_equal(1, objects[0].length, "Returned too many objects: %s" % - objects[0].inspect) - - assert_nothing_raised { - file = objects[0][0] - assert_equal("bin", file["owner"], "Value did not override correctly") - } - end - - def test_multipletypes - scope = Puppet::Parser::Scope.new() - children = [] - - # create the parent class - children << classobj("aclass") - children << classobj("aclass") - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => children - ) - } - - scope = nil - assert_raise(Puppet::ParseError) { - scope = Puppet::Parser::Scope.new() - objects = top.evaluate(:scope => scope) - } - end - - # Verify that definitions have a different context than classes. - def test_newsubcontext - filename = tempfile() - children = [] - - # Create a component - children << compobj("comp", :code => AST::ASTArray.new( - :children => [ - fileobj(filename, "owner" => "root" ) - ] - )) - - # Now create a class that modifies the same file and also - # calls the component - children << classobj("klass", :code => AST::ASTArray.new( - :children => [ - fileobj(filename, "owner" => "bin" ), - AST::ObjectDef.new( - :type => nameobj("comp"), - :params => astarray() - ) - ] - )) - - # Now call the class - children << AST::ObjectDef.new( - :type => nameobj("klass"), - :params => astarray() - ) - - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => children - ) - } + def test_setclass + interp, scope, source = mkclassframing - trans = nil - scope = nil - #assert_nothing_raised { - assert_raise(Puppet::ParseError, "A conflict was allowed") { - scope = Puppet::Parser::Scope.new() - trans = scope.evaluate(:ast => top) - } - # scope = Puppet::Parser::Scope.new() - # trans = scope.evaluate(:ast => top) - #} - end + base = scope.findclass("base") + assert(base, "Could not find base class") + assert(! scope.setclass?(base), "Class incorrectly set") + assert(! scope.classlist.include?("base"), "Class incorrectly in classlist") + assert_nothing_raised do + scope.setclass base + end - def test_defaultswithmultiplestatements - path = tempfile() + assert(scope.setclass?(base), "Class incorrectly unset") + assert(scope.classlist.include?("base"), "Class not in classlist") - stats = [] - stats << defaultobj("file", "group" => "root") - stats << fileobj(path, "owner" => "root") - stats << fileobj(path, "mode" => "755") + # Now try it with a normal string + assert_raise(Puppet::DevError) do + scope.setclass "string" + end - top = AST::ASTArray.new( - :file => __FILE__, - :line => __LINE__, - :children => stats - ) - scope = Puppet::Parser::Scope.new() - trans = nil - assert_nothing_raised { - trans = scope.evaluate(:ast => top) - } + assert(! scope.setclass?("string"), "string incorrectly set") - obj = trans.find do |obj| obj.is_a? Puppet::TransObject end + # Set "" in the class list, and make sure it doesn't show up in the return + top = scope.findclass("") + assert(top, "Could not find top class") + scope.setclass top - assert(obj, "Could not retrieve file obj") - assert_equal("root", obj["group"], "Default did not take") - assert_equal("root", obj["owner"], "Owner did not take") - assert_equal("755", obj["mode"], "Mode did not take") + assert(! scope.classlist.include?(""), "Class list included empty") end - def test_validclassnames - scope = Puppet::Parser::Scope.new() + def test_validtags + scope = mkscope() - ["a class", "Class", "a.class"].each do |bad| + ["a class", "a.class"].each do |bad| assert_raise(Puppet::ParseError, "Incorrectly allowed %s" % bad.inspect) do - scope.setclass(object_id, bad) + scope.tag(bad) end end - ["a-class", "a_class", "class", "yayNess"].each do |good| + ["a-class", "a_class", "Class", "class", "yayNess"].each do |good| assert_nothing_raised("Incorrectly banned %s" % good.inspect) do - scope.setclass(object_id, good) + scope.tag(good) end end end def test_tagfunction - scope = Puppet::Parser::Scope.new() + scope = mkscope() assert_nothing_raised { scope.function_tag(["yayness", "booness"]) } - assert(scope.classlist.include?("yayness"), "tag 'yayness' did not get set") - assert(scope.classlist.include?("booness"), "tag 'booness' did not get set") + assert(scope.tags.include?("yayness"), "tag 'yayness' did not get set") + assert(scope.tags.include?("booness"), "tag 'booness' did not get set") # Now verify that the 'tagged' function works correctly assert(scope.function_tagged("yayness"), @@ -583,77 +293,37 @@ class TestScope < Test::Unit::TestCase end def test_includefunction - scope = Puppet::Parser::Scope.new() - - one = tempfile() - two = tempfile() - - children = [] - - children << classobj("one", :code => AST::ASTArray.new( - :children => [ - fileobj(one, "owner" => "root") - ] - )) + interp = mkinterp + scope = mkscope :interp => interp - children << classobj("two", :code => AST::ASTArray.new( - :children => [ - fileobj(two, "owner" => "root") - ] - )) + myclass = interp.newclass "myclass" + otherclass = interp.newclass "otherclass" - children << Puppet::Parser::AST::Function.new( + function = Puppet::Parser::AST::Function.new( :name => "include", :ftype => :statement, :arguments => AST::ASTArray.new( - :children => [nameobj("one"), nameobj("two")] + :children => [nameobj("myclass"), nameobj("otherclass")] ) ) - top = AST::ASTArray.new(:children => children) - - #assert_nothing_raised { - # scope.function_include(["one", "two"]) - #} - - assert_nothing_raised { - scope.evaluate(:ast => top) - } - - - assert(scope.classlist.include?("one"), "tag 'one' did not get set") - assert(scope.classlist.include?("two"), "tag 'two' did not get set") + assert_nothing_raised do + function.evaluate :scope => scope + end - # Now verify that the 'tagged' function works correctly - assert(scope.function_tagged("one"), - "tagged function incorrectly returned false") - assert(scope.function_tagged("two"), - "tagged function incorrectly returned false") + [myclass, otherclass].each do |klass| + assert(scope.setclass?(klass), + "%s was not set" % klass.fqname) + end end def test_definedfunction - scope = Puppet::Parser::Scope.new() - - one = tempfile() - two = tempfile() - - children = [] - - children << classobj("one", :code => AST::ASTArray.new( - :children => [ - fileobj(one, "owner" => "root") - ] - )) - - children << classobj("two", :code => AST::ASTArray.new( - :children => [ - fileobj(two, "owner" => "root") - ] - )) - - top = AST::ASTArray.new(:children => children) + interp = mkinterp + %w{one two}.each do |name| + interp.newdefine name + end - top.evaluate(:scope => scope) + scope = mkscope :interp => interp assert_nothing_raised { %w{one two file user}.each do |type| @@ -664,40 +334,6 @@ class TestScope < Test::Unit::TestCase assert(!scope.function_defined(["nopeness"]), "Class 'nopeness' was incorrectly considered defined") } - - - end - - # Make sure components acquire defaults. - def test_defaultswithcomponents - children = [] - - # Create a component - filename = tempfile() - args = AST::ASTArray.new( - :file => tempfile(), - :line => rand(100), - :children => [nameobj("argument")] - ) - children << compobj("comp", :args => args, :code => AST::ASTArray.new( - :children => [ - fileobj(filename, "owner" => varref("argument") ) - ] - )) - - # Create a default - children << defaultobj("comp", "argument" => "yayness") - - # lastly, create an object that calls our third component - children << objectdef("comp", "boo", {"argument" => "parentfoo"}) - - trans = assert_evaluate(children) - - flat = trans.flatten - - assert(!flat.empty?, "Got no objects back") - - assert_equal("parentfoo", flat[0]["owner"], "default did not take") end # Make sure we know what we consider to be truth. @@ -714,7 +350,7 @@ class TestScope < Test::Unit::TestCase # Verify scope context is handled correctly. def test_scopeinside - scope = Puppet::Parser::Scope.new() + scope = mkscope() one = :one two = :two @@ -763,9 +399,10 @@ class TestScope < Test::Unit::TestCase end if defined? ActiveRecord - # Verify that we recursively mark as collectable the results of collectable + # Verify that we recursively mark as exported the results of collectable # components. - def test_collectablecomponents + def test_exportedcomponents + interp, scope, source = mkclassframing children = [] args = AST::ASTArray.new( @@ -773,47 +410,44 @@ class TestScope < Test::Unit::TestCase :line => rand(100), :children => [nameobj("arg")] ) + # Create a top-level component - children << compobj("one", :args => args) + interp.newdefine "one", :arguments => [%w{arg}], + :code => AST::ASTArray.new( + :children => [ + resourcedef("file", "/tmp", {"owner" => varref("arg")}) + ] + ) # And a component that calls it - children << compobj("two", :args => args, :code => AST::ASTArray.new( - :children => [ - objectdef("one", "ptest", {"arg" => "parentfoo"}) - ] - )) + interp.newdefine "two", :arguments => [%w{arg}], + :code => AST::ASTArray.new( + :children => [ + resourcedef("one", "ptest", {"arg" => varref("arg")}) + ] + ) # And then a third component that calls the second - children << compobj("three", :args => args, :code => AST::ASTArray.new( - :children => [ - objectdef("two", "yay", {"arg" => "parentfoo"}) - ] - )) + interp.newdefine "three", :arguments => [%w{arg}], + :code => AST::ASTArray.new( + :children => [ + resourcedef("two", "yay", {"arg" => varref("arg")}) + ] + ) # lastly, create an object that calls our third component - obj = objectdef("three", "boo", {"arg" => "parentfoo"}) - - # And mark it as collectable - obj.collectable = true + obj = resourcedef("three", "boo", {"arg" => "parentfoo"}) - children << obj + # And mark it as exported + obj.exported = true - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => children - ) - } + obj.evaluate :scope => scope - trans = nil - scope = nil - assert_nothing_raised { - scope = Puppet::Parser::Scope.new() - trans = scope.evaluate(:ast => top) - } + # And then evaluate it + interp.evaliterate(scope) %w{file}.each do |type| - objects = scope.exported(type) + objects = scope.lookupexported(type) assert(!objects.empty?, "Did not get an exported %s" % type) end @@ -832,11 +466,11 @@ class TestScope < Test::Unit::TestCase File.open(file, "w") { |f| f.puts " class yay { - @host { myhost: ip => \"192.168.0.2\" } + @@host { myhost: ip => \"192.168.0.2\" } } include yay -@host { puppet: ip => \"192.168.0.3\" } -host <||>" +@@host { puppet: ip => \"192.168.0.3\" } +Host <<||>>" } interp = nil @@ -853,7 +487,7 @@ host <||>" # if we pull it up from the database. 2.times { |i| assert_nothing_raised { - objects = interp.run("localhost", {}) + objects = interp.run("localhost", {"hostname" => "localhost"}) } flat = objects.flatten @@ -863,53 +497,95 @@ host <||>" end } end + else + $stderr.puts "No ActiveRecord -- skipping collection tests" + end - # Verify that we cannot override differently exported objects - def test_exportedoverrides - filename = tempfile() - children = [] + # Make sure tags behave appropriately. + def test_tags + interp, scope, source = mkclassframing - obj = fileobj(filename, "owner" => "root") - obj.collectable = true - # create the parent class - children << classobj("parent", :code => AST::ASTArray.new( - :children => [ - obj - ] - )) - - # now create a child class with differ values - children << classobj("child", :parentclass => nameobj("parent"), - :code => AST::ASTArray.new( - :children => [ - fileobj(filename, "owner" => "bin") - ] - )) - - # Now call the child class - assert_nothing_raised("Could not add AST nodes for calling") { - children << AST::ObjectDef.new( - :type => nameobj("child"), - :name => nameobj("yayness"), - :params => astarray() - ) - } + # First make sure we can only set legal tags + ["an invalid tag", "-anotherinvalid", "bad*tag"].each do |tag| + assert_raise(Puppet::ParseError, "Tag #{tag} was considered valid") do + scope.tag tag + end + end - top = nil - assert_nothing_raised("Could not create top object") { - top = AST::ASTArray.new( - :children => children - ) - } + # Now make sure good tags make it through. + tags = %w{good-tag yaytag GoodTag another_tag} + tags.each do |tag| + assert_nothing_raised("Tag #{tag} was considered invalid") do + scope.tag tag + end + end - objects = nil - scope = nil - assert_raise(Puppet::ParseError, "Incorrectly allowed override") { - scope = Puppet::Parser::Scope.new() - objects = scope.evaluate(:ast => top) - } + # And make sure we get each of them. + ptags = scope.tags + tags.each do |tag| + assert(ptags.include?(tag), "missing #{tag}") + end + + + # Now create a subscope and set some tags there + newscope = scope.newscope(:type => 'subscope') + + # set some tags + newscope.tag "onemore", "yaytag" + + # And make sure we get them plus our parent tags + assert_equal((ptags + %w{onemore subscope}).sort, newscope.tags.sort) end - else - $stderr.puts "No ActiveRecord -- skipping collection tests" + + # Make sure we successfully translate objects + def test_translate + interp, scope, source = mkclassframing + + # Create a define that we'll be using + interp.newdefine("wrapper", :code => AST::ASTArray.new(:children => [ + resourcedef("file", varref("name"), "owner" => "root") + ])) + + # Now create a resource that uses that define + define = mkresource(:type => "wrapper", :title => "/tmp/testing", + :scope => scope, :source => source, :params => :none) + + scope.setresource define + + # And a normal resource + scope.setresource mkresource(:type => "file", :title => "/tmp/rahness", + :scope => scope, :source => source, + :params => {:owner => "root"}) + + # Evaluate the the define thing. + define.evaluate + + # Now the scope should have a resource and a subscope. Translate the + # whole thing. + ret = nil + assert_nothing_raised do + ret = scope.translate + end + + assert_instance_of(Puppet::TransBucket, ret) + + ret.each do |obj| + assert(obj.is_a?(Puppet::TransBucket) || obj.is_a?(Puppet::TransObject), + "Got a non-transportable object %s" % obj.class) + end + + rahness = ret.find { |c| c.type == "file" and c.name == "/tmp/rahness" } + assert(rahness, "Could not find top-level file") + assert_equal("root", rahness["owner"]) + + bucket = ret.find { |c| c.class == Puppet::TransBucket and c.name == "/tmp/testing" } + assert(bucket, "Could not find define bucket") + + testing = bucket.find { |c| c.type == "file" and c.name == "/tmp/testing" } + assert(testing, "Could not find define file") + assert_equal("root", testing["owner"]) + end end + +# $Id$ diff --git a/test/language/snippets.rb b/test/language/snippets.rb index 05ac066eb..f2597c8d0 100755 --- a/test/language/snippets.rb +++ b/test/language/snippets.rb @@ -12,7 +12,7 @@ class TestSnippets < Test::Unit::TestCase include ObjectSpace def self.snippetdir - PuppetTest.exampledir "code", "snippets" + PuppetTest.datadir "snippets" end def snippet(name) @@ -464,6 +464,13 @@ class TestSnippets < Test::Unit::TestCase @@tmpfiles << "/tmp/emptyexextest" end + def snippet_multisubs(trans) + path = "/tmp/multisubtest" + assert(FileTest.exists?(path), "Did not create file") + assert_equal("sub2", File.read(path), "sub2 did not override content") + assert_equal(0755, filemode(path), "sub1 did not override mode") + end + def disabled_snippet_dirchmod(trans) dirs = %w{a b}.collect { |letter| "/tmp/dirchmodtest%s" % letter diff --git a/test/language/transportable.rb b/test/language/transportable.rb index 217bb3370..a25500ee8 100755 --- a/test/language/transportable.rb +++ b/test/language/transportable.rb @@ -3,6 +3,7 @@ require 'puppet' require 'puppet/transportable' require 'puppettest' +require 'puppettest/parsertesting' require 'yaml' class TestTransportable < Test::Unit::TestCase diff --git a/test/lib/puppettest.rb b/test/lib/puppettest.rb index e7ee99c35..c6ce54b93 100644 --- a/test/lib/puppettest.rb +++ b/test/lib/puppettest.rb @@ -4,14 +4,14 @@ require 'test/unit' module PuppetTest # Find the root of the Puppet tree; this is not the test directory, but # the parent of that dir. - def basedir + def basedir(*list) unless defined? @@basedir case $0 when /rake_test_loader/ @@basedir = File.dirname(Dir.getwd) else dir = nil - if /^#{File::SEPARATOR}.+\.rb/ + if $0 =~ /^#{File::SEPARATOR}.+\.rb/ dir = $0 else dir = File.join(Dir.getwd, $0) @@ -20,15 +20,19 @@ module PuppetTest @@basedir = dir end end - @@basedir + if list.empty? + @@basedir + else + File.join(@@basedir, *list) + end end def cleanup(&block) @@cleaners << block end - def datadir - File.join(basedir, "test", "data") + def datadir(*list) + File.join(basedir, "test", "data", *list) end def exampledir(*args) @@ -45,6 +49,18 @@ module PuppetTest module_function :basedir, :datadir, :exampledir + # Rails clobbers RUBYLIB, thanks + def libsetup + curlibs = ENV["RUBYLIB"].split(":") + $:.reject do |dir| dir =~ /^\/usr/ end.each do |dir| + unless curlibs.include?(dir) + curlibs << dir + end + end + + ENV["RUBYLIB"] = curlibs.join(":") + end + def rake? $0 =~ /rake_test_loader/ end @@ -90,6 +106,7 @@ module PuppetTest Puppet::Log.level = :debug #$VERBOSE = 1 Puppet.info @method_name + Puppet[:trace] = true end #if $0 =~ /.+\.rb/ or Puppet[:debug] # Puppet::Log.newdestination :console @@ -169,7 +186,9 @@ module PuppetTest @@tmppids.clear Puppet::Type.allclear Puppet::Storage.clear - Puppet::Rails.clear + if defined? Puppet::Rails + Puppet::Rails.clear + end Puppet.clear @memoryatend = Puppet::Util.memory diff --git a/test/lib/puppettest/parsertesting.rb b/test/lib/puppettest/parsertesting.rb index e0606c501..1a6b5b12a 100644 --- a/test/lib/puppettest/parsertesting.rb +++ b/test/lib/puppettest/parsertesting.rb @@ -1,4 +1,5 @@ require 'puppettest' +require 'puppet/rails' module PuppetTest::ParserTesting include PuppetTest @@ -6,23 +7,36 @@ module PuppetTest::ParserTesting def astarray(*args) AST::ASTArray.new( - :children => args - ) + :children => args + ) end - def classobj(name, args = {}) - args[:type] ||= nameobj(name) - args[:code] ||= AST::ASTArray.new( - :file => __FILE__, - :line => __LINE__, - :children => [ - varobj("%svar" % name, "%svalue" % name), - fileobj("/%s" % name) - ] - ) - assert_nothing_raised("Could not create class %s" % name) { - return AST::ClassDef.new(args) - } + def mkinterp(args = {}) + args[:Code] ||= "" + args[:Local] ||= true + Puppet::Parser::Interpreter.new(args) + end + + def mkparser + Puppet::Parser::Parser.new(mkinterp) + end + + def mkscope(hash = {}) + hash[:interp] ||= mkinterp + hash[:source] ||= (hash[:interp].findclass("", "") || + hash[:interp].newclass("")) + + unless hash[:source] + raise "Could not find source for scope" + end + Puppet::Parser::Scope.new(hash) + end + + def classobj(name, hash = {}) + hash[:file] ||= __FILE__ + hash[:line] ||= __LINE__ + hash[:type] ||= name + AST::HostClass.new(hash) end def tagobj(*names) @@ -40,50 +54,47 @@ module PuppetTest::ParserTesting } end - def compobj(name, args = {}) - args[:file] ||= tempfile() - args[:line] ||= rand(100) - args[:type] ||= nameobj(name) - args[:args] ||= AST::ASTArray.new( - :file => tempfile(), - :line => rand(100), - :children => [] - ) - args[:code] ||= AST::ASTArray.new( - :file => tempfile(), - :line => rand(100), - :children => [ - varobj("%svar" % name, "%svalue" % name), - fileobj("/%s" % name) - ] - ) - assert_nothing_raised("Could not create compdef %s" % name) { - return AST::CompDef.new(args) + def resourcedef(type, title, params) + unless title.is_a?(AST) + title = stringobj(title) + end + assert_nothing_raised("Could not create %s %s" % [type, title]) { + return AST::ResourceDef.new( + :file => __FILE__, + :line => __LINE__, + :title => title, + :type => type, + :params => resourceinst(params) + ) } end - def objectdef(type, name, params) + def resourceoverride(type, title, params) assert_nothing_raised("Could not create %s %s" % [type, name]) { - return AST::ObjectDef.new( - :file => __FILE__, - :line => __LINE__, - :name => stringobj(name), - :type => nameobj(type), - :params => objectinst(params) - ) + return AST::ResourceOverride.new( + :file => __FILE__, + :line => __LINE__, + :object => resourceref(type, title), + :type => type, + :params => resourceinst(params) + ) + } + end + + def resourceref(type, title) + assert_nothing_raised("Could not create %s %s" % [type, title]) { + return AST::ResourceRef.new( + :file => __FILE__, + :line => __LINE__, + :type => type, + :title => stringobj(title) + ) } end def fileobj(path, hash = {"owner" => "root"}) assert_nothing_raised("Could not create file %s" % path) { - return objectdef("file", path, hash) - # return AST::ObjectDef.new( - # :file => tempfile(), - # :line => rand(100), - # :name => stringobj(path), - # :type => nameobj("file"), - # :params => objectinst(hash) - # ) + return resourcedef("file", path, hash) } end @@ -123,12 +134,12 @@ module PuppetTest::ParserTesting } end - def objectinst(hash) - assert_nothing_raised("Could not create object instance") { + def resourceinst(hash) + assert_nothing_raised("Could not create resource instance") { params = hash.collect { |param, value| - objectparam(param, value) + resourceparam(param, value) } - return AST::ObjectInst.new( + return AST::ResourceInst.new( :file => tempfile(), :line => rand(100), :children => params @@ -136,16 +147,16 @@ module PuppetTest::ParserTesting } end - def objectparam(param, value) + def resourceparam(param, value) # Allow them to pass non-strings in if value.is_a?(String) value = stringobj(value) end assert_nothing_raised("Could not create param %s" % param) { - return AST::ObjectParam.new( + return AST::ResourceParam.new( :file => tempfile(), :line => rand(100), - :param => nameobj(param), + :param => param, :value => value ) } @@ -194,10 +205,10 @@ module PuppetTest::ParserTesting def defaultobj(type, params) pary = [] params.each { |p,v| - pary << AST::ObjectParam.new( + pary << AST::ResourceParam.new( :file => __FILE__, :line => __LINE__, - :param => nameobj(p), + :param => p, :value => stringobj(v) ) } @@ -208,10 +219,10 @@ module PuppetTest::ParserTesting ) assert_nothing_raised("Could not create defaults for %s" % type) { - return AST::TypeDefaults.new( + return AST::ResourceDefaults.new( :file => __FILE__, :line => __LINE__, - :type => typeobj(type), + :type => type, :params => past ) } @@ -274,7 +285,7 @@ module PuppetTest::ParserTesting return obj end - def mk_transbucket(*objects) + def mk_transbucket(*resources) bucket = nil assert_nothing_raised { bucket = Puppet::TransBucket.new @@ -282,12 +293,12 @@ module PuppetTest::ParserTesting bucket.type = "yaytype" } - objects.each { |o| bucket << o } + resources.each { |o| bucket << o } return bucket end - # Make a tree of objects, yielding if desired + # Make a tree of resources, yielding if desired def mk_transtree(depth = 4, width = 2) top = nil assert_nothing_raised { @@ -300,7 +311,7 @@ module PuppetTest::ParserTesting file = tempfile() depth.times do |i| - objects = [] + resources = [] width.times do |j| path = tempfile + i.to_s obj = Puppet::TransObject.new("file", path) @@ -312,10 +323,10 @@ module PuppetTest::ParserTesting yield(obj, i, j) end - objects << obj + resources << obj end - newbucket = mk_transbucket(*objects) + newbucket = mk_transbucket(*resources) bucket.push newbucket bucket = newbucket @@ -324,13 +335,13 @@ module PuppetTest::ParserTesting return top end - # Take a list of AST objects, evaluate them, and return the results + # Take a list of AST resources, evaluate them, and return the results def assert_evaluate(children) top = nil assert_nothing_raised("Could not create top object") { top = AST::ASTArray.new( - :children => children - ) + :children => children + ) } trans = nil diff --git a/test/lib/puppettest/railstesting.rb b/test/lib/puppettest/railstesting.rb new file mode 100644 index 000000000..3a32d0c9e --- /dev/null +++ b/test/lib/puppettest/railstesting.rb @@ -0,0 +1,34 @@ +module PuppetTest::RailsTesting + Parser = Puppet::Parser + AST = Puppet::Parser::AST + include PuppetTest::ParserTesting + + def railsinit + Puppet::Rails.init + end + + def railsresource(type = "file", title = "/tmp/testing", params = {}) + railsinit + + # We need a host for resources + host = Puppet::Rails::Host.new(:name => Facter.value("hostname")) + + # Now build a resource + resource = host.rails_resources.build( + :title => title, :restype => type, + :exported => true + ) + + # Now add some params + params.each do |param, value| + resource.rails_parameters.build( + :name => param, :value => value + ) + end + + # Now save the whole thing + host.save + end +end + +# $Id$ diff --git a/test/lib/puppettest/resourcetesting.rb b/test/lib/puppettest/resourcetesting.rb new file mode 100644 index 000000000..a7d183ca7 --- /dev/null +++ b/test/lib/puppettest/resourcetesting.rb @@ -0,0 +1,64 @@ +module PuppetTest::ResourceTesting + Parser = Puppet::Parser + AST = Puppet::Parser::AST + def mkclassframing(interp = nil) + interp ||= mkinterp + + interp.newdefine("resource", :arguments => [%w{one}, %w{two value}, %w{three}]) + interp.newclass("") + source = interp.newclass("base") + interp.newclass("sub1", :parent => "base") + interp.newclass("sub2", :parent => "base") + interp.newclass("other") + + scope = Parser::Scope.new(:interp => interp) + scope.source = source + + return interp, scope, source + end + + def mkresource(args = {}) + + if args[:scope] and ! args[:source] + args[:source] = args[:scope].source + end + + unless args[:scope] + unless defined? @scope + raise "Must set @scope to mkresource" + end + end + + {:type => "resource", :title => "testing", + :source => @source, :scope => @scope}.each do |param, value| + args[param] ||= value + end + + unless args[:source].is_a?(Puppet::Parser::AST::HostClass) + args[:source] = args[:scope].findclass(args[:source]) + end + + params = args[:params] || {:one => "yay", :three => "rah"} + if args[:params] == :none + args.delete(:params) + else + args[:params] = paramify args[:source], params + end + + Parser::Resource.new(args) + end + + def param(name, value, source) + Parser::Resource::Param.new(:name => name, :value => value, :source => source) + end + + def paramify(source, hash) + hash.collect do |name, value| + Parser::Resource::Param.new( + :name => name, :value => value, :source => source + ) + end + end +end + +# $Id$ diff --git a/test/lib/puppettest/support/utils.rb b/test/lib/puppettest/support/utils.rb index 00ea1a1c9..ea2d5483c 100644 --- a/test/lib/puppettest/support/utils.rb +++ b/test/lib/puppettest/support/utils.rb @@ -102,7 +102,7 @@ module PuppetTest # a list of files that we can parse for testing def textfiles - textdir = File.join(exampledir,"code", "snippets") + textdir = datadir "snippets" Dir.entries(textdir).reject { |f| f =~ /^\./ or f =~ /fail/ }.each { |f| @@ -111,7 +111,7 @@ module PuppetTest end def failers - textdir = File.join(exampledir,"code", "failers") + textdir = datadir "failers" # only parse this one file now files = Dir.entries(textdir).reject { |file| file =~ %r{\.swp} diff --git a/test/other/config.rb b/test/other/config.rb index 0afe8979b..09d6abe3b 100755 --- a/test/other/config.rb +++ b/test/other/config.rb @@ -3,9 +3,11 @@ require 'puppet' require 'puppet/config' require 'puppettest' +require 'puppettest/parsertesting' class TestConfig < Test::Unit::TestCase include PuppetTest + include PuppetTest::ParserTesting def check_for_users count = Puppet::Type.type(:user).inject(0) { |c,o| @@ -39,21 +41,16 @@ class TestConfig < Test::Unit::TestCase } Puppet[:parseonly] = true - parser = Puppet::Parser::Parser.new() - objects = nil - assert_nothing_raised("Could not parse generated manifest") { - parser.string = manifest - objects = parser.parse - } - scope = Puppet::Parser::Scope.new - assert_nothing_raised("Could not compile objects") { - scope.evaluate(:ast => objects) - } + interp = nil + assert_nothing_raised do + interp = mkinterp :Code => manifest, :UseNodes => false + end + trans = nil - assert_nothing_raised("Could not convert objects to transportable") { - trans = scope.to_trans - } + assert_nothing_raised do + trans = interp.evaluate(nil, {}) + end assert_nothing_raised("Could not instantiate objects") { trans.to_type } diff --git a/test/rails/rails.rb b/test/rails/rails.rb new file mode 100755 index 000000000..c780d7698 --- /dev/null +++ b/test/rails/rails.rb @@ -0,0 +1,87 @@ +#!/usr/bin/ruby + +require 'puppet' +require 'puppet/rails' +require 'puppet/parser/interpreter' +require 'puppet/parser/parser' +require 'puppet/client' +require 'puppettest' +require 'puppettest/parsertesting' +require 'puppettest/resourcetesting' +require 'puppettest/railstesting' + +class TestRails < Test::Unit::TestCase + include PuppetTest::ParserTesting + include PuppetTest::ResourceTesting + include PuppetTest::RailsTesting + + def test_includerails + assert_nothing_raised { + require 'puppet/rails' + } + end + + # Don't do any tests w/out this class + if defined? ActiveRecord::Base + def test_hostcache + @interp, @scope, @source = mkclassframing + # First make some objects + resources = [] + 20.times { |i| + resources << mkresource(:type => "file", :title => "/tmp/file#{i.to_s}", + :params => {:owner => "user#{i}"}) + } + + # Now collect our facts + facts = Facter.to_hash + + assert_nothing_raised { + Puppet::Rails.init + } + + # Now try storing our crap + host = nil + assert_nothing_raised { + host = Puppet::Rails::Host.store( + :resources => resources, + :facts => facts, + :name => facts["hostname"], + :classes => ["one", "two::three", "four"] + ) + } + + assert(host, "Did not create host") + + host = nil + assert_nothing_raised { + host = Puppet::Rails::Host.find_by_name(facts["hostname"]) + } + assert(host, "Could not find host object") + + assert(host.rails_resources, "No objects on host") + + assert_equal(facts["hostname"], host.facts["hostname"], + "Did not retrieve facts") + + count = 0 + host.rails_resources.each do |resource| + count += 1 + i = nil + if resource[:title] =~ /file([0-9]+)/ + i = $1 + else + raise "Got weird resource %s" % resource.inspect + end + + assert_equal("user#{i}", + resource.rails_parameters.find_by_name("owner")[:value]) + end + + assert_equal(20, count, "Did not get enough resources") + end + else + $stderr.puts "Install Rails for Rails and Caching tests" + end +end + +# $Id$ diff --git a/test/rails/railsparameter.rb b/test/rails/railsparameter.rb new file mode 100755 index 000000000..7dc7ef5dd --- /dev/null +++ b/test/rails/railsparameter.rb @@ -0,0 +1,50 @@ +#!/usr/bin/ruby + +require 'puppet' +require 'puppet/rails' +require 'puppettest' +require 'puppettest/railstesting' + +class TestRailsParameter < Test::Unit::TestCase + include PuppetTest::RailsTesting + + # Don't do any tests w/out this class + if defined? ActiveRecord::Base + # Create a resource param from a rails parameter + def test_to_resourceparam + railsinit + # First create our parameter + rparam = nil + hash = { :name => :myparam, :value => "myval", + :file => __FILE__, :line => __LINE__} + assert_nothing_raised do + rparam = Puppet::Rails::RailsParameter.new(hash) + end + + assert(rparam, "Did not create rails parameter") + + # The id doesn't get assigned until we save + rparam.save + + # Now create a source + interp = mkinterp + source = interp.newclass "myclass" + + # And try to convert our parameter + pparam = nil + assert_nothing_raised do + pparam = rparam.to_resourceparam(source) + end + + + assert_instance_of(Puppet::Parser::Resource::Param, pparam) + hash.each do |name, value| + assert_equal(value, pparam.send(name), "%s was not equal" % name) + end + end + else + $stderr.puts "Install Rails for Rails and Caching tests" + end +end + +# $Id$ diff --git a/test/rails/railsresource.rb b/test/rails/railsresource.rb new file mode 100755 index 000000000..86c3b4908 --- /dev/null +++ b/test/rails/railsresource.rb @@ -0,0 +1,60 @@ +#!/usr/bin/ruby + +require 'puppet' +require 'puppet/rails' +require 'puppettest' +require 'puppettest/railstesting' +require 'puppettest/resourcetesting' + +class TestRailsResource < Test::Unit::TestCase + include PuppetTest::RailsTesting + include PuppetTest::ResourceTesting + + # Don't do any tests w/out this class + if defined? ActiveRecord::Base + # Create a resource param from a rails parameter + def test_to_resource + railsinit + + # We need a host for resources + host = Puppet::Rails::Host.new(:name => "myhost") + + # Now build a resource + resource = host.rails_resources.build( + :title => "/tmp/to_resource", :restype => "file", + :exported => true + ) + + # Now add some params + {"owner" => "root", "mode" => "644"}.each do |param, value| + resource.rails_parameters.build( + :name => param, :value => value + ) + end + + # Now save the whole thing + host.save + + # Now, try to convert our resource to a real resource + + # We need a scope + interp, scope, source = mkclassframing + + res = nil + assert_nothing_raised do + res = resource.to_resource(scope) + end + + assert_instance_of(Puppet::Parser::Resource, res) + + assert_equal("root", res[:owner]) + assert_equal("644", res[:mode]) + assert_equal("/tmp/to_resource", res.title) + assert_equal(source, res.source) + end + else + $stderr.puts "Install Rails for Rails and Caching tests" + end +end + +# $Id$ diff --git a/test/tagging/tagging.rb b/test/tagging/tagging.rb index 42f04ff4f..b30160bcb 100644 --- a/test/tagging/tagging.rb +++ b/test/tagging/tagging.rb @@ -1,14 +1,18 @@ require 'puppet' require 'puppettest' +require 'puppettest/parsertesting' +require 'puppettest/resourcetesting' class TestTagging < Test::Unit::TestCase include PuppetTest + include PuppetTest::ParserTesting + include PuppetTest::ResourceTesting # Make sure the scopes are getting the right tags def test_scopetags scope = nil assert_nothing_raised { - scope = Puppet::Parser::Scope.new() + scope = mkscope scope.name = "yayness" scope.type = "solaris" } @@ -22,7 +26,7 @@ class TestTagging < Test::Unit::TestCase def test_deepscopetags scope = nil assert_nothing_raised { - scope = Puppet::Parser::Scope.new() + scope = mkscope scope.name = "yayness" scope.type = "solaris" scope = scope.newscope @@ -40,36 +44,21 @@ class TestTagging < Test::Unit::TestCase def test_objecttags scope = nil assert_nothing_raised { - scope = Puppet::Parser::Scope.new() + scope = mkscope scope.name = "yayness" scope.type = "solaris" } - assert_nothing_raised { - scope.setobject( - :type => "file", - :name => "/etc/passwd", - :arguments => {"owner" => "root"}, - :file => "/yay", - :line => 1 - ) - } + resource = mkresource :type => "file", :title => "/tmp/testing", + :params => {:owner => "root"}, :file => "/yay", :line => 1, + :scope => scope - ast = Puppet::Parser::AST::ASTArray.new({}) - - # We have to use 'evaluate', rather than just calling to_trans directly, - # because scopes do some internal checking to make sure the same object - # is not translated multiple times. - objects = nil assert_nothing_raised { - objects = scope.evaluate(:ast => ast) + scope.setresource(resource) } - # There's only one object, so shift it out - object = objects.shift - assert_nothing_raised { - assert_equal(%w{solaris}, object.tags, + assert_equal(%w{solaris}, resource.tags, "Incorrect tags") } end |