mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-08-22 11:13:09 +02:00
Merging in latest from upstream (TM/task:refs/heads/2.4.0)
* commit 'd8b7d914ac
': (31 commits)
TW-5
TW-306
Code Cleanup
Documentation
TW-285
Unit Tests
Unit Tests
Code Cleanup
TW-115
TW-1257
TW-1300
Code Cleanup
Bug
ChangeLog
TW-1301
Bug TW-1302
Diagnostics
Bug TW-1254
Documentation
Bug TW-1295
...
This commit is contained in:
commit
0b1732fcef
39 changed files with 1557 additions and 609 deletions
12
test/calc.t
12
test/calc.t
|
@ -27,7 +27,7 @@
|
|||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 14;
|
||||
use Test::More tests => 22;
|
||||
|
||||
# '15min' is seen as '15', 'min', not '15min' duration.
|
||||
my $output = qx{../src/calc --debug --noambiguous '12 * 3600 + 34 * 60 + 56'};
|
||||
|
@ -36,6 +36,7 @@ like ($output, qr/token infix '3600' Number/, 'Number 3600');
|
|||
like ($output, qr/token infix '34' Number/, 'Number 60');
|
||||
like ($output, qr/token infix '60' Number/, 'Number 60');
|
||||
like ($output, qr/token infix '56' Number/, 'Number 56');
|
||||
like ($output, qr/no errors/ms, 'No syntax errors');
|
||||
like ($output, qr/^45296$/ms, 'Result 45296');
|
||||
unlike ($output, qr/Error/, 'No errors');
|
||||
|
||||
|
@ -48,5 +49,14 @@ like ($output, qr/token postfix '56' Number/, 'Number 56');
|
|||
like ($output, qr/^45296$/ms, 'Result 45296');
|
||||
unlike ($output, qr/Error/, 'No errors');
|
||||
|
||||
$output = qx{../src/calc --debug --noambiguous '2--3'};
|
||||
like ($output, qr/token infix '2' Number/ms, 'Number 2');
|
||||
like ($output, qr/token infix '-' Operator/ms, 'Operator -');
|
||||
like ($output, qr/token infix '_neg_' Operator/ms, 'operator _neg_');
|
||||
like ($output, qr/token infix '3' Number/ms, 'Number 3');
|
||||
like ($output, qr/no errors/ms, 'No syntax errors');
|
||||
like ($output, qr/^5$/ms, 'Result 5');
|
||||
unlike ($output, qr/Error/, 'No errors');
|
||||
|
||||
exit 0;
|
||||
|
||||
|
|
47
test/count.t
47
test/count.t
|
@ -27,6 +27,7 @@
|
|||
|
||||
use strict;
|
||||
use warnings;
|
||||
use POSIX qw(mktime);
|
||||
use Test::More tests => 7;
|
||||
|
||||
# Ensure environment has no influence.
|
||||
|
@ -49,30 +50,38 @@ qx{../src/task rc:count.rc add three 2>&1};
|
|||
qx{../src/task rc:count.rc 2 delete 2>&1};
|
||||
qx{../src/task rc:count.rc add four wait:eom 2>&1};
|
||||
|
||||
# TODO This fails when today == eom. For example, on 2013-04-30 at 8:00:00, the
|
||||
# value for 'eom' is 2013-04-30 0:00:00, which is already past due, which
|
||||
# means a second child task is generated. This would be fixed by 'eom'
|
||||
# expanding to 2013-04-30 24:00:00, as per ISO-8601.
|
||||
qx{../src/task rc:count.rc add five due:eom recur:monthly 2>&1};
|
||||
TODO: {
|
||||
my @today = localtime;
|
||||
my @tomorrow = @today;
|
||||
$tomorrow[3] += 1;
|
||||
@tomorrow = localtime(mktime(@tomorrow));
|
||||
local $TODO = 'can fail when today == eom' if $today[4] != $tomorrow[4];
|
||||
|
||||
diag ("Problem: the next test fails at EOM");
|
||||
my $output = qx{../src/task rc:count.rc count 2>&1};
|
||||
like ($output, qr/^5\n/ms, 'count');
|
||||
# TODO This fails when today == eom. For example, on 2013-04-30 at 8:00:00, the
|
||||
# value for 'eom' is 2013-04-30 0:00:00, which is already past due, which
|
||||
# means a second child task is generated. This would be fixed by 'eom'
|
||||
# expanding to 2013-04-30 24:00:00, as per ISO-8601.
|
||||
qx{../src/task rc:count.rc add five due:eom recur:monthly 2>&1};
|
||||
|
||||
$output = qx{../src/task rc:count.rc count status:deleted rc.debug:1 2>&1};
|
||||
like ($output, qr/^1\n/ms, 'count status:deleted');
|
||||
diag ("Problem: the next test fails at EOM");
|
||||
my $output = qx{../src/task rc:count.rc count 2>&1};
|
||||
like ($output, qr/^5\n/ms, 'count');
|
||||
|
||||
diag ("Problem: the next test fails at EOM");
|
||||
$output = qx{../src/task rc:count.rc count e 2>&1};
|
||||
like ($output, qr/^3\n/ms, 'count e');
|
||||
$output = qx{../src/task rc:count.rc count status:deleted rc.debug:1 2>&1};
|
||||
like ($output, qr/^1\n/ms, 'count status:deleted');
|
||||
|
||||
diag ("Problem: the next test fails at EOM");
|
||||
$output = qx{../src/task rc:count.rc count description.startswith:f 2>&1};
|
||||
like ($output, qr/^2\n/ms, 'count description.startswith:f');
|
||||
diag ("Problem: the next test fails at EOM");
|
||||
$output = qx{../src/task rc:count.rc count e 2>&1};
|
||||
like ($output, qr/^3\n/ms, 'count e');
|
||||
|
||||
diag ("Problem: the next test fails at EOM");
|
||||
$output = qx{../src/task rc:count.rc count due.any: 2>&1};
|
||||
like ($output, qr/^1\n/ms, 'count due.any:');
|
||||
diag ("Problem: the next test fails at EOM");
|
||||
$output = qx{../src/task rc:count.rc count description.startswith:f 2>&1};
|
||||
like ($output, qr/^2\n/ms, 'count description.startswith:f');
|
||||
|
||||
diag ("Problem: the next test fails at EOM");
|
||||
$output = qx{../src/task rc:count.rc count due.any: 2>&1};
|
||||
like ($output, qr/^1\n/ms, 'count due.any:');
|
||||
}
|
||||
|
||||
# Cleanup.
|
||||
unlink qw(pending.data completed.data undo.data backlog.data count.rc);
|
||||
|
|
|
@ -35,16 +35,18 @@ Context context;
|
|||
// A few hard-coded symbols.
|
||||
bool get (const std::string& name, Variant& value)
|
||||
{
|
||||
if (name == "pi") {value = Variant (3.14159165); return true;}
|
||||
else if (name == "x") {value = Variant (true); return true;}
|
||||
if (name == "x")
|
||||
value = Variant (true);
|
||||
else
|
||||
return false;
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
UnitTest t (43);
|
||||
UnitTest t (46);
|
||||
|
||||
// Test the source independently.
|
||||
Variant v;
|
||||
|
@ -54,10 +56,6 @@ int main (int argc, char** argv)
|
|||
t.is (v.type (), Variant::type_boolean, "get(x) --> boolean");
|
||||
t.is (v.get_bool (), true, "get(x) --> true");
|
||||
|
||||
t.ok (get ("pi", v), "true <-- get(pi)");
|
||||
t.is (v.type (), Variant::type_real, "get(pi) --> real");
|
||||
t.is (v.get_real (), 3.141592, 0.00001, "get(pi) --> 3.14159265");
|
||||
|
||||
Eval e;
|
||||
e.addSource (get);
|
||||
Variant result;
|
||||
|
@ -138,6 +136,20 @@ int main (int argc, char** argv)
|
|||
t.is (result.type (), Variant::type_integer, "infix '2*3+1' --> integer");
|
||||
t.is (result.get_integer (), 7, "infix '2*3+1' --> 7");
|
||||
|
||||
// TW-1254 - Unary minus support.
|
||||
e.evaluateInfixExpression ("2--3", result);
|
||||
t.is (result.type (), Variant::type_integer, "infix '2--3' --> integer");
|
||||
t.is (result.get_integer (), 5, "infix '2--3' --> 5");
|
||||
|
||||
//e.debug ();
|
||||
e.evaluateInfixExpression ("!false", result);
|
||||
t.is (result.type (), Variant::type_boolean, "infix '!false' --> boolean");
|
||||
t.is (result.get_bool (), true, "infix '!false' --> true");
|
||||
|
||||
e.evaluateInfixExpression ("!true", result);
|
||||
t.is (result.type (), Variant::type_boolean, "infix '!true' --> boolean");
|
||||
t.is (result.get_bool (), false, "infix '!true' --> false");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -91,21 +91,24 @@ int main (int argc, char** argv)
|
|||
int local_s = (local_now->tm_hour * 3600) +
|
||||
(local_now->tm_min * 60) +
|
||||
local_now->tm_sec;
|
||||
local_now->tm_hour = 0;
|
||||
local_now->tm_min = 0;
|
||||
local_now->tm_sec = 0;
|
||||
local_now->tm_hour = 0;
|
||||
local_now->tm_min = 0;
|
||||
local_now->tm_sec = 0;
|
||||
local_now->tm_isdst = -1;
|
||||
time_t local = mktime (local_now);
|
||||
std::cout << "# local midnight today " << local << "\n";
|
||||
|
||||
local_now->tm_year = 2013 - 1900;
|
||||
local_now->tm_mon = 12 - 1;
|
||||
local_now->tm_mday = 6;
|
||||
local_now->tm_year = 2013 - 1900;
|
||||
local_now->tm_mon = 12 - 1;
|
||||
local_now->tm_mday = 6;
|
||||
local_now->tm_isdst = 0;
|
||||
time_t local6 = mktime (local_now);
|
||||
std::cout << "# local midnight 2013-12-06 " << local6 << "\n";
|
||||
|
||||
local_now->tm_year = 2013 - 1900;
|
||||
local_now->tm_mon = 12 - 1;
|
||||
local_now->tm_mday = 1;
|
||||
local_now->tm_year = 2013 - 1900;
|
||||
local_now->tm_mon = 12 - 1;
|
||||
local_now->tm_mday = 1;
|
||||
local_now->tm_isdst = 0;
|
||||
time_t local1 = mktime (local_now);
|
||||
std::cout << "# local midnight 2013-12-01 " << local1 << "\n";
|
||||
|
||||
|
@ -113,21 +116,24 @@ int main (int argc, char** argv)
|
|||
int utc_s = (utc_now->tm_hour * 3600) +
|
||||
(utc_now->tm_min * 60) +
|
||||
utc_now->tm_sec;
|
||||
utc_now->tm_hour = 0;
|
||||
utc_now->tm_min = 0;
|
||||
utc_now->tm_sec = 0;
|
||||
utc_now->tm_hour = 0;
|
||||
utc_now->tm_min = 0;
|
||||
utc_now->tm_sec = 0;
|
||||
utc_now->tm_isdst = -1;
|
||||
time_t utc = timegm (utc_now);
|
||||
std::cout << "# utc midnight today " << utc << "\n";
|
||||
|
||||
utc_now->tm_year = 2013 - 1900;
|
||||
utc_now->tm_mon = 12 - 1;
|
||||
utc_now->tm_mday = 6;
|
||||
utc_now->tm_year = 2013 - 1900;
|
||||
utc_now->tm_mon = 12 - 1;
|
||||
utc_now->tm_mday = 6;
|
||||
utc_now->tm_isdst = 0;
|
||||
time_t utc6 = timegm (utc_now);
|
||||
std::cout << "# utc midnight 2013-12-06 " << utc6 << "\n";
|
||||
|
||||
utc_now->tm_year = 2013 - 1900;
|
||||
utc_now->tm_mon = 12 - 1;
|
||||
utc_now->tm_mday = 1;
|
||||
utc_now->tm_year = 2013 - 1900;
|
||||
utc_now->tm_mon = 12 - 1;
|
||||
utc_now->tm_mday = 1;
|
||||
utc_now->tm_isdst = 0;
|
||||
time_t utc1 = timegm (utc_now);
|
||||
std::cout << "# utc midnight 2013-12-01 " << utc1 << "\n";
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#! /bin/sh
|
||||
|
||||
rc=0
|
||||
if [ x"$1" = x"--verbose" ];
|
||||
then
|
||||
for i in ${TESTBLOB}
|
||||
|
@ -9,9 +10,10 @@ then
|
|||
while read LINE
|
||||
do
|
||||
echo "$LINE"
|
||||
done < test.log
|
||||
done < test.log || rc=1
|
||||
rm test.log
|
||||
done
|
||||
exit $rc
|
||||
else
|
||||
date > all.log
|
||||
|
||||
|
@ -37,7 +39,7 @@ else
|
|||
COUNT=`expr $COUNT + 1`
|
||||
fi
|
||||
|
||||
$i >> all.log 2>&1
|
||||
$i >> all.log 2>&1 || rc=1
|
||||
done
|
||||
|
||||
if [ $BAR -eq 1 ]; then
|
||||
|
@ -53,4 +55,5 @@ else
|
|||
printf "Fail: %5d\n" `grep -c '^not' all.log`
|
||||
printf "Skipped: %5d\n" `grep -c '^skip' all.log`
|
||||
printf "Runtime: %5d seconds\n" $RUNTIME
|
||||
exit $rc
|
||||
fi
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <iomanip>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <test.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -84,6 +85,7 @@ UnitTest::~UnitTest ()
|
|||
<< " skipped. "
|
||||
<< std::setprecision (3) << percentPassed
|
||||
<< "% passed.\n";
|
||||
exit (_failed > 0);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
|
75
test/tw-1300.t
Executable file
75
test/tw-1300.t
Executable file
|
@ -0,0 +1,75 @@
|
|||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
import sys
|
||||
import os
|
||||
import signal
|
||||
from glob import glob
|
||||
# Ensure python finds the local simpletap and basetest modules
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from basetest import BaseTestCase
|
||||
|
||||
|
||||
class BaseTestBug1300(BaseTestCase):
|
||||
@classmethod
|
||||
def prepare(cls):
|
||||
with open("bug.rc", 'w') as fh:
|
||||
fh.write("data.location=.\n"
|
||||
"confirmation=no\n")
|
||||
|
||||
def tearDown(self):
|
||||
"""Needed after each test or setUp will cause duplicated data at start
|
||||
of the next test.
|
||||
"""
|
||||
for file in glob("*.data"):
|
||||
os.remove(file)
|
||||
|
||||
@classmethod
|
||||
def cleanup(cls):
|
||||
os.remove("bug.rc")
|
||||
|
||||
|
||||
class TestBug1300(BaseTestBug1300):
|
||||
def test_dom_exit_status_good(self):
|
||||
"""If the DOM recognizes a reference, it should return '0'
|
||||
"""
|
||||
self.callTaskSuccess(["rc:bug.rc", "_get", "context.program"])
|
||||
|
||||
def test_dom_exit_status_bad(self):
|
||||
"""If the DOM does not recognize a reference, it should return '1'
|
||||
"""
|
||||
self.callTaskError(["rc:bug.rc", "_get", "XYZ"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from simpletap import TAPTestRunner
|
||||
import unittest
|
||||
unittest.main(testRunner=TAPTestRunner())
|
||||
|
||||
# vim: ai sts=4 et sw=4
|
116
test/tw-285.t
Executable file
116
test/tw-285.t
Executable file
|
@ -0,0 +1,116 @@
|
|||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
import sys
|
||||
import os
|
||||
import signal
|
||||
from glob import glob
|
||||
# Ensure python finds the local simpletap and basetest modules
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from basetest import BaseTestCase
|
||||
|
||||
|
||||
class BaseTest285(BaseTestCase):
|
||||
@classmethod
|
||||
def prepare(cls):
|
||||
with open("bug.rc", 'w') as fh:
|
||||
fh.write("data.location=.\n"
|
||||
"verbose=nothing\n"
|
||||
"confirmation=no\n")
|
||||
|
||||
def setUp(self):
|
||||
"""Executed before each test in the class"""
|
||||
|
||||
# OVERDUE YESTERDAY DUE TODAY TOMORROW WEEK MONTH YEAR
|
||||
# due:-1week Y - - - - ? ? ?
|
||||
# due:-1day Y Y - - - ? ? ?
|
||||
# due:today Y - Y Y - ? ? ?
|
||||
# due:tomorrow - - Y - Y ? ? ?
|
||||
# due:3days - - Y - - ? ? ?
|
||||
# due:1month - - - - - - - ?
|
||||
# due:1year - - - - - - - -
|
||||
|
||||
self.callTaskSuccess(['rc:bug.rc', 'add', 'due_last_week', 'due:-1week'])
|
||||
self.callTaskSuccess(['rc:bug.rc', 'add', 'due_yesterday', 'due:-1day'])
|
||||
self.callTaskSuccess(['rc:bug.rc', 'add', 'due_earlier_today', 'due:today'])
|
||||
self.callTaskSuccess(['rc:bug.rc', 'add', 'due_later_today', 'due:tomorrow'])
|
||||
self.callTaskSuccess(['rc:bug.rc', 'add', 'due_three_days', 'due:3days'])
|
||||
self.callTaskSuccess(['rc:bug.rc', 'add', 'due_next_month', 'due:1month'])
|
||||
self.callTaskSuccess(['rc:bug.rc', 'add', 'due_next_year', 'due:1year'])
|
||||
|
||||
def tearDown(self):
|
||||
"""Needed after each test or setUp will cause duplicated data at start
|
||||
of the next test.
|
||||
"""
|
||||
for file in glob("*.data"):
|
||||
os.remove(file)
|
||||
|
||||
@classmethod
|
||||
def cleanup(cls):
|
||||
os.remove("bug.rc")
|
||||
|
||||
|
||||
class Test285(BaseTest285):
|
||||
def test_overdue(self):
|
||||
"""+OVERDUE"""
|
||||
code, out, err = self.callTaskSuccess(["rc:bug.rc", "+OVERDUE", "count"])
|
||||
self.assertEqual(out, "3\n", "+OVERDUE == 3 tasks")
|
||||
|
||||
def test_yesterday(self):
|
||||
"""+YESTERDAY"""
|
||||
code, out, err = self.callTaskSuccess(["rc:bug.rc", "+YESTERDAY", "count"])
|
||||
self.assertEqual(out, "1\n", "+YESTERDAY == 1 task")
|
||||
|
||||
def test_due(self):
|
||||
"""+DUE"""
|
||||
code, out, err = self.callTaskSuccess(["rc:bug.rc", "+DUE", "count"])
|
||||
self.assertEqual(out, "3\n", "+DUE == 3 task")
|
||||
|
||||
def test_today(self):
|
||||
"""+TODAY"""
|
||||
code, out, err = self.callTaskSuccess(["rc:bug.rc", "+TODAY", "count"])
|
||||
self.assertEqual(out, "1\n", "+TODAY == 1 task")
|
||||
|
||||
def test_duetoday(self):
|
||||
"""+DUETODAY"""
|
||||
code, out, err = self.callTaskSuccess(["rc:bug.rc", "+DUETODAY", "count"])
|
||||
self.assertEqual(out, "1\n", "+DUETODAY == 1 task")
|
||||
|
||||
def test_tomorrow(self):
|
||||
"""+TOMORROW"""
|
||||
code, out, err = self.callTaskSuccess(["rc:bug.rc", "+TOMORROW", "count"])
|
||||
self.assertEqual(out, "1\n", "+TOMORROW == 1 task")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from simpletap import TAPTestRunner
|
||||
import unittest
|
||||
unittest.main(testRunner=TAPTestRunner())
|
||||
|
||||
# vim: ai sts=4 et sw=4
|
Loading…
Add table
Add a link
Reference in a new issue