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