Add check whether requested intervals have been found when searching by ID

- Restores behaviour which got lost when switching to the new interval filtering in 9968b9e9
- Add test for each command

Signed-off-by: Thomas Lauf <thomas.lauf@tngtech.com>
This commit is contained in:
Thomas Lauf 2022-01-09 11:41:15 +01:00
parent c2e26a989e
commit 993ae85d5c
22 changed files with 329 additions and 8 deletions

View file

@ -68,6 +68,27 @@ int CmdAnnotate (
{
auto filtering = IntervalFilterAllWithIds (ids);
intervals = getTracked (database, rules, filtering);
if (intervals.size () != ids.size ())
{
for (auto& id: ids)
{
bool found = false;
for (auto& interval: intervals)
{
if (interval.id == id)
{
found = true;
break;
}
}
if (!found)
{
throw format ("ID '@{1}' does not correspond to any tracking.", id);
}
}
}
}
// Apply annotation to intervals.

View file

@ -53,6 +53,28 @@ int CmdDelete (
auto filtering = IntervalFilterAllWithIds (ids);
auto intervals = getTracked (database, rules, filtering);
if (intervals.size () != ids.size ())
{
for (auto& id: ids)
{
bool found = false;
for (auto& interval: intervals)
{
if (interval.id == id)
{
found = true;
break;
}
}
if (!found)
{
throw format ("ID '@{1}' does not correspond to any tracking.", id);
}
}
}
for (const auto& interval : intervals)
{
database.deleteInterval (interval);

View file

@ -57,6 +57,27 @@ int CmdJoin (
auto filtering = IntervalFilterAllWithIds (ids);
auto intervals = getTracked (database, rules, filtering);
if (intervals.size () != ids.size ())
{
for (auto& id: ids)
{
bool found = false;
for (auto& interval: intervals)
{
if (interval.id == id)
{
found = true;
break;
}
}
if (!found)
{
throw format ("ID '@{1}' does not correspond to any tracking.", id);
}
}
}
Interval first = intervals[1];
Interval second = intervals[0];

View file

@ -58,6 +58,27 @@ int CmdLengthen (
auto filtering = IntervalFilterAllWithIds (ids);
auto intervals = getTracked (database, rules, filtering);
if (intervals.size () != ids.size ())
{
for (auto& id: ids)
{
bool found = false;
for (auto& interval: intervals)
{
if (interval.id == id)
{
found = true;
break;
}
}
if (!found)
{
throw format ("ID '@{1}' does not correspond to any tracking.", id);
}
}
}
// Lengthen intervals specified by ids
for (auto& interval : intervals)
{

View file

@ -70,6 +70,28 @@ int CmdMove (
auto filtering = IntervalFilterAllWithIds (ids);
auto intervals = getTracked (database, rules, filtering);
if (intervals.size () != ids.size ())
{
for (auto& id: ids)
{
bool found = false;
for (auto& interval: intervals)
{
if (interval.id == id)
{
found = true;
break;
}
}
if (!found)
{
throw format ("ID '@{1}' does not correspond to any tracking.", id);
}
}
}
Interval interval = intervals.at (0);
if (interval.synthetic)

View file

@ -56,7 +56,27 @@ int CmdResize (
auto filtering = IntervalFilterAllWithIds (ids);
auto intervals = getTracked (database, rules, filtering);
// Apply tags to ids.
if (intervals.size () != ids.size ())
{
for (auto& id: ids)
{
bool found = false;
for (auto& interval: intervals)
{
if (interval.id == id)
{
found = true;
break;
}
}
if (!found)
{
throw format ("ID '@{1}' does not correspond to any tracking.", id);
}
}
}
for (auto& interval : intervals)
{
if (interval.is_open ())

View file

@ -57,6 +57,27 @@ int CmdShorten (
auto filtering = IntervalFilterAllWithIds (ids);
auto intervals = getTracked (database, rules, filtering);
if (intervals.size () != ids.size ())
{
for (auto& id: ids)
{
bool found = false;
for (auto& interval: intervals)
{
if (interval.id == id)
{
found = true;
break;
}
}
if (!found)
{
throw format ("ID '@{1}' does not correspond to any tracking.", id);
}
}
}
// Shorten intervals specified by ids
for (auto& interval : intervals)
{

View file

@ -54,7 +54,27 @@ int CmdSplit (
auto filtering = IntervalFilterAllWithIds (ids);
auto intervals = getTracked (database, rules, filtering);
// Apply tags to ids.
if (intervals.size () != ids.size ())
{
for (auto& id: ids)
{
bool found = false;
for (auto& interval: intervals)
{
if (interval.id == id)
{
found = true;
break;
}
}
if (!found)
{
throw format ("ID '@{1}' does not correspond to any tracking.", id);
}
}
}
for (const auto& interval : intervals)
{
Interval first = interval;

View file

@ -78,6 +78,27 @@ int CmdTag (
{
auto filtering = IntervalFilterAllWithIds (ids);
intervals = getTracked (database, rules, filtering);
if (intervals.size () != ids.size ())
{
for (auto& id: ids)
{
bool found = false;
for (auto& interval: intervals)
{
if (interval.id == id)
{
found = true;
break;
}
}
if (!found)
{
throw format ("ID '@{1}' does not correspond to any tracking.", id);
}
}
}
}
// Apply tags to intervals.

View file

@ -77,6 +77,27 @@ int CmdUntag (
{
auto filtering = IntervalFilterAllWithIds (ids);
intervals = getTracked (database, rules, filtering);
if (intervals.size () != ids.size ())
{
for (auto& id: ids)
{
bool found = false;
for (auto& interval: intervals)
{
if (interval.id == id)
{
found = true;
break;
}
}
if (!found)
{
throw format ("ID '@{1}' does not correspond to any tracking.", id);
}
}
}
}
// Remove tags from intervals.

View file

@ -233,6 +233,17 @@ class TestAnnotate(TestCase):
expectedAnnotation="",
description="unmodified interval")
def test_referencing_a_non_existent_interval_is_an_error(self):
"""Calling annotate with a non-existent interval reference is an error"""
code, out, err = self.t.runError("annotate @1 foo")
self.assertIn("ID '@1' does not correspond to any tracking.", err)
self.t("start 1h ago bar")
code, out, err = self.t.runError("annotate @2 foo")
self.assertIn("ID '@2' does not correspond to any tracking.", err)
if __name__ == "__main__":
from simpletap import TAPTestRunner

View file

@ -519,6 +519,16 @@ class TestContinue(TestCase):
code, out, err = self.t.runError("continue @2 from {:%Y-%m-%dT%H:%M:%S}Z".format(now_utc + timedelta(seconds=10)))
self.assertIn("Time tracking cannot be set in the future", err)
def test_referencing_a_non_existent_interval_is_an_error(self):
"""Calling continue with a non-existent interval reference is an error"""
code, out, err = self.t.runError("continue @1")
self.assertIn("ID '@1' does not correspond to any tracking.", err)
self.t("start 1h ago bar")
code, out, err = self.t.runError("continue @2")
self.assertIn("ID '@2' does not correspond to any tracking.", err)
if __name__ == "__main__":
from simpletap import TAPTestRunner

View file

@ -149,6 +149,16 @@ class TestDelete(TestCase):
self.assertEqual(len(j), 0)
def test_referencing_a_non_existent_interval_is_an_error(self):
"""Calling delete with a non-existent interval reference is an error"""
code, out, err = self.t.runError("delete @1")
self.assertIn("ID '@1' does not correspond to any tracking.", err)
self.t("start 1h ago bar")
code, out, err = self.t.runError("delete @2")
self.assertIn("ID '@2' does not correspond to any tracking.", err)
if __name__ == "__main__":
from simpletap import TAPTestRunner

View file

@ -92,6 +92,16 @@ class TestJoin(TestCase):
expectedStart="{:%Y%m%dT%H%M%S}Z".format(five_hours_before_utc),
expectedTags=["foo", "bar"])
def test_referencing_a_non_existent_interval_is_an_error(self):
"""Calling join with a non-existent interval reference is an error"""
code, out, err = self.t.runError("join @1 @2")
self.assertIn("ID '@1' does not correspond to any tracking.", err)
self.t("start 1h ago bar")
code, out, err = self.t.runError("join @1 @2")
self.assertIn("ID '@2' does not correspond to any tracking.", err)
if __name__ == "__main__":
from simpletap import TAPTestRunner

View file

@ -97,7 +97,15 @@ class TestLengthen(TestCase):
self.assertEqual(len(j), 1)
self.assertClosedInterval(j[0])
# TODO Add :adjust tests.
def test_referencing_a_non_existent_interval_is_an_error(self):
"""Calling lengthen with a non-existent interval reference is an error"""
code, out, err = self.t.runError("lengthen @1 @2 5min")
self.assertIn("ID '@1' does not correspond to any tracking.", err)
self.t("start 1h ago bar")
code, out, err = self.t.runError("lengthen @2 5min")
self.assertIn("ID '@2' does not correspond to any tracking.", err)
if __name__ == "__main__":

View file

@ -274,6 +274,13 @@ class TestModify(TestCase):
expectedStart=four_hours_before_utc + timedelta(minutes=10),
expectedTags=['foo'])
def test_referencing_a_non_existent_interval_is_an_error(self):
"""Calling modify with a non-existent interval reference is an error"""
self.t("start 1h ago bar")
code, out, err = self.t.runError("modify start @2")
self.assertIn("ID '@2' does not correspond to any tracking.", err)
if __name__ == "__main__":
from simpletap import TAPTestRunner

View file

@ -27,11 +27,11 @@
###############################################################################
import os
import sys
import unittest
from datetime import datetime, timedelta
import sys
# Ensure python finds the local simpletap module
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
@ -286,7 +286,6 @@ class TestMove(TestCase):
expectedTags=[],
description="unmodified interval")
def test_move_interval_to_enclose_a_month_border(self):
"""Move an interval to enclose a month border"""
self.t("track 20180831T180000 - 20180831T230000 foo")
@ -297,7 +296,15 @@ class TestMove(TestCase):
self.assertEqual(len(j), 1)
self.assertClosedInterval(j[0])
# TODO Add :adjust tests.
def test_referencing_a_non_existent_interval_is_an_error(self):
"""Calling move with a non-existent interval reference is an error"""
code, out, err = self.t.runError("move @1 2h ago")
self.assertIn("ID '@1' does not correspond to any tracking.", err)
self.t("start 1h ago bar")
code, out, err = self.t.runError("move @2 2h ago")
self.assertIn("ID '@2' does not correspond to any tracking.", err)
if __name__ == "__main__":

View file

@ -71,6 +71,16 @@ class TestResize(TestCase):
self.assertEqual(len(j), 1)
self.assertClosedInterval(j[0])
def test_referencing_a_non_existent_interval_is_an_error(self):
"""Calling resize with a non-existent interval reference is an error"""
code, out, err = self.t.runError("resize @1 @2 10min")
self.assertIn("ID '@1' does not correspond to any tracking.", err)
self.t("start 1h ago bar")
code, out, err = self.t.runError("resize @2 10min")
self.assertIn("ID '@2' does not correspond to any tracking.", err)
if __name__ == "__main__":
from simpletap import TAPTestRunner

View file

@ -128,6 +128,16 @@ class TestShorten(TestCase):
self.assertEqual(len(j), 1)
self.assertClosedInterval(j[0])
def test_referencing_a_non_existent_interval_is_an_error(self):
"""Calling shorten with a non-existent interval reference is an error"""
code, out, err = self.t.runError("shorten @1 @2 5min")
self.assertIn("ID '@1' does not correspond to any tracking.", err)
self.t("start 1h ago bar")
code, out, err = self.t.runError("shorten @2 5min")
self.assertIn("ID '@2' does not correspond to any tracking.", err)
if __name__ == "__main__":
from simpletap import TAPTestRunner

View file

@ -70,7 +70,15 @@ class TestSplit(TestCase):
self.assertEqual(j[0]['end'], j[1]['start'])
# TODO Add :adjust tests.
def test_referencing_a_non_existent_interval_is_an_error(self):
"""Calling split with a non-existent interval reference is an error"""
code, out, err = self.t.runError("split @1 @2")
self.assertIn("ID '@1' does not correspond to any tracking.", err)
self.t("start 1h ago bar")
code, out, err = self.t.runError("split @2")
self.assertIn("ID '@2' does not correspond to any tracking.", err)
if __name__ == "__main__":

View file

@ -262,6 +262,16 @@ class TestTag(TestCase):
self.t("stop")
self.t("delete @1")
def test_referencing_a_non_existent_interval_is_an_error(self):
"""Calling tag with a non-existent interval reference is an error"""
code, out, err = self.t.runError("tag @1 @2 foo")
self.assertIn("ID '@1' does not correspond to any tracking.", err)
self.t("start 1h ago bar")
code, out, err = self.t.runError("tag @2 foo")
self.assertIn("ID '@2' does not correspond to any tracking.", err)
if __name__ == "__main__":
from simpletap import TAPTestRunner

View file

@ -219,6 +219,16 @@ class TestUntag(TestCase):
self.assertEqual(len(j), 1)
self.assertClosedInterval(j[0], expectedTags=["bar"])
def test_referencing_a_non_existent_interval_is_an_error(self):
"""Calling untag with a non-existent interval reference is an error"""
code, out, err = self.t.runError("untag @1 @2 bar")
self.assertIn("ID '@1' does not correspond to any tracking.", err)
self.t("start 1h ago bar")
code, out, err = self.t.runError("untag @2 bar")
self.assertIn("ID '@2' does not correspond to any tracking.", err)
if __name__ == "__main__":
from simpletap import TAPTestRunner