Use Time::Fake to avoid sleeping during tests
This commit is contained in:
parent
5b2e6f7d9f
commit
983a4e6485
|
@ -8,19 +8,19 @@ init(
|
|||
'Lemonldap::NG::Handler::Server',
|
||||
{
|
||||
logLevel => 'error',
|
||||
handlerServiceTokenTTL => 2,
|
||||
handlerServiceTokenTTL => 120,
|
||||
vhostOptions => {
|
||||
'test1.example.com' => {
|
||||
vhostHttps => 0,
|
||||
vhostPort => 80,
|
||||
vhostMaintenance => 0,
|
||||
vhostServiceTokenTTL => 3,
|
||||
vhostServiceTokenTTL => 180,
|
||||
},
|
||||
'test2.example.com' => {
|
||||
vhostHttps => 0,
|
||||
vhostPort => 80,
|
||||
vhostMaintenance => 0,
|
||||
vhostServiceTokenTTL => 5,
|
||||
vhostServiceTokenTTL => 300,
|
||||
}
|
||||
},
|
||||
exportedHeaders => {
|
||||
|
@ -48,7 +48,7 @@ ok(
|
|||
VHOSTTYPE => 'ServiceToken',
|
||||
'HTTP_X_LLNG_TOKEN' => $token,
|
||||
),
|
||||
'Query with token'
|
||||
'Query with token 1'
|
||||
);
|
||||
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
|
||||
count(2);
|
||||
|
@ -61,8 +61,8 @@ ok( @values == 2, 'Found 2 service header values' )
|
|||
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||
count(2);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 1;
|
||||
# Waiting
|
||||
Time::Fake->offset("+90s");
|
||||
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
|
@ -70,7 +70,7 @@ ok(
|
|||
VHOSTTYPE => 'ServiceToken',
|
||||
'HTTP_X_LLNG_TOKEN' => $token,
|
||||
),
|
||||
'Query with token'
|
||||
'Query with token 2'
|
||||
);
|
||||
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
|
||||
count(2);
|
||||
|
@ -83,8 +83,8 @@ ok( @values == 2, 'Found 2 service header values' )
|
|||
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||
count(2);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 2;
|
||||
# Waiting
|
||||
Time::Fake->offset("+210s");
|
||||
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
|
@ -92,7 +92,7 @@ ok(
|
|||
VHOSTTYPE => 'ServiceToken',
|
||||
'HTTP_X_LLNG_TOKEN' => $token,
|
||||
),
|
||||
'Query with token'
|
||||
'Query with token 3'
|
||||
);
|
||||
ok( $res->[0] == 302, 'Code is 200' ) or explain( $res->[0], 302 );
|
||||
count(2);
|
||||
|
@ -102,8 +102,8 @@ ok( @headers == 0, 'NONE service header found' )
|
|||
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||
count(1);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 1;
|
||||
# Waiting
|
||||
Time::Fake->offset("+270s");
|
||||
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
|
@ -111,7 +111,7 @@ ok(
|
|||
VHOSTTYPE => 'ServiceToken',
|
||||
'HTTP_X_LLNG_TOKEN' => $token,
|
||||
),
|
||||
'Query with token'
|
||||
'Query with token 4'
|
||||
);
|
||||
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
|
||||
count(2);
|
||||
|
@ -131,8 +131,8 @@ ok( @values == 2, 'Found 2 service header values' )
|
|||
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||
count(2);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 1;
|
||||
# Waiting
|
||||
Time::Fake->offset("+330s");
|
||||
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
|
@ -140,7 +140,7 @@ ok(
|
|||
VHOSTTYPE => 'ServiceToken',
|
||||
'HTTP_X_LLNG_TOKEN' => $token,
|
||||
),
|
||||
'Query with token'
|
||||
'Query with token 5'
|
||||
);
|
||||
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
||||
count(2);
|
||||
|
@ -156,7 +156,7 @@ ok(
|
|||
VHOSTTYPE => 'ServiceToken',
|
||||
'HTTP_X_LLNG_TOKEN' => $token,
|
||||
),
|
||||
'Query with token'
|
||||
'Query with token 6'
|
||||
);
|
||||
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
||||
count(2);
|
||||
|
@ -173,7 +173,7 @@ ok(
|
|||
VHOSTTYPE => 'ServiceToken',
|
||||
'HTTP_X_LLNG_TOKEN' => $token,
|
||||
),
|
||||
'Query with token'
|
||||
'Query with token 7'
|
||||
);
|
||||
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
||||
count(2);
|
||||
|
|
|
@ -0,0 +1,235 @@
|
|||
package Time::Fake;
|
||||
use Carp;
|
||||
use strict;
|
||||
use vars '$VERSION';
|
||||
$VERSION = "0.11";
|
||||
|
||||
#####################
|
||||
|
||||
my $OFFSET = 0;
|
||||
|
||||
*CORE::GLOBAL::time = sub() { CORE::time() + $OFFSET };
|
||||
|
||||
*CORE::GLOBAL::localtime = sub(;$) {
|
||||
@_ ? CORE::localtime($_[0])
|
||||
: CORE::localtime(CORE::time() + $OFFSET);
|
||||
};
|
||||
|
||||
*CORE::GLOBAL::gmtime = sub(;$) {
|
||||
@_ ? CORE::gmtime($_[0])
|
||||
: CORE::gmtime(CORE::time() + $OFFSET);
|
||||
};
|
||||
|
||||
sub import {
|
||||
my $pkg = shift;
|
||||
$pkg->offset(shift);
|
||||
}
|
||||
|
||||
sub offset {
|
||||
my $pkg = shift;
|
||||
return $OFFSET if !@_;
|
||||
|
||||
my $old_offset = $OFFSET;
|
||||
$OFFSET = _to_offset(shift);
|
||||
return $old_offset;
|
||||
}
|
||||
|
||||
sub reset {
|
||||
shift->offset(0);
|
||||
}
|
||||
|
||||
my %mult = (
|
||||
s => 1,
|
||||
m => 60,
|
||||
h => 60*60,
|
||||
d => 60*60*24,
|
||||
M => 60*60*24*30,
|
||||
y => 60*60*24*365,
|
||||
);
|
||||
|
||||
sub _to_offset {
|
||||
my $t = shift || return 0;
|
||||
|
||||
if ($t =~ m/^([+-]\d+)([smhdMy]?)$/) {
|
||||
$t = $1 * $mult{ $2 || "s" };
|
||||
|
||||
} elsif ($t !~ m/\D/) {
|
||||
$t = $t - CORE::time;
|
||||
|
||||
} else {
|
||||
croak "Invalid time offset: `$t'";
|
||||
}
|
||||
|
||||
return $t;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Time::Fake - Simulate different times without changing your system clock
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
Pretend we are running 1 day in the future:
|
||||
|
||||
use Time::Fake '+1d';
|
||||
|
||||
Pretend we are running 1 year in the past:
|
||||
|
||||
use Time::Fake '-1y';
|
||||
|
||||
Pretend the script started at epoch time 1234567:
|
||||
|
||||
use Time::Fake 1234567;
|
||||
|
||||
See what an existing script would do if run 20 years in the future:
|
||||
|
||||
% perl -MTime::Fake="+20y" test.pl
|
||||
|
||||
Run a section of code in a time warp:
|
||||
|
||||
use Time::Fake;
|
||||
|
||||
# do some setup
|
||||
|
||||
Time::Fake->offset("+1y");
|
||||
run_tests(); # thinks it's a year ahead
|
||||
|
||||
Time::Fake->reset; # back to the present
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Use this module to achieve the effect of changing your system clock, but
|
||||
without actually changing your system clock. It overrides the Perl builtin
|
||||
subs C<time>, C<localtime>, and C<gmtime>, causing them to return a
|
||||
"faked" time of your choice. From the script's point of view, time still
|
||||
flows at the normal rate, but it is just offset as if it were executing
|
||||
in the past or present.
|
||||
|
||||
You may find this module useful in writing test scripts for code that has
|
||||
time-sensitive logic.
|
||||
|
||||
=head1 USAGE
|
||||
|
||||
=head2 Using and importing:
|
||||
|
||||
use Time::Fake $t;
|
||||
|
||||
Is equivalent to:
|
||||
|
||||
use Time::Fake;
|
||||
Time::Fake->offset($t);
|
||||
|
||||
See below for arguments to C<offset>. This usage makes it easy to
|
||||
fake the time for existing scripts, as in:
|
||||
|
||||
% perl -MTime::Fake=+1y script.pl
|
||||
|
||||
=head2 offset
|
||||
|
||||
Time::Fake->offset( [$t] );
|
||||
|
||||
C<$t> is either an epoch time, or a relative offset of the following
|
||||
form:
|
||||
|
||||
+3 # 3 seconds in the future
|
||||
-3s # 3 seconds in the past
|
||||
+1h # 1 hour in the future
|
||||
etc..
|
||||
|
||||
Relative offsets must begin with a plus or minus symbol. The supported
|
||||
units are:
|
||||
|
||||
s second
|
||||
m minute
|
||||
h hour
|
||||
d day (24 hours)
|
||||
M month (30 days)
|
||||
y year (365 days)
|
||||
|
||||
If C<$t> is an epoch time, then C<time>, C<localtime>, and C<gmtime>
|
||||
will act as though the the current time (when C<offset> was called) was
|
||||
actually at C<$t> epoch seconds.
|
||||
Otherwise, the offset C<$t> will be added to the times returned by these
|
||||
builtin subs.
|
||||
|
||||
When C<$t> is false, C<time>, C<localtime>, C<gmtime>
|
||||
remain overridden, but their behavior resets to reflect the actual
|
||||
system time.
|
||||
|
||||
When C<$t> is omitted, nothing is changed, but C<offset> returns the
|
||||
current additive offset (in seconds). Otherwise, its return value is
|
||||
the I<previous> offset.
|
||||
|
||||
C<offset> may be called several times. However, I<The effect of multiple
|
||||
calls is NOT CUMULATIVE.> That is:
|
||||
|
||||
Time::Fake->offset("+1h");
|
||||
Time::Fake->offset("+1h");
|
||||
|
||||
## same as
|
||||
# Time::Fake->offset("+1h");
|
||||
|
||||
## NOT the same as
|
||||
# Time::Fake->offset("+2h");
|
||||
|
||||
Each call to C<offset> completely cancels out the effect of any
|
||||
previous calls. To make the effect cumulative, use the return value
|
||||
of calling C<offset> with no arguments:
|
||||
|
||||
Time::Fake->offset("+1h");
|
||||
...
|
||||
Time::Fake->offset( Time::Fake->offset + 3600 ); # add another hour
|
||||
|
||||
=head2 reset
|
||||
|
||||
Time::Fake->reset;
|
||||
|
||||
Is the same as:
|
||||
|
||||
Time::Fake->offset(0);
|
||||
|
||||
That is, it returns all the affected builtin subs to their
|
||||
default behavior -- reporing the actual system time.
|
||||
|
||||
=head1 KNOWN CAVEATS
|
||||
|
||||
Time::Fake must be loaded at C<BEGIN>-time (e.g., with a standard
|
||||
C<use> statement). It must be loaded before perl I<compiles> any code
|
||||
that uses C<time>, C<localtime>, or C<gmtime>. Due to inherent
|
||||
limitations in overriding builtin subs, any code that was compiled
|
||||
before loading Time::Fake will not be affected.
|
||||
|
||||
Because the system clock is not being changed, only Perl code that
|
||||
uses C<time>, C<localtime>, or C<gmtime> will be fooled about the date.
|
||||
In particular, the operating system is not fooled,
|
||||
nor are other programs. If your Perl code modifies a file for example,
|
||||
the file's modification time will reflect the B<actual> (not faked) time.
|
||||
Along the same lines, if your Perl script obtains the time from somewhere
|
||||
other than the affected builtins subs (e.g., C<qx/date/>), the actual
|
||||
(not faked) time will be reflected.
|
||||
|
||||
Time::Fake doesn't affect -M, -A, -C filetest operators in the way you'd
|
||||
probably want. These still report the B<actual> (not faked) script start
|
||||
time minus file access time.
|
||||
|
||||
Time::Fake has not been tested with other modules that override the time
|
||||
builtins, e.g., Time::HiRes.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Time::Warp, which uses XS to fool more of Perl.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Time::Fake is written by Mike Rosulek E<lt>mike@mikero.comE<gt>. Feel
|
||||
free to contact me with comments, questions, patches, or whatever.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (c) 2008 Mike Rosulek. All rights reserved. This module is free
|
||||
software; you can redistribute it and/or modify it under the same terms as Perl
|
||||
itself.
|
|
@ -9,6 +9,10 @@ use_ok('Lemonldap::NG::Common::PSGI::Cli::Lib');
|
|||
our $client;
|
||||
our $count = 1;
|
||||
|
||||
BEGIN {
|
||||
require 't/Time-Fake.pm';
|
||||
}
|
||||
|
||||
no warnings 'redefine';
|
||||
|
||||
my $module;
|
||||
|
|
|
@ -13,7 +13,7 @@ BEGIN {
|
|||
|
||||
my $maintests = 16;
|
||||
my $debug = 'error';
|
||||
my $timeout = 6;
|
||||
my $timeout = 72000;
|
||||
my ( $issuer, $sp, $res );
|
||||
my %handlerOR = ( issuer => [], sp => [] );
|
||||
|
||||
|
@ -164,8 +164,8 @@ SKIP: {
|
|||
expectAutoPost( $res, 'auth.idp.com', '/saml/singleLogout',
|
||||
'SAMLRequest' );
|
||||
|
||||
diag 'Waiting';
|
||||
sleep $timeout + 1;
|
||||
# Jump ahead in time
|
||||
Time::Fake->offset("+".($timeout*1.5)."s");
|
||||
|
||||
# Push SAML logout request to IdP
|
||||
switch ('issuer');
|
||||
|
|
|
@ -65,7 +65,7 @@ SKIP: {
|
|||
expectOK($res);
|
||||
my $idpId = expectCookie($res);
|
||||
pass('Waiting timeout');
|
||||
sleep 3;
|
||||
Time::Fake->offset("+30s");
|
||||
|
||||
# Simple SP access
|
||||
my $res;
|
||||
|
@ -179,7 +179,7 @@ sub issuer {
|
|||
portal => 'http://auth.idp.com',
|
||||
authentication => 'Choice',
|
||||
userDB => 'Same',
|
||||
portalForceAuthnInterval => 2,
|
||||
portalForceAuthnInterval => 5,
|
||||
authChoiceParam => 'test',
|
||||
authChoiceModules => {
|
||||
demo => 'Demo;Demo;Demo',
|
||||
|
|
|
@ -11,7 +11,7 @@ BEGIN {
|
|||
require 't/saml-lib.pm';
|
||||
}
|
||||
|
||||
my $maintests = 12;
|
||||
my $maintests = 11;
|
||||
my $debug = 'error';
|
||||
my ( $issuer, $sp, $res );
|
||||
my %handlerOR = ( issuer => [], sp => [] );
|
||||
|
@ -52,8 +52,9 @@ SKIP: {
|
|||
);
|
||||
expectOK($res);
|
||||
my $idpId = expectCookie($res);
|
||||
pass('Waiting timeout');
|
||||
sleep 3;
|
||||
|
||||
# Skipping time
|
||||
Time::Fake->offset("+30s");
|
||||
|
||||
# Simple SP access
|
||||
my $res;
|
||||
|
@ -168,7 +169,7 @@ sub issuer {
|
|||
portal => 'http://auth.idp.com',
|
||||
authentication => 'Demo',
|
||||
userDB => 'Same',
|
||||
portalForceAuthnInterval => 2,
|
||||
portalForceAuthnInterval => 5,
|
||||
issuerDBSAMLActivation => 1,
|
||||
samlSPMetaDataOptions => {
|
||||
'sp.com' => {
|
||||
|
|
|
@ -50,7 +50,7 @@ my $op = LLNG::Manager::Test->new( {
|
|||
oidcRPMetaDataOptionsIDTokenSignAlg => "HS512",
|
||||
oidcRPMetaDataOptionsClientSecret => "rpsecret",
|
||||
oidcRPMetaDataOptionsUserIDAttr => "",
|
||||
oidcRPMetaDataOptionsAccessTokenExpiration => 1,
|
||||
oidcRPMetaDataOptionsAccessTokenExpiration => 3600,
|
||||
oidcRPMetaDataOptionsBypassConsent => 1,
|
||||
oidcRPMetaDataOptionsRefreshToken => 1,
|
||||
}
|
||||
|
@ -166,7 +166,8 @@ $json = expectJSON($res);
|
|||
|
||||
ok( $json->{'name'} eq "Frédéric Accents", 'Got User Info' );
|
||||
|
||||
sleep(2);
|
||||
# Skip ahead in time
|
||||
Time::Fake->offset("+2h");
|
||||
|
||||
# Access token should have expired
|
||||
$res = $op->_post(
|
||||
|
|
|
@ -55,7 +55,7 @@ my $op = LLNG::Manager::Test->new( {
|
|||
oidcRPMetaDataOptionsIDTokenSignAlg => "HS512",
|
||||
oidcRPMetaDataOptionsClientSecret => "rpsecret",
|
||||
oidcRPMetaDataOptionsUserIDAttr => "",
|
||||
oidcRPMetaDataOptionsAccessTokenExpiration => 1,
|
||||
oidcRPMetaDataOptionsAccessTokenExpiration => 3600,
|
||||
oidcRPMetaDataOptionsBypassConsent => 1,
|
||||
},
|
||||
oauth => {
|
||||
|
@ -187,7 +187,7 @@ ok( $json->{active}, "Token is valid" );
|
|||
is( $json->{sub}, "french", "Response contains the correct sub" );
|
||||
|
||||
# Check status after expiration
|
||||
sleep(2);
|
||||
Time::Fake->offset("+2h");
|
||||
|
||||
$query = "token=$token";
|
||||
ok(
|
||||
|
|
|
@ -55,7 +55,7 @@ my $op = LLNG::Manager::Test->new( {
|
|||
oidcRPMetaDataOptionsIDTokenSignAlg => "HS512",
|
||||
oidcRPMetaDataOptionsClientSecret => "rpsecret",
|
||||
oidcRPMetaDataOptionsUserIDAttr => "",
|
||||
oidcRPMetaDataOptionsAccessTokenExpiration => 1,
|
||||
oidcRPMetaDataOptionsAccessTokenExpiration => 3600,
|
||||
oidcRPMetaDataOptionsBypassConsent => 1,
|
||||
},
|
||||
rp2 => {
|
||||
|
@ -65,7 +65,7 @@ my $op = LLNG::Manager::Test->new( {
|
|||
oidcRPMetaDataOptionsIDTokenSignAlg => "HS512",
|
||||
oidcRPMetaDataOptionsClientSecret => "rp2secret",
|
||||
oidcRPMetaDataOptionsUserIDAttr => "",
|
||||
oidcRPMetaDataOptionsAccessTokenExpiration => 1,
|
||||
oidcRPMetaDataOptionsAccessTokenExpiration => 3600,
|
||||
oidcRPMetaDataOptionsBypassConsent => 1,
|
||||
oidcRPMetaDataOptionsRule => '$uid eq "dwho"',
|
||||
}
|
||||
|
@ -213,7 +213,8 @@ $res = expectJSON($res);
|
|||
my $token = $res->{access_token};
|
||||
ok( $token, 'Access token present' );
|
||||
count(1);
|
||||
sleep(2);
|
||||
Time::Fake->offset("+2h");
|
||||
|
||||
|
||||
ok(
|
||||
$res = $op->_post(
|
||||
|
|
|
@ -20,7 +20,7 @@ SKIP: {
|
|||
totp2fSelfRegistration => 1,
|
||||
totp2fActivation => 1,
|
||||
requireToken => 1,
|
||||
formTimeout => 2,
|
||||
formTimeout => 120,
|
||||
loginHistoryEnabled => 0,
|
||||
authentication => 'Combination',
|
||||
userDB => 'Same',
|
||||
|
@ -153,9 +153,8 @@ SKIP: {
|
|||
'Code' );
|
||||
$query =~ s/code=/code=$code/;
|
||||
|
||||
# Expired token
|
||||
diag 'Waiting';
|
||||
sleep 3;
|
||||
# Skip ahead in time until the form token has expired
|
||||
Time::Fake->offset("+5m");
|
||||
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
|
|
|
@ -122,8 +122,8 @@ ok( $attributes{'_updateTime'} =~ /^\d{14}$/, 'Timestamp found' )
|
|||
or print STDERR Dumper( \%attributes );
|
||||
count(3);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 3;
|
||||
# Waiting
|
||||
Time::Fake->offset("+3s");
|
||||
|
||||
# Refresh rights
|
||||
# ------------------------
|
||||
|
|
|
@ -168,8 +168,8 @@ ok( $res->[2]->[0] =~ /<span trmsg="86"><\/span>/,
|
|||
'Rejected -> Protection enabled' );
|
||||
count(1);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 1;
|
||||
# Waiting
|
||||
Time::Fake->offset("+1s");
|
||||
|
||||
## Sixth failed connection -> Rejected
|
||||
ok(
|
||||
|
@ -187,8 +187,8 @@ ok( $res->[2]->[0] =~ /<span trmsg="86"><\/span>/,
|
|||
'Rejected -> Protection enabled' );
|
||||
count(1);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 2;
|
||||
# Waiting
|
||||
Time::Fake->offset("+3s");
|
||||
|
||||
## Sixth successful connection -> Rejected
|
||||
ok(
|
||||
|
@ -206,8 +206,8 @@ ok( $res->[2]->[0] =~ /<span trmsg="86"><\/span>/,
|
|||
'Rejected -> Protection enabled' );
|
||||
count(1);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 3;
|
||||
# Waiting
|
||||
Time::Fake->offset("+6s");
|
||||
|
||||
## Seventh successful connection -> Accepted
|
||||
ok(
|
||||
|
|
|
@ -14,7 +14,7 @@ my $client = LLNG::Manager::Test->new( {
|
|||
authentication => 'Demo',
|
||||
userdb => 'Same',
|
||||
portalForceAuthn => 1,
|
||||
portalForceAuthnInterval => 2,
|
||||
portalForceAuthnInterval => 5,
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -32,8 +32,8 @@ expectOK($res);
|
|||
my $id1 = expectCookie($res);
|
||||
count(1);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 3;
|
||||
# Skip ahead in time
|
||||
Time::Fake->offset("+30s");
|
||||
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
|
|
|
@ -14,8 +14,8 @@ my $client = LLNG::Manager::Test->new( {
|
|||
logLevel => 'error',
|
||||
authentication => 'Demo',
|
||||
userdb => 'Same',
|
||||
timeoutActivity => 4,
|
||||
timeoutActivityInterval => 2,
|
||||
timeoutActivity => 7200,
|
||||
timeoutActivityInterval => 60,
|
||||
handlerInternalCache => 1,
|
||||
}
|
||||
}
|
||||
|
@ -33,8 +33,8 @@ expectOK($res);
|
|||
my $id1 = expectCookie($res);
|
||||
count(1);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 3;
|
||||
# Skip ahead in time before activity timeout
|
||||
Time::Fake->offset("+20m");
|
||||
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
|
@ -49,8 +49,8 @@ ok( $res->[2]->[0] =~ qr%<span trspan="yourApps">Your applications</span>%,
|
|||
or print STDERR Dumper( $res->[2]->[0] );
|
||||
count(2);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 5;
|
||||
# Skip ahead in time after activity timeout
|
||||
Time::Fake->offset("+3h");
|
||||
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
|
|
|
@ -14,7 +14,7 @@ my $client = LLNG::Manager::Test->new( {
|
|||
logLevel => 'error',
|
||||
authentication => 'Demo',
|
||||
userdb => 'Same',
|
||||
timeout => 10,
|
||||
timeout => 72000,
|
||||
handlerInternalCache => 1,
|
||||
}
|
||||
}
|
||||
|
@ -32,8 +32,8 @@ expectOK($res);
|
|||
my $id1 = expectCookie($res);
|
||||
count(1);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 9;
|
||||
# Skip ahead in time before session timeout
|
||||
Time::Fake->offset("+5h");
|
||||
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
|
@ -48,8 +48,8 @@ ok( $res->[2]->[0] =~ qr%<span trspan="yourApps">Your applications</span>%,
|
|||
or print STDERR Dumper( $res->[2]->[0] );
|
||||
count(2);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 2;
|
||||
# Skip ahead in time after session timeout
|
||||
Time::Fake->offset("+25h");
|
||||
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
|
|
|
@ -18,7 +18,7 @@ my $client = LLNG::Manager::Test->new( {
|
|||
checkUser => 1,
|
||||
requireToken => 1,
|
||||
tokenUseGlobalStorage => 1,
|
||||
formTimeout => 2,
|
||||
formTimeout => 120,
|
||||
checkUserDisplayPersistentInfo => 1,
|
||||
checkUserDisplayEmptyValues => 1,
|
||||
}
|
||||
|
@ -64,9 +64,9 @@ ok( $res->[2]->[0] =~ m%<span trspan="checkUser">%, 'Found trspan="checkUser"' )
|
|||
or explain( $res->[2]->[0], 'trspan="checkUser"' );
|
||||
count(1);
|
||||
|
||||
# Expired token
|
||||
diag 'Waiting';
|
||||
sleep 3;
|
||||
# Skipping time until the form token has expired
|
||||
Time::Fake->offset("+5m");
|
||||
|
||||
$query =~ s/user=/user=rtyler/;
|
||||
$query =~ s/url=/url=http%3A%2F%2Ftest1.example.com/;
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ my $client = LLNG::Manager::Test->new( {
|
|||
checkUser => 1,
|
||||
requireToken => 1,
|
||||
tokenUseGlobalStorage => 0,
|
||||
formTimeout => 2,
|
||||
formTimeout => 120,
|
||||
checkUserDisplayPersistentInfo => 1,
|
||||
checkUserDisplayEmptyValues => 1,
|
||||
}
|
||||
|
@ -64,9 +64,9 @@ ok( $res->[2]->[0] =~ m%<span trspan="checkUser">%, 'Found trspan="checkUser"' )
|
|||
or explain( $res->[2]->[0], 'trspan="checkUser"' );
|
||||
count(1);
|
||||
|
||||
# Expired token
|
||||
diag 'Waiting';
|
||||
sleep 3;
|
||||
# Skipping time ahead until the form token has expired
|
||||
Time::Fake->offset("+5m");
|
||||
|
||||
$query =~ s/user=/user=rtyler/;
|
||||
$query =~ s/url=/url=http%3A%2F%2Ftest1.example.com/;
|
||||
|
||||
|
|
|
@ -36,9 +36,6 @@ ok(
|
|||
count(1);
|
||||
expectReject($res);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 1;
|
||||
|
||||
## Try to authenticate
|
||||
ok( $res = $client->_get( '/', accept => 'text/html' ), 'Get Menu', );
|
||||
count(1);
|
||||
|
@ -74,9 +71,6 @@ expectOK($res);
|
|||
expectAuthenticatedAs( $res, 'rtyler' );
|
||||
$client->logout($id);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 1;
|
||||
|
||||
## Try to Impersonate
|
||||
ok( $res = $client->_get( '/', accept => 'text/html' ), 'Get Menu', );
|
||||
count(1);
|
||||
|
|
|
@ -23,7 +23,7 @@ SKIP: {
|
|||
totp2fActivation => 1,
|
||||
totp2fDigits => 8,
|
||||
totp2fTTL => -1,
|
||||
formTimeout => 2,
|
||||
formTimeout => 120,
|
||||
requireToken => 1,
|
||||
}
|
||||
}
|
||||
|
@ -174,8 +174,8 @@ SKIP: {
|
|||
'LLNG Code' );
|
||||
$query =~ s/code=/code=$code/;
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 3;
|
||||
# Skipping time until form token expiration
|
||||
Time::Fake->offset("+5m");
|
||||
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
|
|
|
@ -18,7 +18,7 @@ SKIP: {
|
|||
logLevel => 'error',
|
||||
totp2fSelfRegistration => 1,
|
||||
totp2fActivation => 1,
|
||||
totp2fTTL => 2,
|
||||
totp2fTTL => 120,
|
||||
sfRemovedMsgRule => '$uid eq "dwho"',
|
||||
sfRemovedUseNotif => 1,
|
||||
portalMainLogo => 'common/logos/logo_llng_old.png',
|
||||
|
@ -130,8 +130,8 @@ SKIP: {
|
|||
$id = expectCookie($res);
|
||||
$client->logout($id);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 3;
|
||||
# Skipping time until TOTP token expiration
|
||||
Time::Fake->offset("+5m");
|
||||
|
||||
# Try to sign-in
|
||||
ok(
|
||||
|
|
|
@ -22,7 +22,7 @@ SKIP: {
|
|||
logLevel => 'error',
|
||||
totp2fSelfRegistration => 1,
|
||||
totp2fActivation => 1,
|
||||
totp2fTTL => 2,
|
||||
totp2fTTL => 120,
|
||||
sfRemovedMsgRule => '$uid eq "dwho"',
|
||||
sfRemovedUseNotif => 1,
|
||||
portalMainLogo => 'common/logos/logo_llng_old.png',
|
||||
|
@ -134,8 +134,8 @@ SKIP: {
|
|||
$id = expectCookie($res);
|
||||
$client->logout($id);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 3;
|
||||
# Skipping time until TOTP expiration
|
||||
Time::Fake->offset("+5m");
|
||||
|
||||
# Try to sign-in
|
||||
ok(
|
||||
|
|
|
@ -17,7 +17,7 @@ SKIP: {
|
|||
logLevel => 'error',
|
||||
totp2fSelfRegistration => 1,
|
||||
totp2fActivation => 1,
|
||||
totp2fTTL => 2,
|
||||
totp2fTTL => 120,
|
||||
portalMainLogo => 'common/logos/logo_llng_old.png',
|
||||
}
|
||||
}
|
||||
|
@ -123,8 +123,8 @@ SKIP: {
|
|||
$id = expectCookie($res);
|
||||
$client->logout($id);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 3;
|
||||
# Skipping time until TOTP expiration
|
||||
Time::Fake->offset("+5m");
|
||||
|
||||
# Try to sign-in
|
||||
ok(
|
||||
|
|
|
@ -18,8 +18,8 @@ SKIP: {
|
|||
u2fSelfRegistration => 1,
|
||||
u2fActivation => 1,
|
||||
portalMainLogo => 'common/logos/logo_llng_old.png',
|
||||
totp2fTTL => 2,
|
||||
u2fTTL => 2,
|
||||
totp2fTTL => 120,
|
||||
u2fTTL => 120,
|
||||
sfRemovedMsgRule => 1,
|
||||
}
|
||||
}
|
||||
|
@ -199,8 +199,8 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
|
|||
);
|
||||
}
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 3;
|
||||
# Skipping time until second factor TTL expiration
|
||||
Time::Fake->offset("+5m");
|
||||
|
||||
# Try to sign-in
|
||||
ok(
|
||||
|
|
|
@ -18,8 +18,8 @@ SKIP: {
|
|||
u2fSelfRegistration => 1,
|
||||
u2fActivation => 1,
|
||||
portalMainLogo => 'common/logos/logo_llng_old.png',
|
||||
totp2fTTL => 2,
|
||||
u2fTTL => 2,
|
||||
totp2fTTL => 120,
|
||||
u2fTTL => 120,
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -198,8 +198,8 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
|
|||
);
|
||||
}
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 3;
|
||||
# Skipping time until second factor registration has expired
|
||||
Time::Fake->offset("+5m");
|
||||
|
||||
# Try to sign-in
|
||||
ok(
|
||||
|
|
|
@ -172,8 +172,7 @@ SKIP: {
|
|||
) or print STDERR Dumper( $res->[2]->[0] );
|
||||
|
||||
# Wait to have two different epoch values
|
||||
diag 'Waiting';
|
||||
sleep 1;
|
||||
Time::Fake->offset("+1m");
|
||||
|
||||
# Ajax registration request
|
||||
ok(
|
||||
|
|
|
@ -76,8 +76,8 @@ count(1);
|
|||
ok( $res->[2]->[0] =~ /<span trmsg="86"><\/span>/, 'Protection enabled' );
|
||||
count(1);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 2;
|
||||
# Cool down
|
||||
Time::Fake->offset("+2s");
|
||||
|
||||
# Try to authenticate
|
||||
# -------------------
|
||||
|
@ -117,8 +117,8 @@ count(1);
|
|||
ok( $res->[2]->[0] =~ /<span trmsg="86"><\/span>/, 'Protection enabled' );
|
||||
count(1);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 4;
|
||||
# Cool down
|
||||
Time::Fake->offset("+6s");
|
||||
|
||||
# Try to authenticate again
|
||||
# -------------------------
|
||||
|
|
|
@ -0,0 +1,235 @@
|
|||
package Time::Fake;
|
||||
use Carp;
|
||||
use strict;
|
||||
use vars '$VERSION';
|
||||
$VERSION = "0.11";
|
||||
|
||||
#####################
|
||||
|
||||
my $OFFSET = 0;
|
||||
|
||||
*CORE::GLOBAL::time = sub() { CORE::time() + $OFFSET };
|
||||
|
||||
*CORE::GLOBAL::localtime = sub(;$) {
|
||||
@_ ? CORE::localtime($_[0])
|
||||
: CORE::localtime(CORE::time() + $OFFSET);
|
||||
};
|
||||
|
||||
*CORE::GLOBAL::gmtime = sub(;$) {
|
||||
@_ ? CORE::gmtime($_[0])
|
||||
: CORE::gmtime(CORE::time() + $OFFSET);
|
||||
};
|
||||
|
||||
sub import {
|
||||
my $pkg = shift;
|
||||
$pkg->offset(shift);
|
||||
}
|
||||
|
||||
sub offset {
|
||||
my $pkg = shift;
|
||||
return $OFFSET if !@_;
|
||||
|
||||
my $old_offset = $OFFSET;
|
||||
$OFFSET = _to_offset(shift);
|
||||
return $old_offset;
|
||||
}
|
||||
|
||||
sub reset {
|
||||
shift->offset(0);
|
||||
}
|
||||
|
||||
my %mult = (
|
||||
s => 1,
|
||||
m => 60,
|
||||
h => 60*60,
|
||||
d => 60*60*24,
|
||||
M => 60*60*24*30,
|
||||
y => 60*60*24*365,
|
||||
);
|
||||
|
||||
sub _to_offset {
|
||||
my $t = shift || return 0;
|
||||
|
||||
if ($t =~ m/^([+-]\d+)([smhdMy]?)$/) {
|
||||
$t = $1 * $mult{ $2 || "s" };
|
||||
|
||||
} elsif ($t !~ m/\D/) {
|
||||
$t = $t - CORE::time;
|
||||
|
||||
} else {
|
||||
croak "Invalid time offset: `$t'";
|
||||
}
|
||||
|
||||
return $t;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Time::Fake - Simulate different times without changing your system clock
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
Pretend we are running 1 day in the future:
|
||||
|
||||
use Time::Fake '+1d';
|
||||
|
||||
Pretend we are running 1 year in the past:
|
||||
|
||||
use Time::Fake '-1y';
|
||||
|
||||
Pretend the script started at epoch time 1234567:
|
||||
|
||||
use Time::Fake 1234567;
|
||||
|
||||
See what an existing script would do if run 20 years in the future:
|
||||
|
||||
% perl -MTime::Fake="+20y" test.pl
|
||||
|
||||
Run a section of code in a time warp:
|
||||
|
||||
use Time::Fake;
|
||||
|
||||
# do some setup
|
||||
|
||||
Time::Fake->offset("+1y");
|
||||
run_tests(); # thinks it's a year ahead
|
||||
|
||||
Time::Fake->reset; # back to the present
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Use this module to achieve the effect of changing your system clock, but
|
||||
without actually changing your system clock. It overrides the Perl builtin
|
||||
subs C<time>, C<localtime>, and C<gmtime>, causing them to return a
|
||||
"faked" time of your choice. From the script's point of view, time still
|
||||
flows at the normal rate, but it is just offset as if it were executing
|
||||
in the past or present.
|
||||
|
||||
You may find this module useful in writing test scripts for code that has
|
||||
time-sensitive logic.
|
||||
|
||||
=head1 USAGE
|
||||
|
||||
=head2 Using and importing:
|
||||
|
||||
use Time::Fake $t;
|
||||
|
||||
Is equivalent to:
|
||||
|
||||
use Time::Fake;
|
||||
Time::Fake->offset($t);
|
||||
|
||||
See below for arguments to C<offset>. This usage makes it easy to
|
||||
fake the time for existing scripts, as in:
|
||||
|
||||
% perl -MTime::Fake=+1y script.pl
|
||||
|
||||
=head2 offset
|
||||
|
||||
Time::Fake->offset( [$t] );
|
||||
|
||||
C<$t> is either an epoch time, or a relative offset of the following
|
||||
form:
|
||||
|
||||
+3 # 3 seconds in the future
|
||||
-3s # 3 seconds in the past
|
||||
+1h # 1 hour in the future
|
||||
etc..
|
||||
|
||||
Relative offsets must begin with a plus or minus symbol. The supported
|
||||
units are:
|
||||
|
||||
s second
|
||||
m minute
|
||||
h hour
|
||||
d day (24 hours)
|
||||
M month (30 days)
|
||||
y year (365 days)
|
||||
|
||||
If C<$t> is an epoch time, then C<time>, C<localtime>, and C<gmtime>
|
||||
will act as though the the current time (when C<offset> was called) was
|
||||
actually at C<$t> epoch seconds.
|
||||
Otherwise, the offset C<$t> will be added to the times returned by these
|
||||
builtin subs.
|
||||
|
||||
When C<$t> is false, C<time>, C<localtime>, C<gmtime>
|
||||
remain overridden, but their behavior resets to reflect the actual
|
||||
system time.
|
||||
|
||||
When C<$t> is omitted, nothing is changed, but C<offset> returns the
|
||||
current additive offset (in seconds). Otherwise, its return value is
|
||||
the I<previous> offset.
|
||||
|
||||
C<offset> may be called several times. However, I<The effect of multiple
|
||||
calls is NOT CUMULATIVE.> That is:
|
||||
|
||||
Time::Fake->offset("+1h");
|
||||
Time::Fake->offset("+1h");
|
||||
|
||||
## same as
|
||||
# Time::Fake->offset("+1h");
|
||||
|
||||
## NOT the same as
|
||||
# Time::Fake->offset("+2h");
|
||||
|
||||
Each call to C<offset> completely cancels out the effect of any
|
||||
previous calls. To make the effect cumulative, use the return value
|
||||
of calling C<offset> with no arguments:
|
||||
|
||||
Time::Fake->offset("+1h");
|
||||
...
|
||||
Time::Fake->offset( Time::Fake->offset + 3600 ); # add another hour
|
||||
|
||||
=head2 reset
|
||||
|
||||
Time::Fake->reset;
|
||||
|
||||
Is the same as:
|
||||
|
||||
Time::Fake->offset(0);
|
||||
|
||||
That is, it returns all the affected builtin subs to their
|
||||
default behavior -- reporing the actual system time.
|
||||
|
||||
=head1 KNOWN CAVEATS
|
||||
|
||||
Time::Fake must be loaded at C<BEGIN>-time (e.g., with a standard
|
||||
C<use> statement). It must be loaded before perl I<compiles> any code
|
||||
that uses C<time>, C<localtime>, or C<gmtime>. Due to inherent
|
||||
limitations in overriding builtin subs, any code that was compiled
|
||||
before loading Time::Fake will not be affected.
|
||||
|
||||
Because the system clock is not being changed, only Perl code that
|
||||
uses C<time>, C<localtime>, or C<gmtime> will be fooled about the date.
|
||||
In particular, the operating system is not fooled,
|
||||
nor are other programs. If your Perl code modifies a file for example,
|
||||
the file's modification time will reflect the B<actual> (not faked) time.
|
||||
Along the same lines, if your Perl script obtains the time from somewhere
|
||||
other than the affected builtins subs (e.g., C<qx/date/>), the actual
|
||||
(not faked) time will be reflected.
|
||||
|
||||
Time::Fake doesn't affect -M, -A, -C filetest operators in the way you'd
|
||||
probably want. These still report the B<actual> (not faked) script start
|
||||
time minus file access time.
|
||||
|
||||
Time::Fake has not been tested with other modules that override the time
|
||||
builtins, e.g., Time::HiRes.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Time::Warp, which uses XS to fool more of Perl.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Time::Fake is written by Mike Rosulek E<lt>mike@mikero.comE<gt>. Feel
|
||||
free to contact me with comments, questions, patches, or whatever.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (c) 2008 Mike Rosulek. All rights reserved. This module is free
|
||||
software; you can redistribute it and/or modify it under the same terms as Perl
|
||||
itself.
|
|
@ -65,6 +65,7 @@ use Lemonldap::NG::Common::FormEncode;
|
|||
no warnings 'redefine';
|
||||
|
||||
BEGIN {
|
||||
require 't/Time-Fake.pm';
|
||||
use_ok('Lemonldap::NG::Portal::Main');
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue