#
# Copyright 2009- ECMWF.
#
# This software is licensed under the terms of the Apache Licence version 2.0
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
# In applying this licence, ECMWF does not waive the privileges and immunities
# granted to it by virtue of its status as an intergovernmental organisation
# nor does it submit to any jurisdiction.
#

from ecflow import Alias, AttrType, Autocancel, CheckPt, ChildCmdType, Client, Clock, Cron, DState, Date, Day, Days, \
    Defs, Ecf, Event, Expression, Family, FamilyVec, File, Flag, FlagType, FlagTypeVec, InLimit, \
    JobCreationCtrl, Label, Late, Limit, Meter, Node, NodeContainer, NodeVec, PartExpression, PrintStyle, \
    Repeat, RepeatDate, RepeatDateTime, RepeatDay, RepeatEnumerated, RepeatInteger, RepeatString, SState, State, Style, \
    Submittable, Suite, SuiteVec, Task, TaskVec, Time, TimeSeries, TimeSlot, Today, UrlCmd, Variable, \
    VariableList, Verify, WhyCmd, ZombieAttr, ZombieType, ZombieUserActionType, Trigger, Complete, Edit, Defstatus
import os
import unittest


class TestAddSuiteFamilyTask0(unittest.TestCase):
    def setUp(self):
        defs = Defs()
        s = Suite('s1')
        f = Family('f1')
        t = Task('t1')
        defs.add_suite(s)
        s.add_family(f)
        f.add_task(t)
        self.defs = defs

    def test_0(self):
        defs = Defs()
        defs.add_suite('s1').add_family('f1').add_task('t1')
        self.assertEqual(self.defs, defs, "defs not equal")

    def test_1(self):
        defs = Defs().add(
            Suite('s1').add(
                Family('f1').add(
                    Task('t1'))))
        self.assertEqual(self.defs, defs, "defs not equal")

    def test_2(self):
        defs = Defs(
            Suite('s1',
                  Family('f1',
                         Task('t1'))))
        self.assertEqual(self.defs, defs, "defs not equal")

    def test_3(self):
        defs = Defs() + (Suite('s1') + (Family('f1') + Task('t1')))
        self.assertEqual(self.defs, defs, "defs not equal")

    def test_3(self):
        defs = Defs() + (Suite('s1') + (Family('f1') + Task('t1')))
        self.assertEqual(self.defs, defs, "defs not equal")


class TestAddSuiteFamilyTask(unittest.TestCase):
    def setUp(self):
        defs = Defs()  # create an empty definition
        suite = defs.add_suite("s1")  # create a suite and add it to the defs
        family = suite.add_family("f1")  # create a family and add it to suite
        for i in ["a", "b", "c"]:  # create task ta,tb,tc
            family.add_task("t" + i)  # create a task and add to family
        defs.save_as_defs("test.def")  # save defs to file "test.def"

        self.defs = defs

    def test_me(self):
        with Defs() as defs:
            with defs.add_suite("s1") as suite:
                with suite.add_family("f1") as family:
                    for i in ["a", "b", "c"]:
                        family.add_task("t" + i)
        defs.save_as_defs("test.def")

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(self.defs, defs, "defs not equal")

    def test_me2(self):
        defs = Defs().add(
            Suite("s1").add(
                Family("f1").add(
                    [Task("t{0}".format(t))
                     for t in ("a", "b", "c")])))
        defs.save_as_defs("test.def")  # save defs to file "test.def"

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(self.defs, defs, "defs not equal")

    def test_me3(self):
        defs = Defs()
        defs += Suite("s1")
        defs.s1 += Family("f1")
        defs.s1.f1 += [Task("t{0}".format(t))
                       for t in ("a", "b", "c")]
        defs.save_as_defs("test.def")  # save defs to file "test.def"

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(self.defs, defs, "defs not equal")

    def test_me4(self):
        defs = Defs(
            Suite("s1",
                  Family("f1",
                         [Task("t{0}".format(t)) for t in ("a", "b", "c")])))
        defs.save_as_defs("test.def")  # save defs to file "test.def"

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(self.defs, defs, "defs not equal")

    def test_me5(self):
        defs = Defs().add(
            [Suite("s{0}".format(i)).add(
                [Family("f{0}".format(i)).add(
                    [Task("t{0}".format(i)) for i in range(1, 6)])
                    for i in range(1, 7)])
                for i in range(1, 6)])
        assert len(defs) == 5, " expected 6 suites but found " + str(len(defs))
        for suites in defs:
            assert len(suites) == 6, " expected 6 families but found " + str(len(suites))
            for fam in suites:
                assert len(fam) == 5, " expected 6 tasks but found " + str(len(fam))

    def test_me6(self):
        defs = Defs(
            [Suite("s{0}".format(i),
                   [Family("f{0}".format(i),
                           [Task("t{0}".format(i)) for i in range(1, 6)])
                    for i in range(1, 7)])
             for i in range(1, 6)])
        assert len(defs) == 5, " expected 5 suites but found " + str(len(defs))
        for suites in defs:
            assert len(suites) == 6, " expected 6 families but found " + str(len(suites))
            for fam in suites:
                assert len(fam) == 5, " expected 5 tasks but found " + str(len(fam))

    def tearDown(self):
        unittest.TestCase.tearDown(self)
        try:
            os.remove("test.def")
        except:
            pass


