daily pastebin goal
75%
SHARE
TWEET

Untitled

a guest Apr 17th, 2018 46 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env ruby
  2. # vim: encoding=utf-8 filetype=ruby
  3.  
  4. require 'rubygems'
  5. require 'optparse'
  6. require 'yaml'
  7.  
  8. options = YAML.load(<<CONF)
  9. color:      true
  10. verbose:    false
  11. target:     'UnitTest'
  12. config:     'Release'
  13. sdkversion: '3.0'
  14. format:     'simple'
  15. CONF
  16.  
  17. if FileTest.exist?('.rocurc')
  18.   options.merge!(YAML.load_file('.rocurc'))
  19. end
  20.  
  21. OptionParser.new { |opt|
  22.   opt.on('-o','--options=FILE')   { |f| options.merge!(YAML.load_file(f)) }
  23.   opt.on('--[no-]color')          { |c| options['color'] = c }
  24.   opt.on('--[no-]verbose')        { |v| options['verbose'] = v }
  25.   opt.on('-t','--target=TARGET')  { |t| options['target'] = t }
  26.   opt.on('--sdk-version=VERSION') { |v| options['sdkversion'] = v }
  27.   opt.on('-f','--format=FORMAT')  { |f| options['format'] = v }
  28.  
  29.   opt.parse!(ARGV)
  30. }
  31.  
  32. TESTCMD = "xcodebuild -target #{options['target']} -configuration #{options['config']} -sdk iphonesimulator#{options['sdkversion']} 2>&1"
  33.  
  34. module DummyANSIColor
  35.   def bold; self; end
  36.   def negative; self; end
  37.   def red; self; end
  38.   def green; self; end
  39.   def yellow; self; end
  40.   def blue; self; end
  41. end
  42.  
  43. if options['color']
  44.   begin
  45.     require 'term/ansicolor'
  46.     class String
  47.       include Term::ANSIColor
  48.     end
  49.   rescue LoadError
  50.     warn "#{$0} depends on Term::ANSIColor!"
  51.   end
  52. end
  53.  
  54. unless String.instance_methods.include?(:bold)
  55.   class String
  56.     include DummyANSIColor
  57.   end
  58. end
  59.  
  60. module XBTools
  61.   class Filter
  62.     Terminator = /\A\*\* BUILD/
  63.  
  64.     def self.process(io, opts={})
  65.       new(io, opts).process
  66.     end
  67.  
  68.     def initialize(io,opts={})
  69.       @input = io
  70.       @log   = []
  71.       @opts  = opts
  72.     end
  73.  
  74.     def parse
  75.       line = @input.gets
  76.       case line
  77.       when Terminator
  78.         false
  79.       else
  80.         @log.push({ :message => line, :type => :unknown })
  81.       end
  82.     end
  83.  
  84.     def fold
  85.       @log.map{ |l|
  86.         line = l[:position] ? "#{l[:message]} (#{l[:position]})" : l[:message]
  87.         line = case l[:type]
  88.                when :header then line.bold
  89.                when :passed then line.green
  90.                when :failed then line.red
  91.                else line end
  92.         line = case l[:level]
  93.                when :error   then line.red.bold
  94.                when :warning then line.yellow
  95.                else line end
  96.         l[:negative] ? line.negative : line
  97.       }.join("\n")
  98.     end
  99.  
  100.     def process
  101.       while parse; end
  102.       fold
  103.     end
  104.   end
  105.  
  106.   class BuildFilter < XBTools::Filter
  107.     Terminator = /\APhaseScriptExecution/
  108.  
  109.     def initialize(io,opts={})
  110.       super
  111.       @in_submsg = false
  112.     end
  113.  
  114.     def parse
  115.       return false unless super
  116.       line = @log.pop
  117.       return false unless line
  118.       case line[:message]
  119.       when /\A(?:#{Dir.pwd}\/)?(.+); In function (.+)/
  120.         @log.push( :message => $2, :position => $1, :type => :info )
  121.       when /\A(?:#{Dir.pwd}\/)?(.+[0-9]+): (warning|error): (.+)/
  122.         pos   = $1
  123.         level = $2.intern
  124.         msg   = $3
  125.         if @in_submsg
  126.           @log.last[:message] << msg
  127.           @in_submsg = false if msg =~ /\)(\n|\z)/
  128.         elsif msg =~ /\A\(/
  129.           @log.last[:message] << ' ' << msg
  130.           @in_submsg = true
  131.         else
  132.           @log.push( :message => msg, :position => pos, :level => level )
  133.         end
  134.       when Terminator
  135.         return false
  136.       end
  137.       true
  138.     end
  139.   end
  140.  
  141.   class OCUnitFilter < Filter
  142.     def initialize(io,opts={})
  143.       super
  144.       @in_subtest = false
  145.       @failures   = []
  146.       @opts[:format] ||= 'simple'
  147.     end
  148.  
  149.     def fold
  150.       if @opts[:format] == 'specdoc'
  151.         super
  152.       else
  153.         log     = {}
  154.         current = ''
  155.         result  = nil
  156.         if (@log.last)[:message] =~ /Executed/
  157.           result = @log.pop
  158.         end
  159.         @log.each do |l|
  160.           if l[:type] == :header
  161.             current = l[:message]
  162.             log[current] = {
  163.               :results => [],
  164.               :errors  => []
  165.             }
  166.           else
  167.             section = log[current]
  168.             if !!section
  169.               msg = l[:position] ? "#{l[:message]} (#{l[:position]})" : l[:message]
  170.               msg.gsub!(/\t/,'') unless msg.nil?
  171.               case l[:type]
  172.               when :passed
  173.                 section[:results] << '.'.green
  174.               when :failed
  175.                 section[:results] << 'E'.red
  176.                 section[:errors]  << msg.red.bold
  177.               else
  178.                 case l[:level]
  179.                 when :error
  180.                   section[:errors] << msg.red.bold
  181.                 when :warning
  182.                   section[:errors] << msg.yellow
  183.                 end
  184.               end
  185.             end
  186.           end
  187.         end
  188.         output = ""
  189.         errors = []
  190.         log.each_pair do |key,val|
  191.           output << val[:results].join('')
  192.           unless val[:errors].empty?
  193.             errors << [key.bold, *val[:errors]].join("\n")
  194.           end
  195.         end
  196.         output = "#{output}\n\n#{errors.join("\n\n")}"
  197.         output << "\n\n#{(result[:type] == :passed ? result[:message].green : result[:message].red).negative}" if !!result
  198.         output
  199.       end
  200.     end
  201.  
  202.     def parse
  203.       return false unless super
  204.       line = @log.pop
  205.       return false unless line
  206.       case line[:message]
  207.       when /\A(?:#{Dir.pwd}\/)?(.+[0-9]+): error: -\[.+\] : (.+)/
  208.         pos = $1
  209.         msg = $2
  210.         if @failures.last && @failures.last[:type] == 'assert' && !@failures.last[:message]
  211.           @failures.last[:message] = "Assertion failure. #{msg} (#{@failures.last[:position]})"
  212.         elsif pos =~ /Unknown.m:0/
  213.           @failures << { :type => 'runtime', :message => msg }
  214.         else
  215.           @failures << { :type => 'test', :message => "#{msg} (#{pos})" }
  216.         end
  217.       when /\*\*\* Assertion failure in (?:-|\+)\[.+\], (?:#{Dir.pwd}\/)?(.+)/
  218.         @failures.push( :type => 'assert', :position => $1 )
  219.       when /\AExecuted/
  220.         if @in_subtest
  221.           @in_subtest = false
  222.         else
  223.           msg = line[:message]
  224.           @log.push(
  225.             :message  => msg,
  226.             :type     => msg =~ /with 0 failure/ ? :passed : :failed,
  227.             :negative => true
  228.           )
  229.         end
  230.       when /\ATest Suite '([a-zA-Z0-9]+)' started/
  231.         @log.push( :message => "#{$1}:", :type => :header )
  232.         @in_subtest = true
  233.       when /\ATest Suite '(.+)' started/
  234.         @log.push( :message => "#{$1}:", :type => :header )
  235.       when /\ATest Case '(-\[.+\])' passed/
  236.         @log.push( :message => "\t#{$1}", :type => :passed )
  237.       when /\ATest Case '(-\[.+\])' failed/
  238.         @log.push( :message => "\t#{$1}", :type => :failed )
  239.         @failures.each do |assert|
  240.           case assert[:type]
  241.           when 'test'
  242.             @log.push( :message => "\t\t#{assert[:message]}", :type => :failed )
  243.           when 'assert'
  244.             @log.push( :message => "\t\t#{assert[:message]}", :level => :warning )
  245.           when 'runtime'
  246.             @log.push( :message => "\t\t#{assert[:message]}", :level => :error )
  247.           end
  248.         end
  249.         @failures = []
  250.       when /\ATest Suite '.+' finished/
  251.         @log.push( :message => 'All test finished.' ) unless @in_subtest
  252.       end
  253.       true
  254.     end
  255.  
  256.     def message(m)
  257.     end
  258.     private :message
  259.   end
  260. end
  261.  
  262. if $0 == __FILE__
  263.   IO.popen(TESTCMD) { |io|
  264.     puts '=== BUILD PHASE ==='
  265.     puts XBTools::BuildFilter.process(io)
  266.     puts '=== TEST PHASE ==='
  267.     puts XBTools::OCUnitFilter.process(io, :format => options['format'])
  268.   }
  269. end
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top