From 18ef827e7f7c3dcc646892b0ab53f5b295d442b5 Mon Sep 17 00:00:00 2001 From: Jonathan Cran Date: Sun, 10 Oct 2010 01:55:50 +0000 Subject: [PATCH] Split the unit testing and log regexing capabilities - this should make it easier to regex msf logs for failure / success if you're doing automated testing with the framework. git-svn-id: file:///home/svn/framework3/trunk@10628 4d416f70-5f16-0410-b530-b9f4589650da --- test/lib/msftest.rb | 91 ++++++----------------------- test/lib/regexr.rb | 133 ++++++++++++++++++++++++++++++++++++++++++ test/lib/regexr.rb.ut | 73 +++++++++++++++++++++++ 3 files changed, 223 insertions(+), 74 deletions(-) create mode 100644 test/lib/regexr.rb create mode 100644 test/lib/regexr.rb.ut diff --git a/test/lib/msftest.rb b/test/lib/msftest.rb index 94ce3ea336..b01b7b0857 100644 --- a/test/lib/msftest.rb +++ b/test/lib/msftest.rb @@ -1,84 +1,27 @@ -class Test::Unit::TestCase +## This class consists of assert helper methods for regexing logs +## +## $id$ +$:.unshift(File.expand_path(File.dirname(__FILE__)) - @case_insensitive = true +require 'regexr' +require 'test/unit' - # All tests will scan for start and end lines. This ensures the task - # actually completed and didn't hang, and that the start and end lines - # are actually at the start and end of the task file. - def scan_for_startend(data,thestart,theend) - data_lines = data.split("\n") - regex_start = Regexp.new(thestart, @case_insensitive) - regex_endline = Regexp.new(theend, @case_insensitive) +class MSFTest < Test::Unit::TestCase - assert_match regex_start, data_lines.first - assert_match regex_endline, data_lines.last + def initialize + @case_insensitive = true + @regexr = Regexr.new end - # Tests can scan for any number of success lines. In order to pass, - # all successes must match. - def scan_for_successes(data,regexes) - data_lines = data.split("\n") - if regexes - success = false - target_successes = regexes.size - count = 0 - regexes.each { |condition| - matched = false - re = Regexp.new(condition, @case_insensitive) - data_lines.each {|line| - if line =~ re - count += 1 - matched = true - break - end - } - # A way to tell if a match was never found. - assert matched, "Didn't see success condition '#{condition}'" - - } - assert_equal target_successes, count, "Didn't get enough successes, somehow.\n" - else - assert true # No successes are defined, so count this as a pass. - end + def assert_complete(data,thestart,theend) + assert_true @regexr.verify_start_and_end(data,thestart,theend), "The start or end did not match the expected string" end - # Tests may scan for failures -- if any failure matches, the test flunks. - def scan_for_failures(data,regexes,exceptions) - data_lines = data.split("\n") - if regexes - regexes.each {|condition| - ## for each failure condition that we've been passed - re = Regexp.new(condition, @case_insensitive) - ## we'll look at the whole doc - data_lines.each {|line| - if line =~ re - ## First check the exceptions to make sure that this wasn't among them. - ## The reason for exceptions is that we may want to check for generic error - ## messages but have specific matched strings which we know are harmless. - - ## Guilty til proven innocent, assume it's not an exception - guilty = true - - ## But let's check anyway - exceptions.map { |exception| - reg_exception = Regexp.new(exception, @case_insensitive) - ## if the exception matches here, we'll spare it - if line =~ reg_exception - guilty = false - break - end - } - - ## If we didn't find an exception, we have to flunk. do not pass go. - if guilty - flunk "Saw failure condition '#{condition}' in #{line}; regex matched: #{re.inspect}" - end - end - } - } - else - assert true # No failures, so count this as a pass. - end + def assert_all_successes(data, regexes) + assert_true @regexr.scan_for_successes(data,regexes), "All strings were found in the data" end + def assert_no_failures(data, regexes, exceptions) + assert_true @regexr.scan_for_failures(data,regexes,exceptions), "A non-exccepted failure was found in the data" + end end diff --git a/test/lib/regexr.rb b/test/lib/regexr.rb new file mode 100644 index 0000000000..b473250b4a --- /dev/null +++ b/test/lib/regexr.rb @@ -0,0 +1,133 @@ +## This class consists of helper methods for regexing logs +## +## TODO - clean up the style. looks like it was written in the early 90s +## +## $id$ + +class Regexr + + def initialize + @verbose = true + end + + # Check for the beginning line. Handy when you need to ensure a log has started + def verify_start(data,the_start) + data_lines = data.split("\n") + regex_start = Regexp.new(the_start, @case_insensitive) + return regex_start.match(data_lines.first) + end + + # Check for end line. Handy when you need to ensure a log has completed. + def verify_end(data,the_end) + data_lines = data.split("\n") + regex_end = Regexp.new(the_end, @case_insensitive) + return regex_end.match(data_lines.last) + end + + # Check for the beginning and end lines. Handy when you need to ensure a log has started & completed + def verify_start_and_end(data,the_start,the_end) + data_lines = data.split("\n") + regex_start = Regexp.new(the_start, @case_insensitive) + regex_endline = Regexp.new(the_end, @case_insensitive) + + + ## yuck, refactor this - TODO + if regex_start.match == data_lines.first + return regex_endline == data_lines.last + end + + return false + end + + # Scan for any number of success lines. In order to pass, all successes must match. + def ensure_all_exist_in_data(data,regexes=[]) + data_lines = data.split("\n") + if regexes + success = false + target_successes = regexes.size + count = 0 + regexes.each { |condition| + matched = false + re = Regexp.new(condition, @case_insensitive) + data_lines.each {|line| + if line =~ re + count += 1 + matched = true + break + end + } + + # A way to tell if a match was never found. + if !matched + if @verbose + puts "DEBUG: Didn't see success condition '#{condition}'" + end + return false + end + } + + if target_successes == count + if @verbose + puts "DEBUG: woot, got all successes" + end + return true + else + if @verbose + puts "DEBUG: Didn't get enough successes, somehow. (" + count + "/" + target_successes + ")" + end + end + else + return true # No successes are defined, so count this as a pass (true). + end + end + + # Scan for failures -- if any single failure matches, the test returns true. + def ensure_none_exist_in_data(data,regexes=[],exceptions=[]) + data_lines = data.split("\n") + if regexes + regexes.each { |condition| + ## for each failure condition that we've been passed + re = Regexp.new(condition, @case_insensitive) + + ## assume we're okay + okay = true + + data_lines.each { |line| + + if re.match(line) + okay = false # oh, we found a match + + if @verbose + puts "found " + line + end + + + # but let's check the exceptions + exceptions.map { |exception| + reg_exception = Regexp.new(exception, @case_insensitive) + + # If the exception matches here, we'll spare it + if reg_exception.match(line) + if @verbose + puts "\'" + line + "\' is an exception, we can ignore it." + end + okay = true + break + end + } + + # If we didn't find an exception, we have to fail it. do not pass go. + if !okay + if @verbose + puts "DEBUG: Saw failure condition '#{condition}' in #{line}; regex matched: #{re.inspect}" + end + return false + end + end + } + } + else + return false # we gots no failures, so count this as a pass. + end + end +end diff --git a/test/lib/regexr.rb.ut b/test/lib/regexr.rb.ut new file mode 100644 index 0000000000..f9bb76dc03 --- /dev/null +++ b/test/lib/regexr.rb.ut @@ -0,0 +1,73 @@ +## +## Tests for the regexr library +## $id$ + +$:.unshift(File.expand_path(File.dirname(__FILE__)) ) + +require 'test/unit' +require 'regexr' + +class RegexrTest < Test::Unit::TestCase + + def setup + @r = Regexr.new + end + + def teardown + @r = nil + end + + def test_determine_start + assert @r.verify_start("this is the start\nof a line", "this is the start") + end + + def test_determine_end + assert @r.verify_end("this is the start\nof a line", "of a line") + end + + def test_determine start_end + assert @r.verify_start_and_end("this is the start\nof a line", "this is the start", "of a line") + end + + def test_success_not_defined + assert @r.ensure_all_exist_in_data("i can't get no\nsatisfaction") + end + + def test_no_success + assert !@r.ensure_all_exist_in_data("i can't get no\nsatisfaction", ["beast of burden"]) + end + + def test_single_success + assert @r.ensure_all_exist_in_data("this is the start\nof a line\nbut it's not the end", ["of a line"]) + end + + def test_multiple_successes + assert @r.ensure_all_exist_in_data("this is the start\nof a line\nbut it's not the end", ["this is the start","of a line"]) + end + + def test_failure_not_defined + assert @r.ensure_none_exist_in_data("this is the start\nof a line\nbut it's not the end") + end + + def test_no_failure + assert @r.ensure_none_exist_in_data("this is the start\nof a line\nbut it's not the end", ["nope, no failure here"]) + end + + def test_single_failure + assert !@r.ensure_none_exist_in_data("this is the start\nof a line\nbut it's not the end", ["of a line", "there's a failure here somewhere"]) + end + + def test_multiple_failures + assert !@r.ensure_none_exist_in_data("this is the start\nof a line\nbut it's not the end", ["of a line","but it's not the end"]) + end + + def test_excepted_failure + assert @r.ensure_none_exist_in_data("this is the start\nof a line\nbut it's not the end", ["no way man", "end"], ["but it's not the end"]) + end + + def test_success_and_failure + assert @r.ensure_all_exist_in_data("this is the start\nof a line\nbut it's not the end", ["but it's not the end"]) + assert !@r.ensure_none_exist_in_data("this is the start\nof a line\nbut it's not the end", ["no way man", "end"]) + end + +end