class TestAddMeterEventLabel(unittest.TestCase):
    def setUp(self):
        defs = Defs()
        suite = Suite("s1")
        task = Task("t1")
        defs.add_suite(suite)
        suite.add_task(task)
        task.add_event(2)  # event reference with 2
        task.add_event("wow")  # event reference with name "wow"
        task.add_event(10, "Eventname2")  # event referenced with name "Eventname2"
        task.add_meter("metername3", 0, 100)  # name, min, max
        task.add_label("label_name4", "value")  # name, value

        self.defs = defs

    def test_alternative(self):
        defs = Defs().add(
            Suite("s1").add(
                Task("t1").add(
                    Event(2),
                    Event("wow"),
                    Event(10, "Eventname2"),
                    Meter("metername3", 0, 100),
                    Label("label_name4", "value"))))

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative1(self):
        defs = Defs() + Suite("s1")
        defs.s1 += Task("t1") + Event(2) + Event("wow") + \
                   Event(10, "Eventname2") + Meter("metername3", 0, 100) + \
                   Label("label_name4", "value")

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative2(self):
        with Defs() as defs:
            with defs.add_suite("s1") as suite:
                with suite.add_task("t1") as t1:
                    t1 += [Event(2),
                           Event("wow"),
                           Event(10, "Eventname2"),
                           Meter("metername3", 0, 100),
                           Label("label_name4", "value")]

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative3(self):
        defs = Defs(
            Suite('s1',
                  Task("t1",
                       Event(2),
                       Event("wow"),
                       Event(10, "Eventname2"),
                       Meter("metername3", 0, 100),
                       Label("label_name4", "value"))))

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")


class TestAddLimitInlimit(unittest.TestCase):

    def setUp(self):
        defs = Defs()
        s1 = defs.add_suite("s1")
        s1.add_limit("limitName4", 10)  # name, maximum token
        f1 = s1.add_family("f1")
        f1.add_inlimit("limitName4", "/s1/f1", 2)  # limit name, path to limit, tokens consumed
        for i in range(1, 4):
            f1.add_task("t{0}".format(i))

        self.defs = defs

    def test_alternative(self):
        defs = Defs().add(
            Suite("s1").add(
                Limit("limitName4", 10),
                Family("f1").add(
                    InLimit("limitName4", "/s1/f1", 2),
                    [Task("t{0}".format(t)) for t in range(1, 4)]
                )))

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative1(self):
        defs = Defs() + Suite("s1")
        defs.s1 += [Limit("limitName4", 10), Family("f1")]
        defs.s1.f1 += [InLimit("limitName4", "/s1/f1", 2),
                       [Task("t{0}".format(t)) for t in range(1, 4)]]

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative2(self):
        with Defs() as defs:
            with defs.add_suite("s1") as s1:
                s1.add_limit("limitName4", 10)  # name, maximum token
                with s1.add_family("f1") as f1:
                    f1.add_inlimit("limitName4", "/s1/f1", 2)  # limit name, path to limit, tokens consumed
                    f1 += [Task("t{0}".format(t)) for t in range(1, 4)]

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative3(self):
        defs = Defs(
            Suite("s1",
                  Limit("limitName4", 10),  # name, maximum token
                  Family("f1",
                         InLimit("limitName4", "/s1/f1", 2),  # limit name, path to limit, tokens consumed
                         [Task("t{0}".format(t)) for t in range(1, 4)])))

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")


