# # File:: spit_error.rb # Description:: Error filtration - success logic of a smoke test TTY dump. # # - Takes an input filename, parses it line by line piping what is deemed to be an error to stderr. # - Further, everything that is not an error is piped to stdout. # - File contents that are deemed warnings are wrapped with a warning syntax. # - This is used by the smoke tester. # # Author:: Derek Ward # Date:: 16th October 2009 # # Passed in :- filename to parse # Passed out :- stderr contains all errors # stdout for all other contents of file. # Returns :- returns non zero upon detecting any errors #----------------------------------------------------------------------------- # Uses / Requires #----------------------------------------------------------------------------- #require 'pipeline/log/log' require 'pipeline/os/getopt' include Pipeline #----------------------------------------------------------------------------- # Constants #----------------------------------------------------------------------------- OPTIONS = [ [ "--help", "-h", Getopt::BOOLEAN, "display usage information." ], [ "--errorsarenotfail", "-e", Getopt::BOOLEAN, "Does occurence of an error constitute a fail?" ], [ "--callstack", "-c", Getopt::BOOLEAN, "display callstacks." ], [ "--filename", "-f", Getopt::REQUIRED, "Filename to parse." ] ] REGEXP_EXCEPTION = /(.+)(\*\*\* EXCEPTION |Exception:|detected an interrupt)(.+)/i REGEXP_FATAL_ERROR = /(.+)(Fatal Error)(.+)/i REGEXP_BASIC_ERROR = /(.+)(Error\s:|Error:\s)(.+)/i REGEXP_WARNING = /(.+)(Warning:\s)(.+)/i REGEXP_INFO = /(.+)\[AssetTest\]\s(.+)/i REGEXP_START = /(.+)Smoke Test(.+)started\sDuration\s(-{0,1}\d+)\sCommandLine\s(.+)/i REGEXP_STOP = /(.+)Smoke Test finished/i REGEXP_DESC = /(.+)Smoke Test Description : (.+)/i REGEXP_CALLSTACK = /(.+)\[35m(.+)/ REGEXP_CALLSTACK_EXCLUSION = /(.+)(- notfound|sysIpcThreadWrapper|CommonMain|ExceptMain|Main\(|rage::diagAssertHelper|rage::diagLog|mainCRTStartup)(.+)/ #----------------------------------------------------------------------------- # Application entry point #----------------------------------------------------------------------------- colourise_callstack = "[colourise=grey]" colourise_callstack_inside = "[colourise=red]" colourise_outside = "[colourise=grey]" colourise_info = "[colourise=black]" colourise_ok = "[colourise=green]" colourise_error = "[colourise=red]" lines_read = 0 error_outside_count = 0 warning_outside_count = 0 error_inside_count = 0 warning_inside_count = 0 info_inside_count = 0 info_outside_count = 0 started = false stopped = false inside = "INSIDE SMOKETEST:" outside = "OUTSIDE SMOKETEST:" info = "INFO_MSG: " context_msg_error = "#{colourise_info} ONLY ERRORS *DURING THE SMOKETEST* ARE USED TO DETERMINE IF THIS BUILD FAILED." context_msg_no_error = "#{colourise_info} ERRORS WILL NOT MAKE THIS BUILD FAIL." failed = 0 need_smoke_end = true ignore = "ccignore:" commandline = "" description = nil name = nil duration = nil errorsarefail = true begin #--------------------------------------------------------------------- # Parse Command Line. #--------------------------------------------------------------------- opts, trailing = OS::Getopt.getopts( OPTIONS ) if ( opts['help'] ) puts OS::Getopt.usage( OPTIONS ) puts ("Press Enter to continue...") $stdin.getc( ) exit( 1 ) end if ( opts['errorsarenotfail'] ) errorsarefail = false end #--------------------------------------------------------------------- # Parse file. #--------------------------------------------------------------------- if ( opts['filename'] ) filename = opts['filename'] lines = [] file = File.new(filename, "r") while (line = file.gets) lines << line end file.close lines.each_with_index do |line,line_idx| if ( line =~ REGEXP_START) started = true name = $2.to_s duration = $3.to_i commandline = $4.to_s need_smoke_end = false if duration <= 0 end if ( line =~ REGEXP_DESC) description = $2.to_s end lines_read += 1 is_inside = (started and not stopped) is_info = ( line =~ REGEXP_INFO or line.include? "Player pos" or line.include? "Camera pos" or line.include? "Camera dir" or line.include? "[Script_AUTOPLAY]") is_warning = line =~ REGEXP_WARNING is_error = ( line =~ REGEXP_EXCEPTION or line =~ REGEXP_FATAL_ERROR or line =~ REGEXP_BASIC_ERROR ) is_callstack = line =~ REGEXP_CALLSTACK # determine if for an error or a warning?! callstack_warning = "" callstack_prefix = "" callstack_colourise = "" is_callstack = false if ( is_callstack and line =~ REGEXP_CALLSTACK_EXCLUSION ) is_callstack = false unless opts['callstack'] if (is_callstack and not (is_error or is_warning) ) callstack_colourise = colourise_callstack callstack_colourise_inside = colourise_callstack_inside lines[line_idx..-1].each do |search_line| callstack_prefix = " ***CALLSTACK*** " is_warning = ( search_line =~ REGEXP_WARNING ) is_error = ( search_line =~ REGEXP_EXCEPTION or search_line =~ REGEXP_FATAL_ERROR or search_line =~ REGEXP_BASIC_ERROR ) if (is_error) break elsif (is_warning) callstack_warning = "Warning:" break end end if (not is_error and (not is_warning) ) is_error = true end end if ( is_error ) if error_inside_count == 0 and error_outside_count == 0 if (not is_callstack) $stderr.puts context_msg_error if errorsarefail $stderr.puts context_msg_no_error unless errorsarefail end end if ( is_inside ) $stderr.puts "#{callstack_colourise_inside} #{lines_read}: #{line}" puts "#{callstack_colourise_inside} #{lines_read}: #{ignore} #{line}" error_inside_count += 1 unless (is_callstack) else $stderr.puts "#{callstack_colourise}#{callstack_prefix}#{outside} #{colourise_outside} #{lines_read}: #{line}" puts "#{callstack_colourise}#{callstack_prefix}#{outside} #{lines_read}: #{ignore} #{line}" error_outside_count += 1 unless (is_callstack) end elsif ( is_warning ) if ( is_inside ) puts "#{callstack_colourise}#{callstack_prefix}#{inside} #{lines_read}: #{callstack_warning} #{line}" warning_inside_count += 1 unless (is_callstack) else puts "#{callstack_colourise}#{callstack_prefix}#{outside} #{colourise_outside} #{lines_read}: #{callstack_warning} #{line}" warning_outside_count += 1 unless (is_callstack) end elsif ( is_info ) if (is_inside ) puts "#{callstack_colourise}#{callstack_prefix}#{inside} #{info} #{colourise_info} #{lines_read}: #{line}" info_inside_count += 1 unless (is_callstack) else puts "#{callstack_colourise}#{callstack_prefix}#{outside} #{colourise_outside} #{info} #{lines_read}: #{line}" info_outside_count += 1 unless (is_callstack) end else if (is_inside ) puts "#{callstack_colourise}#{callstack_prefix}#{inside} #{lines_read}: #{line}" else puts "#{callstack_colourise}#{callstack_prefix}#{outside} #{lines_read}: #{line}" end end stopped = true if ( line =~ REGEXP_STOP ) end failed = -1 if (error_inside_count > 0 and errorsarefail) failed = -1 if not started puts "#{info} #{colourise_info} ******** SMOKETEST SUMMARY ********" puts "#{info} #{colourise_info} Smoke name : #{name}" if name puts "#{info} #{colourise_info} Smoke description : #{description}" if description puts "#{info} #{colourise_info} Smoke duration was ~#{duration} seconds." if duration puts "#{info} #{colourise_info} Smoke has No end criteria." unless need_smoke_end puts "#{info} #{colourise_info} Smoke has end criteria." if need_smoke_end puts "#{info} #{colourise_info} Started #{started}, Stopped #{stopped}." puts "#{info} #{colourise_info} Read #{lines_read} lines." puts "#{info} #{colourise_info} CommandLine for repro: #{commandline}" puts "#{info} #{colourise_info} Result (Outside of test) #{error_outside_count} errors #{warning_outside_count} warnings #{info_outside_count} infos. ( these do not effect the notion of success / failure in the build )" puts "#{info} #{colourise_ok} **** THE SMOKE TEST RAN TO COMPLETION. ****" if started and stopped if not started $stderr.puts "Error: **** THE SMOKE TEST DID NOT START. ****" puts "Error: #{ignore} **** THE SMOKE TEST DID NOT START. ****" puts "#{info} #{colourise_error} **** THE SMOKE TEST DID NOT START. ****" failed = -1 end if need_smoke_end and started and not stopped $stderr.puts "Error: **** THE SMOKE TEST STARTED BUT DID NOT COMPLETE. ****" puts "Error: #{ignore} **** THE SMOKE TEST STARTED BUT DID NOT COMPLETE. ****" puts "#{info} #{colourise_error} **** THE SMOKE TEST STARTED BUT DID NOT COMPLETE. ****" failed = -1 end colour = (error_inside_count>0 and errorsarefail) ? "#{colourise_error}" : "#{colourise_info}" str = errorsarefail ? "" : "( these do not effect the notion of success / failure in the build )" puts "#{info} #{colour} Result (INSIDE of test) #{error_inside_count} errors #{warning_inside_count} warnings #{info_inside_count} infos. #{str}" puts "#{info} #{colourise_ok} BUILD OK" if failed == 0 puts "#{info} #{colourise_error} BUILD FAILED" unless failed == 0 puts "#{info} #{colourise_info} ******** END SMOKETEST SUMMARY ********" end rescue Exception => ex $stderr.puts "Unhandled exception: #{ex.message}" $stderr.puts "Backtrace:" ex.backtrace.each { |m| $stderr.puts "\t#{m}" } exit -1 end exit failed