Treat a nonzero exit status as a failure (#3430)

And fix the test cases that have been failing ,undetected
This commit is contained in:
Dustin J. Mitchell 2024-05-03 09:58:09 -04:00 committed by GitHub
parent 50cfbe8b63
commit 28a46880a2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 62 additions and 75 deletions

View file

@ -439,6 +439,7 @@ Context* Context::context;
////////////////////////////////////////////////////////////////////////////////
Context& Context::getContext ()
{
assert (Context::context);
return *Context::context;
}

View file

@ -28,6 +28,7 @@
#include <CmdVersion.h>
#include <sstream>
#include <stdlib.h>
#include <Datetime.h>
#include <Context.h>
#include <Table.h>
#ifdef HAVE_COMMIT
@ -70,6 +71,8 @@ int CmdVersion::execute (std::string& output)
link.add ("");
link.set (link.addRow (), 0, "Documentation for Taskwarrior can be found using 'man task', 'man taskrc', 'man task-color', 'man task-sync' or at https://taskwarrior.org");
Datetime now;
Color bold;
if (Context::getContext ().color ())
bold = Color ("bold");
@ -78,7 +81,7 @@ int CmdVersion::execute (std::string& output)
<< format ("{1} {2} built for ", bold.colorize (PACKAGE), bold.colorize (VERSION))
<< osName ()
<< '\n'
<< "Copyright (C) 2006 - 2021 T. Babej, P. Beckingham, F. Hernandez."
<< "Copyright (C) 2006 - " << now.year () << " T. Babej, P. Beckingham, F. Hernandez."
<< '\n'
<< '\n'
<< disclaimer.render ()

View file

@ -42,6 +42,9 @@ DEFAULT_HOOK_PATH = os.path.abspath(
os.path.join("${CMAKE_SOURCE_DIR}", "test", "test_hooks")
)
# Source directory
SOURCE_DIR = os.path.abspath("${CMAKE_SOURCE_DIR}")
# Environment flags to control skipping of task tests
TASKW_SKIP = os.environ.get("TASKW_SKIP", False)

View file

@ -26,6 +26,7 @@
#include <cmake.h>
#include <test.h>
#include <Context.h>
#include <Eval.h>
////////////////////////////////////////////////////////////////////////////////
@ -44,6 +45,8 @@ bool get (const std::string& name, Variant& value)
int main (int, char**)
{
UnitTest t (52);
Context context;
Context::setContext(&context);
// Test the source independently.
Variant v;

View file

@ -37,7 +37,7 @@
int main (int, char**)
{
#ifdef PRODUCT_TASKWARRIOR
UnitTest t (1253);
UnitTest t (1255);
#else
UnitTest t (1235);
#endif

View file

@ -47,6 +47,9 @@ def run_test(testqueue, outqueue, threadname):
if sys.version_info > (3,):
out, err = out.decode('utf-8'), err.decode('utf-8')
if p.returncode != 0:
out = out + "\nnot ok - test executable failed\n"
output = ("# {0}\n".format(os.path.basename(test)), out, err)
log.debug("Collected output %s", output)
outqueue.put(output)

View file

@ -33,6 +33,8 @@
int main (int, char**)
{
UnitTest test (49);
Context context;
Context::setContext(&context);
// Ensure environment has no influence.
unsetenv ("TASKDATA");
@ -152,44 +154,10 @@ TODO Task::decode
////////////////////////////////////////////////////////////////////////////////
Task task;
// (blank)
good = true;
try {task = Task ("");}
catch (const std::string& e){test.diag (e); good = false;}
test.notok (good, "Task::Task ('')");
// []
good = true;
try {task = Task ("[]");}
catch (const std::string& e){test.diag (e); good = false;}
test.notok (good, "Task::Task ('[]')");
// [name:"value"]
good = true;
try {task = Task ("[name:\"value\"]");}
catch (const std::string& e){test.diag (e); good = false;}
test.ok (good, "Task::Task ('[name:\"value\"]')");
test.is (task.get ("name"), "value", "name=value");
// [name:"one two"]
good = true;
try {task = Task ("[name:\"one two\"]");}
catch (const std::string& e){test.diag (e); good = false;}
test.ok (good, "Task::Task ('[name:\"one two\"]')");
test.is (task.get ("name"), "one two", "name=one two");
// [one:two three:four]
good = true;
try {task = Task (R"([one:"two" three:"four"])");}
catch (const std::string& e){test.diag (e); good = false;}
test.ok (good, R"(Task::Task ('[one:"two" three:"four"]'))");
test.is (task.get ("one"), "two", "one=two");
test.is (task.get ("three"), "four", "three=four");
// Task::set
task = Task();
task.set ("name", "value");
test.is (task.composeF4 (), "[name:\"value\"]", "Task::set");
test.is (task.composeJSON (), "{\"name\":\"value\"}", "Task::set");
// Task::has
test.ok (task.has ("name"), "Task::has");
@ -197,18 +165,18 @@ TODO Task::decode
// Task::get_int
task.set ("one", 1);
test.is (task.composeF4 (), R"([name:"value" one:"1"])", "Task::set");
test.is (task.composeJSON (), R"({"name":"value","one":"1"})", "Task::set");
test.is (task.get_int ("one"), 1, "Task::get_int");
// Task::get_ulong
task.set ("two", "4294967295");
test.is (task.composeF4 (), R"([name:"value" one:"1" two:"4294967295"])", "Task::set");
test.is (task.composeJSON (), R"({"name":"value","one":"1","two":"4294967295"})", "Task::set");
test.is ((size_t)task.get_ulong ("two"), (size_t)4294967295UL, "Task::get_ulong");
// Task::remove
task.remove ("one");
task.remove ("two");
test.is (task.composeF4 (), "[name:\"value\"]", "Task::remove");
test.is (task.composeJSON (), "{\"name\":\"value\"}", "Task::remove");
// Task::all
test.is (task.all ().size (), (size_t)1, "Task::all size");
@ -230,16 +198,14 @@ TODO Task::decode
catch (const std::string& e){test.diag (e); good = false;}
test.ok (good, "Task::Task ('{<minimal>}')");
// Verify tag handling is correct between F4 and JSON.
// Verify tag handling is correct
Task t6;
t6.set ("entry", "20130602T224000Z");
t6.set ("description", "DESC");
t6.addTag ("tag1");
test.is (t6.composeF4 (), R"([description:"DESC" entry:"20130602T224000Z" tags:"tag1"])", "F4 good");
test.is (t6.composeJSON (), R"({"description":"DESC","entry":"20130602T224000Z","tags":["tag1"]})", "JSON good");
t6.addTag ("tag2");
test.is (t6.composeF4 (), R"([description:"DESC" entry:"20130602T224000Z" tags:"tag1,tag2"])", "F4 good");
test.is (t6.composeJSON (), R"({"description":"DESC","entry":"20130602T224000Z","tags":["tag1","tag2"]})", "JSON good");
good = true;
@ -247,7 +213,6 @@ TODO Task::decode
try {t7 = Task (R"({"description":"DESC","entry":"20130602T224000Z","tags":["tag1","tag2"]})");}
catch (const std::string& e){test.diag (e); good = false;}
test.ok (good, "Task::Task ('{two tags}')");
test.is (t7.composeF4 (), R"([description:"DESC" entry:"1370212800" tags:"tag1,tag2"])", "F4 good");
test.is (t7.composeJSON (), R"({"description":"DESC","entry":"20130602T224000Z","tags":["tag1","tag2"]})", "JSON good");
return 0;

View file

@ -37,16 +37,15 @@ void cleardb ()
{
// Remove any residual test files.
rmdir ("./extensions");
unlink ("./pending.data");
unlink ("./completed.data");
unlink ("./undo.data");
unlink ("./backlog.data");
unlink ("./taskchampion.sqlite3");
}
////////////////////////////////////////////////////////////////////////////////
int main (int, char**)
{
UnitTest t (12);
Context context;
Context::setContext(&context);
// Ensure environment has no influence.
unsetenv ("TASKDATA");
@ -84,8 +83,8 @@ int main (int, char**)
t.is ((int) pending.size (), 1, "TDB2 after add, 1 pending task");
t.is ((int) completed.size (), 0, "TDB2 after add, 0 completed tasks");
t.is ((int) num_reverts_possible, 3, "TDB2 after add, 3 undo lines");
t.is ((int) num_local_changes, 1, "TDB2 after add, 1 backlog task");
t.is ((int) num_reverts_possible, 1, "TDB2 after add, 1 revert possible");
t.is ((int) num_local_changes, 6, "TDB2 after add, 6 local changes");
task.set ("description", "This is a test");
context.tdb2.modify (task);
@ -95,10 +94,10 @@ int main (int, char**)
num_reverts_possible = context.tdb2.num_reverts_possible ();
num_local_changes = context.tdb2.num_local_changes ();
t.is ((int) pending.size (), 1, "TDB2 after add, 1 pending task");
t.is ((int) completed.size (), 0, "TDB2 after add, 0 completed tasks");
t.is ((int) num_reverts_possible, 7, "TDB2 after add, 7 undo lines");
t.is ((int) num_local_changes, 2, "TDB2 after add, 2 backlog task");
t.is ((int) pending.size (), 1, "TDB2 after set, 1 pending task");
t.is ((int) completed.size (), 0, "TDB2 after set, 0 completed tasks");
t.is ((int) num_reverts_possible, 1, "TDB2 after set, 1 revert possible");
t.is ((int) num_local_changes, 7, "TDB2 after set, 7 local changes");
// Reset for reuse.
cleardb ();

View file

@ -128,7 +128,8 @@ void UnitTest::ok (bool expression, const std::string& name, bool expfail /* = f
}
else
{
++_failed;
if (success == expfail)
++_failed;
std::cout << red ("not ok")
<< " "
<< _counter
@ -158,7 +159,8 @@ void UnitTest::notok (bool expression, const std::string& name, bool expfail /*
}
else
{
++_failed;
if (success == expfail)
++_failed;
std::cout << red ("not ok")
<< " "
<< _counter
@ -187,7 +189,8 @@ void UnitTest::is (bool actual, bool expected, const std::string& name, bool exp
}
else
{
++_failed;
if (success == expfail)
++_failed;
std::cout << red ("not ok")
<< " "
<< _counter
@ -220,7 +223,8 @@ void UnitTest::is (size_t actual, size_t expected, const std::string& name, bool
}
else
{
++_failed;
if (success == expfail)
++_failed;
std::cout << red ("not ok")
<< " "
<< _counter
@ -253,7 +257,8 @@ void UnitTest::is (int actual, int expected, const std::string& name, bool expfa
}
else
{
++_failed;
if (success == expfail)
++_failed;
std::cout << red ("not ok")
<< " "
<< _counter
@ -286,7 +291,8 @@ void UnitTest::is (double actual, double expected, const std::string& name, bool
}
else
{
++_failed;
if (success == expfail)
++_failed;
std::cout << red ("not ok")
<< " "
<< _counter
@ -319,7 +325,8 @@ void UnitTest::is (double actual, double expected, double tolerance, const std::
}
else
{
++_failed;
if (success == expfail)
++_failed;
std::cout << red ("not ok")
<< " "
<< _counter
@ -352,7 +359,8 @@ void UnitTest::is (unsigned char actual, unsigned char expected, const std::stri
}
else
{
++_failed;
if (success == expfail)
++_failed;
std::cout << red ("not ok")
<< " "
<< _counter
@ -389,7 +397,8 @@ void UnitTest::is (
}
else
{
++_failed;
if (success == expfail)
++_failed;
std::cout << red ("not ok")
<< " "
<< _counter
@ -427,7 +436,8 @@ void UnitTest::is (
}
else
{
++_failed;
if (success == expfail)
++_failed;
std::cout << red ("not ok")
<< " "
<< _counter

View file

@ -35,6 +35,8 @@
int main (int, char**)
{
UnitTest t (19);
Context context;
Context::setContext(&context);
// Ensure environment has no influence.
unsetenv ("TASKDATA");

View file

@ -35,7 +35,7 @@ from datetime import datetime
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from basetest import Task, TestCase
from basetest.utils import run_cmd_wait
from basetest.utils import run_cmd_wait, SOURCE_DIR
class TestVersion(TestCase):
@ -50,7 +50,6 @@ class TestVersion(TestCase):
self.assertIn("You must specify a command or a task to modify", err)
@unittest.skip(reason="See #3424")
def test_copyright_up_to_date(self):
"""Copyright is current"""
code, out, err = self.t("version")
@ -58,18 +57,16 @@ class TestVersion(TestCase):
expected = r"Copyright \(C\) \d{4} - %d" % (datetime.now().year,)
self.assertRegex(out, expected)
def slurp(self, file="../CMakeLists.txt"):
number = r"\.".join(["[0-9]+"] * 3)
ver = re.compile("^set \\(PROJECT_VERSION \"({0}[^\"]*)\"\\)$".format(number))
def slurp(self, file=os.path.join(SOURCE_DIR, "CMakeLists.txt")):
number = "\.".join(["[0-9]+"] * 3)
ver = re.compile("^ *VERSION ({0}[^\"]*)$".format(number))
with open(file) as fh:
for line in fh:
if "PROJECT_VERSION" in line:
match = ver.match(line)
if match:
return match.group(1)
match = ver.match(line)
if match:
return match.group(1).strip()
raise ValueError("Couldn't find matching version in {0}".format(file))
@unittest.skip(reason="See #3424")
def test_version(self):
"""version command outputs expected version and license"""
code, out, err = self.t("version")
@ -79,7 +76,6 @@ class TestVersion(TestCase):
self.assertIn("MIT license", out)
self.assertIn("https://taskwarrior.org", out)
@unittest.skip(reason="See #3424")
def test_under_version(self):
"""_version and diagnostics output expected version and syntax"""
code, out, err = self.t("_version")

View file

@ -43,6 +43,8 @@ extern std::string configurationDefaults;
int main (int, char**)
{
UnitTest t (1);
Context context;
Context::setContext(&context);
// Ensure environment has no influence.
unsetenv ("TASKDATA");