class TestAddVariable(unittest.TestCase):

    def setUp(self):
        defs = Defs()
        s1 = defs.add_suite("s1")
        s1.add_variable("HELLO", "world")  # name, value
        s1.add_variable({"NAME": "value", "NAME2": "value2", "NAME3": "value3", "NAME4": 4})
        s1.add_variable(Variable("FRED", "bloggs"))
        s1.add_variable(Variable("BILL", "1"))

        defs.s1.sort_attributes("variable");  # sort since with dictionary order of addition is arbitary
        self.defs = defs

    def test_alternative0(self):
        defs = Defs(Suite("s1", HELLO="world", FRED="bloggs", BILL=1, NAME="value", NAME2="value2"))
        defs.s1.add_variable('NAME4', 4)
        defs.s1 += Edit(NAME3="value3")

        defs.s1.sort_attributes("variable");
        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative(self):
        defs = Defs().add(
            Suite("s1").add(
                Edit(HELLO="world", FRED="bloggs", BILL=1, NAME="value", NAME2="value2", NAME3="value3", NAME4=4)
            ))

        defs.s1.sort_attributes("variable");
        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative1(self):
        defs = Defs() + Suite("s1", Edit(HELLO="world"))
        defs.s1 += [Edit({"NAME": "value", "NAME2": "value2", "NAME3": "value3", "NAME4": 4}, BILL=1),
                    Edit(FRED="bloggs")]

        defs.s1.sort_attributes("variable");
        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative2(self):
        defs = Defs(
            Suite("s1",
                  {"HELLO": "world", "NAME": "value", "NAME2": "value2",
                   "NAME3": "value3", "NAME4": 4, "BILL": 1, "FRED": "bloggs"}))

        defs.s1.sort_attributes("variable");
        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")


class TestAddTrigger(unittest.TestCase):

    def setUp(self):
        defs = Defs()
        s1 = defs.add_suite("s1")
        t1 = s1.add_task("t1")
        t2 = s1.add_task("t2")
        t2.add_trigger("t1 == active and t3 == aborted")
        t2.add_complete("t3 == complete")
        t3 = s1.add_task("t3")
        self.defs = defs

    def test_alternative0(self):
        defs = Defs(
            Suite("s1",
                  Task("t1"),
                  Task("t2",
                       Trigger("t1 == active and t3 == aborted"),
                       Complete("t3 == complete")),
                  Task("t3")))

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative(self):
        defs = Defs().add(
            Suite("s1").add(
                Task("t1"), Task("t2").add(
                    Trigger("t1 == active and t3 == aborted"),
                    Complete("t3 == complete")),
                Task("t3")))

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative1(self):
        defs = Defs() + Suite("s1")
        defs.s1 += [Task("t{0}".format(i)) for i in range(1, 4)]
        defs.s1.t2 += [Trigger("t1 == active and t3 == aborted"),
                       Complete("t3 == complete")]

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")


class TestAddTaskChain(unittest.TestCase):

    def setUp(self):
        defs = Defs(
            Suite("s1",
                  Task("t1"),
                  Task("t2", Trigger("t1 == complete")),
                  Task("t3", Trigger("t2 == complete")),
                  Task("t4", Trigger("t3 == complete"))))
        self.defs = defs

    def test_alternative(self):
        defs = Defs() + Suite("s1")
        defs.s1 += [Task("t1"), Task("t2"),
                    Task("t3"), Task("t4")]
        defs.s1.t2 += Trigger(["t1"])
        defs.s1.t3 += Trigger(["t2"])
        defs.s1.t4 += Trigger(["t3"])

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative1(self):
        defs = Defs() + Suite("s1")
        defs.s1 += [Task("t1"), Task("t2"), Task("t3"), Task("t4")]
        defs.s1.t2 += Trigger([defs.s1.t1])
        defs.s1.t3 += Trigger([defs.s1.t2])
        defs.s1.t4 += Trigger([defs.s1.t3])

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative1(self):
        defs = Defs(Suite("s1"))
        defs.s1 >> Task("t1") >> Task("t2") >> Task("t3") >> Task("t4")

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")


