From 720acfbb953a6f23803d0242d23fde65b6d131fd Mon Sep 17 00:00:00 2001 From: greg-williams Date: Thu, 7 Feb 2008 03:00:54 +0000 Subject: [PATCH] Initial project population git-svn-id: http://unity.svn.sourceforge.net/svnroot/unity/trunk@1 e7d17a6e-8845-0410-bbbc-c8efb4fdad7e --- auto/unity_test_summary.rb | 203 +++++++++++ docs/Unity Summary.odt | Bin 0 -> 18359 bytes docs/Unity Summary.pdf | Bin 0 -> 99972 bytes docs/Unity Summary.txt | 202 +++++++++++ makefile | 13 + rakefile | 72 ++++ rakefile_helper.rb | 93 ++++++ src/unity.c | 336 +++++++++++++++++++ src/unity.h | 206 ++++++++++++ test/testunity.c | 669 +++++++++++++++++++++++++++++++++++++ test/testunity_Runner.c | 111 ++++++ 11 files changed, 1905 insertions(+) create mode 100644 auto/unity_test_summary.rb create mode 100644 docs/Unity Summary.odt create mode 100644 docs/Unity Summary.pdf create mode 100644 docs/Unity Summary.txt create mode 100644 makefile create mode 100644 rakefile create mode 100644 rakefile_helper.rb create mode 100644 src/unity.c create mode 100644 src/unity.h create mode 100644 test/testunity.c create mode 100644 test/testunity_Runner.c diff --git a/auto/unity_test_summary.rb b/auto/unity_test_summary.rb new file mode 100644 index 0000000..b8fdb61 --- /dev/null +++ b/auto/unity_test_summary.rb @@ -0,0 +1,203 @@ +#!/usr/bin/ruby +# +# unity_test_summary.rb +# +require 'fileutils' +require 'set' + +class UnityTestSummary + + include FileUtils::Verbose + + def run + + $stderr.flush + $stdout.flush + + # Clean up result file names + results = @targets.map {|target| target.gsub(/\\/,'/')} + + # Dig through each result file, looking for details on pass/fail: + total_tests = 0 + total_failures = 0 + total_ignored = 0 + + failure_output = "" + ignore_output = "" + + results.each do |result_file| + lines = File.readlines(result_file).map { |line| line.chomp } + if lines.length == 0 + puts "Empty test result file: #{result_file}" + else + summary_line = -2 + output = get_details(result_file, lines) + failure_output += output[:failures] if !output[:failures].empty? + ignore_output += output[:ignores] if !output[:ignores].empty? + tests,failures,ignored = parse_test_summary(lines[summary_line]) + total_tests += tests + total_failures += failures + total_ignored += ignored + end + end + + if total_ignored > 0 + puts "\n" + puts "--------------------------\n" + puts "UNITY IGNORED TEST SUMMARY\n" + puts "--------------------------\n" + puts ignore_output + end + + if total_failures > 0 + puts "\n" + puts "--------------------------\n" + puts "UNITY FAILED TEST SUMMARY\n" + puts "--------------------------\n" + puts failure_output + end + + puts "\n" + puts "--------------------------\n" + puts "OVERALL UNITY TEST SUMMARY\n" + puts "--------------------------\n" + puts "TOTAL TESTS: #{total_tests} TOTAL FAILURES: #{total_failures} IGNORED: #{total_ignored}\n" + puts "\n" + + return total_failures + end + + def usage(err_msg=nil) + puts err_msg if err_msg + puts "Usage: unity_test_summary.rb" + exit 1 + end + + def set_targets(target_array) + @targets = target_array + end + + def set_root_path(path) + @root = path + puts "root_path = " + @root + end + + protected + + @@targets=nil + @@path=nil + @@root=nil + + def get_details(result_file, lines) + fail_lines = [] # indices of lines with failures + ignore_lines = [] # indices of lines with ignores + lines.each_with_index do |line,i| + if (i < (lines.length - 2) && !(line =~ /PASS$/)) + if line =~ /(^.*\.c):(\d+)/ + if line =~ /IGNORED$/ + ignore_lines << i + else + fail_lines << i + end + elsif line =~ /IGNORED$/ + ignore_lines << i + end + end + end + + failures = [] + fail_lines.each do |fail_line| + if lines[fail_line] =~ /\w:/ + src_file,src_line,test_name,msg = lines[fail_line].split(/:/) + src_file = "#{@root}#{src_file}" unless @root == nil || @root.length == 0 + detail = "#{src_file}:#{src_line}:#{test_name}:: #{msg}" + failures << detail.gsub(/\//, "\\") + end + end + if failures.length == 0 + failure_results = "" + else + failure_results = failures.join("\n") + "\n" + end + + ignores = [] + ignore_lines.each do |ignore_line| + if lines[ignore_line] =~ /\w:/ + src_file,src_line,test_name,msg = lines[ignore_line].split(/:/) + src_file = "#{@root}#{src_file}" unless @root == nil || @root.length == 0 + detail = "#{src_file}:#{src_line}:#{test_name}:: #{msg}" + ignores << detail.gsub(/\//, "\\") + end + end + if ignores.length == 0 + ignore_results = "" + else + ignore_results = ignores.join("\n") + "\n" + end + + results = {:failures => failure_results, :ignores => ignore_results} + end + + def parse_test_summary(summary) + if summary =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ + [$1.to_i,$2.to_i,$3.to_i] + else + raise "Couldn't parse test results: #{summary}" + end + end + + def here; File.expand_path(File.dirname(__FILE__)); end + + def valid_file(fname) + raise "Can't find file #{fname}" unless File.exists?(fname) + fname + end + + def valid_dir(dirname) + raise "Can't find dir #{dirname}" unless File.exists?(dirname) + dirname + end + + def search_file_and_replace(file_name, pattern, replacement) + text = File.read(valid_file(file_name)) + text.gsub!(pattern, replacement) + File.open(file_name, "w") do |f| f.write text end + end + + def create_file_from_template(dest_file, template_file) + raise "#{dest_file} already exists; remove it first" if File.exists?(dest_file) + + template_file = valid_file("#{here}/rscript_template.rb") + template = ERB.new(File.read(template_file)) + + File.open(dest_file,"w") do |f| + f.write template.result(binding) + end + end + + def humanize(lower_case_and_underscored_word) + lower_case_and_underscored_word.to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize + end + + def camelize(lower_case_and_underscored_word) + lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase } + end + + def titleize(word) + humanize(underscore(word)).gsub(/\b([a-z])/) { $1.capitalize } + end + + def underscore(camel_cased_word) + camel_cased_word.to_s.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').gsub(/([a-z\d])([A-Z])/,'\1_\2').downcase + end + +end + +if $0 == __FILE__ + script = UnityTestSummary.new + begin + script.run + rescue Exception => e + script.usage e.message + end +end diff --git a/docs/Unity Summary.odt b/docs/Unity Summary.odt new file mode 100644 index 0000000000000000000000000000000000000000..fb5745e86cdd6cce3ae0767f8be381ee9658bca1 GIT binary patch literal 18359 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 CnZexv literal 0 HcmV?d00001 diff --git a/docs/Unity Summary.pdf b/docs/Unity Summary.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2ddf129c954e10a62c5d30c1612ebb25db1751f7 GIT binary patch literal 99972 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