nasl-pedant 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/.gitignore +10 -0
  2. data/Gemfile +4 -0
  3. data/Rakefile +8 -0
  4. data/bin/pedant +33 -0
  5. data/lib/pedant/check.rb +135 -0
  6. data/lib/pedant/checks/conditional_or_loop_is_empty.rb +70 -0
  7. data/lib/pedant/checks/contains_ip_address_literals.rb +49 -0
  8. data/lib/pedant/checks/contains_no_carriage_returns.rb +48 -0
  9. data/lib/pedant/checks/contains_no_tabs.rb +48 -0
  10. data/lib/pedant/checks/contains_registration_section.rb +107 -0
  11. data/lib/pedant/checks/contains_unreachable_code.rb +68 -0
  12. data/lib/pedant/checks/ends_with_newline.rb +49 -0
  13. data/lib/pedant/checks/files_parse_without_error.rb +101 -0
  14. data/lib/pedant/checks/parse_test_code.rb +63 -0
  15. data/lib/pedant/checks/plugin_type_not_specified.rb +79 -0
  16. data/lib/pedant/cli.rb +82 -0
  17. data/lib/pedant/command.rb +96 -0
  18. data/lib/pedant/commands/check.rb +76 -0
  19. data/lib/pedant/commands/test.rb +37 -0
  20. data/lib/pedant/knowledge_base.rb +42 -0
  21. data/lib/pedant/test.rb +59 -0
  22. data/lib/pedant/version.rb +3 -0
  23. data/lib/pedant.rb +51 -0
  24. data/pedant.gemspec +25 -0
  25. data/test/test_helper.rb +5 -0
  26. data/test/unit/checks/conditional_or_loop_is_empty.rb +125 -0
  27. data/test/unit/checks/contains_ip_address_literals.rb +45 -0
  28. data/test/unit/checks/contains_no_carriage_returns.rb +43 -0
  29. data/test/unit/checks/contains_no_tabs.rb +45 -0
  30. data/test/unit/checks/contains_registration_section.rb +101 -0
  31. data/test/unit/checks/contains_unreachable_code.rb +93 -0
  32. data/test/unit/checks/ends_with_newline.rb +45 -0
  33. data/test/unit/checks/plugin_type_not_specified.rb +72 -0
  34. metadata +123 -0
