#!/usr/bin/perl
################################################################
# \file AutoTestRun.pl
#
# 
#
# Usage:
#   AutoTestRun.pl <simdir> <romfile>
#
# \license
# 
# Copyright (c) 2003 PalmOne Inc., All Rights Reserved
#
# \author Scott Vail
# 
################################################################

use lib "./Perl";


use EmRPC;
use EmFunctions;
use IO::Socket;
use IO::File;
use LWP::UserAgent; 
use HTTP::Request::Common qw(POST); 



use constant kThLoopbackName			=> 'localhost';
use constant kThTestHarnessAppName		=> 'THApp';
use constant kThDefaultPostURL			=> 'http://mambo/thparser.php';
use constant kThDefaultHostControlPort	=> 2000;
use constant kThDefaultListenPort		=> 33713;
use constant kThProjectNameFile			=> 'ThProjectName.txt';


my $simPid = 0;
my $harnessPid = 0;


sub main(@);
main (@ARGV);




##################################################################
# help
##
# Simple instructions on how to use the app.
#
# \author  Scott Vail
#
##################################################################

sub help()
{
  print "$ARG[0] <simdir> <rom>";
  exit 0;
}


sub MyKill ($)
{
  my ($arg) = @_;
  my $proclist = `./pulist.exe`;
  my @kills;
  while ($proclist =~ /\b$arg\s*(\d+)/g) {
	push @kills, $1;
  }

  if (scalar @kills > 0) {
    system "./Kill.exe", @kills;
  }
}


##################################################################
# CleanUp
##
# Clean up and kill the simulator.
#
# \author  Scott Vail
#
##################################################################

sub CleanUp()
{
  MyKill ("PalmSim.exe");
  kill $simPid;
  if (-e "c:/PALM/SimSlotDriverVolume") {
	system "rm -rf c:/PALM/SimSlotDriverVolume";
  }
}


##################################################################
# GetDisplayDimensions
##
# Get the screen resolution.
#
# \author  Scott Vail
#
##################################################################

sub GetDisplayDimensions()
{
  my $err;
  my $result;
  my $height;
  my $width;
  my $host = kThLoopbackName;
  my $port = kThDefaultHostControlPort;

  OpenConnection ("$host:$port#Console");

  ($err, $result) = HwrDisplayAttributes (0, hwrDispWidth, "xx");
  if ($err) {
    $width = 320;
  }
  else {
    $width = unpack ("n", $result);
  }

  ($err, $result) = HwrDisplayAttributes (0, hwrDispHeight, "xx");
  if ($err) {
    $height = 320;
  }
  else {
    $height = unpack ("n", $result);
  }

  CloseConnection ();

  return ($height, $width);
}


##################################################################
# SkipStartup
##
# Use the most appropriate SkipStartup.*.pl script based 
# on the simulator ROM type.
#
# \author  Scott Vail
#
##################################################################

sub SkipStartup($)
{
  my ($target) = @_;
  my @list;
  my $filename;

  my $carrier;
  my $radio;
  my $reldbg;
  my $oppreldbg;
  my $lang;
  my $region;
  my $height;
  my $width;

  ($height, $width) = GetDisplayDimensions ();

  $oppreldbg = "Debug";

  # First try using the SkipStartup associated
  # with the target of the build...

  for ($target) {
    m/(.*)(Gsm|Cdma)(Rel|Debug)(..)(..)/o;
	$carrier = $1;
	$radio = $2;
	$reldbg = $3;
	$lang = $4;
	$region = $5;
  }

  # Opposite of rel/debug

  if (defined $reldbg) {
    if ($reldbg =~ "Debug") {
	  $oppreldbg = "Rel";
	}
  }

  # Create a list of possible SkipStartup 
  # scripts beginning with the most specific to
  # the current ROM to the least...

  @list = (
	"${carrier}${radio}${reldbg}${lang}${region}",
	"${carrier}${radio}${oppreldbg}${lang}${region}",
	"${carrier}${radio}${lang}${region}",
	"${carrier}${lang}${region}",
	"${carrier}${lang}",
	"${carrier}${region}",
	"${carrier}",
	"${radio}${reldbg}${lang}${region}",
	"${radio}${oppreldbg}${lang}${region}",
	"${radio}${lang}${region}",
	"${radio}${lang}",
	"${radio}${region}",
	"${radio}",
	"");

  # Search for suitable SkipStartup scripts
  # in order of specificity...

  foreach (@list) {
    $filename = "SkipStartup";
	if (defined $_) {
	  $filename .= ".$_";
	}
	$filename .= ".pl";

	if (-e $filename) {
      print "using $filename : ${height}x${width}...\n";
	  if (system ("perl","$filename", "$height", "$width") != 0) {
		return 0;
	  }
	  last;
	}
  }

  return 1;
}


##################################################################
# ListenForResults
##
# Create a socket and listen for results from the test harness.
#
# \author  Scott Vail
#
##################################################################

sub ListenForResults()
{
  my $results;
  my $new_sock;
  my $sock;
  
  $sock = new IO::Socket::INET (
		LocalAddr 	=> kThLoopbackName, 
		LocalPort 	=> kThDefaultListenPort, 
		Proto 		=> 'tcp',
		Listen 		=> 1 );

  $sock || die "Could not create server $!\n";

  $new_sock = $sock->accept();
		
  while (defined ($line = <$new_sock>)) {
	$results .= $line;
  }
  $sock->close();

  return $results;
}


