Home | History | Annotate | Line # | Download | only in auto
      1 #============================================================
      2 #  Author:   John Theofanopoulos
      3 #  A simple parser.   Takes the output files generated during the build process and
      4 # extracts information relating to the tests.  
      5 #
      6 #  Notes:
      7 #    To capture an output file under VS builds use the following:
      8 #      devenv [build instructions]  > Output.txt & type Output.txt
      9 # 
     10 #    To capture an output file under GCC/Linux builds use the following:
     11 #      make | tee Output.txt
     12 #
     13 #    To use this parser use the following command
     14 #    ruby parseOutput.rb [options] [file]
     15 #        options:  -xml  : produce a JUnit compatible XML file
     16 #        file      :  file to scan for results
     17 #============================================================
     18 
     19 
     20 class ParseOutput
     21 # The following flag is set to true when a test is found or false otherwise.
     22     @testFlag
     23     @xmlOut
     24     @arrayList
     25     @totalTests
     26     @classIndex
     27 
     28 #   Set the flag to indicate if there will be an XML output file or not  
     29     def setXmlOutput()
     30         @xmlOut = true
     31     end
     32     
     33 #  if write our output to XML
     34     def writeXmlOuput()
     35             output = File.open("report.xml", "w")
     36             output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
     37             @arrayList.each do |item|
     38                 output << item << "\n"
     39             end
     40             output << "</testsuite>\n"
     41     end
     42     
     43 #  This function will try and determine when the suite is changed.   This is
     44 # is the name that gets added to the classname parameter.
     45     def  testSuiteVerify(testSuiteName)
     46         if @testFlag == false
     47             @testFlag = true;
     48             # Split the path name 
     49             testName = testSuiteName.split("/")
     50             # Remove the extension
     51             baseName = testName[testName.size - 1].split(".")
     52             @testSuite = "test." + baseName[0]
     53             printf "New Test: %s\n", @testSuite
     54         end
     55     end
     56     
     57 
     58 # Test was flagged as having passed so format the output
     59     def testPassed(array)
     60         lastItem = array.length - 1
     61         testName = array[lastItem - 1]
     62         testSuiteVerify(array[@className])
     63         printf "%-40s PASS\n", testName
     64         if @xmlOut == true
     65             @arrayList.push "     <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\"/>"
     66         end          
     67     end
     68 
     69 # Test was flagged as being ingored so format the output
     70     def testIgnored(array)
     71         lastItem = array.length - 1
     72         testName = array[lastItem - 2]
     73         reason = array[lastItem].chomp
     74         testSuiteVerify(array[@className])
     75         printf "%-40s IGNORED\n", testName
     76         if @xmlOut == true
     77             @arrayList.push "     <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\">"
     78             @arrayList.push "            <skipped type=\"TEST IGNORED\"> " + reason + " </skipped>"
     79             @arrayList.push "     </testcase>"
     80         end          
     81     end
     82 
     83 # Test was flagged as having failed  so format the line
     84     def testFailed(array)
     85         lastItem = array.length - 1
     86         testName = array[lastItem - 2]
     87         reason = array[lastItem].chomp + " at line: " + array[lastItem - 3]
     88         testSuiteVerify(array[@className])
     89         printf "%-40s FAILED\n", testName
     90         if @xmlOut == true
     91             @arrayList.push "     <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\">"
     92             @arrayList.push "            <failure type=\"ASSERT FAILED\"> " + reason + " </failure>"
     93             @arrayList.push "     </testcase>"
     94         end          
     95     end
     96 
     97     
     98 # Figure out what OS we are running on.   For now we are assuming if it's not Windows it must
     99 # be Unix based.  
    100     def detectOS()
    101         myOS = RUBY_PLATFORM.split("-")
    102         if myOS.size == 2
    103             if myOS[1] == "mingw32"
    104                 @className = 1
    105             else
    106                 @className = 0
    107             end
    108 	else
    109                 @className = 0
    110         end
    111         
    112     end
    113 
    114 # Main function used to parse the file that was captured.
    115     def process(name)
    116         @testFlag = false
    117         @arrayList = Array.new
    118 
    119         detectOS()
    120 
    121         puts "Parsing file: " + name
    122     
    123       
    124         testPass = 0
    125         testFail = 0
    126         testIgnore = 0
    127         puts ""
    128         puts "=================== RESULTS ====================="
    129         puts ""
    130         File.open(name).each do |line|
    131         # Typical test lines look like this:
    132         # <path>/<test_file>.c:36:test_tc1000_opsys:FAIL: Expected 1 Was 0
    133         # <path>/<test_file>.c:112:test_tc5004_initCanChannel:IGNORE: Not Yet Implemented
    134         # <path>/<test_file>.c:115:test_tc5100_initCanVoidPtrs:PASS
    135         #
    136         # where path is different on Unix vs Windows devices (Windows leads with a drive letter)
    137             lineArray = line.split(":")
    138             lineSize = lineArray.size
    139             # If we were able to split the line then we can look to see if any of our target words
    140             # were found.  Case is important.
    141             if lineSize >= 4
    142                 # Determine if this test passed
    143                 if  line.include? ":PASS"
    144                     testPassed(lineArray)
    145                     testPass += 1
    146                 elsif line.include? ":FAIL:"
    147                     testFailed(lineArray)
    148                     testFail += 1
    149                 elsif line.include? ":IGNORE:"
    150                     testIgnored(lineArray)
    151                     testIgnore += 1
    152                 # If none of the keywords are found there are no more tests for this suite so clear
    153                 # the test flag
    154                 else
    155                     @testFlag = false
    156                 end
    157             else
    158                 @testFlag = false
    159                 end
    160             end
    161         puts ""
    162         puts "=================== SUMMARY ====================="
    163         puts ""
    164         puts "Tests Passed  : " + testPass.to_s
    165         puts "Tests Failed  : " + testFail.to_s
    166         puts "Tests Ignored : " + testIgnore.to_s
    167         @totalTests = testPass + testFail + testIgnore
    168         if @xmlOut == true
    169             heading = "<testsuite tests=\"" +  @totalTests.to_s  + "\" failures=\"" + testFail.to_s + "\""  + " skips=\"" +  testIgnore.to_s + "\">" 
    170             @arrayList.insert(0, heading) 
    171             writeXmlOuput()
    172         end
    173 
    174     #  return result
    175     end
    176 
    177  end
    178 
    179 # If the command line has no values in, used a default value of Output.txt
    180 parseMyFile = ParseOutput.new
    181 
    182 if ARGV.size >= 1 
    183     ARGV.each do |a|
    184         if a == "-xml"
    185             parseMyFile.setXmlOutput();
    186         else
    187             parseMyFile.process(a)
    188             break
    189         end
    190     end
    191 end
    192