#!/usr/bin/perl use lib '../src'; use strict; use warnings; use POSIX (); use Data::Dumper; use Time::Local; use Test::More; use PVE::CalendarEvent; # Time tests should run in a controlled setting $ENV{TZ} = 'UTC'; POSIX::tzset(); my $alldays = [0,1,2,3,4,5,6]; my $tests = [ [ '*', undef, [ [0, 60], [30, 60], [59, 60], [60, 120], ] ], [ '*/10', undef, [ [0, 600], [599, 600], [600, 1200], [50*60, 60*60] ] ], [ '*/12:0' , undef, [ [ 10, 43200], [ 13*3600, 24*3600], ] ], [ '1/12:0/15' , undef, [ [0, 3600], [3600, 3600+15*60], [3600+16*60, 3600+30*60 ], [3600+30*60, 3600+45*60 ], [3600+45*60, 3600+12*3600], [13*3600 + 1, 13*3600+15*60], [13*3600 + 15*60, 13*3600+30*60], [13*3600 + 30*60, 13*3600+45*60], [13*3600 + 45*60, 25*3600], ], ], [ '1,4,6', undef, [ [0, 60], [60, 4*60], [4*60+60, 6*60], [6*60, 3600+60], ] ], [ '0..3', undef, ], [ '23..23:0..3', undef, ], [ 'Mon', undef, [ [0, 4*86400], # Note: Epoch 0 is Thursday, 1. January 1970 [4*86400, 11*86400], [11*86400, 18*86400], ], ], [ 'sat..sun', undef, [ [0, 2*86400], [2*86400, 3*86400], [3*86400, 9*86400], ] ], [ 'sun..sat', undef, ], [ 'Fri..Mon', { error => "wrong order in range 'Fri..Mon'" }, ], [ 'wed,mon..tue,fri', undef, ], [ 'mon */15', undef, ], [ '22/1:0', undef, [ [0, 22*60*60], [22*60*60, 23*60*60], [22*60*60 + 59*60, 23*60*60] ], ], [ '*/2:*', undef, [ [0, 60], [60*60, 2*60*60], [2*60*60, 2*60*60 + 60] ] ], [ '20..22:*/30', undef, [ [0, 20*60*60], [20*60*60, 20*60*60 + 30*60], [22*60*60 + 30*60, 44*60*60] ] ], [ '61', { error => "value '61' out of range" }, ], [ '*/61', { error => "repetition '61' out of range" }, ], [ '0..80', { error => "range end '80' out of range" }, ], [ ' mon 0 0 0', { error => "unable to parse calendar event - unused parts" }, ], [ '', { error => "unable to parse calendar event - event is empty" }, ], [ ' mon 0 0', { error => "unable to parse calendar event - unused parts" }, ], [ '0,1,3..5', undef, [ [0, 60], [60, 3*60], [5*60, 60*60] ] ], [ '2,4:0,1,3..5', undef, [ [0, 2*60*60], [2*60*60 + 60, 2*60*60 + 3*60], [2*60*60 + 5*60, 4*60*60] ] ], ]; foreach my $test (@$tests) { my ($t, $expect, $nextsync) = @$test; $expect //= {}; my $timespec; eval { $timespec = PVE::CalendarEvent::parse_calendar_event($t); }; my $err = $@; if ($expect->{error}) { chomp $err if $err; ok(defined($err) == defined($expect->{error}), "parsing '$t' failed expectedly"); die "unable to execute nextsync tests" if $nextsync; } next if !$nextsync; foreach my $nt (@$nextsync) { my ($last, $expect_next) = @$nt; my $msg = "next event '$t' $last => ${expect_next}"; $timespec->{utc} = 1; my $next = PVE::CalendarEvent::compute_next_event($timespec, $last); is($next, $expect_next, $msg); } }; sub tztest { my ($calspec, $last) = @_; my $spec = PVE::CalendarEvent::parse_calendar_event($calspec); return PVE::CalendarEvent::compute_next_event($spec, $last); } # Test loop termination at CEST/CET switch (cannot happen here in UTC) is(tztest('mon..fri', timelocal(0, 0, 0, 28, 9, 2018)), timelocal(0, 0, 0, 29, 9, 2018)); is(tztest('mon..fri UTC', timelocal(0, 0, 0, 28, 9, 2018)), timelocal(0, 0, 0, 29, 9, 2018)); # Now in the affected time zone $ENV{TZ} = ':Europe/Vienna'; POSIX::tzset(); is(tztest('mon..fri', timelocal(0, 0, 0, 28, 9, 2018)), timelocal(0, 0, 0, 29, 9, 2018)); # Specifically requesting UTC in the calendar spec means the resulting output # time as seen locally (timelocal() as opposed to timegm()) is shifted by 1 # hour. is(tztest('mon..fri UTC', timelocal(0, 0, 0, 28, 9, 2018)), timelocal(0, 0, 1, 29, 9, 2018)); $ENV{TZ} = 'UTC'; POSIX::tzset(); done_testing();