class TestAddReverseTaskChain(unittest.TestCase):

    def setUp(self):
        defs = Defs(
            Suite("s1",
                  Task("t1", Trigger("t2 == complete")),
                  Task("t2", Trigger("t3 == complete")),
                  Task("t3", Trigger("t4 == complete")),
                  Task("t4")))
        self.defs = defs

    def test_alternative1(self):
        defs = Defs() + Suite("s1")
        defs.s1 << Task("t1") << Task("t2") << Task("t3") << Task("t4")

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")


class TestAddLargeTrigger(unittest.TestCase):

    def setUp(self):
        defs = Defs()
        s1 = defs.add_suite("s1")
        t1 = s1.add_task("t1")
        t2 = s1.add_task("t2")
        t3 = s1.add_task("t3")
        t3.add_part_trigger("t1 == complete")
        t3.add_part_trigger("t2 == active", True)  # here True means add as 'AND'
        t3.add_part_trigger("t2 == aborted", False)  # here False means add as 'OR'
        self.defs = defs

    def test_alternative0(self):
        defs = Defs(
            Suite("s1",
                  Task("t1"),
                  Task("t2"),
                  Task("t3",
                       Trigger("t1 == complete"),
                       Trigger("t2 == active"),
                       Trigger("t2 == aborted", False))))

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative(self):
        defs = Defs().add(
            Suite("s1").add(
                Task("t1"),
                Task("t2"),
                Task("t3").add(
                    Trigger("t1 == complete"),
                    Trigger("t2 == active"),
                    Trigger("t2 == aborted", False),
                )
            ))
        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative1(self):
        defs = Defs() + Suite("s1")
        defs.s1 += [Task("t{0}".format(i)) for i in range(1, 4)]
        defs.s1.t3 += [Trigger("t1 == complete"),
                       Trigger("t2 == active"),
                       Trigger("t2 == aborted", False)]

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")


