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