diff --git a/src/tests/add.t b/src/tests/add.t index 26a82f0ee..db6f5c553 100755 --- a/src/tests/add.t +++ b/src/tests/add.t @@ -63,7 +63,7 @@ like ($output, qr/Status\s+Pending\n/, 'add Pending'); # Cleanup. unlink 'pending.data'; -ok (!-r 'pendind.data', 'Removed pending.data'); +ok (!-r 'pending.data', 'Removed pending.data'); unlink 'add.rc'; ok (!-r 'add.rc', 'Removed add.rc'); diff --git a/src/tests/bug_hang.t b/src/tests/bug_hang.t new file mode 100755 index 000000000..dbe229919 --- /dev/null +++ b/src/tests/bug_hang.t @@ -0,0 +1,83 @@ +#! /usr/bin/perl +################################################################################ +## task - a command line task list manager. +## +## Copyright 2006 - 2009, Paul Beckingham. +## All rights reserved. +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 2 of the License, or (at your option) any later +## version. +## +## This program is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, write to the +## +## Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, +## Boston, MA +## 02110-1301 +## USA +## +################################################################################ + +use strict; +use warnings; +use Test::More tests => 5; + +# Create the rc file. +if (open my $fh, '>', 'hang.rc') +{ + print $fh "data.location=.\n", + "shadow.file=shadow.txt\n", + "shadow.command=list\n"; + close $fh; + ok (-r 'hang.rc', 'Created hang.rc'); +} + +=pod +I found a bug in the current version of task. Using recur and a shadow file will +lead to an infinite loop. To reproduce it, define a shadow file in the .taskrc, +set a command for it that rebuilds the database, e.g. "list", and then add a +task with a recurrence set, e.g. "task add due:today recur:1d infinite loop". +Task will then loop forever and add the same recurring task until it runs out of +memory. So I checked the source and I believe I found the cause. +handleRecurrence() in task.cpp will modify the mask, but writes it only after it +has added all new tasks. Adding the task will, however, invoke onChangeCallback, +which starts the same process all over again. +=cut + +eval +{ + $SIG{'ALRM'} = sub {die "alarm\n"}; + alarm 10; + my $output = qx{../task rc:hang.rc list; + ../task rc:hang.rc add due:today recur:1d infinite loop; + ../task rc:hang.rc info 1}; + alarm 0; + + like ($output, qr/^Description\s+infinite loop\n/m, 'no hang'); +}; + +if ($@ eq "alarm\n") +{ + fail ('task hang on add or recurring task, with shadow file, for 10s'); +} + +# Cleanup. +unlink 'shadow.txt'; +ok (!-r 'shadow.txt', 'Removed shadow.txt'); + +unlink 'pending.data'; +ok (!-r 'pending.data', 'Removed pending.data'); + +unlink 'hang.rc'; +ok (!-r 'hang.rc', 'Removed hang.rc'); + +exit 0; + diff --git a/src/tests/bug_period.t b/src/tests/bug_period.t new file mode 100755 index 000000000..dff6888ff --- /dev/null +++ b/src/tests/bug_period.t @@ -0,0 +1,164 @@ +#! /usr/bin/perl +################################################################################ +## task - a command line task list manager. +## +## Copyright 2006 - 2009, Paul Beckingham. +## All rights reserved. +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 2 of the License, or (at your option) any later +## version. +## +## This program is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, write to the +## +## Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, +## Boston, MA +## 02110-1301 +## USA +## +################################################################################ + +use strict; +use warnings; +use Test::More tests => 41; + +# Create the rc file. +if (open my $fh, '>', 'period.rc') +{ + print $fh "data.location=.\n"; + close $fh; + ok (-r 'period.rc', 'Created period.rc'); +} + +=pod +http://github.com/pbeckingham/task/blob/857f813a24f7ce15fea9f2c28aadad84cb5c8847/src/task.cpp +619 // If the period is an 'easy' one, add it to current, and we're done. +620 int days = convertDuration (period); + +Date getNextRecurrence (Date& current, std::string& period) + +starting at line 509 special cases several possibilities for period, '\d\s?m' +'monthly', 'quarterly', 'semiannual', 'bimonthly', 'biannual', 'biyearly'. +Everything else falls through with period being passed to convertDuration. +convertDuration doesn't know about 'daily' though so it seems to be returning 0. + +Confirmed: + getNextRecurrence convertDuration + ----------------- --------------- + daily + day + weekly + sennight + biweekly + fortnight + monthly monthly + quarterly quarterly + semiannual semiannual + bimonthly bimonthly + biannual biannual + biyearly biyearly + annual + yearly + *m *m + *q *q + *d + *w + *y +=cut + +my $output = qx{../task rc:period.rc add daily due:tomorrow recur:daily}; +like ($output, qr/^$/, 'recur:daily'); + +$output = qx{../task rc:period.rc add day due:tomorrow recur:day}; +like ($output, qr/^$/, 'recur:day'); + +$output = qx{../task rc:period.rc add weekly due:tomorrow recur:weekly}; +like ($output, qr/^$/, 'recur:weekly'); + +$output = qx{../task rc:period.rc add sennight due:tomorrow recur:sennight}; +like ($output, qr/^$/, 'recur:sennight'); + +$output = qx{../task rc:period.rc add biweekly due:tomorrow recur:biweekly}; +like ($output, qr/^$/, 'recur:biweekly'); + +$output = qx{../task rc:period.rc add fortnight due:tomorrow recur:fortnight}; +like ($output, qr/^$/, 'recur:fortnight'); + +$output = qx{../task rc:period.rc add monthly due:tomorrow recur:monthly}; +like ($output, qr/^$/, 'recur:monthly'); + +$output = qx{../task rc:period.rc add quarterly due:tomorrow recur:quarterly}; +like ($output, qr/^$/, 'recur:quarterly'); + +$output = qx{../task rc:period.rc add semiannual due:tomorrow recur:semiannual}; +like ($output, qr/^$/, 'recur:semiannual'); + +$output = qx{../task rc:period.rc add bimonthly due:tomorrow recur:bimonthly}; +like ($output, qr/^$/, 'recur:bimonthly'); + +$output = qx{../task rc:period.rc add biannual due:tomorrow recur:biannual}; +like ($output, qr/^$/, 'recur:biannual'); + +$output = qx{../task rc:period.rc add biyearly due:tomorrow recur:biyearly}; +like ($output, qr/^$/, 'recur:biyearly'); + +$output = qx{../task rc:period.rc add annual due:tomorrow recur:annual}; +like ($output, qr/^$/, 'recur:annual'); + +$output = qx{../task rc:period.rc add yearly due:tomorrow recur:yearly}; +like ($output, qr/^$/, 'recur:yearly'); + +$output = qx{../task rc:period.rc add 2d due:tomorrow recur:2d}; +like ($output, qr/^$/, 'recur:2m'); + +$output = qx{../task rc:period.rc add 2w due:tomorrow recur:2w}; +like ($output, qr/^$/, 'recur:2q'); + +$output = qx{../task rc:period.rc add 2m due:tomorrow recur:2m}; +like ($output, qr/^$/, 'recur:2d'); + +$output = qx{../task rc:period.rc add 2q due:tomorrow recur:2q}; +like ($output, qr/^$/, 'recur:2w'); + +$output = qx{../task rc:period.rc add 2y due:tomorrow recur:2y}; +like ($output, qr/^$/, 'recur:2y'); + +# Verify that the recurring task instances get created. One of each. +$output = qx{../task rc:period.rc list}; +like ($output, qr/\bdaily\b/, 'verify daily'); +like ($output, qr/\bday\b/, 'verify day'); +like ($output, qr/\bweekly\b/, 'verify weekly'); +like ($output, qr/\bsennight\b/, 'verify sennight'); +like ($output, qr/\bbiweekly\b/, 'verify biweekly'); +like ($output, qr/\bfortnight\b/, 'verify fortnight'); +like ($output, qr/\bmonthly\b/, 'verify monthly'); +like ($output, qr/\bquarterly\b/, 'verify quarterly'); +like ($output, qr/\bsemiannual\b/, 'verify semiannual'); +like ($output, qr/\bbimonthly\b/, 'verify bimonthly'); +like ($output, qr/\bbiannual\b/, 'verify biannual'); +like ($output, qr/\bbiyearly\b/, 'verify biyearly'); +like ($output, qr/\bannual\b/, 'verify annual'); +like ($output, qr/\byearly\b/, 'verify yearly'); +like ($output, qr/\b2d\b/, 'verify 2d'); +like ($output, qr/\b2w\b/, 'verify 2w'); +like ($output, qr/\b2m\b/, 'verify 2m'); +like ($output, qr/\b2q\b/, 'verify 2q'); +like ($output, qr/\b2y\b/, 'verify 2y'); + +# Cleanup. +unlink 'pending.data'; +ok (!-r 'pending.data', 'Removed pending.data'); + +unlink 'period.rc'; +ok (!-r 'period.rc', 'Removed period.rc'); + +exit 0; + diff --git a/src/tests/bug_sort.t b/src/tests/bug_sort.t index 4b9c4973a..0d0d49eac 100755 --- a/src/tests/bug_sort.t +++ b/src/tests/bug_sort.t @@ -53,7 +53,7 @@ like ($output, qr/three.*one.*two/msi, 'list did not hang after pri:H on 1'); # Cleanup. unlink 'pending.data'; -ok (!-r 'pendind.data', 'Removed pending.data'); +ok (!-r 'pending.data', 'Removed pending.data'); unlink 'bug_sort.rc'; ok (!-r 'bug_sort.rc', 'Removed bug_sort.rc'); diff --git a/src/tests/nag.t b/src/tests/nag.t index d9dc94d76..d55aac456 100755 --- a/src/tests/nag.t +++ b/src/tests/nag.t @@ -56,7 +56,7 @@ ok (qx{../task rc:nag.rc do 1} !~ qr/NAG/, 'do due:yesterday -> no nag'); # Cleanup. unlink 'pending.data'; -ok (!-r 'pendind.data', 'Removed pending.data'); +ok (!-r 'pending.data', 'Removed pending.data'); unlink 'nag.rc'; ok (!-r 'nag.rc', 'Removed nag.rc'); diff --git a/src/tests/tag.t b/src/tests/tag.t index ceeb24dea..f55ba0dbf 100755 --- a/src/tests/tag.t +++ b/src/tests/tag.t @@ -40,7 +40,6 @@ if (open my $fh, '>', 'tag.rc') # Add task with tags. my $output = qx{../task rc:tag.rc add +1 This +2 is a test +3; ../task rc:tag.rc info 1}; -#like ($output, qr/^Tags\s+1 2 3$/ms, 'tags found'); like ($output, qr/^Tags\s+1 2 3\n/m, 'tags found'); # Remove tags. @@ -65,7 +64,7 @@ unlike ($output, qr/^Tags/m, '-missing NOP'); # Cleanup. unlink 'pending.data'; -ok (!-r 'pendind.data', 'Removed pending.data'); +ok (!-r 'pending.data', 'Removed pending.data'); unlink 'tag.rc'; ok (!-r 'tag.rc', 'Removed tag.rc');