class TestAddTimeDependencies(unittest.TestCase):

    def setUp(self):
        defs = Defs()
        s1 = defs.add_suite("s1")
        t1 = s1.add_task("date")
        t1.add_date(1, 0, 0)  # first of every month and every year
        t1.add_date(Date("2.*.*"))  # second of every month and every year
        t1.add_date(28, 2, 2026)  # 28 february 2026

        t2 = s1.add_task("day")
        t2.add_day("monday")
        t2.add_day(Days.tuesday)

        t3 = s1.add_task("time")
        t3.add_time("+00:30")  # 30 minutes after suite has begun
        t3.add_time("+00:30 20:00 01:00")  # 00:30,01:30,02:30....07:30 after suite start

        t3.add_time(0, 59, True)  # 00:59 - 59 minutes past midnight
        t3.add_time(Time(TimeSlot(20, 10)))  # 20:10 - 10 minutes pas eight
        t3.add_time(Time(TimeSlot(20, 20), True))  # +20:20 - 20 minutes and 20 hours, after suite start

        start = TimeSlot(0, 0)
        finish = TimeSlot(23, 0)
        incr = TimeSlot(0, 30)
        time_series = TimeSeries(start, finish, incr, True)
        t3.add_time(Time(time_series))
        t3.add_time(Time(0, 10))  # 00:10
        t3.add_time(Time("+00:40"))  # +00:40
        t3.add_time(Time("+00:40 20:00 01:00"))  # 00:40,01:40,02:30...17:40 after suite start

        cron = Cron()
        cron.set_week_days([0, 1, 2, 3, 4, 5, 6])
        cron.set_days_of_month([1, 2, 3, 4, 5, 6])
        cron.set_months([1, 2, 3, 4, 5, 6])
        cron.set_time_series("+00:00 23:00 00:30")
        s1.add_task("cron").add_cron(cron);

        self.defs = defs

    def test_alternative0(self):
        start = TimeSlot(0, 0)
        finish = TimeSlot(23, 0)
        incr = TimeSlot(0, 30)
        time_series = TimeSeries(start, finish, incr, True)

        defs = Defs(
            Suite("s1",
                  Task("date",
                       Date(1, 0, 0),  # first of every month and every year
                       Date("2.*.*"),  # second of every month and every yea
                       Date(28, 2, 2026)),  # 28 february 2026
                  Task("day",
                       Day("monday"),
                       Day(Days.tuesday)),
                  Task("time",
                       Time("+00:30"),  # 30 minutes after suite has begun
                       Time("+00:30 20:00 01:00"),  # 00:30,01:30,02:30....07:30 after suite start
                       Time(0, 59, True),  # 00:59 - 59 minutes past midnight
                       Time(TimeSlot(20, 10)),  # 20:10 - 10 minutes pas eight
                       Time(TimeSlot(20, 20), True),  # +20:20 - 20 minutes and 20 hours, after suite start
                       Time(time_series),
                       Time(0, 10),
                       Time("+00:40"),
                       Time("+00:40 20:00 01:00")),
                  Task("cron",
                       Cron("+00:00 23:00 00:30", days_of_week=[0, 1, 2, 3, 4, 5, 6], days_of_month=[1, 2, 3, 4, 5, 6], months=[1, 2, 3, 4, 5, 6]))))

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative(self):
        start = TimeSlot(0, 0)
        finish = TimeSlot(23, 0)
        incr = TimeSlot(0, 30)
        time_series = TimeSeries(start, finish, incr, True)

        cron = Cron()
        cron.set_week_days([0, 1, 2, 3, 4, 5, 6])
        cron.set_days_of_month([1, 2, 3, 4, 5, 6])
        cron.set_months([1, 2, 3, 4, 5, 6])
        cron.set_time_series("+00:00 23:00 00:30")

        defs = Defs().add(
            Suite("s1").add(
                Task("date").add(
                    Date(1, 0, 0),
                    Date("2.*.*"),
                    Date(28, 2, 2026)),
                Task("day").add(
                    Day("monday"),
                    Day(Days.tuesday)),
                Task("time").add(
                    Time("+00:30"),
                    Time("+00:30 20:00 01:00"),
                    Time(0, 59, True),
                    Time(TimeSlot(20, 10)),
                    Time(TimeSlot(20, 20), True),
                    Time(time_series),
                    Time(0, 10),
                    Time("+00:40"),
                    Time("+00:40 20:00 01:00")),
                Task("cron").add(
                    cron)))

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative1(self):
        start = TimeSlot(0, 0)
        finish = TimeSlot(23, 0)
        incr = TimeSlot(0, 30)
        time_series = TimeSeries(start, finish, incr, True)

        defs = Defs() + (Suite("s1") + Task("date") + Task("day") + Task("time") + Task("cron"))
        defs.s1.date += [Date(1, 0, 0), Date("2.*.*"), Date(28, 2, 2026)]
        defs.s1.day += [Day("monday"), Day(Days.tuesday)]
        defs.s1.time += [Time("+00:30"), Time("+00:30 20:00 01:00"), Time(0, 59, True),
                         Time(TimeSlot(20, 10)), Time(TimeSlot(20, 20), True),
                         Time(time_series), Time(0, 10), Time("+00:40"),
                         Time("+00:40 20:00 01:00")]
        defs.s1.cron += Cron("+00:00 23:00 00:30",
                             days_of_week=[0, 1, 2, 3, 4, 5, 6],
                             days_of_month=[1, 2, 3, 4, 5, 6],
                             months=[1, 2, 3, 4, 5, 6])

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")


class TestAddDefStatus(unittest.TestCase):

    def setUp(self):
        defs = Defs()
        s1 = defs.add_suite("s1")
        s1.add_task("t1").add_defstatus(Defstatus("complete"))
        s1.add_task("t2").add_defstatus(DState.complete)

        self.defs = defs

    def test_alternative0(self):
        defs = Defs(
            Suite("s1",
                  Task("t1", Defstatus("complete")),
                  Task("t2", Defstatus(DState.complete))))

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative(self):
        defs = Defs().add(
            Suite("s1").add(
                Task("t1").add(Defstatus("complete")),
                Task("t2").add(Defstatus(DState.complete))))

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative1(self):
        defs = Defs() + (Suite("s1") + Task("t1") + Task("t2"))
        defs.s1.t1 += Defstatus("complete")
        defs.s1.t2 += Defstatus(DState.complete)

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")


