#!/usr/bin/perl -w
#
# Tests for basic krenew functionality.
#
# Written by Russ Allbery <rra@stanford.edu>
# Copyright 2008, 2009, 2011
#     The Board of Trustees of the Leland Stanford Junior University
#
# See LICENSE for licensing terms.

use Test::More;

# The full path to the newly-built krenew client.
our $KRENEW = "$ENV{BUILD}/../krenew";

# The path to our data directory, which contains the keytab to use to test.
our $DATA = "$ENV{BUILD}/data";

# Load our test utility programs.
require "$ENV{SOURCE}/libtest.pl";

# Decide whether we have the configuration to run the tests.
my $principal;
if (not -f "$DATA/test.keytab" or not -f "$DATA/test.principal") {
    plan skip_all => 'no keytab configuration';
    exit 0;
} else {
    $principal = contents ("$DATA/test.principal");
    $ENV{KRB5CCNAME} = 'krb5cc_test';
    unlink 'krb5cc_test';
    unless (kinit ("$DATA/test.keytab", $principal, '-r', '2h', '-l', '10m')) {
        plan skip_all => 'cannot get renewable tickets';
        exit 0;
    }
    plan tests => 36;
}

# We should be okay for five minute tickets without doing anything.
($out, $err, $status) = command ($KRENEW, '-vH', '5');
is ($status, 0, 'krenew -H 5 succeeds without reauthenticating');
is ($err, '', ' with no errors');
is ($out, '', ' and no output');

# We should be able to renew to get 30 minute tickets.
($out, $err, $status) = command ($KRENEW, '-vH', '30');
is ($status, 0, 'krenew -H 30 succeeds with authentication');
is ($err, '', ' with no errors');
like ($out,
      qr/^krenew: renewing credentials for \Q$principal\E(\@\S+)?\n\z/,
      ' and the right output');

# But we fail if we try to get 3 hour tickets, since we can't renew for
# that long.
($out, $err, $status) = command ($KRENEW, '-vH', '180');
is ($status, 1, 'krenew -H 180 fails');
is ($err, "krenew: ticket cannot be renewed for long enough\n",
    ' with the right error');
is ($out, '', ' and no output');

# Test running a command.  klist may fail if we have no K4 tickets since
# we're not giving the -5 option; allow for that (we'll catch real
# failures in the regex match on the output).
($out, $err, $status) = command ($KRENEW, 'klist');
ok ($status == 0 || $status == 1, 'krenew with command succeeds');
ok ($err eq '' || $err eq "klist: You have no tickets cached\n",
    ' with no or expected errors');
like ($out, qr,^\s*(Ticket|Credentials)\ cache:
               \ (FILE:)?/tmp/krb5cc_\d+_\S{6}\n
               \s*(Default\ )?[Pp]rincipal:\ \Q$principal\E(\@\S+)?\n,xm,
      ' and the right output');
($cache) = ($out =~ /cache: (?:FILE:)?(\S+)/);
ok (!$cache || !-f $cache, ' and the new cache file was deleted');
ok (-f 'krb5cc_test', ' but the default one was unaffected');

# Test running a command with --.
($out, $err, $status) = command ($KRENEW, '--', 'klist', '-5');
is ($status, 0, 'krenew with command and -- succeeds');
is ($err, '', ' with no errors');
like ($out, qr,^\s*(Ticket|Credentials)\ cache:
               \ (FILE:)?/tmp/krb5cc_\d+_\S{6}\n
               \s*(Default\ )?[Pp]rincipal:\ \Q$principal\E(\@\S+)?\n,xm,
      ' and the right output');
($cache) = ($out =~ /cache: (?:FILE:)?(\S+)/);
ok (!$cache || !-f $cache, ' and the new cache file was deleted');
ok (-f 'krb5cc_test', ' but the default one was unaffected');

# Test propagation of exit status from a command.
($out, $err, $status)
    = command ($KRENEW, '--', 'sh', '-c', 'klist -5; exit 3');
is ($status, 3, 'krenew of exit 3 returns correct exit status');
is ($err, '', ' with no errors');
like ($out, qr,^\s*(Ticket|Credentials)\ cache:
               \ (FILE:)?/tmp/krb5cc_\d+_\S{6}\n
               \s*(Default\ )?[Pp]rincipal:\ \Q$principal\E(\@\S+)?\n,xm,
      ' and the right output');
($cache) = ($out =~ /cache: (?:FILE:)?(\S+)/);
ok (!$cache || !-f $cache, ' and the new cache file was deleted');
ok (-f 'krb5cc_test', ' and the default cache file was unaffected');

# Check exit status if the ticket cache doesn't exist.
unlink 'krb5cc_test';
($out, $err, $status) = command ($KRENEW);
is ($status, 1, 'krenew fails with no ticket cache');
is ($out, '', ' with no output');
like ($err, qr/^krenew: error reading ticket cache: /, ' and the right error');
($out, $err, $status) = command ($KRENEW, '-vH', 5);
is ($status, 1, 'krenew -H fails with no ticket cache');
is ($out, '', ' with no output');
like ($err, qr/^krenew: error reading ticket cache: /, ' and the right error');

# We should still exit with the same error if -i was given.
($out, $err, $status) = command ($KRENEW, '-vi');
is ($status, 1, 'krenew -i fails with no ticket cache');
is ($out, '', ' with no output');
like ($err, qr/^krenew: error reading ticket cache: /, ' and the right error');
($out, $err, $status) = command ($KRENEW, '-viH', 5);
is ($status, 1, 'krenew -iH fails with no ticket cache');
is ($out, '', ' with no output');
like ($err, qr/^krenew: error reading ticket cache: /, ' and the right error');
