Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env ruby
- # vim: encoding=utf-8 filetype=ruby
- require 'rubygems'
- require 'optparse'
- require 'yaml'
- options = YAML.load(<<CONF)
- color: true
- verbose: false
- target: 'UnitTest'
- config: 'Release'
- sdkversion: '3.0'
- format: 'simple'
- CONF
- if FileTest.exist?('.rocurc')
- options.merge!(YAML.load_file('.rocurc'))
- end
- OptionParser.new { |opt|
- opt.on('-o','--options=FILE') { |f| options.merge!(YAML.load_file(f)) }
- opt.on('--[no-]color') { |c| options['color'] = c }
- opt.on('--[no-]verbose') { |v| options['verbose'] = v }
- opt.on('-t','--target=TARGET') { |t| options['target'] = t }
- opt.on('--sdk-version=VERSION') { |v| options['sdkversion'] = v }
- opt.on('-f','--format=FORMAT') { |f| options['format'] = v }
- opt.parse!(ARGV)
- }
- TESTCMD = "xcodebuild -target #{options['target']} -configuration #{options['config']} -sdk iphonesimulator#{options['sdkversion']} 2>&1"
- module DummyANSIColor
- def bold; self; end
- def negative; self; end
- def red; self; end
- def green; self; end
- def yellow; self; end
- def blue; self; end
- end
- if options['color']
- begin
- require 'term/ansicolor'
- class String
- include Term::ANSIColor
- end
- rescue LoadError
- warn "#{$0} depends on Term::ANSIColor!"
- end
- end
- unless String.instance_methods.include?(:bold)
- class String
- include DummyANSIColor
- end
- end
- module XBTools
- class Filter
- Terminator = /\A\*\* BUILD/
- def self.process(io, opts={})
- new(io, opts).process
- end
- def initialize(io,opts={})
- @input = io
- @log = []
- @opts = opts
- end
- def parse
- line = @input.gets
- case line
- when Terminator
- false
- else
- @log.push({ :message => line, :type => :unknown })
- end
- end
- def fold
- @log.map{ |l|
- line = l[:position] ? "#{l[:message]} (#{l[:position]})" : l[:message]
- line = case l[:type]
- when :header then line.bold
- when :passed then line.green
- when :failed then line.red
- else line end
- line = case l[:level]
- when :error then line.red.bold
- when :warning then line.yellow
- else line end
- l[:negative] ? line.negative : line
- }.join("\n")
- end
- def process
- while parse; end
- fold
- end
- end
- class BuildFilter < XBTools::Filter
- Terminator = /\APhaseScriptExecution/
- def initialize(io,opts={})
- super
- @in_submsg = false
- end
- def parse
- return false unless super
- line = @log.pop
- return false unless line
- case line[:message]
- when /\A(?:#{Dir.pwd}\/)?(.+); In function (.+)/
- @log.push( :message => $2, :position => $1, :type => :info )
- when /\A(?:#{Dir.pwd}\/)?(.+[0-9]+): (warning|error): (.+)/
- pos = $1
- level = $2.intern
- msg = $3
- if @in_submsg
- @log.last[:message] << msg
- @in_submsg = false if msg =~ /\)(\n|\z)/
- elsif msg =~ /\A\(/
- @log.last[:message] << ' ' << msg
- @in_submsg = true
- else
- @log.push( :message => msg, :position => pos, :level => level )
- end
- when Terminator
- return false
- end
- true
- end
- end
- class OCUnitFilter < Filter
- def initialize(io,opts={})
- super
- @in_subtest = false
- @failures = []
- @opts[:format] ||= 'simple'
- end
- def fold
- if @opts[:format] == 'specdoc'
- super
- else
- log = {}
- current = ''
- result = nil
- if (@log.last)[:message] =~ /Executed/
- result = @log.pop
- end
- @log.each do |l|
- if l[:type] == :header
- current = l[:message]
- log[current] = {
- :results => [],
- :errors => []
- }
- else
- section = log[current]
- if !!section
- msg = l[:position] ? "#{l[:message]} (#{l[:position]})" : l[:message]
- msg.gsub!(/\t/,'') unless msg.nil?
- case l[:type]
- when :passed
- section[:results] << '.'.green
- when :failed
- section[:results] << 'E'.red
- section[:errors] << msg.red.bold
- else
- case l[:level]
- when :error
- section[:errors] << msg.red.bold
- when :warning
- section[:errors] << msg.yellow
- end
- end
- end
- end
- end
- output = ""
- errors = []
- log.each_pair do |key,val|
- output << val[:results].join('')
- unless val[:errors].empty?
- errors << [key.bold, *val[:errors]].join("\n")
- end
- end
- output = "#{output}\n\n#{errors.join("\n\n")}"
- output << "\n\n#{(result[:type] == :passed ? result[:message].green : result[:message].red).negative}" if !!result
- output
- end
- end
- def parse
- return false unless super
- line = @log.pop
- return false unless line
- case line[:message]
- when /\A(?:#{Dir.pwd}\/)?(.+[0-9]+): error: -\[.+\] : (.+)/
- pos = $1
- msg = $2
- if @failures.last && @failures.last[:type] == 'assert' && !@failures.last[:message]
- @failures.last[:message] = "Assertion failure. #{msg} (#{@failures.last[:position]})"
- elsif pos =~ /Unknown.m:0/
- @failures << { :type => 'runtime', :message => msg }
- else
- @failures << { :type => 'test', :message => "#{msg} (#{pos})" }
- end
- when /\*\*\* Assertion failure in (?:-|\+)\[.+\], (?:#{Dir.pwd}\/)?(.+)/
- @failures.push( :type => 'assert', :position => $1 )
- when /\AExecuted/
- if @in_subtest
- @in_subtest = false
- else
- msg = line[:message]
- @log.push(
- :message => msg,
- :type => msg =~ /with 0 failure/ ? :passed : :failed,
- :negative => true
- )
- end
- when /\ATest Suite '([a-zA-Z0-9]+)' started/
- @log.push( :message => "#{$1}:", :type => :header )
- @in_subtest = true
- when /\ATest Suite '(.+)' started/
- @log.push( :message => "#{$1}:", :type => :header )
- when /\ATest Case '(-\[.+\])' passed/
- @log.push( :message => "\t#{$1}", :type => :passed )
- when /\ATest Case '(-\[.+\])' failed/
- @log.push( :message => "\t#{$1}", :type => :failed )
- @failures.each do |assert|
- case assert[:type]
- when 'test'
- @log.push( :message => "\t\t#{assert[:message]}", :type => :failed )
- when 'assert'
- @log.push( :message => "\t\t#{assert[:message]}", :level => :warning )
- when 'runtime'
- @log.push( :message => "\t\t#{assert[:message]}", :level => :error )
- end
- end
- @failures = []
- when /\ATest Suite '.+' finished/
- @log.push( :message => 'All test finished.' ) unless @in_subtest
- end
- true
- end
- def message(m)
- end
- private :message
- end
- end
- if $0 == __FILE__
- IO.popen(TESTCMD) { |io|
- puts '=== BUILD PHASE ==='
- puts XBTools::BuildFilter.process(io)
- puts '=== TEST PHASE ==='
- puts XBTools::OCUnitFilter.process(io, :format => options['format'])
- }
- end
Add Comment
Please, Sign In to add comment