Guest User

Untitled

a guest
Apr 17th, 2018
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.24 KB | None | 0 0
  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
Add Comment
Please, Sign In to add comment