class TestAddAutocancel(unittest.TestCase):

    def setUp(self):
        defs = Defs()
        s1 = defs.add_suite("s1")
        s1.add_task("t1").add_autocancel(3)  # delete task after 3 days after completion
        s1.add_task("t2").add_autocancel(1, 10, True)  # delete task 1hr 10 min after task completion
        s1.add_task("t3").add_autocancel(TimeSlot(2, 10), True)  # delete task 2hr 10 min after task completion
        s1.add_task("t4").add_autocancel(Autocancel(1))  # delete task after 1 day after task completion
        s1.add_task("t5").add_autocancel(Autocancel(18, 10, False))  # delete task at 6:10pm once it has completed
        s1.add_task("t6").add_autocancel(Autocancel(TimeSlot(2, 10), False))  # delete task at 2:10am once it has completed

        self.defs = defs

    def test_alternative0(self):
        defs = Defs(
            Suite("s1",
                  Task("t1", Autocancel(3)),  # delete task after 3 days after completion
                  Task("t2", Autocancel(1, 10, True)),  # delete task 1hr 10 min after task completion
                  Task("t3", Autocancel(TimeSlot(2, 10), True)),  # delete task 2hr 10 min after task completion
                  Task("t4", Autocancel(1)),  # delete task after 1 day after task completion
                  Task("t5", Autocancel(18, 10, False)),  # delete task at 6:10pm once it has completed
                  Task("t6", Autocancel(2, 10, False))))  # delete task at 2:10am once it has completed

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative(self):
        defs = Defs().add(
            Suite("s1").add(
                Task("t1").add(Autocancel(3)),
                Task("t2").add(Autocancel(1, 10, True)),
                Task("t3").add(Autocancel(TimeSlot(2, 10), True)),
                Task("t4").add(Autocancel(1)),
                Task("t5").add(Autocancel(18, 10, False)),
                Task("t6").add(Autocancel(2, 10, False))))

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative1(self):
        defs = Defs() + (Suite("s1") + [Task("t{0}".format(i)) for i in range(1, 7)])
        defs.s1.t1 += Autocancel(3)
        defs.s1.t2 += Autocancel(1, 10, True)
        defs.s1.t3 += Autocancel(TimeSlot(2, 10), True)
        defs.s1.t4 += Autocancel(1)
        defs.s1.t5 += Autocancel(18, 10, False)
        defs.s1.t6 += Autocancel(2, 10, False)

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")


