A metronome using the FRDM K64F board

Committer:
ram54288
Date:
Sun May 14 18:40:18 2017 +0000
Revision:
0:a7a43371b306
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ram54288 0:a7a43371b306 1 #!/usr/bin/ruby
ram54288 0:a7a43371b306 2 #
ram54288 0:a7a43371b306 3 # unity_to_junit.rb
ram54288 0:a7a43371b306 4 #
ram54288 0:a7a43371b306 5 require 'fileutils'
ram54288 0:a7a43371b306 6 require 'optparse'
ram54288 0:a7a43371b306 7 require 'ostruct'
ram54288 0:a7a43371b306 8 require 'set'
ram54288 0:a7a43371b306 9
ram54288 0:a7a43371b306 10 require 'pp'
ram54288 0:a7a43371b306 11
ram54288 0:a7a43371b306 12 VERSION = 1.0
ram54288 0:a7a43371b306 13
ram54288 0:a7a43371b306 14 class ArgvParser
ram54288 0:a7a43371b306 15
ram54288 0:a7a43371b306 16 #
ram54288 0:a7a43371b306 17 # Return a structure describing the options.
ram54288 0:a7a43371b306 18 #
ram54288 0:a7a43371b306 19 def self.parse(args)
ram54288 0:a7a43371b306 20 # The options specified on the command line will be collected in *options*.
ram54288 0:a7a43371b306 21 # We set default values here.
ram54288 0:a7a43371b306 22 options = OpenStruct.new
ram54288 0:a7a43371b306 23 options.results_dir = "."
ram54288 0:a7a43371b306 24 options.root_path = "."
ram54288 0:a7a43371b306 25 options.out_file = "results.xml"
ram54288 0:a7a43371b306 26
ram54288 0:a7a43371b306 27 opts = OptionParser.new do |opts|
ram54288 0:a7a43371b306 28 opts.banner = "Usage: unity_to_junit.rb [options]"
ram54288 0:a7a43371b306 29
ram54288 0:a7a43371b306 30 opts.separator ""
ram54288 0:a7a43371b306 31 opts.separator "Specific options:"
ram54288 0:a7a43371b306 32
ram54288 0:a7a43371b306 33 opts.on("-r", "--results <dir>", "Look for Unity Results files here.") do |results|
ram54288 0:a7a43371b306 34 #puts "results #{results}"
ram54288 0:a7a43371b306 35 options.results_dir = results
ram54288 0:a7a43371b306 36 end
ram54288 0:a7a43371b306 37
ram54288 0:a7a43371b306 38 opts.on("-p", "--root_path <path>", "Prepend this path to files in results.") do |root_path|
ram54288 0:a7a43371b306 39 options.root_path = root_path
ram54288 0:a7a43371b306 40 end
ram54288 0:a7a43371b306 41
ram54288 0:a7a43371b306 42 opts.on("-o", "--output <filename>", "XML file to generate.") do |out_file|
ram54288 0:a7a43371b306 43 #puts "out_file: #{out_file}"
ram54288 0:a7a43371b306 44 options.out_file = out_file
ram54288 0:a7a43371b306 45 end
ram54288 0:a7a43371b306 46
ram54288 0:a7a43371b306 47 opts.separator ""
ram54288 0:a7a43371b306 48 opts.separator "Common options:"
ram54288 0:a7a43371b306 49
ram54288 0:a7a43371b306 50 # No argument, shows at tail. This will print an options summary.
ram54288 0:a7a43371b306 51 opts.on_tail("-h", "--help", "Show this message") do
ram54288 0:a7a43371b306 52 puts opts
ram54288 0:a7a43371b306 53 exit
ram54288 0:a7a43371b306 54 end
ram54288 0:a7a43371b306 55
ram54288 0:a7a43371b306 56 # Another typical switch to print the version.
ram54288 0:a7a43371b306 57 opts.on_tail("--version", "Show version") do
ram54288 0:a7a43371b306 58 puts "unity_to_junit.rb version #{VERSION}"
ram54288 0:a7a43371b306 59 exit
ram54288 0:a7a43371b306 60 end
ram54288 0:a7a43371b306 61 end
ram54288 0:a7a43371b306 62
ram54288 0:a7a43371b306 63 opts.parse!(args)
ram54288 0:a7a43371b306 64 options
ram54288 0:a7a43371b306 65 end # parse()
ram54288 0:a7a43371b306 66
ram54288 0:a7a43371b306 67 end # class OptparseExample
ram54288 0:a7a43371b306 68
ram54288 0:a7a43371b306 69 class UnityToJUnit
ram54288 0:a7a43371b306 70 include FileUtils::Verbose
ram54288 0:a7a43371b306 71 attr_reader :report, :total_tests, :failures, :ignored
ram54288 0:a7a43371b306 72
ram54288 0:a7a43371b306 73 def initialize
ram54288 0:a7a43371b306 74 @report = ''
ram54288 0:a7a43371b306 75 @unit_name = ''
ram54288 0:a7a43371b306 76 end
ram54288 0:a7a43371b306 77
ram54288 0:a7a43371b306 78 def run
ram54288 0:a7a43371b306 79 # Clean up result file names
ram54288 0:a7a43371b306 80 results = @targets.map {|target| target.gsub(/\\/,"/")}
ram54288 0:a7a43371b306 81 #puts "Output File: #{@out_file}"
ram54288 0:a7a43371b306 82 f = File.new(@out_file, "w")
ram54288 0:a7a43371b306 83 write_xml_header(f)
ram54288 0:a7a43371b306 84 write_suites_header( f )
ram54288 0:a7a43371b306 85 results.each do |result_file|
ram54288 0:a7a43371b306 86 lines = File.readlines(result_file).map { |line| line.chomp }
ram54288 0:a7a43371b306 87 if lines.length == 0
ram54288 0:a7a43371b306 88 raise "Empty test result file: #{result_file}"
ram54288 0:a7a43371b306 89 else
ram54288 0:a7a43371b306 90 result_output = get_details(result_file, lines)
ram54288 0:a7a43371b306 91 tests,failures,ignored = parse_test_summary(lines)
ram54288 0:a7a43371b306 92 result_output[:counts][:total] = tests
ram54288 0:a7a43371b306 93 result_output[:counts][:failed] = failures
ram54288 0:a7a43371b306 94 result_output[:counts][:ignored] = ignored
ram54288 0:a7a43371b306 95 result_output[:counts][:passed] = (result_output[:counts][:total] - result_output[:counts][:failed] - result_output[:counts][:ignored])
ram54288 0:a7a43371b306 96 end
ram54288 0:a7a43371b306 97 #use line[0] from the test output to get the test_file path and name
ram54288 0:a7a43371b306 98 test_file_str = lines[0].gsub("\\","/")
ram54288 0:a7a43371b306 99 test_file_str = test_file_str.split(":")
ram54288 0:a7a43371b306 100 test_file = if (test_file_str.length < 2)
ram54288 0:a7a43371b306 101 result_file
ram54288 0:a7a43371b306 102 else
ram54288 0:a7a43371b306 103 test_file_str[0] + ':' + test_file_str[1]
ram54288 0:a7a43371b306 104 end
ram54288 0:a7a43371b306 105 result_output[:source][:path] = File.dirname(test_file)
ram54288 0:a7a43371b306 106 result_output[:source][:file] = File.basename(test_file)
ram54288 0:a7a43371b306 107
ram54288 0:a7a43371b306 108 # save result_output
ram54288 0:a7a43371b306 109 @unit_name = File.basename(test_file, ".*")
ram54288 0:a7a43371b306 110
ram54288 0:a7a43371b306 111 write_suite_header( result_output[:counts], f)
ram54288 0:a7a43371b306 112 write_failures( result_output, f )
ram54288 0:a7a43371b306 113 write_tests( result_output, f )
ram54288 0:a7a43371b306 114 write_ignored( result_output, f )
ram54288 0:a7a43371b306 115 write_suite_footer( f )
ram54288 0:a7a43371b306 116 end
ram54288 0:a7a43371b306 117 write_suites_footer( f )
ram54288 0:a7a43371b306 118 f.close
ram54288 0:a7a43371b306 119 end
ram54288 0:a7a43371b306 120
ram54288 0:a7a43371b306 121 def set_targets(target_array)
ram54288 0:a7a43371b306 122 @targets = target_array
ram54288 0:a7a43371b306 123 end
ram54288 0:a7a43371b306 124
ram54288 0:a7a43371b306 125 def set_root_path(path)
ram54288 0:a7a43371b306 126 @root = path
ram54288 0:a7a43371b306 127 end
ram54288 0:a7a43371b306 128 def set_out_file(filename)
ram54288 0:a7a43371b306 129 @out_file = filename
ram54288 0:a7a43371b306 130 end
ram54288 0:a7a43371b306 131 def usage(err_msg=nil)
ram54288 0:a7a43371b306 132 puts "\nERROR: "
ram54288 0:a7a43371b306 133 puts err_msg if err_msg
ram54288 0:a7a43371b306 134 puts "Usage: unity_to_junit.rb [options]"
ram54288 0:a7a43371b306 135 puts ""
ram54288 0:a7a43371b306 136 puts "Specific options:"
ram54288 0:a7a43371b306 137 puts " -r, --results <dir> Look for Unity Results files here."
ram54288 0:a7a43371b306 138 puts " -p, --root_path <path> Prepend this path to files in results."
ram54288 0:a7a43371b306 139 puts " -o, --output <filename> XML file to generate."
ram54288 0:a7a43371b306 140 puts ""
ram54288 0:a7a43371b306 141 puts "Common options:"
ram54288 0:a7a43371b306 142 puts " -h, --help Show this message"
ram54288 0:a7a43371b306 143 puts " --version Show version"
ram54288 0:a7a43371b306 144
ram54288 0:a7a43371b306 145 exit 1
ram54288 0:a7a43371b306 146 end
ram54288 0:a7a43371b306 147
ram54288 0:a7a43371b306 148 protected
ram54288 0:a7a43371b306 149 def get_details(result_file, lines)
ram54288 0:a7a43371b306 150 results = get_results_structure
ram54288 0:a7a43371b306 151 lines.each do |line|
ram54288 0:a7a43371b306 152 line = line.gsub("\\","/")
ram54288 0:a7a43371b306 153 src_file,src_line,test_name,status,msg = line.split(/:/)
ram54288 0:a7a43371b306 154 line_out = ((@root and (@root != 0)) ? "#{@root}#{line}" : line ).gsub(/\//, "\\")
ram54288 0:a7a43371b306 155 case(status)
ram54288 0:a7a43371b306 156 when 'IGNORE' then results[:ignores] << {:test => test_name, :line => src_line, :message => msg}
ram54288 0:a7a43371b306 157 when 'FAIL' then results[:failures] << {:test => test_name, :line => src_line, :message => msg}
ram54288 0:a7a43371b306 158 when 'PASS' then results[:successes] << {:test => test_name, :line => src_line, :message => msg}
ram54288 0:a7a43371b306 159 end
ram54288 0:a7a43371b306 160 end
ram54288 0:a7a43371b306 161 return results
ram54288 0:a7a43371b306 162 end
ram54288 0:a7a43371b306 163
ram54288 0:a7a43371b306 164 def parse_test_summary(summary)
ram54288 0:a7a43371b306 165 if summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ }
ram54288 0:a7a43371b306 166 [$1.to_i,$2.to_i,$3.to_i]
ram54288 0:a7a43371b306 167 else
ram54288 0:a7a43371b306 168 raise "Couldn't parse test results: #{summary}"
ram54288 0:a7a43371b306 169 end
ram54288 0:a7a43371b306 170 end
ram54288 0:a7a43371b306 171 def here; File.expand_path(File.dirname(__FILE__)); end
ram54288 0:a7a43371b306 172
ram54288 0:a7a43371b306 173 private
ram54288 0:a7a43371b306 174
ram54288 0:a7a43371b306 175 def get_results_structure
ram54288 0:a7a43371b306 176 return {
ram54288 0:a7a43371b306 177 :source => {:path => '', :file => ''},
ram54288 0:a7a43371b306 178 :successes => [],
ram54288 0:a7a43371b306 179 :failures => [],
ram54288 0:a7a43371b306 180 :ignores => [],
ram54288 0:a7a43371b306 181 :counts => {:total => 0, :passed => 0, :failed => 0, :ignored => 0},
ram54288 0:a7a43371b306 182 :stdout => [],
ram54288 0:a7a43371b306 183 }
ram54288 0:a7a43371b306 184 end
ram54288 0:a7a43371b306 185
ram54288 0:a7a43371b306 186 def write_xml_header( stream )
ram54288 0:a7a43371b306 187 stream.puts "<?xml version='1.0' encoding='utf-8' ?>"
ram54288 0:a7a43371b306 188 end
ram54288 0:a7a43371b306 189
ram54288 0:a7a43371b306 190 def write_suites_header( stream )
ram54288 0:a7a43371b306 191 stream.puts "<testsuites>"
ram54288 0:a7a43371b306 192 end
ram54288 0:a7a43371b306 193
ram54288 0:a7a43371b306 194 def write_suite_header( counts, stream )
ram54288 0:a7a43371b306 195 stream.puts "\t<testsuite errors=\"0\" skipped=\"#{counts[:ignored]}\" failures=\"#{counts[:failed]}\" tests=\"#{counts[:total]}\" name=\"unity\">"
ram54288 0:a7a43371b306 196 end
ram54288 0:a7a43371b306 197
ram54288 0:a7a43371b306 198 def write_failures( results, stream )
ram54288 0:a7a43371b306 199 result = results[:failures]
ram54288 0:a7a43371b306 200 result.each do |item|
ram54288 0:a7a43371b306 201 filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*'))
ram54288 0:a7a43371b306 202 stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\">"
ram54288 0:a7a43371b306 203 stream.puts "\t\t\t<failure message=\"#{item[:message]}\" type=\"Assertion\"/>"
ram54288 0:a7a43371b306 204 stream.puts "\t\t\t<system-err>&#xD;[File] #{filename}&#xD;[Line] #{item[:line]}&#xD;</system-err>"
ram54288 0:a7a43371b306 205 stream.puts "\t\t</testcase>"
ram54288 0:a7a43371b306 206 end
ram54288 0:a7a43371b306 207 end
ram54288 0:a7a43371b306 208
ram54288 0:a7a43371b306 209 def write_tests( results, stream )
ram54288 0:a7a43371b306 210 result = results[:successes]
ram54288 0:a7a43371b306 211 result.each do |item|
ram54288 0:a7a43371b306 212 filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*'))
ram54288 0:a7a43371b306 213 stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\" />"
ram54288 0:a7a43371b306 214 end
ram54288 0:a7a43371b306 215 end
ram54288 0:a7a43371b306 216
ram54288 0:a7a43371b306 217 def write_ignored( results, stream )
ram54288 0:a7a43371b306 218 result = results[:ignores]
ram54288 0:a7a43371b306 219 result.each do |item|
ram54288 0:a7a43371b306 220 filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*'))
ram54288 0:a7a43371b306 221 puts "Writing ignored tests for test harness: #{filename}"
ram54288 0:a7a43371b306 222 stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\">"
ram54288 0:a7a43371b306 223 stream.puts "\t\t\t<skipped message=\"#{item[:message]}\" type=\"Assertion\"/>"
ram54288 0:a7a43371b306 224 stream.puts "\t\t\t<system-err>&#xD;[File] #{filename}&#xD;[Line] #{item[:line]}&#xD;</system-err>"
ram54288 0:a7a43371b306 225 stream.puts "\t\t</testcase>"
ram54288 0:a7a43371b306 226 end
ram54288 0:a7a43371b306 227 end
ram54288 0:a7a43371b306 228
ram54288 0:a7a43371b306 229 def write_suite_footer( stream )
ram54288 0:a7a43371b306 230 stream.puts "\t</testsuite>"
ram54288 0:a7a43371b306 231 end
ram54288 0:a7a43371b306 232
ram54288 0:a7a43371b306 233 def write_suites_footer( stream )
ram54288 0:a7a43371b306 234 stream.puts "</testsuites>"
ram54288 0:a7a43371b306 235 end
ram54288 0:a7a43371b306 236 end #UnityToJUnit
ram54288 0:a7a43371b306 237
ram54288 0:a7a43371b306 238 if __FILE__ == $0
ram54288 0:a7a43371b306 239 #parse out the command options
ram54288 0:a7a43371b306 240 options = ArgvParser.parse(ARGV)
ram54288 0:a7a43371b306 241
ram54288 0:a7a43371b306 242 #create an instance to work with
ram54288 0:a7a43371b306 243 utj = UnityToJUnit.new
ram54288 0:a7a43371b306 244 begin
ram54288 0:a7a43371b306 245 #look in the specified or current directory for result files
ram54288 0:a7a43371b306 246 targets = "#{options.results_dir.gsub(/\\/, '/')}**/*.test*"
ram54288 0:a7a43371b306 247
ram54288 0:a7a43371b306 248 results = Dir[targets]
ram54288 0:a7a43371b306 249 raise "No *.testpass, *.testfail, or *.testresults files found in '#{targets}'" if results.empty?
ram54288 0:a7a43371b306 250 utj.set_targets(results)
ram54288 0:a7a43371b306 251
ram54288 0:a7a43371b306 252 #set the root path
ram54288 0:a7a43371b306 253 utj.set_root_path(options.root_path)
ram54288 0:a7a43371b306 254
ram54288 0:a7a43371b306 255 #set the output XML file name
ram54288 0:a7a43371b306 256 #puts "Output File from options: #{options.out_file}"
ram54288 0:a7a43371b306 257 utj.set_out_file(options.out_file)
ram54288 0:a7a43371b306 258
ram54288 0:a7a43371b306 259 #run the summarizer
ram54288 0:a7a43371b306 260 puts utj.run
ram54288 0:a7a43371b306 261 rescue Exception => e
ram54288 0:a7a43371b306 262 utj.usage e.message
ram54288 0:a7a43371b306 263 end
ram54288 0:a7a43371b306 264 end