Populated Bestine Capitol Building with missing NPCs. Also spawns several other missi...
[swg-src.git] / tools / test_build_linux.pl
blob76f4590845ea83a1d06330f74f8becd298f4460e
1 #! /usr/bin/perl
2 # ======================================================================
3 # ======================================================================
5 use warnings;
6 use strict;
7 use Socket;
8 use Getopt::Long;
9 use File::Copy;
11 # ======================================================================
12 # Constants
13 # ======================================================================
15 use constant START_BOOTLEG_TEST => "A";
16 use constant END_COMMUNICATION => "B";
17 use constant SUCCESSFUL_TEST => "C";
18 use constant UNSUCCESSFUL_TEST => "D";
19 use constant SERVER_READY => "E";
20 use constant BOOTLEG_MISMATCH => "F";
21 use constant CLIENT_KILL => "G";
22 use constant CLIENT_OK => "H";
24 # ======================================================================
25 # Globals
26 # ======================================================================
28 my $scriptName = $0;
29 $scriptName =~ s/^(.*)\\//;
31 my $depotdir = "/swg";
32 my $builddir = "/mnt/misc/builds";
33 my $logfile = "test_build.log";
34 my $win32machine = "64.37.133.173";
35 my $port = "98514";
36 my $emailRecipients = "vthakkar\@soe.sony.com";
38 my $waittime = "180";
39 my $branch = "";
40 my $oldbootleg = "";
41 my $newbootleg = "";
42 my $loginpid;
43 my $taskpid;
45 my $numbootlegs = 7;
47 my @steps = (0, 0, 0, 0);
49 # ======================================================================
50 # Subroutines
51 # ======================================================================
53 sub usage
55 print "\n\t$scriptName <optional parameters> <branch>\n\n".
56 "\tOptional parameters:\n\n".
57 "\t\t--install\t: Install newest build\n".
58 "\t\t--test\t\t: Test build\n".
59 "\t\t--email\t\t: Send email about results\n".
60 "\t\t--upkeep\t: Perform upkeep on bootleg directories\n";
61 die "\n";
64 sub writelog
66 my $message = shift @_;
67 chomp $message;
68 my ($sec, $min, $hr, $day, $mon, $yr) = localtime time;
69 my $timestamp = sprintf "%4s-%02s-%02s\t%02s:%02s:%02s", ($yr + 1900), ($mon + 1), $day, $hr, $min, $sec;
71 print LOG join("\t", $timestamp, $message), "\n";
74 sub fatal
76 my $message = shift @_;
77 print "Fatal error running: $message\n";
78 writelog("Fatal error running: $message");
79 close(LOG);
80 die;
83 sub unbuffer
85 my $oldSelect = select($_[0]);
86 $| = 1;
87 select($oldSelect);
90 sub unbufferReadline
92 my ($fh) = @_;
93 my $buffer;
94 my $return = "";
95 while(sysread($fh, $buffer, 1))
97 $return .= $buffer;
98 last if($buffer eq "\n");
100 return $return;
103 sub perforceWhere
105 local $_;
107 # find out where a perforce file resides on the local machine
108 my $result;
110 open(P4, "p4 where $_[0] |");
111 $_ = <P4>;
112 chomp;
113 my @where = split;
114 $result = $where[2];
115 close(P4);
118 return $result;
122 sub openClientSocket
124 socket(SOCKET, PF_INET, SOCK_STREAM, getprotobyname('tcp')) || closeServer("socket failed\n");
126 my $destination = inet_aton($win32machine) || closeServer("inet_aton failed\n");
127 my $paddr = sockaddr_in($port, $destination);
128 connect(SOCKET, $paddr) || closeServer("connect failed\n");
130 # unbuffer the socket
131 my $oldSelect = select(SOCKET);
132 $| = 1;
133 select($oldSelect);
135 # put the socket into binary mode
136 binmode SOCKET;
140 sub getCurrentBootleg
142 my $bootleg = 0;
144 open(VER, perforceWhere("//depot/swg/$branch/tools/VersionNumber") . " -r ".perforceWhere("//depot/swg/$branch/bootleg/linux/debug/lib/libsharedFoundataion.so")." |");
145 while(<VER>)
147 $bootleg = $1 if(/\s(\d+)\.0 bootleg/);
149 close(VER);
151 return $bootleg;
155 sub installBootleg
157 print "Installing bootleg...\n";
158 writelog("Installing bootleg");
160 open(INSTALL, "perl " . perforceWhere("//depot/swg/current/tools/InstallBootleg.pl") . " --list --force_newest --server_only --install_as_build_cluster --update_database $branch |") or fatal "Error running InstallBootleg.pl\n";
162 my $complete = 0;
164 while(<INSTALL>)
166 print;
167 writelog($_);
168 $complete = 1 if(/^Update complete\./);
169 $oldbootleg = $1 if($oldbootleg eq "" && /^\d+\s+(\d+)\s+blessed/);
170 $newbootleg = $1 if(/^Updating to build: (\d+)/);
173 close(INSTALL);
175 print "Bootleg installation incomplete\n" if(!$complete);
176 print "Completed installing bootleg.\n\n" if($complete);
177 writelog("OldBootleg: $oldbootleg, InstallBootleg complete: $complete");
179 return $complete;
182 sub closeServer
184 print "Fatal Error: Killing forked processes\n";
185 endServer();
186 fatal $_[0];
189 sub startServer
191 my $loginServer = "debug/LoginServer";
192 my $taskManager = "debug/TaskManager";
194 writelog("Starting Server");
195 my $serverdir = perforceWhere("//depot/swg/$branch/bootleg/linux/fakefile");
196 $serverdir =~ s/fakefile$//;
197 chdir($serverdir) || fatal "Cannot change directory to $serverdir\n";
199 print "Starting up server...\n";
200 $loginpid = open(LOGINSERVER, "$loginServer -- \@loginServer.cfg 2>&1 |") or closeServer("Can't open LoginServer\n");
201 binmode LOGINSERVER;
203 while(<LOGINSERVER>)
205 writelog("LoginServer: $_") if(/\S+/);
206 last if(/^Cluster \d+:/);
209 $taskpid = open(TASKMANAGER, "$taskManager -- \@taskmanager.cfg 2>&1 |") or closeServer("Can't open TaskManager\n");
210 binmode TASKMANAGER;
212 while(<TASKMANAGER>)
214 writelog("TaskManager: $_") if(/\S+/);
215 last if(/^Preload finished on all planets/);
219 sub endServer
221 writelog("Ending Server");
222 print "Shutting down server.\n";
223 kill 1, $taskpid if(defined $taskpid);
224 kill 1, $loginpid if(defined $loginpid);
225 system("killall CommoditiesServer");
226 system("killall ChatServer");
227 close(TASKMANAGER);
228 close(LOGINSERVER);
231 sub startClient
233 writelog("Starting Client");
234 print "Starting up client...\n";
236 openClientSocket();
238 print SOCKET START_BOOTLEG_TEST;
239 print SOCKET pack("N", length $branch);
240 print SOCKET $branch;
243 sub endClient
245 writelog("Ending Client");
246 print SOCKET CLIENT_KILL;
247 print "Shutting down client.\n";
248 close(SOCKET);
251 sub checkResponses
253 writelog("Verifying server and client responses");
254 my $loginsuccess = 0;
255 my $tasksuccess = 0;
256 my $buffer;
258 print "Verifying client and server have same bootleg installation.\n";
259 read(SOCKET, $buffer, 4) == 4 or fatal "Error reading from win32 machine\n";
260 my $clientbootleg = unpack("N", $buffer);
262 $newbootleg = getCurrentBootleg() if(!defined $newbootleg);
264 if($clientbootleg ne $newbootleg)
266 writelog("Mismatch in client / server bootlegs - client: $clientbootleg, server: $newbootleg");
267 print "Mismatch in client / server bootlegs - client: $clientbootleg, server: $newbootleg\n";
268 print SOCKET BOOTLEG_MISMATCH;
269 return 0;
271 print "Both client and server have bootleg $newbootleg installed\n";
272 writelog("Both client and server have bootleg $newbootleg installed");
274 print SOCKET SERVER_READY;
276 my $starttime = time;
277 writelog("Beginning test with client - timeout of $waittime seconds");
279 # used to create non-blocking reading of both filehandles
280 while(1)
282 my $rin = '';
283 my $rout;
284 my $line;
285 vec($rin, fileno(LOGINSERVER), 1) = 1;
286 vec($rin, fileno(TASKMANAGER), 1) = 1;
288 if(select($rout=$rin, undef, undef, 0))
290 if (vec($rout, fileno(LOGINSERVER), 1))
292 $line = unbufferReadline(\*LOGINSERVER);
293 if(defined $line)
295 writelog("LoginServer: $line") if($line =~ /\S+/);
296 ++$loginsuccess if($loginsuccess == 0 && $line =~ /^connection opened for service on port \d+/);
297 ++$loginsuccess if($loginsuccess == 1 && $line =~ /^Encrypting with key:/);
298 ++$loginsuccess if($loginsuccess == 2 && $line =~ /^Client connected\. Station Id: \d+, Username: bootleg/);
299 ++$loginsuccess if($loginsuccess == 3 && $line =~ /^Client \d+ disconnected/);
301 last if ($line =~ /ERROR/ or $line =~ /FATAL/);
304 if (vec($rout, fileno(TASKMANAGER), 1))
306 $line = unbufferReadline(\*TASKMANAGER);
307 if(defined $line)
309 writelog("TaskManager: $line") if($line =~ /\S+/);
310 ++$tasksuccess if($tasksuccess == 0 && $line =~ /^connection opened for service on port \d+/);
311 ++$tasksuccess if($tasksuccess == 1 && $line =~ /^Opened connection with client/);
312 ++$tasksuccess if($tasksuccess == 2 && $line =~ /^Recieved ClientIdMsg/);
313 ++$tasksuccess if($tasksuccess == 3 && $line =~ /^Decrypting with key: /);
314 ++$tasksuccess if($tasksuccess == 4 && $line =~ /^succeeded/);
315 ++$tasksuccess if($tasksuccess == 5 && $line =~ /^ValidateAccountMessage/);
316 ++$tasksuccess if($tasksuccess == 6 && $line =~ /^ValidateAccountReplyMessage/);
317 ++$tasksuccess if($tasksuccess == 7 && $line =~ /^Permissions for \d+:/);
318 ++$tasksuccess if($tasksuccess == 8 && $line =~ /canLogin/);
319 ++$tasksuccess if($tasksuccess == 9 && $line =~ /canCreateRegularCharacter/);
320 ++$tasksuccess if($tasksuccess == 10 && $line =~ /^Recvd SelectCharacter message for \d+/);
321 ++$tasksuccess if($tasksuccess == 11 && $line =~ /^Got ValidateCharacterForLoginMessage acct \d+, character \d+/);
322 ++$tasksuccess if($tasksuccess == 12 && $line =~ /^Pending character \d+ is logging in or dropping/);
324 last if ($line =~ /ERROR/ or $line =~ /FATAL/);
329 return 0 if((time - $starttime) > $waittime);
330 last if($loginsuccess == 4 && $tasksuccess == 13);
333 writelog("LoginServer success: $loginsuccess/4, Taskmanager success: $tasksuccess/13");
334 return 0 if($loginsuccess != 4 || $tasksuccess != 13);
336 # Tell win32 machine that the client is ok (don't need to kill it)
337 print SOCKET CLIENT_OK;
339 read(SOCKET, $buffer, 1) == 1 or fatal "Error reading from win32 machine\n";
341 my $clientsuccess = 0;
342 $clientsuccess = 1 if($buffer eq SUCCESSFUL_TEST);
344 writelog("Client success: $clientsuccess/1");
345 return 0 if($clientsuccess != 1);
347 return 1;
350 sub testBootleg
352 print "Testing build...\n";
353 writelog("Testing build");
354 my $test = 0;
356 startServer();
357 startClient();
359 $test = checkResponses();
361 endServer();
362 endClient();
364 fatal "Test for build $newbootleg unsuccessful\n" if(!$test);
365 print "Testing successful.\n\n";
366 writelog("Test for build successful: $test");
367 open(BLESS, ">$builddir/$branch/$newbootleg/blessed.txt");
368 close(BLESS);
370 return 1;
373 sub email
375 # If we don't know the old bootleg (from install), get it
376 if($oldbootleg eq "")
378 my @bootlegs;
380 opendir DH, "$builddir/$branch" or fatal "Cannot open $builddir/$branch: $!\n";
381 foreach (readdir DH)
383 push @bootlegs, $_ if(/^\d+$/ && -d ("$builddir/$branch/$_"));
385 closedir DH;
387 foreach (sort {$b <=> $a} @bootlegs)
389 if(-e "$builddir/$branch/$_/blessed.txt")
391 # This is the first blessed bootleg
392 $newbootleg = $_ if($newbootleg eq "");
394 # This is the second blessed bootleg
395 $oldbootleg = $_ if($newbootleg ne $_);
397 last if($oldbootleg ne "");
401 print "Emailing about changes from bootleg $oldbootleg to $newbootleg...\n";
402 writelog("Emailing changes from $oldbootleg to $newbootleg");
403 return 0 if($oldbootleg eq "");
404 open(EMAIL, "| mail -s \"[bootleg] $branch.$newbootleg.0 is up\" $emailRecipients");
406 print EMAIL "${builddir}/\n".
407 "\n-Vijay\n\n";
409 print EMAIL "Changes between $oldbootleg and $newbootleg\n";
411 open(CHANGES, "perl ${depotdir}/swg/current/tools/BuildChanges.pl -i //depot/swg/$branch/... $oldbootleg $newbootleg |");
412 while(<CHANGES>)
414 next if(/^Change (\d+) on/ || /^\[(public|internal)\]/ || /^\n/ || /.?none.?/i || /n(\/|\.)a/i || /^---/ || /ignoring script recompile/i);
415 s/^\s*-?\s*//;
416 print EMAIL "\t- $_";
418 close(CHANGES);
419 print "Completed emailing.\n\n";
420 writelog("Completed emailing.");
422 return 1;
425 sub upkeep
427 my $removedbootlegs = 0;
429 print "Performing upkeep on bootleg directory for $branch...\n";
430 writelog("Performing upkeep on bootleg directory for $branch...");
432 my $controller = perforceWhere("//depot/swg/current/tools/build_cluster_controller.pl");
433 my $buildcluster;
435 open(BUILD, "perl $controller -bootleg-version 2>&1 |");
436 while(<BUILD>)
438 $buildcluster = $1 if(/^Build cluster bootleg version is: (\d+)/);
440 close(BUILD);
442 return 0 if(!defined $buildcluster);
444 my @bootlegs;
445 opendir DH, "$builddir/$branch" or fatal "Cannot open $builddir/$branch: $!\n";
446 foreach (readdir DH)
448 push @bootlegs, $_ if(/^\d+$/ && -d ("$builddir/$branch/$_"));
450 closedir DH;
452 @bootlegs = sort { $a <=> $b } @bootlegs;
454 while(@bootlegs > $numbootlegs)
456 my $bootleg = shift @bootlegs;
457 next if($buildcluster == $bootleg);
459 print STDERR "Removing bootleg $bootleg...\n";
460 writelog("Removing bootleg $bootleg...");
461 system("rm -fr $builddir/$branch/$branch/$bootleg");
462 ++$removedbootlegs;
465 print STDERR "Completed upkeep on bootleg directory - removed $removedbootlegs bootlegs.\n";
466 writelog("Completed upkeep on bootleg directory - removed $removedbootlegs bootlegs.");
468 return 1;
471 # ======================================================================
472 # Main
473 # ======================================================================
475 usage() if(!GetOptions('install' => \$steps[0], 'test' => \$steps[1], 'email' => \$steps[2], 'upkeep' => \$steps[3]));
476 usage() if(@ARGV != 1);
478 # open the log file
479 open(LOG, ">>$logfile");
480 unbuffer(\*LOG);
482 $branch = shift;
483 print "Beginning test for branch $branch\n";
484 writelog("Beginning test for branch $branch");
486 installBootleg() || fatal "installBootleg" if($steps[0]);
487 testBootleg() || fatal "testBootleg" if($steps[1]);
488 email() || fatal "email" if($steps[2]);
489 upkeep() || fatal "upkeep" if($steps[3]);
491 print "Test of $newbootleg complete.\n";
492 writelog("test of $newbootleg complete");
494 close(LOG);