##################################################################
# WriteResults
##
# Write the results to a file.
#
# \author  Scott Vail
#
##################################################################

sub WriteResults($$)
{
  my ($results, $resultspath) = @_;
  my $file;
  
  $file = new IO::File;
  $file->open("> $resultspath") ||
	die "Could not create file $resultspath: $!\n";

  print $file $results;

  $file->close();
}


##################################################################
# PostResults
##
# Upload the results to the web.
#
# \author  Scott Vail
#
##################################################################

sub PostResults($$)
{
  my ($url, $resultspath) = @_;
  my $ua;
  my $req;
  
  $ua = new LWP::UserAgent;
  $req = $ua->request(POST "$url", 
	Content_Type => 'multipart/form-data', 
	Content => [filePath => ["$resultspath"],]);

  $req || die "Request failed";

  return $req->is_success;
}


##################################################################
# LaunchSimulator
##
# Start the simulator.
#
# \author  Scott Vail
#
##################################################################

sub LaunchSimulator($$)
{
  my ($simDir, $romName) = @_;
  my @args;

  @args = ("$simDir/PalmSim.exe", 
				"-rom:$simDir/$romName", 
				"-RedirectNetLibCalls:1", 
				"-SuppressAutoloadResetDialog:1");

  $simPid = fork ();
  if (defined $simPid) {
    if ($simPid == 0) {
	  exec (@args);
	  exit 0;
	}

	return 1;
  }

  return 0;
}


##################################################################
# LaunchTestHarness
##
# Launch the THApp in the Simulator.
#
# \author  Scott Vail
#
##################################################################

sub LaunchTestHarness()
{
  my $harnessPid, $testHarnessId;
  my $appName = kThTestHarnessAppName;
  my $launchCode = 0;
  my $host = kThLoopbackName;
  my $port = kThDefaultHostControlPort;

  OpenConnection ("$host:$port#Console");
  $testHarnessId = DmFindDatabase (0, $appName);
  CloseConnection ();
  if (!$testHarnessId) {
    print "No $appName found\n";
	return 0;
  }

  $harnessPid = fork ();
  if (defined $harnessPid) {
    if ($harnessPid == 0) {
	  sleep 1;
	  OpenConnection ("$host:$port#Console");
      $testHarnessId = DmFindDatabase (0, $appName);
	  $err = SysUIAppSwitch (0, $testHarnessId, $launchCode, 0);
      CloseConnection ();
	  if ($err) {
	    print "Error switching to $appName\n";
	  }
	  exit $err;
	}
  }

  return 1;
}


##################################################################
# main
##
# The main entry point of this script.
#
# \author  Scott Vail
#
##################################################################

sub main(@)
{
  my ($simdir, $romName, $buildNum, $type) = @_;
  my $results;
  my $filename;
  my $target;
  my $url;
  my $id;
  my $projname;

  chomp ($simdir);
  chomp ($romName);
  chomp ($buildNum);
  chomp ($type);

  if (!defined @_)
    {
	  help ();
	}

  if (!defined $buildNum) {
    $buildNum = 0;
  }

  if (!defined $type) {
    $type = "u";
  }

  for ($romName) {
    m/Simulator\.(.+)\.rom/o;
	$target = $1;
  }

  $projname = "TestRun";
  if (-e kThProjectNameFile) {
    open FILE, kThProjectNameFile;
	while (<FILE>) {
	  chomp;
	  if (/^(\w*)/) {
	    $projname = $1;
		last;
	  }
	}
	close FILE;
  }
  else {
    print kThProjectNameFile . " not found.\n";
  }

  print "Project name: $projname\n";

  # Make sure the simulator isn't already running.
  MyKill ("PalmSim.exe");
  # Make sure there isn't an NVFS file laying around
  if (-e "c:/PALM/SimSlotDriverVolume") {
	system "rm -rf c:/PALM/SimSlotDriverVolume";
  }

  print "Launching simulator...\n";
  if (!LaunchSimulator ($simdir, $romName)) {
    die "Cannot fork";
  }

  sleep 50;

  print "Tapping through startup screens...\n";
  if (!SkipStartup ($target)) {
	CleanUp ();
	die "Cannot SkipStartup";
  }

  sleep 10;

  print "Launching Test Harness...\n";
  if (!LaunchTestHarness ()) {
	CleanUp ();
	die "Error launching test harness"
  }

  print "Listening for results...\n";
  $results = ListenForResults ();
  if (! length ($results)) {
	CleanUp ();
    die "No results available";
  }

  $id = 0;
  do {
    $filename = "$projname.$target.$buildNum.$type.$id.xml";
	$id++;
  }
  until (! -e "$filename");

  print "Writing results to $filename...\n";
  WriteResults ($results, $filename);

  $url = kThDefaultPostURL;
  print "Posting results to $url...\n";
  if (!PostResults ($url, $filename)) {
    CleanUp ();
	die "Failed to post results";
  }

  CleanUp ();

  while (`./pulist.exe` =~ /\bPalmSim.exe\s*(\d+)/g) {
	if ($1 > 0) {
	  print "Simulator is still running!";
	  MyKill ("PalmSim.exe");
	}
  }

  print "Done!\n";
}


1;
