# Before `make install' is performed this script should be runnable with
# `make test'. After `make install' it should work as `perl test.pl'

######################### We start with some black magic to print on failure.

# Change 1..1 below to 1..last_test_to_print .
# (It may become useful if the test is moved to ./t subdirectory.)

BEGIN { $| = 1; print "1..88\n"; }
END {print "not ok 1\n" unless $loaded;}
use Socket;
use Zephyr;
use Zephyr::Notice;
$loaded = 1;
print "ok 1\n";

######################### End of black magic.

# Insert your test code below (better if it prints "ok 13"
# (correspondingly "not ok 13") depending on the success of chunk 13
# of the test code):

# get Athena version
my $athvers;

if (open(AVERSION, "/etc/athena/version")) {
    my @tmp = <AVERSION>;	# suck in the file
    close(AVERSION);

    @tmp = ($tmp[$#tmp] =~ /Version\s+(\d+\.\d+)/);
    $athvers = $tmp[0];
} else {
    # Not an athena workstation
    $athvers = 0;
}

# 8.1 doesn't implement InitLocationInfo(), so we use the $ENV{'DISPLAY'}
# hack...but first, we'll save the old display so we can restore it later.

my $savedisp = $ENV{'DISPLAY'};

# Test  2: InitLocationInfo() (Athena 8.2 only; dummy in 8.1)
print((Zephyr::InitLocationInfo($ENV{'HOST'}, 'pZephyr')) ?
      "ok 2\n" : "not ok 2\n");

my $expose;

# Test  3: ParseExposureLevel() (Athena 8.2 only; dummy in 8.1)
print(($expose = Zephyr::ParseExposureLevel(Zephyr::EXPOSE_NETANN())) ?
      "ok 3\n" : "not ok 3\n");

# Test  4: SetLocation()
print((Zephyr::SetLocation($expose)) ? "ok 4\n" : "not ok 4\n");

my $user = $ENV{'USER'} . '@' . Zephyr::GetRealm();

# Test  5: GetRealm()
if ($user =~ /.*\@[a-zA-Z_.]+/) {
    print "ok 5\n";
} else {
    print "not ok 5\n";
}

# Test  6: GetSender()
print(($user eq Zephyr::GetSender()) ? "ok 6\n" : "not ok 6\n");

my @locs;

# Test  7: LocateUser()
print((@locs = Zephyr::LocateUser($user, Zephyr::ZAUTH())) ?
      "ok 7\n" : "not ok 7\n");

my ($loc, $tmp);

foreach $tmp (@locs) {
    $loc = $tmp
	if ($tmp->[2] eq "pZephyr");
}

# Test  8: LocateUser() function
print((defined($loc)) ? "ok 8\n" : "not ok 8\n");

# Test  9: UnsetLocation()
print((Zephyr::UnsetLocation()) ? "ok 9\n" : "not ok 9\n");

my @tmp = Zephyr::LocateUser($user, Zephyr::ZAUTH());

# Test 10: UnsetLocation() function and LocateUser() function
print(($#tmp == $#locs - 1) ? "ok 10\n" : "not ok 10\n");

# Test 11: FlushMyLocations()
print((Zephyr::FlushMyLocations()) ? "ok 11\n" : "not ok 11\n");

$tmp = Zephyr::LocateUser($user, ZAUTH);

# Test 12: FlushMyLocations() function and LocateUser()
#   function in scalar context
print(($tmp == 0) ? "ok 12\n" : "not ok 12\n");

# be nice to the debugger and set him visible again
$ENV{'DISPLAY'} = $savedisp;
system("zctl unhide");

# Test 13: GetFD()
print((Zephyr::GetFD() < 0) ? "not ok 13\n" : "ok 13\n");

# Test 14: SetFD()
print((Zephyr::SetFD(5)) ? "ok 14\n" : "not ok 14\n");

# Test 15: SetFD()/GetFD function
print((Zephyr::GetFD() == 5) ? "ok 15\n" : "not ok 15\n");

# Test 16: ClosePort()
print((Zephyr::ClosePort()) ? "ok 16\n" : "not ok 16\n");

my $port;

# Test 17: OpenPort()
print(($port = Zephyr::OpenPort()) ? "ok 17\n" : "not ok 17\n");

my ($destaddr, $badaddr);

$badaddr = sockaddr_in(80, inet_aton(10.0.0.0));

# Test 18: GetDestAddr()
print(($destaddr = Zephyr::GetDestAddr()) ? "ok 18\n" : "not ok 18\n");

# Test 19: SetDestAddr()
print((Zephyr::SetDestAddr($badaddr)) ? "ok 19\n" : "not ok 19\n");

# Test 20: SetDestAddr()/GetDestAddr() function
print((Zephyr::GetDestAddr() eq $badaddr) ? "ok 20\n" : "not ok 20\n");

# Test 21: SetDestAddr() (put correct value back)
print((Zephyr::SetDestAddr($destaddr)) ? "ok 21\n" : "not ok 21\n");

# Test 22: SetVariable()
print((Zephyr::SetVariable("pZephyrTest", "test")) ?
      "ok 22\n" : "not ok 22\n");

# Test 23: GetVariable(), SetVariable() function
print((Zephyr::GetVariable("pZephyrTest") eq "test") ?
      "ok 23\n" : "not ok 23\n");

# Test 24: UnsetVariable()
print((Zephyr::UnsetVariable("pZephyrTest")) ? "ok 24\n" : "not ok 24\n");

# Test 25: UnsetVariable() function -- note '!'; should fail
print(!(Zephyr::GetVariable("pZephyrTest")) ? "ok 25\n" : "not ok 25\n");

# Test 26: set up to check SetVariable() function
print((Zephyr::SetVariable("pZephyrTest", "test")) ?
      "ok 26\n" : "not ok 26\n");

# Test 27: SetVariable(), one argument
print((Zephyr::SetVariable("pZephyrTest")) ? "ok 27\n" : "not ok 27\n");

# Test 28: SetVariable(), one argument, function -- note '!'; should fail
print(!(Zephyr::GetVariable("pZephyrTest")) ? "ok 28\n" : "not ok 28\n");

# need a temporary file; NOTE THIS IS NOT THAT SECURE
for ($tmp = 0; -e "/tmp/wg.pZephyr.$tmp"; $tmp++) {
}

my $savewg = $ENV{'WGFILE'};

$ENV{'WGFILE'} = "/tmp/wg.pZephyr.$tmp";

# record our port number
open(TMP, "> $ENV{'WGFILE'}");
print TMP "$port\n";
close(TMP);

my $wgport;

# Test 29: GetWGPort()
print(($wgport = Zephyr::GetWGPort()) ? "ok 29\n" : "not ok 29\n");

# Test 30: GetWGPort() function
print(($wgport == $port) ? "ok 30\n" : "not ok 30\n");

# done with temp file; NOTE THIS IS NOT THAT SECURE
unlink($ENV{'WGFILE'});
$ENV{'WGFILE'} = $savewg;

# Test 31: SubscribeTo()
print((Zephyr::SubscribeTo()) ? "ok 31\n" : "not ok 31\n");

my @subs;
#my @defsubs;

# Test 32: GetSubscriptions()
print((@subs = Zephyr::GetSubscriptions()) ? "ok 32\n" : "not ok 32\n");

# GetDefaultSubscriptions() doesn't currently work due to a zephyr _server_
# bug (that will get fixed when the zephyr servers are upgraded)

# Test 33: GetDefaultSubscriptions()
print((@defsubs = Zephyr::GetDefaultSubscriptions()) ?
      "ok 33\n" : "not ok 33\n");

# This test will fail because the GetDefaultSubscriptions() test above
# fails due to the server bug

# Test 34: SubscribeTo()/GetSubscriptions()/GetDefaultSubscriptions() function
$tmp = 0;
if ($#subs == $#defsubs) {
    for (; $tmp <= $#subs; $tmp++) {
	last
	    if ($subs[$tmp][0] ne $defsubs[$tmp][0] or
		$subs[$tmp][1] ne $defsubs[$tmp][1] or
		$subs[$tmp][2] ne $defsubs[$tmp][2]);
    }
}

if ($tmp == scalar(@subs)) {
    print("ok 34\n");
} else {
    print("not ok 34\n");
}

# Test 35: UnsubscribeTo()
print((Zephyr::UnsubscribeTo($subs[0])) ? "ok 35\n" : "not ok 35\n");

# Test 36: UnsubscribeTo() function
print(((scalar Zephyr::GetSubscriptions()) == $#subs) ?
      "ok 36\n" : "not ok 36\n");

# Test 37: CancelSubscriptions()
print((Zephyr::CancelSubscriptions()) ? "ok 37\n" : "not ok 37\n");

# Test 38: CancelSubscriptions() function
print(((scalar Zephyr::GetSubscriptions()) == 0) ? "ok 38\n" : "not ok 38\n");

# Test 39: SubscribeToSansDefaults()
print((Zephyr::SubscribeToSansDefaults([ "pzephyr", "test",
				         Zephyr::GetSender() ])) ?
      "ok 39\n" : "not ok 39\n");

# Test 40: GetSubscriptions()
print((@subs = Zephyr::GetSubscriptions()) ? "ok 40\n" : "not ok 40\n");

# Test 41: GetSubscriptions() function
print(($#subs == 0) ? "ok 41\n" : "not ok 41\n");

# Test 42: SubscribeToSansDefaults()/GetSubscriptions() function
print(($subs[0][0] eq "pzephyr" and
       $subs[0][1] eq "test" and
       $subs[0][2] eq Zephyr::GetSender()) ? "ok 42\n" : "not ok 42\n");

if (! -e $ENV{'WGFILE'}) {
    print "ok 43\nok 44\nok 45\n";
} else {
    $wgport = Zephyr::GetWGPort();

    # Test 43: GetSubscriptions()
    print((@subs = Zephyr::GetSubscriptions($wgport)) ?
	  "ok 43\n" : "not ok 43\n");

    # Test 44: SubscribeToSansDefaults()
    print((Zephyr::SubscribeToSansDefaults($wgport, [ "pzephyr", "test",
						      Zephyr::GetSender() ])) ?
	  "ok 44\n" : "not ok 44\n");

    # Test 45: UnsubscribeTo()
    print((Zephyr::UnsubscribeTo($wgport, [ "pzephyr", "test",
					    Zephyr::GetSender() ])) ?
	  "ok 45\n" : "not ok 45\n");
}

my $ascii;

# Test 46: MakeAscii()
print((($ascii = Zephyr::MakeAscii("ABCabc")) eq "0x41424361 0x6263") ?
      "ok 46\n" : "not ok 46\n");

# Test 47: ReadAscii()
print((Zephyr::ReadAscii($ascii) eq "ABCabc") ? "ok 47\n" : "not ok 47\n");

# Test 48: MakeAscii16()
print((($ascii = Zephyr::MakeAscii16(32)) eq "0x0020") ?
      "ok 48\n" : "not ok 48\n");

# Test 49: ReadAscii16()
print(((Zephyr::ReadAscii16($ascii) + 1) == 33) ? "ok 49\n" : "not ok 49\n");

# Test 50: MakeAscii32()
print((($ascii = Zephyr::MakeAscii32(70000)) eq "0x00011170") ?
      "ok 50\n" : "not ok 50\n");

# Test 51: ReadAscii32()
print(((Zephyr::ReadAscii32($ascii) + 1) == 70001) ?
      "ok 51\n" : "not ok 51\n");

my $notice;

# Test 52: new Zephyr::Notice()
print(($notice = new Zephyr::Notice()) ? "ok 52\n" : "not ok 52\n");

# Test 53: new Zephyr::Notice()
print(($notice = new Zephyr::Notice(
				    'kind'	=> UNACKED,
				    'port'	=> 80,
				    'auth'	=> ZNOAUTH,
				    'targets'	=> [
						    "$ENV{USER}",
						    ["help"],
						    ["syslog", "starkiller"],
						    ["command", "foobar",
						     "$ENV{USER}"]
						    ],
				    'opcode'	=> 'pong',
				    'sender'	=> 'fake',
				    'format'	=> 'an empty place',
				    'other'	=> [
						    "foo",
						    "bar"
						    ],
				    'message'	=> [
						    "signature",
						    "message"
						    ]
				    )) ? "ok 53\n" : "not ok 53\n");

# Test 54: getKind()
print(($notice->getKind() == UNACKED) ? "ok 54\n" : "not ok 54\n");

# Test 55: getPort()
print(($notice->getPort() == 80) ? "ok 55\n" : "not ok 55\n");

# Test 56: getAuth()
print(($notice->getAuth() == ZNOAUTH) ? "ok 56\n" : "not ok 56\n");

# Test 57: getTargets()
my @targets;
print((@targets = $notice->getTargets()) ? "ok 57\n" : "not ok 57\n");

# Test 58: getTargets() - "recipient"
print(($targets[0][0] eq "message" and
       $targets[0][1] eq "personal" and
       $targets[0][2] eq "$ENV{USER}") ? "ok 58\n" : "not ok 58\n");

# Test 59: getTargets() - [ "instance" ]
print(($targets[1][0] eq "message" and
       $targets[1][1] eq "help" and
       $targets[1][2] eq "") ? "ok 59\n" : "not ok 59\n");

# Test 60: getTargets() - [ "class", "instance" ]
print(($targets[2][0] eq "syslog" and
       $targets[2][1] eq "starkiller" and
       $targets[2][2] eq "") ? "ok 60\n" : "not ok 60\n");

# Test 61: getTargets() - [ "class", "instance", "recipient" ]
print(($targets[3][0] eq "command" and
       $targets[3][1] eq "foobar" and
       $targets[3][2] eq "$ENV{USER}") ? "ok 61\n" : "not ok 61\n");

# Test 62: getOpcode()
print(($notice->getOpcode() eq "pong") ? "ok 62\n" : "not ok 62\n");

# Test 63: getSender()
print(($notice->getSender() eq "fake") ? "ok 63\n" : "not ok 63\n");

# Test 64: getFormat()
print(($notice->getFormat() eq "an empty place") ? "ok 64\n" : "not ok 64\n");

# Test 65: getOther()
my @other;
print((@other = $notice->getOther()) ? "ok 65\n" : "not ok 65\n");

# Test 66: getOther() function
print(($other[0] eq "foo" and
       $other[1] eq "bar" and
       $#other == 1) ? "ok 66\n" : "not ok 66\n");

# Test 67: getMessage() function
my @msg;
print((@msg = $notice->getMessage()) ? "ok 67\n" : "not ok 67\n");

# Test 68: getMessage() function
print(($msg[0] eq "signature" and
       $msg[1] eq "message" and
       $#msg == 1) ? "ok 68\n" : "not ok 68\n");

# Test 69: set()
print(($notice->set('opcode' => 'barfoo')) ? "ok 69\n" : "not ok 69\n");

# Test 70: set() function
print(($notice->getOpcode() eq "barfoo") ? "ok 70\n" : "not ok 70\n");

# Test 71: wasSent()
print(!($notice->wasSent()) ? "ok 71\n" : "not ok 71\n");

# Test 72: wasReceived()
print(!($notice->wasReceived()) ? "ok 72\n" : "not ok 72\n");

# Test 73: isImmutable()
print(!($notice->isImmutable()) ? "ok 73\n" : "not ok 73\n");

# Test 74: send()
my @notices = new Zephyr::Notice('targets' => [Zephyr::GetSender()],
				 'message' => ['welcome to pZephyr'])->send();
my $tmp = 1;
foreach my $notice (@notices) {
  if ($notice->[1]) {
    $temp = 0;
  }
}
print $tmp ? "ok 74\n" : "not ok 74\n";

# Test 75: Pending()
print((Zephyr::Pending() >= 0) ? "ok 75\n" : "not ok 75\n");

# Test 76: QLength()
print((Zephyr::QLength() >= 0) ? "ok 76\n" : "not ok 76\n");

@notices = new Zephyr::Notice('targets' => [["pzephyr",
					     "test",
					     Zephyr::GetSender()]],
			      'message' => ['test message field 0',
					    'test message field 1',
					    'test message field 2',
					    'test message field 3'])->send();

# @subs = Zephyr::GetSubscriptions();
# foreach $asub (@subs) {
#     print "<$asub->[0], $asub->[1], $asub->[2]>\n";
# }

# sleep long enough to receive the replies...
sleep(1);

# Test 77: Pending()
print((Zephyr::Pending() > 0) ? "ok 77\n" : "not ok 77\n");

# Test 78: QLength()
print((Zephyr::QLength() > 0) ? "ok 78\n" : "not ok 78\n");

my $nnot;

# Test 79: PeekIfNotice()
$notice = $notices[0]->[0];
print(($nnot = Zephyr::PeekIfNotice(Zephyr::PRED_UID, $notice->getUID())) ?
      "ok 79\n" : "not ok 79\n");

my @msg;

@msg = $nnot->getMessage();

# Test 80: PeekIfNotice() function
print(($msg[0] eq "test message field 0" &&
       $msg[1] eq "test message field 1" &&
       $msg[2] eq "test message field 2" &&
       $msg[3] eq "test message field 3") ? "ok 80\n" : "not ok 80\n");

sub pred {
    my ($notice, $onotice) = @_;

    return Zephyr::CompareUID($notice->getUID(), $onotice->getUID());
}

# Test 81: PeekIfNotice()
print(($nnot = Zephyr::PeekIfNotice(\&pred, $notice)) ?
      "ok 81\n" : "not ok 81\n");

@msg = $nnot->getMessage();

# Test 82: PeekIfNotice() function
print(($msg[0] eq "test message field 0" &&
       $msg[1] eq "test message field 1" &&
       $msg[2] eq "test message field 2" &&
       $msg[3] eq "test message field 3") ? "ok 82\n" : "not ok 82\n");

my $zald;

# Test 83: RequestLocations()
print(($zald = Zephyr::RequestLocations(Zephyr::GetSender(), Zephyr::ZAUTH(),
					Zephyr::UNACKED())) ?
      "ok 83\n" : "not ok 83\n");

# Test 84: ALD::getUID()
print(($zald->getUID()) ? "ok 84\n" : "not ok 84\n");

# Test 85: RequestLocations() function
print(($notice = Zephyr::IfNotice(Zephyr::PRED_ALD(), $zald)) ?
      "ok 85\n" : "not ok 85\n");

my $user;

# Test 86: ParseLocations()
print((($user, @locs) = Zephyr::ParseLocations($notice, $zald)) ?
      "ok 86\n" : "not ok 86\n");

# Test 87: ParseLocations() function
print(($user eq Zephyr::GetSender()) ? "ok 87\n" : "not ok 87\n");

# Test 88: ParseLocations() function
print(($#locs >= 0) ? "ok 88\n" : "not ok 88\n");
