Files
gtav-src/tools_ng/script/coding/protection/launcherTester/launcherTester.rb
T
2025-09-29 00:52:08 +02:00

1546 lines
55 KiB
Ruby
Executable File

require 'getoptlong'
require 'Logger'
require 'singleton'
require 'fileutils'
require 'net/ftp'
require 'net/smtp'
require 'iconv'
require 'erb'
include ERB::Util
# Setting up
RAGE_DIR = ENV['RAGE_DIR'].gsub(/\\/, "/")
RS_CODEBRANCH = ENV['RS_CODEBRANCH'].gsub(/\\/, "/")
RS_BUILDBRANCH = ENV['RS_BUILDBRANCH'].gsub(/\\/, "/")
RS_TOOLSROOT = ENV['RS_TOOLSROOT'].gsub(/\\/, "/")
RS_TITLE = ENV['RS_TITLE']
USER_PROFILE = ENV['USERPROFILE']
USER_DESKTOP = USER_PROFILE + "/Desktop"
USERNAME = ENV['USERNAME']
USER_LOG_PATH = USER_PROFILE + "/Documents/Rockstar Games/GTA V"
GAME = "GTAV"
PROTECTION_PATH = RS_TOOLSROOT + "/script/coding/protection"
TOOL_PATH = PROTECTION_PATH + "/launcherTester"
GENERATED_PATH = PROTECTION_PATH + "/generated"
CURR_TIME = Time.now.strftime("%Y%m%d.%H.%M.%S")
LOG_SEVERITY_LEVEL = Logger::INFO
DEFAULT_RELEASE = ""
DEFAULT_SKIP_BUILDS = false
DEFAULT_USERNAME = ""
DEFAULT_PASSWORD = ""
PATCHBUILDER_DIR = RS_CODEBRANCH + "/extra/patchbuilder"
PATCHBUILDER_DATA_DIR = PATCHBUILDER_DIR + "/Data/"
PATCHBUILDER_OUTPUT_DIR = PATCHBUILDER_DIR + "/Output/"
GAME_DIR = "C:/Program Files/Rockstar Games/Grand Theft Auto V/"
OLD_PATCH = "1.0.0.0"
OLD_PATCH_REGEX = "1([._,])0([._,])0([._,])0"
NEW_PATCH_UNDERSCORE = "1_0_0_1"
NEW_PATCH_REGEX = "1\\10\\10\\11"
OLD_XML_FILE = "launcher_version.xml"
NEW_XML_FILE = "launcher_version.testing.#{USERNAME}.xml"
PROGFILESX86 = ENV['ProgramFiles(x86)'].gsub(/\\/, "/")
SIGNTOOL_DIR = PROGFILESX86 + "/Windows Kits/8.0/bin/x86/"
$LOG_DIR = "C:/"
$SHOW_ERROR_DELAY = 500
# Clearing out our data directory, as we don't need it any more. We do this ahead of the creation, so the directory will be there for when we need to write to it.
FileUtils.rm_rf("#{PATCHBUILDER_DATA_DIR}")
# Then our generated paths
def safecreatepath(path)
begin
FileUtils.mkdir_p(path) unless File.exists?(path)
rescue Exception =>e
puts e.message
end
end
safecreatepath(GENERATED_PATH)
safecreatepath(PATCHBUILDER_OUTPUT_DIR)
safecreatepath(PATCHBUILDER_DATA_DIR)
safecreatepath(PROTECTION_PATH)
class Parameters
attr_reader :release
attr_reader :skipbuilds
attr_reader :skipupload
attr_reader :username
attr_reader :password
attr_reader :emailfrom
attr_reader :emailto
attr_reader :yes
attr_reader :showerror
attr_reader :errorsonly
attr_reader :noerrors
attr_reader :preloader
def initialize
@release = DEFAULT_RELEASE #nil
@skipbuilds = DEFAULT_SKIP_BUILDS
@skipupload = DEFAULT_SKIP_BUILDS
@username = DEFAULT_USERNAME
@password = DEFAULT_PASSWORD
@emailfrom = ""
@emailto = ""
@yes = false
@showerror = false
@errorsonly = false
@noerrors = false
@preloader = false
@opts = GetoptLong.new(
[ '--release', '-r', GetoptLong::REQUIRED_ARGUMENT ],
[ '--username', '-u', GetoptLong::REQUIRED_ARGUMENT ],
[ '--password', '-p', GetoptLong::REQUIRED_ARGUMENT ],
[ '--skipbuild', '-s', GetoptLong::NO_ARGUMENT ],
[ '--skipupload', '-k', GetoptLong::NO_ARGUMENT ],
[ '--emailfrom', '-e', GetoptLong::REQUIRED_ARGUMENT ],
[ '--emailto', '-t', GetoptLong::REQUIRED_ARGUMENT ],
[ '--always-yes', '-y', GetoptLong::NO_ARGUMENT ],
[ '--showerror', '-o', GetoptLong::NO_ARGUMENT ],
[ '--errorsonly', '-z', GetoptLong::NO_ARGUMENT ],
[ '--noerrors', '-x', GetoptLong::NO_ARGUMENT ],
[ '--logdir', '-l', GetoptLong::REQUIRED_ARGUMENT ],
[ '--errordelay', '-d', GetoptLong::REQUIRED_ARGUMENT ],
[ '--preloader', '-h', GetoptLong::NO_ARGUMENT ]
)
end
def PrintHelp()
RsgLog.instance().info("DNE Yet");
end
def ParseArguments()
@opts.each do |opt, arg|
case opt
when '--help'
PrintHelp()
exit
when '--skipbuild'
@skipbuilds = true
when '--skipupload'
@skipupload = true
when '--always-yes'
@yes = true;
when '--username'
@username = arg
when '--password'
@password = arg
when '--emailfrom'
@emailfrom = arg
when '--emailto'
@emailto = arg
when '--showerror'
@showerror = true
when '--errorsonly'
@errorsonly = true
when '--noerrors'
@noerrors = true
when '--preloader'
@preloader = true
when '--logdir'
$LOG_DIR = arg
when '--errordelay'
$SHOW_ERROR_DELAY = arg
when '--release'
case arg
when /release/i,/bankrelease/i,/debug/i,/final/i,/beta/i, /master/i
@release = arg
else
RsgLog.instance().error("Invalid release [#{arg}] specified")
exit
end
end
end
end
end
class MultiDelegator
def initialize(*targets)
@targets = targets
end
def self.delegate(*methods)
methods.each do |m|
define_method(m) do |*args|
@targets.map { |t| t.send(m, *args) }
end
end
self
end
class <<self
alias to new
end
end
class RsgLog
include Singleton
attr_accessor :log
def initialize()
log_file = File.open(GENERATED_PATH + "/" + CURR_TIME + ".log", "w")
@log = Logger.new MultiDelegator.delegate(:write, :close).to(STDOUT, log_file)
@log.datetime_format = "%Y%m%d-%H:%M:%S"
@log.level = LOG_SEVERITY_LEVEL
@log.formatter = proc do |serverity, time, progname, msg|
"[#{time.strftime(@log.datetime_format)}]\t[#{serverity}]\t#{msg}"
end
end
def info(msg, newline=true)
if newline == true
msg = msg + "\n"
end
@log.info(msg)
end
def debug(msg, newline=true)
if newline == true
msg = msg + "\n"
end
@log.debug(msg)
end
def warn(msg, newline=true)
if newline == true
msg = msg + "\n"
end
@log.warn(msg)
end
def error(msg, newline=true)
if newline == true
msg = msg + "\n"
end
@log.error(msg)
end
def SetLevel(level)
@log.level = level
end
end
class LauncherTestPerforceHandler
include Singleton
attr_reader :verbose
def initialize()
@depotArray = Array.new
@depotArray.push("//depot/gta5/src/dev_ng/extra/launcher/Bootstrap/Bootstrap.rc")
@depotArray.push("//depot/gta5/src/dev_ng/extra/launcher/Launcher/Launcher.rc")
@depotArray.push("//depot/gta5/src/dev_ng/extra/launcher/Launcher/res/launcher_config.xml")
FileUtils.cp("#{RS_CODEBRANCH}/extra/launcher/Launcher/res/launcher_config.xml", "#{GENERATED_PATH}/#{CURR_TIME}.launcher_config.xml")
end
def Revert()
@depotArray.each { |x|
cmd = "p4 revert #{x}"
output = `#{cmd}`
RsgLog.instance().debug(output)
}
end
def Edit()
@depotArray.each { |x|
cmd = "p4 edit #{x}"
output = `#{cmd}`
RsgLog.instance().debug(output)
}
end
end
def ReplaceTokenInFile(filename, oldString, newString)
text = File.read(filename)
newContents = text.gsub(/#{oldString}/, newString)
# To write changes to the file, use:
File.open(filename, "w") {|file| file.puts newContents }
end
def CleanSolution(slnPath, release)
system("\"C:\\Program Files (x86)\\Xoreax\\IncrediBuild\\BuildConsole.exe\" #{slnPath} /clean /Silent /cfg=\"#{release}|x64\"")
if $?.exitstatus !=0
log.error("Danger Will Robinson! Error found. Exiting!")
exit
end
end
def BuildSolution(slnPath, release)
system("\"C:\\Program Files (x86)\\Xoreax\\IncrediBuild\\BuildConsole.exe\" #{slnPath} /build /Silent /cfg=\"#{release}|x64\"")
if $?.exitstatus !=0
log.error("Danger Will Robinson! Error found. Exiting!")
exit
end
end
def ProcessConfiguration(slnPath, release)
# Call all the functionality needed to do one clean / build
CleanSolution(slnPath,release)
BuildSolution(slnPath,release)
end
def ProtectIT(lorp, release, preloader)
cmd = "ruby #{RS_TOOLSROOT}\\script\\coding\\protection\\ProtectIT.rb -r #{release} -f -v -g "
if preloader == true
RsgLog.instance().info("Preloader Iteration Detected!")
if lorp == "launcher"
cmd+="#{RS_TOOLSROOT}\\script\\coding\\protection\\preloaderlauncher.gsml"
elsif lorp == "bootstrap"
cmd+="#{RS_TOOLSROOT}\\script\\coding\\protection\\preloaderbootstrap.gsml"
end
else
RsgLog.instance().info("Regular Iteration Detected!")
if lorp == "launcher"
cmd+="#{RS_TOOLSROOT}\\script\\coding\\protection\\launcher.gsml"
elsif lorp == "bootstrap"
cmd+="#{RS_TOOLSROOT}\\script\\coding\\protection\\prelauncher.gsml"
end
end
system(cmd)
if $?.exitstatus !=0
RsgLog.instance().error("Danger Will Robinson! Error found. Exiting!")
exit
end
end
def GetMostRecentFile()
returnFile = Dir.glob("#{RS_TOOLSROOT}/script/coding/protection/generated/*.exe").max_by {|f| File.mtime(f)}
if returnFile.empty?
RsgLog.instance().error("Most recent file came back empty. Exiting.")
exit
end
# Now lets sign the protected executable, whatever we're fetching
SignFile(returnFile)
# Return the signed protected file
return returnFile
end
def SignFile(path)
pfxPath = "#{RS_CODEBRANCH}/rage/suite/src/rgsc/rockstar.pfx"
cmd = "#{PROGFILESX86}/signtool.exe sign /f #{pfxPath} /p uci5eNJRxv! /t http://timestamp.verisign.com/scripts/timstamp.dll /v #{path}"
system(cmd)
end
def ShoveIntoDataDirectory(pathToPatch)
end
def DeleteSomeFiles()
# Deleting some local RPFs to test the downloading of pipes
RsgLog.instance().info("Deleting some local RPF files...")
begin
FileUtils.rm("#{GAME_DIR}/x64a.rpf")
FileUtils.rm("#{GAME_DIR}/x64b.rpf")
FileUtils.rm("#{GAME_DIR}/x64c.rpf")
FileUtils.rm("#{GAME_DIR}/x64d.rpf")
rescue
end
# Deleting game executable to test the downloading of patches
RsgLog.instance().info("Deleting the local game exe...")
begin
FileUtils.rm("#{GAME_DIR}/gta5.exe")
rescue
end
end
# </loggingSetup>
log = RsgLog.instance()
# Banner
log.info("=======================")
log.info("Launcher Testing Script")
log.info("=======================")
log.info("Parsing arguments...")
parameters = Parameters.new
parameters.ParseArguments()
if !parameters.skipupload && !parameters.showerror && !parameters.errorsonly
if !parameters.yes
log.warn("THIS SCRIPT REVERTS AND MODIFIES YOUR LAUNCHER_CONFIG.XML FILE. PRESS ANY KEY TO CONTINUE.")
system("pause")
end
if parameters.release == ""
parameters.PrintHelp()
log.error("Invalid release [#{parameters.release}] specified")
exit
end
if parameters.username == ""
parameters.PrintHelp()
log.error("Invalid username [#{parameters.username}] specified")
exit
end
if parameters.password == ""
parameters.PrintHelp()
log.error("Invalid password [#{parameters.password}] specified")
exit
end
# Revert and edit the Bootstrap
log.info("Checking out files in Perforce...")
LauncherTestPerforceHandler.instance().Revert()
LauncherTestPerforceHandler.instance().Edit()
# Good, now the files we care about are in a pristine state (or should be)
if parameters.skipbuilds == false
# Now lets swap out the tokens in our XML file so we point to the right patch file on the server
ReplaceTokenInFile("#{RS_CODEBRANCH}\\extra\\launcher\\Launcher\\res\\launcher_config.xml", OLD_XML_FILE, NEW_XML_FILE)
# Lets build the first version of the Bootstrap
log.info("Building first version of the Bootstrap...");
ProcessConfiguration("#{RS_CODEBRANCH}\\extra\\launcher\\Bootstrap.sln", parameters.release)
log.info("Protecting first version of the Bootstrap...")
ProtectIT("bootstrap", parameters.release, parameters.preloader)
firstProtectedBootstrap = GetMostRecentFile()
log.info("First Protected Bootstrap #{firstProtectedBootstrap}")
# Increment the version number
# Since Ruby 1.8.7 has absolute shit support for UTF-16 search/replacing, I'm just copying over a new file
# Yes it's a hack. I've spent 2 hours trying to do it the proper way. I give up.
FileUtils.cp("#{TOOL_PATH}/patched/Bootstrap.rc", "#{RS_CODEBRANCH}/extra/launcher/Bootstrap/Bootstrap.rc")
# Build the second version of the bootstrap (the one we're patching down
log.info("Building second version of the Bootstrap...");
ProcessConfiguration("#{RS_CODEBRANCH}\\extra\\launcher\\Bootstrap.sln", parameters.release)
log.info("Protecting second version of the Bootstrap...")
ProtectIT("bootstrap", parameters.release,parameters.preloader)
secondProtectedBootstrap = GetMostRecentFile()
log.info("Second Protected Bootstrap #{secondProtectedBootstrap}")
# Do the same thing with the Launcher
log.info("Building first version of the Launcher...");
ProcessConfiguration("#{RS_CODEBRANCH}\\extra\\launcher\\Launcher.sln", parameters.release)
log.info("Protecting first version of the Launcher...")
ProtectIT("launcher", parameters.release,parameters.preloader)
firstProtectedLauncher = GetMostRecentFile()
log.info("First Protected Launcher #{firstProtectedLauncher}")
# Increment the Version #
FileUtils.cp("#{TOOL_PATH}/patched/Launcher.rc", "#{RS_CODEBRANCH}/extra/launcher/Launcher/Launcher.rc")
# Second version of the launcher
log.info("Building second version of the Launcher...");
ProcessConfiguration("#{RS_CODEBRANCH}\\extra\\launcher\\Launcher.sln", parameters.release)
log.info("Protecting second version of the Launcher...")
ProtectIT("launcher", parameters.release,parameters.preloader)
secondProtectedLauncher = GetMostRecentFile()
log.info("Second Protected Launcher #{secondProtectedLauncher}")
# Now we have to do the same with RGSC. #stellar.
# The worst part is, it requires interaction with the user
# The good part is, all I need to do is call the collect_ script.
# Lets create the first protected version of RGSC
# Create the second protected version of RGSC
end
# Create the patches
# First lets create the bootstrap patch
# We do this by copying the second bootstrap into the data directory of the patchbuilder
log.info("Building the installable patch executables...")
# First clear out the directory
FileUtils.rm_rf("#{PATCHBUILDER_DATA_DIR}/*")
# Copy the file over
FileUtils.cp(secondProtectedBootstrap, PATCHBUILDER_DATA_DIR + "/PlayGTAV.exe")
# Now we run the CreatePatchTool to build the patch
system("#{RS_CODEBRANCH}/extra/patchbuilder/CreatePatchTest.bat Prelauncher #{NEW_PATCH_UNDERSCORE} > #{GENERATED_PATH}/#{CURR_TIME}.bootstrap.patchbuilder.log")
# First clear out the directory
FileUtils.rm_rf("#{PATCHBUILDER_DATA_DIR}/*")
# Copy the file over
FileUtils.cp(secondProtectedLauncher, PATCHBUILDER_DATA_DIR + "/GTAVLauncher.exe")
# Now we run the CreatePatchTool to build the patch
system("#{RS_CODEBRANCH}/extra/patchbuilder/CreatePatchTest.bat Launcher #{NEW_PATCH_UNDERSCORE} > #{GENERATED_PATH}/#{CURR_TIME}.launcher.patchbuilder.log")
sleep(3)
# Create our FTP pipe
log.info("Creating our FTP connection...")
ftp = Net::FTP.new("rsgames.upload.llnw.net")
ftp.login(parameters.username, parameters.password)
# Upload the patches to the FTP
log.info("Uploading the patches...")
ftp.chdir('/patches/dev/gtav/Launcher_EFIGS')
Dir.glob("#{PATCHBUILDER_OUTPUT_DIR}/*.exe").each do |patch|
# Sign the file before we do anything with it
log.info("Signing #{patch}...")
SignFile(patch)
# Now upload it to the server
log.info("Uploading #{patch}...")
ftp.putbinaryfile(patch)
end
# Upload the XML files to the FTP
log.info("Uploading new XML files...")
ftp.chdir('/patches/dev/gtav')
# Remove old files - hitting errors where they are read-only
begin
FileUtils.rm_f("#{GENERATED_PATH}/launcher_version.testing.#{USERNAME}.xml")
rescue
end
begin
FileUtils.rm_f("#{GENERATED_PATH}/prelauncher_version.testing.#{USERNAME}.xml")
rescue
end
FileUtils.cp("#{TOOL_PATH}/patched/launcher_version.testing.xml", "#{GENERATED_PATH}/launcher_version.testing.#{USERNAME}.xml")
FileUtils.cp("#{TOOL_PATH}/patched/prelauncher_version.testing.xml", "#{GENERATED_PATH}/prelauncher_version.testing.#{USERNAME}.xml")
ftp.putbinaryfile("#{GENERATED_PATH}/launcher_version.testing.#{USERNAME}.xml")
ftp.putbinaryfile("#{GENERATED_PATH}/prelauncher_version.testing.#{USERNAME}.xml")
# Copy over the first iterations to our build directory
log.info("Copying executables over to the build directory...")
if parameters.skipbuilds == false
FileUtils.cp(firstProtectedBootstrap, GAME_DIR + "/PlayGTAV.exe")
FileUtils.cp(firstProtectedLauncher, GAME_DIR + "/GTAVLauncher.exe")
FileUtils.cp(firstProtectedBootstrap, RS_BUILDBRANCH + "/PlayGTAV.exe")
FileUtils.cp(firstProtectedLauncher, RS_BUILDBRANCH + "/GTAVLauncher.exe")
end
# Deleting a local file to test the downloading of pipes
log.info("Deleting a local RPF file...")
begin
FileUtils.rm("#{GAME_DIR}/x64a.rpf")
rescue
end
# Deleting game executable to test the downloading of patches
log.info("Deleting a local RPF file...")
begin
FileUtils.rm("#{GAME_DIR}/gta5.exe")
rescue
end
# Revert back out the files we opened up
log.info("Reverting files that we've opened up...");
LauncherTestPerforceHandler.instance().Revert()
# Restore the files that we've previously clobbered
# Close FTP connection
log.info("Closing FTP connection...")
ftp.close
else
log.info("Skipping build / upload.")
DeleteSomeFiles()
end
# Defining the testing functions down here, to not get mixed up with the
# patch-building / -uploading code.
PASS_COLOUR = "#004400"
FAIL_COLOUR = "#880000"
INFO_COLOUR = "#202020"
$currentLogfilePath = ""
$currentLogfileDestPath = ""
$currentLogFile = nil
$reportHtml = ""
$sectionTitle = ""
$sectionBody = ""
$sectionPassed = true
$sections = []
def StartReport()
$reportHtml = '<head><meta charset="UTF-8"></head>'
$reportHtml += "\n<div style=\"font-family: Sans-serif;\">\n<h1>Launcher Automated Test Results</h1>\n"
$reportHtml += "<div><div style=\"font-size:150%;font-weight:bold;\">Summary</div>\n<ul>"
$reportHtml += "<li>User: " + USERNAME + "</li>\n"
$reportHtml += "<li>Userprofile: " + USER_PROFILE + "</li>\n"
$reportHtml += "<li>Log dir: " + USER_LOG_PATH + "</li>\n"
p4ver = "(unknown)"
begin
p4ver = `p4 changes -m 1 X:\\gta5\\src\\dev_ng\\extra\\launcher...#have`
p4ver = p4ver.split(" ")[1]
rescue
end
$reportHtml += "<li>CL: " + p4ver.to_s + "</li>\n"
end
def StartSection(title)
RsgLog.instance().info("Starting section \"#{title}\"...")
$sectionTitle = title
$sectionBody = ""
$sectionPassed = true
$sectionBody += "<table width=\"100%\" border=\"1\" style=\"font-family:Sans-serif;\">\n"
end
def OpenLogFile(filename)
RsgLog.instance().info("Opening log file \"#{filename}\"...")
$currentLogfilePath = "#{USER_LOG_PATH}/#{filename}"
begin
$currentLogFile = File.open($currentLogfilePath)
rescue
$currentLogFile = nil
end
end
def InsertLogFilePath()
$sectionBody += "<tr><td style=\"font-size:75%;\">Logfile: #{$currentLogfileDestPath}</td><td>[<a href=\"#{$currentLogfileDestPath}\">open</a>]</td></tr>\n"
end
def CopyAndOpenLogFile(filename)
$currentLogfilePath = "#{USER_LOG_PATH}/#{filename}"
destPath = "#{$LOG_DIR}/" + Time.now.strftime("%Y%m%d.%H.%M.%S") + "." + filename
#destPath = "#{$LOG_DIR}/#{CURR_TIME}.#{filename}"
RsgLog.instance().info("Source log: "+$currentLogfilePath)
RsgLog.instance().info("Dest log: "+destPath)
FileUtils.cp($currentLogfilePath, destPath)
$currentLogFile = File.open($currentLogfilePath)
$currentLogfileDestPath = destPath
InsertLogFilePath()
end
def ContinueLogFileSearch(string)
line = nil
pos = $currentLogFile.pos
while (line = $currentLogFile.gets) != nil
if (line.include?(string))
return true
end
end
# Rewind on failure
$currentLogFile.close
$currentLogFile = File.open($currentLogfilePath)
$currentLogFile.pos = pos
return false
end
def ContinueLogFileSearchPassFail(string0, string1)
line = nil
pos = $currentLogFile.pos
while (line = $currentLogFile.gets) != nil
if (line.include?(string0))
return 0
end
if (line.include?(string1))
# Rewind on failure
$currentLogFile.pos = pos
return 1
end
end
# Rewind on failure
$currentLogFile.close
$currentLogFile = File.open($currentLogfilePath)
$currentLogFile.pos = pos
return -1
end
def ContinueLogFileSearchReturnLine(string0)
line = nil
pos = $currentLogFile.pos
while (line = $currentLogFile.gets) != nil
if (line.include?(string0))
return line
end
end
# Rewind on failure
$currentLogFile.close
$currentLogFile = File.open($currentLogfilePath)
$currentLogFile.pos = pos
return nil
end
def ReadLineFromFile(file, linenumber)
line = nil
begin
File.open(file) do |f|
linenumber.times { line = f.gets }
end
rescue
end
return line
end
def AddResultLine(text, passed)
if passed
RsgLog.instance().info("#{text} - PASSED")
$sectionBody += "<tr style=\"color:#{PASS_COLOUR}\"><td>#{text}</td><td>PASSED</td></tr>\n"
else
RsgLog.instance().info("#{text} - FAILED")
$sectionBody += "<tr style=\"color:#{FAIL_COLOUR}\"><td>#{text}</td><td>FAILED</td></tr>\n"
$sectionPassed = false
end
end
def AddInfoLine(text)
RsgLog.instance().info("#{text} - INFO")
$sectionBody += "<tr style=\"color:#{INFO_COLOUR}\"><td>#{text}</td><td>INFO</td></tr>\n"
end
def AddSmallInfoLine(text)
RsgLog.instance().info("#{text} - INFO")
$sectionBody += "<tr style=\"color:#{INFO_COLOUR};\"><td style=\"font-size:75%;\">#{text}</td><td>INFO</td></tr>\n"
end
def AddCodeLine(text)
if text == nil
return
end
text = html_escape(text)
RsgLog.instance().info("#{text} - INFO")
$sectionBody += '<tr style="color:#{INFO_COLOUR};"><td style="font-size:75%;font-family:monospace;">' + text + '</td><td>INFO</td></tr>'
$sectionBody += "\n"
end
def TestForLogLine(search)
AddResultLine("Check for \"#{search}\"", ContinueLogFileSearch(search))
end
def TestForLogPassFail(pass, fail)
AddResultLine("Check for \"#{pass}\"", ContinueLogFileSearchPassFail(pass, fail) == 0)
end
def CloseLogFile()
$currentLogFile.close
end
def Countdown(var)
while var > 0
RsgLog.instance().info(var.to_s + "... ")
sleep(1)
var = var - 1
end
end
def EndSection()
RsgLog.instance().info("Ending section...")
section = "<div><div style=\"font-size:150%;font-weight:bold;\">" + $sectionTitle
if $sectionPassed
section += " - <span style=\"color:#{PASS_COLOUR}\">PASSED</span></div>\n"
else
section += " - <span style=\"color:#{FAIL_COLOUR}\">FAILED</span></div>\n"
end
section += $sectionBody
section += "\n</table></div>\n<br>\n\n"
$sections.push(section)
$reportHtml += "<li style=\"font-weight:normal;\">" + $sectionTitle
if $sectionPassed
$reportHtml += " - <span style=\"color:#{PASS_COLOUR}\">PASSED</span></li>\n"
else
$reportHtml += " - <span style=\"color:#{FAIL_COLOUR}\">FAILED</span></li>\n"
end
sleep(0.2)
end
def EndReport()
$reportHtml += "</ul></div>\n<br>\n"
$sections.each {|i| $reportHtml += i }
$reportHtml += "</div>"
end
def BootstrapSelfPatchTest()
random_arg = "-autotest_random_arg_" + rand(100).to_s
RsgLog.instance().info("Launching Bootstrap only...")
result = system(GAME_DIR + "/PlayGTAV.exe", "-autotest_bootstrap_nolauncher", random_arg)
StartSection("Bootstrap Patch Check")
AddResultLine("Execution success", result)
AddResultLine("Process return code == 0", $? == 0)
generated_log = false
OpenLogFile("bootstrap.log")
generated_log = ContinueLogFileSearch(random_arg)
CloseLogFile()
AddResultLine("Created log file", generated_log)
AddResultLine("Generated a log file", generated_log)
CopyAndOpenLogFile("bootstrap.log")
if generated_log
TestForLogLine("Bootstrap starting!")
TestForLogLine("Bmp size: 573 x 601")
TestForLogLine("There is/are 2 check(s) to do")
TestForLogLine("Update check 1/2 starting")
TestForLogPassFail("RockstarDownloader doing download.", "Setting error condition")
TestForLogPassFail("RockstarDownloader checking URL validity...", "Setting error condition")
TestForLogPassFail("RockstarDownloader checking disk...", "Setting error condition")
TestForLogPassFail("prelauncher_version.testing.#{USERNAME}.xml to determine length...", "Setting error condition")
TestForLogPassFail("Update check 1/2 done", "Update check 1/2 failed")
TestForLogPassFail("Check 1 patch 1 is not installed; queueing.", "Check 1 patch 1 is installed.")
TestForLogLine("Update check 2/2 starting")
TestForLogPassFail("launcher_version.testing.#{USERNAME}.xml to determine length...", "Setting error condition")
TestForLogPassFail("Update check 2/2 done", "Update check 2/2 failed")
TestForLogPassFail("Check 2 patch 1 is not installed; queueing.", "Check 2 patch 1 is installed.")
TestForLogLine("Found 2 patches.")
TestForLogLine("Installing patch")
TestForLogLine("Install needs restart")
TestForLogLine("Installer requested restart")
TestForLogLine("Restart required; exiting")
end
CloseLogFile()
EndSection()
end
def BootstrapLauncherPatchTest()
random_arg = "-autotest_random_arg_" + rand(100).to_s
RsgLog.instance().info("Launching Bootstrap only...")
result = system(GAME_DIR + "/PlayGTAV.exe", "-autotest_bootstrap_nolauncher", random_arg)
StartSection("Launcher Patch Check")
AddResultLine("Execution success", result)
AddResultLine("Process return code == 0", $? == 0)
generated_log = false
OpenLogFile("bootstrap.log")
generated_log = ContinueLogFileSearch(random_arg)
CloseLogFile()
AddResultLine("Generated a log file", generated_log)
CopyAndOpenLogFile("bootstrap.log")
if generated_log
TestForLogLine("Bootstrap starting!")
TestForLogLine("Bmp size: 573 x 601")
TestForLogLine("There is/are 2 check(s) to do")
TestForLogLine("Update check 1/2 starting")
TestForLogPassFail("RockstarDownloader doing download.", "Setting error condition")
TestForLogPassFail("RockstarDownloader checking URL validity...", "Setting error condition")
TestForLogPassFail("RockstarDownloader checking disk...", "Setting error condition")
TestForLogPassFail("prelauncher_version.testing.#{USERNAME}.xml to determine length...", "Setting error condition")
TestForLogPassFail("Update check 1/2 done", "Update check 1/2 failed")
TestForLogPassFail("Check 1 was up-to-date.", "Check 1 patch 1 is not installed; queueing.")
TestForLogLine("Update check 2/2 starting")
TestForLogPassFail("launcher_version.testing.#{USERNAME}.xml to determine length...", "Setting error condition")
TestForLogPassFail("Update check 2/2 done", "Update check 2/2 failed")
TestForLogPassFail("Check 2 patch 1 is not installed; queueing.", "Check 2 patch 1 is installed.")
TestForLogLine("Found 1 patches.")
TestForLogLine("Installing patch")
TestForLogLine("About to launch process")
TestForLogPassFail("Pid:", "Error launching process")
TestForLogLine("Waiting for handle")
TestForLogLine("Finished waiting")
TestForLogPassFail("Successfully installed patch", "Failed to install patch")
TestForLogLine("No restart required; chaining Launcher")
end
CloseLogFile()
EndSection()
end
def BootstrapLauncherRunTest()
random_arg = "-autotest_random_arg_" + rand(100).to_s
RsgLog.instance().info("Launching Bootstrap (expecting Launcher as well)...")
result = system(GAME_DIR + "/PlayGTAV.exe", "-autotest_launcher_exitimmediately", random_arg)
StartSection("Bootstrap Starting Launcher")
AddResultLine("Execution success", result)
AddResultLine("Process return code == 0", $? == 0)
OpenLogFile("bootstrap.log")
generated_log = ContinueLogFileSearch(random_arg)
CloseLogFile()
AddResultLine("Bootstrap generated a log file", generated_log)
CopyAndOpenLogFile("bootstrap.log")
if generated_log
TestForLogLine("Bootstrap starting!")
TestForLogLine("Bmp size: 573 x 601")
TestForLogLine("There is/are 2 check(s) to do")
TestForLogLine("Update check 1/2 starting")
TestForLogPassFail("RockstarDownloader doing download.", "Setting error condition")
TestForLogPassFail("RockstarDownloader checking URL validity...", "Setting error condition")
TestForLogPassFail("RockstarDownloader checking disk...", "Setting error condition")
TestForLogPassFail("prelauncher_version.testing.#{USERNAME}.xml to determine length...", "Setting error condition")
TestForLogPassFail("Update check 1/2 done", "Update check 1/2 failed")
TestForLogPassFail("Check 1 was up-to-date.", "Check 1 patch 1 is not installed; queueing.")
TestForLogLine("Update check 2/2 starting")
TestForLogPassFail("launcher_version.testing.#{USERNAME}.xml to determine length...", "Setting error condition")
TestForLogPassFail("Update check 2/2 done", "Update check 2/2 failed")
TestForLogPassFail("Check 2 was up-to-date.", "Check 2 patch 1 is not installed; queueing.")
TestForLogLine("Found 0 patches.")
TestForLogLine("No restart required; chaining Launcher")
end
CloseLogFile()
# Give it a moment
sleep(3)
OpenLogFile("launcher.log")
generated_log = ContinueLogFileSearch(random_arg)
CloseLogFile()
AddResultLine("Launcher generated a log file", generated_log)
CopyAndOpenLogFile("launcher.log")
CloseLogFile()
EndSection()
end
def LauncherRunTest()
random_arg = "-autotest_random_arg_" + rand(100).to_s
RsgLog.instance().info("Launching Launcher...")
result = system(GAME_DIR + "/GTAVLauncher.exe", random_arg, "-autotest_launcher_selfsignin", "-autotest_launcher_digitalupdate")
StartSection("Launcher Startup")
AddResultLine("Execution success", result)
AddResultLine("Process return code == 0", $? == 0)
OpenLogFile("launcher.log")
generated_log = ContinueLogFileSearch(random_arg)
CloseLogFile()
AddResultLine("Launcher generated a log file", generated_log)
if !generated_log
EndSection()
return
end
CopyAndOpenLogFile("launcher.log")
TestForLogLine("Running as admin")
TestForLogLine("P4 Version")
TestForLogLine("Waiting for connections on named pipe instance")
TestForLogLine("Social Club constructed")
TestForLogLine("Now on background")
TestForLogLine("Hiding all controls")
TestForLogLine("Found 0 in-file(s)")
TestForLogLine("OS version")
TestForLogLine("Controller monitor thread launched")
EndSection()
StartSection("Launcher Online Config")
InsertLogFilePath()
TestForLogLine("eDownloadOnlineConfig")
TestForLogLine("JOB_DOWNLOAD_ONLINE_CONFIG")
TestForLogLine("launcher_online_config.xml to determine length...")
TestForLogPassFail("Content length", "error")
TestForLogPassFail("Download succeeded", "nothing to download")
EndSection()
StartSection("Launcher RGSC Update")
InsertLogFilePath()
TestForLogPassFail("Entering state 2 (eCheckForRGSCUpdates)", "eCheckForInPlaceDownload")
TestForLogLine("Dev server looks accessible")
TestForLogPassFail("There is/are 1 check(s) to do.", "error")
TestForLogPassFail("Update check 1/1 starting...", "error")
TestForLogPassFail("Getting temp path...", "error")
TestForLogPassFail("sc_installer_version.xml", "error")
TestForLogPassFail("XML file: sc_installer_version.xml", "error")
TestForLogPassFail("Starting downloader synchronously...", "error")
TestForLogPassFail("Downloading", "error")
TestForLogPassFail("Selecting regular downloader.", "error")
TestForLogPassFail("RockstarDownloader starting.", "error")
TestForLogPassFail("RockstarDownloader doing download.", "error")
TestForLogPassFail("RockstarDownloader checking URL validity...", "error")
TestForLogPassFail("RockstarDownloader checking disk...", "error")
TestForLogPassFail("sc_installer_version.xml to determine length...", "error")
TestForLogPassFail("Content length", "error")
TestForLogPassFail("bytes available; we only need", "error")
TestForLogPassFail("RockstarDownloader receiving data...", "error")
TestForLogPassFail("GET to patches.rockstargames.com", "error")
TestForLogPassFail("Download succeeded.", "error")
TestForLogPassFail("Parsing XML...", "error")
TestForLogPassFail("Adding RGSC patch (removing any previous).", "error")
TestForLogPassFail("Cleaning up XML...", "error")
TestForLogPassFail("Checking EXE...", "error")
TestForLogPassFail("File version", "error")
TestForLogPassFail("Executable version", "error")
TestForLogPassFail("Checking 1 patches...", "error")
TestForLogPassFail("Patch 1 is already installed.", "error")
TestForLogLine("Finished job: JOB_CHECK_FOR_SC_UPDATES")
TestForLogPassFail("No patches to install; we are up-to-date.", "Entering state 3 (eSocialClub)")
EndSection()
StartSection("Launcher SC Init")
InsertLogFilePath()
TestForLogLine("Entering state 3 (eSocialClub)")
TestForLogPassFail("Social Club initializing...", "error")
TestForLogPassFail("Starting Social Club thread...", "error")
TestForLogPassFail("Loading DLL...", "error")
TestForLogPassFail("Calling LoadLibraryExA: C:\\Program Files (x86)\\Rockstar Games\\Social Club\\socialclub64.dll", "error")
TestForLogPassFail("Initialising DLL...", "error")
TestForLogPassFail("Getting proc address...", "error")
TestForLogPassFail("Obtaining interfaces...", "error")
TestForLogPassFail("Setting up ROS interface...", "error")
TestForLogPassFail("Beginning decryption of ROS Secrets", "error")
TestForLogPassFail("Beginning Decryption", "error")
TestForLogPassFail("Finished Decryption", "error")
TestForLogPassFail("Finished decryption of ROS Secrets", "error")
TestForLogPassFail("Initialising RGSC...", "error")
TestForLogPassFail("Setting up SCUI...", "error")
TestForLogPassFail("Getting activation system...", "error")
TestForLogPassFail("Notifying SCUI of OnCreateDevice...", "error")
TestForLogPassFail("Attempting to create device...", "error")
TestForLogPassFail("Attempting to initialise DX9 COM object...", "error")
TestForLogPassFail("Created Direct3D.", "error")
TestForLogPassFail("Window size: 800 x 600", "error")
TestForLogPassFail("Attempting D3DFMT_UNKNOWN, D3DCREATE_HARDWARE_VERTEXPROCESSING, D3DCREATE_MULTITHREADED...", "error")
TestForLogPassFail("Successfully created DX Device!", "error")
TestForLogPassFail("Social Club seems to have loaded correctly.", "error")
TestForLogPassFail("Entitlement seems to have initialized correctly.", "error")
TestForLogPassFail("SCUI is ready to accept commands. Showing SCUI...", "error")
TestForLogPassFail("Pre-rendering...", "error")
TestForLogPassFail("SCUI is visible.", "error")
TestForLogPassFail("Showing DxSurface9.", "error")
TestForLogPassFail("SCUI is ready for commands.", "error")
TestForLogPassFail("SCUI is visible.", "error")
EndSection()
StartSection("Launcher Simulate Logging In")
InsertLogFilePath()
TestForLogLine("SetTextBoxHasFocusV2(true, Nickname/Email")
TestForLogLine("SetTextBoxHasFocusV2(false")
TestForLogLine("SetTextBoxHasFocusV2(true, Password")
TestForLogLine("SetTextBoxHasFocusV2(false")
TestForLogLine("Signed-in; continuing.")
EndSection()
StartSection("Launcher Checking Entitlement")
InsertLogFilePath()
TestForLogPassFail("Entering state 4 (eCheckForEntitlement)", "error")
TestForLogLine("Erasing completed state (eCheckForEntitlement)")
EndSection()
StartSection("Launcher In-place Download")
InsertLogFilePath()
TestForLogLine("Entering state 5 (eCheckForInPlaceDownload)")
TestForLogPassFail("manifest to determine length", "error")
TestForLogPassFail("we only need", "error")
TestForLogPassFail("GET to patches.rockstargames.com", "error")
TestForLogPassFail("Download succeeded", "error")
TestForLogPassFail("x64a.rpf missing", "x64a.rpf seems complete")
TestForLogLine("In-place download is not up-to-date; download required")
TestForLogLine("Finished job: JOB_CHECK_FOR_IN_PLACE_DOWNLOAD")
TestForLogLine("Entering state 12 (eGameInstallAvailable)")
TestForLogLine("Posting SCUI message")
TestForLogPassFail("AutotestDigitalUpdate pressing update button...", "error")
TestForLogPassFail("Inserting new flow state at the front: eDownloadInPlaceData", "error")
TestForLogPassFail("Entering state 13 (eDownloadInPlaceData)", "error")
TestForLogLine("Beginning job: JOB_DOWNLOAD_IN_PLACE")
TestForLogLine("Initialising downloader.")
TestForLogLine("Starting downloader synchronously...")
TestForLogLine("Selecting chunked downloader.")
TestForLogLine("RockstarDownloader starting.")
TestForLogLine("RockstarDownloader doing download.")
TestForLogLine("RockstarDownloader checking URL validity...")
TestForLogLine("RockstarDownloader checking disk...")
TestForLogLine("to determine length...")
TestForLogLine("Content length")
TestForLogLine("available; we only need")
TestForLogLine("RockstarDownloader receiving data...")
TestForLogLine("RockstarDownloader starting.")
TestForLogLine("RockstarDownloader doing download.")
TestForLogLine("RockstarDownloader checking URL validity...")
TestForLogLine("RockstarDownloader checking disk...")
TestForLogLine("hash to determine length...")
TestForLogLine("Content length")
TestForLogLine("available; we only need")
TestForLogLine("RockstarDownloader receiving data...")
TestForLogLine("GET to patches.rockstargames.com")
TestForLogLine("Download succeeded.")
TestForLogLine("[1] Using range header: Range: bytes=")
TestForLogLine("[1] Sending request.")
TestForLogLine("[1] 16KB @ ")
TestForLogLine("Checking hash")
TestForLogLine("Hashes match:")
TestForLogLine("Hash check succeeded.")
TestForLogLine("Starting another chunk.")
TestForLogLine("AutotestDigitalUpdate terminating launcher...")
EndSection()
StartSection("Launcher Clean Shutdown")
InsertLogFilePath()
TestForLogPassFail("Entering state 30 (eShuttingDown)", "error")
TestForLogPassFail("Shutting down.", "error")
TestForLogPassFail("Joining WorkerThread.", "error")
TestForLogPassFail("Signaling WorkerThread to stop.", "error")
TestForLogPassFail("Ending Social Club thread...", "error")
TestForLogPassFail("Thread no longer running.", "error")
TestForLogPassFail("Shutting down Entitlement...", "error")
TestForLogPassFail("Shutting down SCUI...", "error")
TestForLogPassFail("Shutting down RGSC...", "error")
TestForLogPassFail("Freeing library...", "error")
TestForLogPassFail("Uninitializing.", "error")
TestForLogPassFail("Social Club destructed.", "error")
EndSection()
CloseLogFile()
end
def LauncherPatchTest()
random_arg = "-autotest_random_arg_" + rand(100).to_s
RsgLog.instance().info("Launching Launcher...")
result = system(GAME_DIR + "/GTAVLauncher.exe", random_arg, "-autotest_launcher_selfsignin", "-autotest_launcher_gamepatch")
StartSection("Launcher Check For Game Patch")
AddResultLine("Execution success", result)
AddResultLine("Process return code == 0", $? == 0)
OpenLogFile("launcher.log")
generated_log = ContinueLogFileSearch(random_arg)
CloseLogFile()
AddResultLine("Launcher generated a log file", generated_log)
if !generated_log
EndSection()
return
end
CopyAndOpenLogFile("launcher.log")
TestForLogLine("Entering state 6 (eCheckForUpdate)")
TestForLogLine("Beginning job: JOB_CHECK_FOR_GAME_UPDATES")
TestForLogLine("Dev server has already been checked.")
TestForLogLine("Initialising downloader.")
TestForLogLine("Checking for updates...")
TestForLogLine("There is/are 2 check(s) to do.")
TestForLogLine("Update check 1/2 starting...")
TestForLogLine("Clearing temporary patch list...")
TestForLogLine("Getting temp path...")
TestForLogLine("gtav_version.xml")
TestForLogLine("Queueing file...")
TestForLogLine("Starting file...")
TestForLogLine("Starting downloader synchronously...")
TestForLogLine("Downloading")
TestForLogLine("Selecting regular downloader.")
TestForLogLine("RockstarDownloader starting.")
TestForLogLine("RockstarDownloader doing download.")
TestForLogLine("RockstarDownloader checking URL validity...")
TestForLogLine("RockstarDownloader checking disk...")
TestForLogLine("gtav_version.xml to determine length...")
TestForLogLine("Content length")
TestForLogLine("bytes available; we only need")
TestForLogLine("RockstarDownloader receiving data...")
TestForLogLine("GET to patches.rockstargames.com")
TestForLogLine("Download succeeded.")
TestForLogLine("Download complete.")
TestForLogLine("Synchronous downloading ended.")
TestForLogLine("File finished.")
TestForLogLine("Parsing XML...")
TestForLogLine("Adding game patch.")
TestForLogLine("Cleaning up XML...")
TestForLogLine("Checking EXE...")
TestForLogLine("Unable to get file version info size")
TestForLogLine("The system cannot find the file specified.")
TestForLogLine("Executable version 0.0.0.0")
TestForLogLine("Checking 1 patches...")
TestForLogLine("Patch 1 needs installing.")
TestForLogLine("Update check 1/2 done.")
TestForLogLine("Check 1 was not up-to-date; adding patches.")
TestForLogLine("Check 1 patch 1 is not installed; queueing.")
TestForLogLine("Update check 2/2 starting...")
TestForLogLine("Clearing temporary patch list...")
TestForLogLine("Getting temp path...")
TestForLogLine("dlc_version.xml")
TestForLogLine("Selecting regular downloader.")
TestForLogLine("RockstarDownloader starting.")
TestForLogLine("RockstarDownloader doing download.")
TestForLogLine("RockstarDownloader checking URL validity...")
TestForLogLine("RockstarDownloader checking disk...")
TestForLogLine("dlc_version.xml to determine length...")
TestForLogLine("Content length")
TestForLogLine("bytes available; we only need")
TestForLogLine("RockstarDownloader receiving data...")
TestForLogLine("GET to patches.rockstargames.com")
TestForLogLine("Download succeeded.")
TestForLogLine("Download complete.")
TestForLogLine("Synchronous downloading ended.")
TestForLogLine("File finished.")
TestForLogLine("Parsing XML...")
TestForLogLine("Cleaning up XML...")
TestForLogLine("Checking EXE...")
TestForLogLine("Executable version 0.0.0.0")
TestForLogLine("No patches to check.")
TestForLogLine("Update check 2/2 done.")
TestForLogLine("Check 2 was up-to-date.")
TestForLogLine("No more checks.")
TestForLogLine("We have become mandatory.")
TestForLogLine("Shutting down downloader.")
TestForLogLine("Finished job: JOB_CHECK_FOR_GAME_UPDATES")
TestForLogLine("Erasing completed state (eCheckForUpdate)")
TestForLogLine("1 patch(es) to install; we are not up-to-date.")
TestForLogLine("Flow disrupted due to update available.")
EndSection()
StartSection("Launcher Download patch")
InsertLogFilePath()
TestForLogLine("Entering state 9 (eRequiredUpdate)")
TestForLogLine("Hiding all controls.")
TestForLogLine("Posting SCUI message: ")
TestForLogLine("AutotestGamePatch pressing update button...")
TestForLogLine("Inserting new flow state at the front: eDownloadUpdate")
TestForLogLine("Entering state 15 (eDownloadUpdate)")
TestForLogLine("Beginning job: JOB_DOWNLOAD_UPDATE")
TestForLogLine("Running patch process.")
TestForLogLine("We have (or can acquire) admin rights.")
TestForLogLine("1 patch to process.")
TestForLogLine("Attempting to download patch:")
TestForLogLine("Initialising downloader.")
TestForLogLine("Starting downloader synchronously...")
TestForLogLine("Downloading http://patches.rockstargames.com/")
TestForLogLine("Selecting chunked downloader.")
TestForLogLine("RockstarDownloader starting.")
TestForLogLine("RockstarDownloader doing download.")
TestForLogLine("RockstarDownloader checking URL validity...")
TestForLogLine("RockstarDownloader checking disk...")
TestForLogLine(" to determine length...")
TestForLogLine("Content length")
TestForLogLine("bytes available; we only need")
TestForLogLine("RockstarDownloader starting.")
TestForLogLine("RockstarDownloader doing download.")
TestForLogLine("RockstarDownloader checking URL validity...")
TestForLogLine("RockstarDownloader checking disk...")
TestForLogLine(".hash to determine length...")
TestForLogLine("Query failed.")
TestForLogLine("[1] Using range header: Range:")
TestForLogLine("[1] Sending request.")
TestForLogLine("[1] 16KB @")
TestForLogLine("No more incomplete ranges.")
TestForLogLine("Deleting partfile.")
TestForLogLine("Download complete.")
TestForLogLine("Synchronous downloading ended.")
TestForLogLine("Attempting to install patch.")
TestForLogLine("Installing patch")
TestForLogLine("About to launch process:")
TestForLogLine("Pid:")
TestForLogLine("Waiting for handle")
TestForLogLine("Finished waiting.")
TestForLogLine("Exit code: 0")
TestForLogLine("Successfully installed patch ")
TestForLogLine("Finished job: JOB_DOWNLOAD_UPDATE")
TestForLogLine("Erasing completed state (eDownloadUpdate)")
EndSection()
StartSection("Launcher Launching Game")
InsertLogFilePath()
TestForLogLine("Entering state 8 (eLoading)")
TestForLogPassFail("Launching game...", "error")
TestForLogPassFail("(path: ", "error")
TestForLogLine("autotest_launcher_gamepatch killing process")
EndSection()
end
def LauncherErrorScreenTest(title, extra_args, start_error = 1, stop_error = 50)
DeleteSomeFiles()
errornumber = start_error
StartSection(title)
AddInfoLine("Adding parameters: " + extra_args.join(","))
while errornumber < stop_error
# There's no easy way to say this. It's a hack.
# These cases trigger B*2149495, which need SC DLL support.
if (errornumber >= 34 && errornumber <= 37)
AddInfoLine("[Skipping test "+errornumber.to_s+' due to <a href="url:bugstar:2149495">Bug 2149495</a>]');
errornumber += 1
next
end
random_arg = "-autotest_random_arg_" + rand(100).to_s
RsgLog.instance().info("AutotestFail "+errornumber.to_s+"...")
args = [random_arg, "-autotest_launcher_selfsignin", "-autotest_launcher_errors="+errornumber.to_s, "-autotest_launcher_errors_delay="+$SHOW_ERROR_DELAY.to_s, *extra_args]
result = system(GAME_DIR + "/GTAVLauncher.exe ", *args)
OpenLogFile("launcher.log")
generated_log = ContinueLogFileSearch(random_arg)
if (!generated_log)
AddResultLine("Test "+errornumber.to_s+": Generated log file", false)
CloseLogFile()
CopyAndOpenLogFile("launcher.log")
CloseLogFile()
break
end
errorTest = "Testing error message at "
test_line = ContinueLogFileSearchReturnLine(errorTest)
if (test_line == nil)
break;
end
indexof = test_line.index(errorTest)+errorTest.length
test_location = test_line[indexof,test_line.length-indexof-1]
test_filename = test_location.gsub(/(.:.*):.*/, "\\1")
test_linenumber = test_location.gsub(/.:.*:(.*)/, "\\1")
test_complete_line = ReadLineFromFile(test_filename, test_linenumber.to_i)
test_location.gsub!("\\","/")
test_file = test_location.gsub(/(.:.*):.*/, "file:///\\1")
test_location = errornumber.to_s + ": at <a href=\"#{test_file}\">#{test_location}</a>"
if ($? != 0)
AddResultLine(test_location, false)
AddCodeLine(test_complete_line)
AddInfoLine("Test "+errornumber.to_s+": Appears to have crashed. Exit code: "+$?.to_s)
CloseLogFile()
CopyAndOpenLogFile("launcher.log")
CloseLogFile()
break
end
saw_error_screen = ContinueLogFileSearch("AutotestFail: Notified about reaching error screen")
if saw_error_screen
AddResultLine(test_location, true)
AddCodeLine(test_complete_line)
line = ContinueLogFileSearchReturnLine("AutotestFail: Error state:")
if (line != nil)
line.gsub!(/.*Error state:(.*)/,'\\1')
AddSmallInfoLine("Reached error screen:" + line)
else
AddSmallInfoLine("Reached error screen.")
end
line = ContinueLogFileSearchReturnLine("AutotestFail: UI state:")
if (line != nil)
line.gsub!(/.*(UI state:.*)/,'\\1')
AddSmallInfoLine(line)
end
else
retrying = ContinueLogFileSearch("AutotestFail: Notified about retrying")
if (retrying)
AddResultLine(test_location, true)
AddCodeLine(test_complete_line)
AddInfoLine("Retried.")
else
if (ContinueLogFileSearch("AutotestFail: Notified that this is not an error"))
AddResultLine(test_location, true)
AddCodeLine(test_complete_line)
AddInfoLine("Not an error.")
else
AddResultLine(test_location, false)
AddCodeLine(test_complete_line)
end
end
end
CloseLogFile()
if (!saw_error_screen)
CopyAndOpenLogFile("launcher.log")
CloseLogFile()
end
errornumber = errornumber + 1
end
EndSection()
end
# Okay! We're done. Now lets actually launch the stuff....
# Handle showing a single error code
if parameters.showerror
puts
puts
puts "Which section is the error screen from? (1 or 2)"
section = gets.to_i
puts "Which error number would you like? (see automated email for numbers)"
errornumber = gets.to_i
args = ["-autotest_launcher_selfsignin", "-autotest_launcher_errors="+errornumber.to_s, "-noautokill"]
if section == 1
args.push("-autotest_launcher_digitalupdate")
else
args.push("-autotest_launcher_gamepatch")
end
system(GAME_DIR + "/GTAVLauncher.exe ", *args)
exit
end
StartReport()
if !parameters.errorsonly
if !parameters.skipupload
BootstrapSelfPatchTest()
Countdown(10)
BootstrapLauncherPatchTest()
Countdown(3)
end
BootstrapLauncherRunTest()
Countdown(5)
LauncherRunTest()
Countdown(3)
LauncherPatchTest()
Countdown(3)
end
if !parameters.noerrors
LauncherErrorScreenTest("Launcher Error Screens 1", ["-autotest_launcher_digitalupdate"], 1, 60)
LauncherErrorScreenTest("Launcher Error Screens 2", ["-autotest_launcher_gamepatch"], 27, 65)
#TODO: Test https://dev.ros.rockstargames.com/scui/v2/api/test/resetrecaptcha
end
EndReport()
#log.info("Report: "+$reportHtml)
File.open("report.html", "w") do |f|
f.write($reportHtml)
end
if (parameters.emailfrom != nil) && (parameters.emailto != nil)
log.info("Mailing out results...")
log.info("From: #{parameters.emailfrom}")
log.info("To: #{parameters.emailto}")
recipients = parameters.emailto.split(";")
log.info(recipients.size.to_s + " recipients")
message = "From: Launcher Automated Test Tool <#{parameters.emailfrom}>\n"
message += "To: "
first = true
recipients.each { |i|
if first
first = false
else
message += ", "
end
message += "<#{i}>"
log.info(" #{i}")
}
message += "MIME-Version: 1.0\n"
message += "Content-type: text/html\n"
message += "Subject: Launcher Automated Test Results\n\n"
message += $reportHtml
Net::SMTP.start('smtp.rockstar.t2.corp') do |smtp|
smtp.send_message message, parameters.emailfrom, recipients
end
end
# Exiting
log.info("All done! Exiting!")