class TestAddRepeat(unittest.TestCase):
    def setUp(self):
        def add_tasks(fam):
            for i in range(1, 3):
                fam.add_task(Task("t{0}".format(i)))

        defs = Defs()
        s1 = defs.add_suite("s1")
        f1 = s1.add_family("f1")
        f1.add_repeat(RepeatDate("YMD", 20100111, 20100115, 2))
        add_tasks(f1)

        f2 = s1.add_family("f2")
        f2.add_repeat(RepeatInteger("count", 0, 100, 2))
        add_tasks(f2)

        f3 = s1.add_family("f3")
        f3.add_repeat(RepeatEnumerated("enum", ["red", "green", "blue"]))
        add_tasks(f3)

        f4 = s1.add_family("f4")
        f4.add_repeat(RepeatString("enum", ["a", "b", "c"]))
        add_tasks(f4)

        f5 = s1.add_family("f5")
        f5.add_repeat(RepeatDay(1))
        add_tasks(f5)

        f6 = s1.add_family("f6")
        f6.add_repeat(RepeatDateTime("DT", "20100111T000000", "20100115T000000", "48:00:00"))
        add_tasks(f6)

        self.defs = defs

    def test_alternative0(self):
        defs = Defs(
            Suite("s1",
                  Family("f1",
                         RepeatDate("YMD", 20100111, 20100115, 2),
                         [Task("t{0}".format(i)) for i in range(1, 3)]),
                  Family("f2",
                         RepeatInteger("count", 0, 100, 2),
                         [Task("t{0}".format(i)) for i in range(1, 3)]),
                  Family("f3",
                         RepeatEnumerated("enum", ["red", "green", "blue"]),
                         [Task("t{0}".format(i)) for i in range(1, 3)]),
                  Family("f4",
                         RepeatString("enum", ["a", "b", "c"]),
                         [Task("t{0}".format(i)) for i in range(1, 3)]),
                  Family("f5",
                         RepeatDay(1),
                         [Task("t{0}".format(i)) for i in range(1, 3)]),
                  Family("f6",
                         RepeatDateTime("DT", "20100111T000000", "20100115T000000", "48:00:00"),
                         [Task("t{0}".format(i)) for i in range(1, 3)])))

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative1(self):
        defs = Defs().add(
            Suite("s1").add(
                Family("f1").add(
                    RepeatDate("YMD", 20100111, 20100115, 2),
                    [Task("t{0}".format(i)) for i in range(1, 3)]),
                Family("f2").add(
                    RepeatInteger("count", 0, 100, 2),
                    [Task("t{0}".format(i)) for i in range(1, 3)]),
                Family("f3").add(
                    RepeatEnumerated("enum", ["red", "green", "blue"]),
                    [Task("t{0}".format(i)) for i in range(1, 3)]),
                Family("f4").add(
                    RepeatString("enum", ["a", "b", "c"]),
                    [Task("t{0}".format(i)) for i in range(1, 3)]),
                Family("f5").add(
                    RepeatDay(1),
                    [Task("t{0}".format(i)) for i in range(1, 3)]),
                Family("f6").add(
                    RepeatDateTime("DT", "20100111T000000", "20100115T000000", "48:00:00"),
                    [Task("t{0}".format(i)) for i in range(1, 3)])))

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_alternative2(self):
        defs = Defs() + Suite("s1")
        defs.s1 += [Family("f{0}".format(i)).add(
            [Task("t{0}".format(i)) for i in range(1, 3)])
            for i in range(1, 7)]
        defs.s1.f1 += RepeatDate("YMD", 20100111, 20100115, 2)
        defs.s1.f2 += RepeatInteger("count", 0, 100, 2)
        defs.s1.f3 += RepeatEnumerated("enum", ["red", "green", "blue"])
        defs.s1.f4 += RepeatString("enum", ["a", "b", "c"])
        defs.s1.f5 += RepeatDay(1)
        defs.s1.f6 += RepeatDateTime("DT", "20100111T000000", "20100115T000000", "48:00:00")

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")


class TestAddLate(unittest.TestCase):
    def setUp(self):
        defs = Defs()
        suite = defs.add_suite('s1')

        late = Late()
        late.submitted(20, 10)  # hour, min
        late.active(2, 10)  # hour, min
        late.complete(3, 10, True)  # hour, min, relative
        suite.add_task('t1').add_late(late)
        self.defs = defs

    def test_1(self):
        # Can also pass late into the Task constructor
        defs = Defs(
            Suite('s1',
                  Task('t1',
                       Late(submitted='20:10', active='02:10', complete='+03:10'))))

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")

    def test_2(self):
        # Can also pass late into the Task constructor
        defs = Defs() + (Suite('s1') + Task('t1'))
        defs.s1.t1 += Late(submitted='20:10', active='02:10', complete='+03:10')

        Ecf.set_debug_equality(True)
        equals = (self.defs == defs)
        Ecf.set_debug_equality(False)
        self.assertEqual(defs, self.defs, "expected defs to be the same")


class Deadlock(unittest.TestCase):
    def setUp(self):
        defs = Defs().add(
            Suite("dead_lock").add(
                Family("family").add(
                    Task("t1").add(Trigger("t2 == complete")),
                    Task("t2").add(Trigger("t1 == complete")))))

        self.defs = defs

    def test_me(self):
        defs = Defs(
            Suite("dead_lock",
                  Family('family',
                         Task('t1',
                              Trigger("t2 == complete")),
                         Task('t2',
                              Trigger("t1 == complete")))))

        self.assertEqual(defs, self.defs, "expected defs to be the same")


if __name__ == "__main__":
    unittest.main()
    print("All Tests pass")