@@ -0,0 +1,101 @@
1
+ ################################################################################
2
+ # Copyright (c) 2011, Mak Kolybabi
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ ################################################################################
26
+
27
+ module Pedant
28
+ class CheckFilesParseWithoutErrors < Check
29
+ def self.requires
30
+ super + [:file_mode, :base, :main]
31
+ end
32
+
33
+ def provides
34
+ super + [:codes, :trees]
35
+ end
36
+
37
+ def run
38
+ def import(path)
39
+ # All files should be relative to the main file's base in practice.
40
+ path = @kb[:base] + path
41
+
42
+ # Since there are potentially several ways to write the path leading to
43
+ # a file, we'll use the basename as the key for hashes. This will
44
+ # prevent parsing the same file multiple times.
45
+ file = path.basename
46
+
47
+ # Mark a placeholder key in the KB for this file. This will prevent us
48
+ # from trying to parse a library more than once if there is a failure.
49
+ @kb[:codes][file] = :pending
50
+ @kb[:trees][file] = :pending
51
+
52
+ begin
53
+ contents = File.open(path, "rb").read
54
+ @kb[:codes][file] = contents
55
+ report(:info, "Read contents of #{path}.")
56
+ rescue
57
+ report(:error, "Failed to read contents #{path}.")
58
+ return fatal
59
+ end
60
+
61
+ begin
62
+ tree = Nasl::Parser.new.parse(contents, path)
63
+ @kb[:trees][file] = tree
64
+ report(:info, "Parsed contents of #{path}.")
65
+ rescue
66
+ # XXX-MAK: Incorporate the error from the parser, as it gives full,
67
+ # coloured context.
68
+ report(:error, "Failed to parse #{path}.")
69
+ return fatal
70
+ end
71
+ end
72
+
73
+ # This check will pass by default.
74
+ pass
75
+
76
+ # Initialize the keys written by this check.
77
+ @kb[:codes] = {}
78
+ @kb[:trees] = {}
79
+
80
+ # Load up the main file.
81
+ import(@kb[:main])
82
+
83
+ return
84
+
85
+ while true
86
+ # Get the list of all Includes, and prune any that have already had the
87
+ # files they reference parsed.
88
+ libs = Nasl::Include.all.map do |inc|
89
+ (@kb[:base] + inc.filename.text).basename
90
+ end
91
+
92
+ libs.delete_if { |lib| lib == @kb[:main] || @kb[:trees].has_key?(lib) }
93
+
94
+ break if libs.empty?
95
+
96
+ # Try and parse each library, continuing on failures.
97
+ libs.each { |lib| import(lib) }
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,63 @@
1
+ ################################################################################
2
+ # Copyright (c) 2011, Mak Kolybabi
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ ################################################################################
26
+
27
+ module Pedant
28
+ class CheckParseTestCode < Check
29
+ def self.requires
30
+ super + [:codes, :main, :test_mode]
31
+ end
32
+
33
+ def self.provides
34
+ super + [:trees]
35
+ end
36
+
37
+ def run
38
+ def import(path)
39
+ # Since there are potentially several ways to write the path leading to
40
+ # a file, we'll use the basename as the key for hashes. This will
41
+ # prevent parsing the same file multiple times.
42
+ file = path.basename
43
+
44
+ # Mark a placeholder key in the KB for this file. This will prevent us
45
+ # from trying to parse a library more than once if there is a failure.
46
+ @kb[:trees][file] = :pending
47
+
48
+ tree = Nasl::Parser.new.parse(@kb[:codes][file], path)
49
+ @kb[:trees][file] = tree
50
+ report(:info, "Parsed contents of #{path}.")
51
+ end
52
+
53
+ # This check will pass by default.
54
+ pass
55
+
56
+ # Initialize the keys written by this check.
57
+ @kb[:trees] = {}
58
+
59
+ # Load up the main file.
60
+ import(@kb[:main])
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,79 @@
1
+ ################################################################################
2
+ # Copyright (c) 2011, Mak Kolybabi
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ ################################################################################
26
+
27
+ module Pedant
28
+ class CheckPluginTypeNotSpecified < Check
29
+ def self.requires
30
+ super + [:main, :trees]
31
+ end
32
+
33
+ def run
34
+ # This check only applies to plugins.
35
+ return skip unless @kb[:main].extname == '.nasl'
36
+
37
+ args = []
38
+
39
+ tree = @kb[:trees][@kb[:main]]
40
+
41
+ tree.all(:Call).each do |node|
42
+ next unless node.name.name == 'script_set_attribute'
43
+ next unless node.arg.has_key? 'attribute'
44
+
45
+ # Pull out the attribute argument.
46
+ arg = node.arg['attribute']
47
+ next if !arg.is_a? Nasl::String
48
+ next if arg.text != 'plugin_type'
49
+
50
+ # Pull out the value argument.
51
+ arg = node.arg['value']
52
+ next if !arg.is_a? Nasl::String
53
+
54
+ # Ensure that the plugin type is valid.
55
+ unless ['combined', 'local', 'remote'].include? arg.text
56
+ report(:info, "Plugin is of unknown type #{arg.text}:\n#{arg.context(node)}")
57
+ return fail
58
+ end
59
+
60
+ args << [arg, node]
61
+ end
62
+
63
+ case args.length
64
+ when 0
65
+ report(:error, "Plugin does not specify a type.")
66
+ fail
67
+ when 1
68
+ arg = args.first[0]
69
+ call = args.first[1]
70
+ report(:info, "Plugin is of type #{arg.text}:\n#{arg.context(call)}")
71
+ pass
72
+ else
73
+ report(:error, "Plugin specifies multiple types.")
74
+ args.each { |arg, call| report(:error, arg.context(call)) }
75
+ fail
76
+ end
77
+ end
78
+ end
79
+ end
data/lib/pedant/cli.rb ADDED
@@ -0,0 +1,82 @@
1
+ ################################################################################
2
+ # Copyright (c) 2011, Mak Kolybabi
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ ################################################################################
26
+
27
+ require 'optparse'
28
+
29
+ module Pedant
30
+ class Cli
31
+ def self.run
32
+ cfg = {}
33
+
34
+ Command.initialize!
35
+
36
+ optparse = OptionParser.new do |opts|
37
+ opts.banner = "Usage: pedant [options] [command [args]]"
38
+
39
+ cfg[:verbose] = 0
40
+ opts.on('-v', '--verbose', 'Output more information') do
41
+ cfg[:verbose] += 1
42
+ end
43
+ end
44
+
45
+ optparse.parse!
46
+
47
+ # Sanity check the command line arguments.
48
+ if ARGV.empty?
49
+ puts "No command was specified."
50
+ puts
51
+ usage
52
+ exit 1
53
+ end
54
+
55
+ cmd = ARGV.shift
56
+ cls = Command.find(cmd)
57
+ if cls.nil? then
58
+ puts "Command '#{cmd}' not supported."
59
+ puts
60
+ usage
61
+ exit 1
62
+ end
63
+
64
+ # Run the command.
65
+ cls.run(cfg, ARGV)
66
+ end
67
+
68
+ def self.usage
69
+ puts "For the moment, you have to run Pedant from its top-level directory."
70
+ puts
71
+ puts "./bin/pedant [flags] [command] [filename ...]"
72
+ puts
73
+ puts "Flags:"
74
+ puts " -v Display more verbose (warning) messages. "
75
+ puts " -vv Display more verbose (informational) messages. "
76
+ puts
77
+ puts "Commands:"
78
+ puts " check Runs all included checks against the specified plugin(s)."
79
+ puts " test Runs the specified unit tests, all are selected by default."
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,96 @@
1
+ ################################################################################
2
+ # Copyright (c) 2011, Mak Kolybabi
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ ################################################################################
26
+
27
+ module Pedant
28
+ class Command
29
+ def self.initialize!
30
+ Dir.glob(Pedant.lib + 'pedant/commands/*.rb').each {|f| load(f)}
31
+ end
32
+
33
+ def self.all
34
+ (@_all ||= [])
35
+ end
36
+
37
+ def self.inherited(cls)
38
+ all << cls
39
+ end
40
+
41
+ def self.find(cmd)
42
+ all.each do |cls|
43
+ return cls if cls.binding == cmd
44
+ end
45
+
46
+ nil
47
+ end
48
+
49
+ def self.banner(title, width=80)
50
+ # Create center of banner.
51
+ middle = "[ #{title} ]"
52
+
53
+ # Make sure width is a float.
54
+ width = width.to_f
55
+
56
+ # Create bars on either side.
57
+ leftover = (width - middle.length) / 2
58
+ left = '-' * leftover.floor
59
+ right = '-' * leftover.ceil
60
+
61
+ left + middle + right
62
+ end
63
+
64
+ def self.run(cfg, args)
65
+ # Separate plugins and libraries from the rest of the arguments.
66
+ paths = args.select { |arg| arg =~ /(\/|\.(inc|nasl))$/ }
67
+ args -= paths
68
+
69
+ # If we have no paths to process, there's a problem. Special purpose
70
+ # commands that don't require files to be declared should override this
71
+ # method.
72
+ if paths.empty?
73
+ puts "No directories (/), libraries (.inc), or plugins (.nasl) were specified."
74
+ exit 1
75
+ end
76
+
77
+ # Collect all the paths together, recursively.
78
+ dirents = []
79
+ paths.each do |path|
80
+ Pathname.new(path).find do |dirent|
81
+ if dirent.file? && dirent.extname =~ /inc|nasl/
82
+ dirents << dirent
83
+ end
84
+ end
85
+ end
86
+
87
+ # If the command is capable of handling all the paths at once, send them
88
+ # in a group, otherwise send them individually.
89
+ if self.respond_to? :analyze_all then
90
+ analyze_all(cfg, dirents, args)
91
+ else
92
+ dirents.each { |d| analyze(cfg, d, args) }
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,76 @@
1
+ ################################################################################
2
+ # Copyright (c) 2011, Mak Kolybabi
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ ################################################################################
26
+
27
+ module Pedant
28
+ class CommandCheck < Command
29
+ def self.binding
30
+ 'check'
31
+ end
32
+
33
+ def self.analyze(cfg, path, args)
34
+ Check.initialize!
35
+
36
+ # Get a list of every existing check.
37
+ pending = Check.all
38
+
39
+ # Initialize the knowledge base where checks can store information for
40
+ # other checks.
41
+ kb = KnowledgeBase.new(:file_mode, path)
42
+
43
+ # Try to run each pending check, until we've run all our checks or
44
+ # deadlocked.
45
+ fatal = false
46
+ until pending.empty? || fatal
47
+ # Find all of the checks that can run right now.
48
+ ready = pending.select { |cls| cls.ready?(kb) }
49
+ break if ready.empty?
50
+
51
+ # Run all of the checks that are ready.
52
+ ready.each do |cls|
53
+ # Create a new check instance.
54
+ chk = cls.new(kb)
55
+ pending.delete(cls)
56
+
57
+ chk.run
58
+
59
+ # Fatal errors mean that no further checks should be processed.
60
+ if chk.result == :fatal
61
+ fatal = true
62
+ break
63
+ end
64
+
65
+ # Display the results of the check.
66
+ puts chk.report(cfg[:verbose])
67
+ end
68
+ end
69
+
70
+ # Notify the user if any checks did not run due to unsatisfied
71
+ # dependencies or a fatal error occurring before they had the chance to
72
+ # run.
73
+ pending.each { |cls| puts cls.new(kb).report(cfg[:verbose]) }
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,37 @@
1
+ ################################################################################
2
+ # Copyright (c) 2011, Mak Kolybabi
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ ################################################################################
26
+
27
+ module Pedant
28
+ class CommandTest < Command
29
+ def self.binding
30
+ 'test'
31
+ end
32
+
33
+ def self.run(cfg, args)
34
+ Test.initialize!(args)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,42 @@
1
+ ################################################################################
2
+ # Copyright (c) 2011, Mak Kolybabi
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ ################################################################################
26
+
27
+ module Pedant
28
+ class KnowledgeBase < Hash
29
+ def initialize(mode, path=nil)
30
+ self[mode] = true
31
+
32
+ case mode
33
+ when :file_mode
34
+ self[:base] = path.dirname
35
+ self[:main] = path.basename
36
+ when :test_mode
37
+ self[:base] = Pathname.new('/var/empty')
38
+ self[:main] = Pathname.new('test.nasl')
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,59 @@
1
+ ################################################################################
2
+ # Copyright (c) 2011, Mak Kolybabi
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ ################################################################################
26
+
27
+ require 'test/unit'
28
+
29
+ module Pedant
30
+ module Test
31
+ def self.initialize!(args)
32
+ # Run all tests by default.
33
+ args = ['unit/*', 'unit/*/*'] if args.empty?
34
+
35
+ # Run each test or category of tests specified on the command line.
36
+ args.each do |test|
37
+ Dir.glob(Pedant.test + (test + '.rb')).each { |f| load(f) }
38
+ end
39
+
40
+ Check.initialize!
41
+ end
42
+
43
+ def check(result, cls, code)
44
+ # Create a knowledge base.
45
+ kb = KnowledgeBase.new(:test_mode)
46
+
47
+ # Put test code into the knowledge base.
48
+ kb[:codes] = {}
49
+ kb[:codes][kb[:main]] = code
50
+
51
+ # Create a new instance of the check, which will execute all dependencies.
52
+ chk = Pedant.const_get(cls).new(kb)
53
+
54
+ # Run the test and ensure we got the expected result.
55
+ chk.run
56
+ assert_equal(result, chk.result)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,3 @@
1
+ module Pedant
2
+ VERSION = '0.0.1'
3
+ end