269 lines
9.9 KiB
Ruby
Executable File
269 lines
9.9 KiB
Ruby
Executable File
#
|
|
# 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 <derek.ward@rockstarnorth.com>
|
|
# 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
|
|
|