From b0e06103e24f90d700861997ec2d631e44395a95 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rn=20K=C3=BCnsem=C3=B6ller?=
 <jkuensem@physik.uni-bielefeld.de>
Date: Mon, 10 May 2021 16:30:22 +0200
Subject: [PATCH] TMSS-703: add more test, also in prep of TMSS-704

---
 .../scheduling/test/t_dynamic_scheduling.py   | 1497 ++++++++++-------
 1 file changed, 844 insertions(+), 653 deletions(-)

diff --git a/SAS/TMSS/backend/services/scheduling/test/t_dynamic_scheduling.py b/SAS/TMSS/backend/services/scheduling/test/t_dynamic_scheduling.py
index 93aea38eb9f..b1acbd07b96 100755
--- a/SAS/TMSS/backend/services/scheduling/test/t_dynamic_scheduling.py
+++ b/SAS/TMSS/backend/services/scheduling/test/t_dynamic_scheduling.py
@@ -1094,657 +1094,657 @@ class TestTimeConstraints(TestCase):
 
         # Set datetime constraints after lower bound, and with too little space left in window for obs duration
         self.clear_time_constraints()
-        self.scheduling_unit_blueprint.scheduling_constraints_doc['time']["before"] = datetime(2020, 1, 1, 13, 0, 0).isoformat()
-        self.assertFalse(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                                                            datetime(2020, 1, 1, 12, 0, 0),
-                                                                            datetime(2020, 1, 2, 12, 0, 0)))
-
-    def test_can_run_within_before_returns_true(self):
-
-        # Set datetime constraints after upper bounds, and with sufficient window for obs duration
-        self.clear_time_constraints()
-        self.scheduling_unit_blueprint.scheduling_constraints_doc['time']["before"] = datetime(2020, 1, 2, 13, 0, 0).isoformat()
-        self.assertTrue(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                                                            datetime(2020, 1, 1, 12, 0, 0),
-                                                                            datetime(2020, 1, 2, 12, 0, 0)))
-
-        # Set datetime constraints after lower bounds, but with sufficient space left in window for obs duration
-        self.clear_time_constraints()
-        self.scheduling_unit_blueprint.scheduling_constraints_doc['time']["before"] = datetime(2020, 1, 1, 15, 0, 0).isoformat()
-        self.assertTrue(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                                                            datetime(2020, 1, 1, 12, 0, 0),
-                                                                            datetime(2020, 1, 2, 12, 0, 0)))
-
-    # 'between' constraint
-
-    def test_can_run_anywhere_between_returns_false(self):
-        """
-        Test 'between' constraint with start/stop datetime constraints 'outside' upper_bound or lower_bound
-        """
-        # Set datetime constraints start > lower_bound and stop > upper_bound
-        self.clear_time_constraints()
-        self.add_time_between_constraint(datetime(2020, 1, 1, 13, 0, 0), datetime(2020, 1, 2, 15, 0, 0))
-        self.assertFalse(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                         datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
-
-        # Set datetime constraints start < lower_bound and stop < upper_bound
-        self.clear_time_constraints()
-        self.add_time_between_constraint(datetime(2020, 1, 1, 8, 0, 0), datetime(2020, 1, 2, 8, 0, 0))
-        self.assertFalse(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                         datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
-
-        # Set datetime constraints start > lower_bound and stop > upper_bound (1 second only)
-        self.clear_time_constraints()
-        self.add_time_between_constraint(datetime(2020, 1, 1, 12, 0, 1), datetime(2020, 1, 2, 12, 0, 1))
-        self.assertFalse(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                         datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
-
-        # Set datetime constraints start > lower_bound and stop < upper_bound
-        self.clear_time_constraints()
-        self.add_time_between_constraint(datetime(2020, 1, 1, 18, 0, 0), datetime(2020, 1, 1, 19, 0, 0))
-        self.assertFalse(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                         datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
-
-    def test_can_run_anywhere_between_returns_true(self):
-        """
-        Test 'between' constraint with start/stop datetime constraints 'outside' upper_bound and lower_bound
-        """
-        # Set datetime constraints start < lower_bound and stop > upper_bound
-        self.clear_time_constraints()
-        self.add_time_between_constraint(datetime(2020, 1, 1, 11, 0, 0), datetime(2020, 1, 2, 13, 0, 0))
-        self.assertTrue(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                         datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
-
-        # Set datetime constraints start = lower_bound and stop = upper_bound
-        self.clear_time_constraints()
-        self.add_time_between_constraint(datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0))
-        self.assertTrue(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                         datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
-
-    def test_can_run_within_between_returns_true(self):
-        """
-        Test 'between' constraint with start/stop datetime constraints (within, not anywhere within)
-        """
-        # Set datetime constraints start > lower_bound and stop > upper_bound, large window
-        self.clear_time_constraints()
-        self.add_time_between_constraint(datetime(2020, 1, 1, 13, 0, 0), datetime(2020, 1, 2, 12, 0, 0))
-        self.assertTrue(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                         datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 1, 20, 0, 0)))
-
-        # Set datetime constraints start = lower_bound and stop = upper_bound, window just large enough for obs
-        self.clear_time_constraints()
-        self.add_time_between_constraint(datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 1, 14, 0, 0))
-        self.assertTrue(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                         datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 1, 14, 10, 0)))
-
-    def test_can_run_within_between_returns_false(self):
-        """
-        Test 'between' constraint with start/stop datetime constraints (within, not anywhere within)
-        """
-        # Set datetime constraints start < lower_bound and stop < upper_bound, too little overlap for obs
-        self.clear_time_constraints()
-        self.add_time_between_constraint(datetime(2020, 1, 1, 10, 0, 0), datetime(2020, 1, 1, 13, 0, 0))
-        self.assertFalse(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                         datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 1, 20, 0, 0)))
-
-        # Set datetime constraints start > lower_bound and stop < upper_bound, constraint window too small for obs
-        self.clear_time_constraints()
-        self.add_time_between_constraint(datetime(2020, 1, 1, 14, 0, 0), datetime(2020, 1, 1, 15, 0, 0))
-        self.assertFalse(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                         datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 1, 20, 10, 0)))
-
-    # 'not between' contraint
-
-    def test_can_run_anywhere_not_between_returns_false(self):
-        """
-        Test 'not_between' constraint with start/stop datetime constraints 'inside' upper_bound or lower_bound
-        """
-        # Set datetime constraints start > lower_bound and stop > upper_bound
-        self.clear_time_constraints()
-        self.add_time_not_between_constraint(datetime(2020, 1, 1, 13, 0, 0), datetime(2020, 1, 2, 15, 0, 0))
-        self.assertFalse(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                             datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
-
-        # Set datetime constraints start < lower_bound and stop > lower_bound and < upper_bound
-        self.clear_time_constraints()
-        self.add_time_not_between_constraint(datetime(2020, 1, 1, 8, 0, 0), datetime(2020, 1, 2, 8, 0, 0))
-        self.assertFalse(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                             datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
-
-        # Set datetime constraints start > lower_bound and stop < upper_bound
-        self.clear_time_constraints()
-        self.add_time_not_between_constraint(datetime(2020, 1, 1, 16, 0, 0), datetime(2020, 1, 2, 8, 0, 0))
-        self.assertFalse(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                             datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
-
-        # Set datetime constraints start < lower_bound and stop > upper_bound
-        self.clear_time_constraints()
-        self.add_time_not_between_constraint(datetime(2020, 1, 1, 8, 0, 0), datetime(2020, 1, 2, 14, 0, 0))
-        self.assertFalse(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                            datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
-
-    def test_can_run_anywhere_not_between_returns_true(self):
-        """
-        Test 'not_between' constraint with start/stop datetime constraints 'outside' upper_bound and lower_bound
-        """
-        # Set datetime constraints start < lower_bound and stop < lower_bound
-        self.clear_time_constraints()
-        self.add_time_not_between_constraint(datetime(2020, 1, 1, 3, 0, 0), datetime(2020, 1, 1, 11, 0, 0))
-        self.assertTrue(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                             datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 1, 16, 0, 0)))
-
-        # Set datetime constraints start > upper_bound and stop > upper_bound
-        self.clear_time_constraints()
-        self.add_time_not_between_constraint(datetime(2020, 1, 1, 16, 0, 0), datetime(2020, 1, 1, 20, 0, 0))
-        self.assertTrue(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                             datetime(2020, 1, 1, 13, 0, 0), datetime(2020, 1, 1, 15, 0, 0)))
-
-    # several simultaneous time ranges in 'at' / 'between' / 'not between' constraints
-
-    def execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary(self):
-        """
-        Just a simple wrapper to call 'can_run_within_timewindow_with_time_constraints' function
-        with a 24 hours boundary 2020-01-01 12:00 - 2020-01-02 12:00
-        """
-        return (tc1.can_run_within_timewindow_with_time_constraints(
-                    self.scheduling_unit_blueprint, datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
-
-    def test_can_run_within_at_constraint(self):
-        """
-        Test "at" constraint with both boundary and 'inside' upper_bound and lower_bound
-        """
-        # no constraints defined so should be OK
-        self.clear_time_constraints()
-        self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # Set datetime constraint before lower_bound
-        self.clear_time_constraints()
-        self.add_time_at_constraint(datetime(2020, 1, 1, 11, 0, 0))
-        self.assertFalse(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                                                            datetime(2020, 1, 1, 12, 0, 0),
-                                                                            datetime(2020, 1, 1, 14, 0, 0)))
-
-        # Set datetime constraint at lower_bound, but duration exceeds upper_bound
-        self.clear_time_constraints()
-        self.add_time_at_constraint(datetime(2020, 1, 1, 12, 0, 0))
-        self.assertFalse(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                                                            datetime(2020, 1, 1, 12, 0, 0),
-                                                                            datetime(2020, 1, 1, 14, 0, 0)))
-
-        # Set datetime constraint at upper_bound
-        self.clear_time_constraints()
-        self.add_time_at_constraint(datetime(2020, 1, 1, 14, 0, 0))
-        self.assertFalse(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                                                             datetime(2020, 1, 1, 12, 0, 0),
-                                                                             datetime(2020, 1, 1, 14, 0, 0)))
-
-        # Set datetime constraint after upper_bound
-        self.clear_time_constraints()
-        self.add_time_at_constraint(datetime(2020, 1, 1, 15, 0, 0))
-        self.assertFalse(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
-                                                                            datetime(2020, 1, 1, 12, 0, 0),
-                                                                            datetime(2020, 1, 1, 14, 0, 0)))
-
-        # Set datetime constraint at lower_bound
-        self.clear_time_constraints()
-        self.add_time_at_constraint(datetime(2020, 1, 1, 12, 0, 0))
-        self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # Set datetime constraint that fits the time window
-        self.clear_time_constraints()
-        self.add_time_at_constraint(datetime(2020, 1, 1, 18, 30, 0))
-        self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # Set datetime constraint so that obs lasts till exactly upper_bound
-        self.clear_time_constraints()
-        self.add_time_at_constraint(datetime(2020, 1, 2, 9, 50, 0))
-        self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-    def test_can_run_within_between_constraints(self):
-        """
-        Test multiple 'between' constraints within 24 boundary and check overall result of
-        'can_run_within_timewindow_with_time_constraints'
-        This function will iterate between the boundary with boundary shift of 1hr and boundary length of
-        the observation duration, which is in this testcase two hour
-        i.e. 12-14, 13-15, 14-16,..etc.., 9-11
-        """
-        # no constraints defined so should be OK
-        self.clear_time_constraints()
-        self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # Add constraints of 1hr, we cannot run
-        self.add_time_between_constraint(datetime(2020, 1, 1, 13, 0, 0), datetime(2020, 1, 1, 14, 0, 0))
-        self.add_time_between_constraint(datetime(2020, 1, 1, 16, 0, 0), datetime(2020, 1, 1, 17, 0, 0))
-        self.assertFalse(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # Add constraints of 2hr, but partially outside the bounds, we still cannot run
-        self.add_time_between_constraint(datetime(2020, 1, 2, 11, 0, 0), datetime(2020, 1, 2, 13, 0, 0))
-        self.assertFalse(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # Add constraints of 2hr, we can run again
-        self.add_time_between_constraint(datetime(2020, 1, 1, 17, 0, 0), datetime(2020, 1, 1, 19, 0, 0))
-        self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # Add constraint of 24hr constraint, we still 'can_run'
-        self.add_time_between_constraint(datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0))
-        self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # Clear all between constraints
-        self.clear_time_constraints()
-
-        # Add constraints after the 24hr, now we 'can not run'
-        self.add_time_between_constraint(datetime(2020, 1, 2, 13, 0, 0), datetime(2020, 1, 2, 15, 0, 0))
-        self.add_time_between_constraint(datetime(2020, 1, 2, 16, 0, 0), datetime(2020, 1, 2, 20, 0, 0))
-        self.assertFalse(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # Add constraint before the 24hr, we 'still can not run'
-        self.add_time_between_constraint(datetime(2020, 1, 1, 9, 0, 0), datetime(2020, 1, 1, 12, 0, 0))
-        self.assertFalse(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # add one 'inside' constraint of 3 hours, so overall must be ok again.
-        # Note that 2 hrs would only be sufficient if they match the moving window exactly (here: full hour)
-        self.add_time_between_constraint(datetime(2020, 1, 1, 14, 30, 0), datetime(2020, 1, 1, 17, 30, 0))
-        self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-    def test_can_run_within_not_between_constraints(self):
-        """
-        Test multiple 'not_between' constraints within 24 boundary and check overall result of
-        'can_run_within_timewindow_with_time_constraints'
-        This function will iterate between the boundary with boundary shift of 1hr and boundary length of
-        the observation duration, which is in this testcase two hour
-        i.e. 12-14, 13-15, 14-16,..etc.., 9-11
-        """
-        # no constraints defined so should be OK
-        self.clear_time_constraints()
-        self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # Add constraints of 1hr, we still 'can_run'
-        self.add_time_not_between_constraint(datetime(2020, 1, 1, 13, 0, 0), datetime(2020, 1, 1, 14, 0, 0))
-        self.add_time_not_between_constraint(datetime(2020, 1, 1, 16, 0, 0), datetime(2020, 1, 1, 17, 0, 0))
-        self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # Add constraints of 2hr, we still 'can_run'
-        self.add_time_not_between_constraint(datetime(2020, 1, 1, 18, 0, 0), datetime(2020, 1, 1, 20, 0, 0))
-        self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # Add constraint of 20hr constraint, we still 'can_run'
-        self.add_time_not_between_constraint(datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 8, 0, 0))
-        self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # Add constraint of 2hr, to fill the 'last gap', now we can not run
-        self.add_time_not_between_constraint(datetime(2020, 1, 2, 10, 0, 0), datetime(2020, 1, 2, 12, 0, 0))
-        self.assertFalse(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        self.clear_time_constraints()
-
-        # Add 4 hr constraints within 24 hours boundary, we can run
-        self.add_time_not_between_constraint(datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 1, 16, 0, 0))
-        self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-    # combined time contraints tests
-
-    def test_can_run_anywhere_combined_time_constraints(self):
-        """
-        Test multiple time constraints in combination and make sure that they block the time window as expected,
-        even though each constraint individually would allow the observation to run.
-        """
-
-        # Set before and after constraint with sufficient gap to fit observation, and assert True
-        self.clear_time_constraints()
-        self.scheduling_unit_blueprint.scheduling_constraints_doc['time']["after"] = datetime(2020, 1, 1, 12, 59, 59).isoformat()
-        self.scheduling_unit_blueprint.scheduling_constraints_doc['time']["before"] = datetime(2020, 1, 1, 15, 0, 1).isoformat()
-        self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # set before and after constraint with slightly smaller gap for observation, and assert False
-        self.clear_time_constraints()
-        self.scheduling_unit_blueprint.scheduling_constraints_doc['time']["after"] = datetime(2020, 1, 1, 13, 0, 0).isoformat()
-        self.scheduling_unit_blueprint.scheduling_constraints_doc['time']["before"] = datetime(2020, 1, 1, 15, 0, 0).isoformat()
-        self.assertFalse(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # set before and after constraint with large gap
-        # then and add additional between and not between constraints until window is blocked
-        # can run 13-8h
-        self.clear_time_constraints()
-        self.scheduling_unit_blueprint.scheduling_constraints_doc['time']["after"] = datetime(2020, 1, 1, 13, 0, 0).isoformat()
-        self.scheduling_unit_blueprint.scheduling_constraints_doc['time']["before"] = datetime(2020, 1, 2, 8, 0, 0).isoformat()
-        self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # can run 13h-20h
-        self.add_time_between_constraint(datetime(2020, 1, 1, 11, 0, 0), datetime(2020, 1, 1, 20, 0, 0))
-        self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # can run 13h-17h
-        self.add_time_not_between_constraint(datetime(2020, 1, 1, 17, 0, 0), datetime(2020, 1, 2, 4, 0, 0))
-        self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # can not run anymore
-        self.add_time_not_between_constraint(datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 1, 16, 0, 0))
-        self.assertFalse(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # add another between window, can run 4h-8h
-        self.add_time_between_constraint(datetime(2020, 1, 1, 2, 0, 0), datetime(2020, 1, 2, 12, 0, 0))
-        self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-        # move before constraint, can not run anymore
-        self.scheduling_unit_blueprint.scheduling_constraints_doc['time']["before"] = datetime(2020, 1, 2, 5, 0, 0).isoformat()
-        self.assertFalse(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
-
-
-@unittest.skip("TODO: fix, make less dependend on strategy template defaults")
-class TestReservedStations(unittest.TestCase):
-    """
-    Tests for the reserved stations used in dynamic scheduling
-    Test with different boundaries of scheduling unit start and stop times
-    Reservation 'visualized'
-          @ = station reservation start_time, * = station reservation stop_time
-               SUB start_time     SUB stop_time                 Expected Result
-     1.                |     @ ......|...*                      can NOT run
-     2.             @..|..*          |                          can NOT run
-     3.                |  @.....*    |                          can NOT run
-     4.             @..|.............|......*                   can NOT run
-     5.       @......* |             |                          can run
-     6.                |             |   @.....*                can run
-    """
-
-    @staticmethod
-    def create_station_reservation(additional_name, lst_stations, start_time=datetime(2100, 1, 1, 0, 0, 0),
-                                                                   stop_time=datetime(2100, 1, 2, 0, 0, 0)):
-        """
-        Create a station reservation with given list of stations, start_time and stop_time (optional)
-        Default duration is 24 hours (defined in seconds)
-        """
-        reservation_template = models.ReservationTemplate.objects.get(name="resource reservation")
-        reservation_template_spec = get_default_json_object_for_schema(reservation_template.schema)
-        reservation_template_spec["resources"] = {"stations": lst_stations }
-        res = models.Reservation.objects.create(name="Station Reservation %s" % additional_name,
-                                   description="Station reservation for testing",
-                                   specifications_template=reservation_template,
-                                   specifications_doc=reservation_template_spec,
-                                   start_time=start_time,
-                                   stop_time=stop_time)
-        return res
-
-    def setUp(self) -> None:
-        # scheduling unit
-        self.obs_duration = 120 * 60 # 2 hours
-        scheduling_set = models.SchedulingSet.objects.create(**SchedulingSet_test_data())
-        scheduling_unit_draft = TestDynamicScheduling.create_simple_observation_scheduling_unit(
-            "scheduling unit for %s" % self._testMethodName,
-            scheduling_set=scheduling_set,
-            obs_duration=self.obs_duration)
-        self.scheduling_unit_blueprint = create_task_blueprints_and_subtasks_from_scheduling_unit_draft(
-            scheduling_unit_draft)
-        # wipe all reservations in between tests, so the tests don't influence each other
-        for reservation in models.Reservation.objects.all():
-            reservation.delete()
-
-    def set_1_reservation_start_time_gt_sub_start_time_and_stop_time_gt_sub_stop_time(self, station_reservation):
-        """
-        Set (1) reservation start_time > SUB start_time and reservation stop_time > SUB stop_time
-        """
-        station_reservation.start_time = self.scheduling_unit_blueprint.start_time + timedelta(minutes=5)
-        station_reservation.stop_time = self.scheduling_unit_blueprint.stop_time + timedelta(minutes=5)
-        station_reservation.save()
-
-    def set_2_reservation_start_time_lt_sub_start_time_and_stop_time_lt_sub_stop_time(self, station_reservation):
-        """
-        Set (2) reservation start_time < SUB start_time and reservation stop_time < SUB stop_time
-        """
-        station_reservation.start_time = self.scheduling_unit_blueprint.start_time - timedelta(minutes=5)
-        station_reservation.stop_time = self.scheduling_unit_blueprint.stop_time - timedelta(minutes=5)
-        station_reservation.save()
-
-    def set_3_reservation_start_time_gt_sub_start_time_and_stop_time_lt_sub_stop_time(self, station_reservation):
-        """
-        Set (3) reservation start_time > SUB start_time and reservation stop_time < SUB stop_time
-        """
-        station_reservation.start_time = self.scheduling_unit_blueprint.start_time + timedelta(minutes=5)
-        station_reservation.stop_time = self.scheduling_unit_blueprint.stop_time - timedelta(minutes=5)
-        station_reservation.save()
-
-    def set_4_reservation_start_time_lt_sub_start_time_and_stop_time_gt_sub_stop_time(self, station_reservation):
-        """
-        Set (4) reservation start_time < SUB start_time and reservation stop_time > SUB stop_time
-        """
-        station_reservation.start_time = self.scheduling_unit_blueprint.start_time - timedelta(minutes=5)
-        station_reservation.stop_time = self.scheduling_unit_blueprint.stop_time + timedelta(minutes=5)
-        station_reservation.save()
-
-    def set_5_reservation_start_time_and_stop_time_lt_sub_start_time(self, station_reservation):
-        """
-        Set (5) reservation start_time and reservation stop_time < SUB start_time
-        """
-        station_reservation.start_time = self.scheduling_unit_blueprint.start_time - timedelta(minutes=60)
-        station_reservation.stop_time = self.scheduling_unit_blueprint.start_time - timedelta(minutes=5)
-        station_reservation.save()
-
-    def set_6_reservation_start_time_and_stop_time_gt_sub_stop_time(self, station_reservation):
-        """
-        Set (6) reservation start_time and reservation stop_time > SUB stop_time
-        """
-        station_reservation.start_time = self.scheduling_unit_blueprint.stop_time + timedelta(minutes=5)
-        station_reservation.stop_time = self.scheduling_unit_blueprint.stop_time + timedelta(minutes=65)
-        station_reservation.save()
-
-    def update_station_groups_of_scheduling_unit_blueprint(self):
-        """
-        Use the UC1 strategy template to 'easily' extend the station group of the scheduling_unit
-        For info, it will have three station groups
-        - dutch station with max_nr_missing=4
-        - international with max_nr_missing=2
-        - international required with max_nr_missing=1
-        """
-        uc1_strategy_template = models.SchedulingUnitObservingStrategyTemplate.objects.get(name="UC1 CTC+pipelines")
-        scheduling_unit_spec = add_defaults_to_json_object_for_schema(uc1_strategy_template.template,
-                                                                      uc1_strategy_template.scheduling_unit_template.schema)
-        station_groups = scheduling_unit_spec['tasks']['Target Observation']['specifications_doc']['station_groups']
-        self.scheduling_unit_blueprint.requirements_doc['tasks']['Observation']['specifications_doc']['station_groups'] = station_groups
-
-    def test_one_station_reserved(self):
-        """
-        Test station reservation when 1 station (CS001) is reserved and station CS001 is used in scheduling_unit
-        with different reservation start and stop times
-        """
-        reservation_one = self.create_station_reservation("One", ["CS001"])
-        # reservation start_time > SUB start_time and reservation stop_time > SUB stop_time
-        self.set_1_reservation_start_time_gt_sub_start_time_and_stop_time_gt_sub_stop_time(reservation_one)
-        self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-        # reservation start_time < SUB start_time and stop_time < SUB stop_time
-        self.set_2_reservation_start_time_lt_sub_start_time_and_stop_time_lt_sub_stop_time(reservation_one)
-        self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-        # reservation start_time > SUB start_time and stop_time < SUB stop_time
-        self.set_3_reservation_start_time_gt_sub_start_time_and_stop_time_lt_sub_stop_time(reservation_one)
-        self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-        # reservation start_time < SUB start_time and stop_time > SUB stop_time
-        self.set_4_reservation_start_time_lt_sub_start_time_and_stop_time_gt_sub_stop_time(reservation_one)
-        self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-        # Reservations outside boundary
-        # start_time and stop_time < SUB start_time
-        self.set_5_reservation_start_time_and_stop_time_lt_sub_start_time(reservation_one)
-        self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-        # start_time and stop_time > SUB stop_time
-        self.set_6_reservation_start_time_and_stop_time_gt_sub_stop_time(reservation_one)
-        self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-    def test_two_stations_reserved(self):
-        """
-        Test station reservation when 2 station (CS001,CS002) are reserved and station CS001 is used in scheduling_unit
-        with different reservation start and stop times
-        """
-        reservation_two = self.create_station_reservation("Two", ["CS001", "CS002"])
-        # reservation start_time > SUB start_time and reservation stop_time > SUB stop_time
-        self.set_1_reservation_start_time_gt_sub_start_time_and_stop_time_gt_sub_stop_time(reservation_two)
-        self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-        # reservation start_time < SUB start_time and stop_time < SUB stop_time
-        self.set_2_reservation_start_time_lt_sub_start_time_and_stop_time_lt_sub_stop_time(reservation_two)
-        self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-        # reservation start_time > SUB start_time and stop_time < SUB stop_time
-        self.set_3_reservation_start_time_gt_sub_start_time_and_stop_time_lt_sub_stop_time(reservation_two)
-        self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-        # reservation start_time < SUB start_time and stop_time > SUB stop_time
-        self.set_4_reservation_start_time_lt_sub_start_time_and_stop_time_gt_sub_stop_time(reservation_two)
-        self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-        # Reservations outside boundary
-        # start_time and stop_time < SUB start_time
-        self.set_5_reservation_start_time_and_stop_time_lt_sub_start_time(reservation_two)
-        self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-        # start_time and stop_time > SUB stop_time
-        self.set_6_reservation_start_time_and_stop_time_gt_sub_stop_time(reservation_two)
-        self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-    def test_two_stations_reserved_but_not_used(self):
-        """
-        Test station reservation when 2 stations (CS002, CS003) are reserved and station CS001 is used in scheduling_unit
-        with different reservation start and stop times
-        All possibilities should result in 'can run'
-        """
-        reservation_two_no_overlap = self.create_station_reservation("Two-NoOverlap", ["CS002", "CS003"])
-        # reservation start_time > SUB start_time and reservation stop_time > SUB stop_time
-        self.set_1_reservation_start_time_gt_sub_start_time_and_stop_time_gt_sub_stop_time(reservation_two_no_overlap)
-        self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-        # reservation start_time < SUB start_time and stop_time < SUB stop_time
-        self.set_2_reservation_start_time_lt_sub_start_time_and_stop_time_lt_sub_stop_time(reservation_two_no_overlap)
-        self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-        # reservation start_time > SUB start_time and stop_time < SUB stop_time
-        self.set_3_reservation_start_time_gt_sub_start_time_and_stop_time_lt_sub_stop_time(reservation_two_no_overlap)
-        self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-        # reservation start_time < SUB start_time and stop_time > SUB stop_time
-        self.set_4_reservation_start_time_lt_sub_start_time_and_stop_time_gt_sub_stop_time(reservation_two_no_overlap)
-        self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-        # Reservations outside boundary
-        # start_time and stop_time < SUB start_time
-        self.set_5_reservation_start_time_and_stop_time_lt_sub_start_time(reservation_two_no_overlap)
-        self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-        # start_time and stop_time > SUB stop_time
-        self.set_6_reservation_start_time_and_stop_time_gt_sub_stop_time(reservation_two_no_overlap)
-        self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-    def test_two_stations_reserved_with_duration_null(self):
-        """
-        Test station reservation when two stations (CS001,CS002) are reserved with duration null and so reserved indefinitely
-        and station CS001 is used in scheduling_unit
-        Test with different reservation start time and NO stop_time
-        start_time after SUB stop_time 'can run' all others 'can NOT run'
-        """
-        reservation_two_no_duration = self.create_station_reservation("Two-NoDuration", ["CS001", "CS002"], stop_time=None)
-        # reservation start_time > SUB start_time and < SUB stop_time
-        reservation_two_no_duration.start_time = self.scheduling_unit_blueprint.start_time + timedelta(minutes=5)
-        reservation_two_no_duration.save()
-        self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-        # reservation start_time < SUB start_time (and < SUB stop_time of course)
-        reservation_two_no_duration.start_time = self.scheduling_unit_blueprint.start_time - timedelta(minutes=5)
-        reservation_two_no_duration.save()
-        self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-        # reservation start_time > SUB stop time
-        reservation_two_no_duration.start_time = self.scheduling_unit_blueprint.stop_time + timedelta(minutes=5)
-        reservation_two_no_duration.save()
-        self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-    def test_dutch_stations_conflicts_result_false(self):
-        """
-        Test conflict of 'Dutch' station which have a default of max_nr_missing=4,
-        Create stations reservation equal to max_nr_missing+1 and check that it can not run
-        """
-        self.update_station_groups_of_scheduling_unit_blueprint()
-        # Create a reservation within scheduling_unit
-        self.create_station_reservation("Dutch", ['CS001', 'CS002', 'CS003', 'CS401', 'CS501'],
-                                        start_time=self.scheduling_unit_blueprint.start_time)
-        self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-    def test_dutch_stations_conflicts_result_true(self):
-        """
-        Test conflict of 'Dutch' station which have a default of max_nr_missing=4,
-        Create stations reservation equal to max_nr_missing and check that it can run
-        """
-        self.update_station_groups_of_scheduling_unit_blueprint()
-        # Create a reservation within scheduling_unit
-        self.create_station_reservation("Dutch", ['CS001', 'CS002', 'CS003', 'CS401'],
-                                        start_time=self.scheduling_unit_blueprint.start_time)
-        self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-    def test_international_stations_conflicts_result_false(self):
-        """
-        Test conflict of 'International' stations which have a default of max_nr_missing=2,
-        Create stations reservation equal to max_nr_missing+1 and check that it can not run
-        """
-        self.update_station_groups_of_scheduling_unit_blueprint()
-        # Create a reservation within scheduling_unit
-        self.create_station_reservation("International", ['SE607', 'PL610', 'PL612'],
-                                        start_time=self.scheduling_unit_blueprint.start_time)
-        self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-    def test_international_stations_conflicts_result_true(self):
-        """
-        Test conflict of 'International' stations which are have a default of max_nr_missing=2,
-        Create stations reservation equal to max_nr_missing and check that it can run
-        """
-        self.update_station_groups_of_scheduling_unit_blueprint()
-        # Create a reservation within scheduling_unit
-        self.create_station_reservation("International", ['SE607', 'PL610'],
-                                        start_time=self.scheduling_unit_blueprint.start_time)
-        self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-    def test_international_required_stations_conflicts_result_false(self):
-        """
-        Test conflict of 'International Required' stations which are have a default of max_nr_missing=1,
-        Create stations reservation equal to max_nr_missing+1 and check that it can not run
-        """
-        self.update_station_groups_of_scheduling_unit_blueprint()
-        # Create a reservation within scheduling_unit
-        self.create_station_reservation("International Required", ['DE601', 'DE605'],
-                                        start_time=self.scheduling_unit_blueprint.start_time)
-        self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-    def test_international_required_stations_conflicts_result_true(self):
-        """
-        Test conflict of 'International Required' stations which are have a default of max_nr_missing=1,
-        Create stations reservation equal to max_nr_missing and check that it can run
-        """
-        self.update_station_groups_of_scheduling_unit_blueprint()
-        # Create a reservation within scheduling_unit
-        self.create_station_reservation("International Required", ['DE605'],
-                                        start_time=self.scheduling_unit_blueprint.start_time)
-        self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-    def test_mixed_required_stations_conflicts_result_false(self):
-        """
-        Test conflict of 'mixed' stations which are have a default of max_nr_missing,
-        Create stations reservation equal to max_nr_missing and one station group max_nr_missing+1
-        and check that it can not run
-        """
-        self.update_station_groups_of_scheduling_unit_blueprint()
-        # Create a reservation within scheduling_unit
-        self.create_station_reservation("Mixed", ['DE605', 'SE607', 'PL610', 'CS001', 'CS002', 'CS003', 'CS401'],
-                                        start_time=self.scheduling_unit_blueprint.start_time)
-        self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
-
-    def test_mixed_required_stations_conflicts_result_true(self):
-        """
-        Test conflict of 'mixed' stations which are have a default of max_nr_missing,
-        Create stations reservation equal to max_nr_missing and check that it can run
-        """
-        self.update_station_groups_of_scheduling_unit_blueprint()
-        # Create a reservation within scheduling_unit
-        self.create_station_reservation("Mixed", ['DE605', 'PL610', 'CS001', 'CS002', 'CS003', 'CS401'],
-                                        start_time=self.scheduling_unit_blueprint.start_time)
-        self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#         self.scheduling_unit_blueprint.scheduling_constraints_doc['time']["before"] = datetime(2020, 1, 1, 13, 0, 0).isoformat()
+#         self.assertFalse(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                                                             datetime(2020, 1, 1, 12, 0, 0),
+#                                                                             datetime(2020, 1, 2, 12, 0, 0)))
+#
+#     def test_can_run_within_before_returns_true(self):
+#
+#         # Set datetime constraints after upper bounds, and with sufficient window for obs duration
+#         self.clear_time_constraints()
+#         self.scheduling_unit_blueprint.scheduling_constraints_doc['time']["before"] = datetime(2020, 1, 2, 13, 0, 0).isoformat()
+#         self.assertTrue(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                                                             datetime(2020, 1, 1, 12, 0, 0),
+#                                                                             datetime(2020, 1, 2, 12, 0, 0)))
+#
+#         # Set datetime constraints after lower bounds, but with sufficient space left in window for obs duration
+#         self.clear_time_constraints()
+#         self.scheduling_unit_blueprint.scheduling_constraints_doc['time']["before"] = datetime(2020, 1, 1, 15, 0, 0).isoformat()
+#         self.assertTrue(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                                                             datetime(2020, 1, 1, 12, 0, 0),
+#                                                                             datetime(2020, 1, 2, 12, 0, 0)))
+#
+#     # 'between' constraint
+#
+#     def test_can_run_anywhere_between_returns_false(self):
+#         """
+#         Test 'between' constraint with start/stop datetime constraints 'outside' upper_bound or lower_bound
+#         """
+#         # Set datetime constraints start > lower_bound and stop > upper_bound
+#         self.clear_time_constraints()
+#         self.add_time_between_constraint(datetime(2020, 1, 1, 13, 0, 0), datetime(2020, 1, 2, 15, 0, 0))
+#         self.assertFalse(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                          datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
+#
+#         # Set datetime constraints start < lower_bound and stop < upper_bound
+#         self.clear_time_constraints()
+#         self.add_time_between_constraint(datetime(2020, 1, 1, 8, 0, 0), datetime(2020, 1, 2, 8, 0, 0))
+#         self.assertFalse(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                          datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
+#
+#         # Set datetime constraints start > lower_bound and stop > upper_bound (1 second only)
+#         self.clear_time_constraints()
+#         self.add_time_between_constraint(datetime(2020, 1, 1, 12, 0, 1), datetime(2020, 1, 2, 12, 0, 1))
+#         self.assertFalse(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                          datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
+#
+#         # Set datetime constraints start > lower_bound and stop < upper_bound
+#         self.clear_time_constraints()
+#         self.add_time_between_constraint(datetime(2020, 1, 1, 18, 0, 0), datetime(2020, 1, 1, 19, 0, 0))
+#         self.assertFalse(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                          datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
+#
+#     def test_can_run_anywhere_between_returns_true(self):
+#         """
+#         Test 'between' constraint with start/stop datetime constraints 'outside' upper_bound and lower_bound
+#         """
+#         # Set datetime constraints start < lower_bound and stop > upper_bound
+#         self.clear_time_constraints()
+#         self.add_time_between_constraint(datetime(2020, 1, 1, 11, 0, 0), datetime(2020, 1, 2, 13, 0, 0))
+#         self.assertTrue(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                          datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
+#
+#         # Set datetime constraints start = lower_bound and stop = upper_bound
+#         self.clear_time_constraints()
+#         self.add_time_between_constraint(datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0))
+#         self.assertTrue(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                          datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
+#
+#     def test_can_run_within_between_returns_true(self):
+#         """
+#         Test 'between' constraint with start/stop datetime constraints (within, not anywhere within)
+#         """
+#         # Set datetime constraints start > lower_bound and stop > upper_bound, large window
+#         self.clear_time_constraints()
+#         self.add_time_between_constraint(datetime(2020, 1, 1, 13, 0, 0), datetime(2020, 1, 2, 12, 0, 0))
+#         self.assertTrue(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                          datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 1, 20, 0, 0)))
+#
+#         # Set datetime constraints start = lower_bound and stop = upper_bound, window just large enough for obs
+#         self.clear_time_constraints()
+#         self.add_time_between_constraint(datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 1, 14, 0, 0))
+#         self.assertTrue(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                          datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 1, 14, 10, 0)))
+#
+#     def test_can_run_within_between_returns_false(self):
+#         """
+#         Test 'between' constraint with start/stop datetime constraints (within, not anywhere within)
+#         """
+#         # Set datetime constraints start < lower_bound and stop < upper_bound, too little overlap for obs
+#         self.clear_time_constraints()
+#         self.add_time_between_constraint(datetime(2020, 1, 1, 10, 0, 0), datetime(2020, 1, 1, 13, 0, 0))
+#         self.assertFalse(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                          datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 1, 20, 0, 0)))
+#
+#         # Set datetime constraints start > lower_bound and stop < upper_bound, constraint window too small for obs
+#         self.clear_time_constraints()
+#         self.add_time_between_constraint(datetime(2020, 1, 1, 14, 0, 0), datetime(2020, 1, 1, 15, 0, 0))
+#         self.assertFalse(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                          datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 1, 20, 10, 0)))
+#
+#     # 'not between' contraint
+#
+#     def test_can_run_anywhere_not_between_returns_false(self):
+#         """
+#         Test 'not_between' constraint with start/stop datetime constraints 'inside' upper_bound or lower_bound
+#         """
+#         # Set datetime constraints start > lower_bound and stop > upper_bound
+#         self.clear_time_constraints()
+#         self.add_time_not_between_constraint(datetime(2020, 1, 1, 13, 0, 0), datetime(2020, 1, 2, 15, 0, 0))
+#         self.assertFalse(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                              datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
+#
+#         # Set datetime constraints start < lower_bound and stop > lower_bound and < upper_bound
+#         self.clear_time_constraints()
+#         self.add_time_not_between_constraint(datetime(2020, 1, 1, 8, 0, 0), datetime(2020, 1, 2, 8, 0, 0))
+#         self.assertFalse(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                              datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
+#
+#         # Set datetime constraints start > lower_bound and stop < upper_bound
+#         self.clear_time_constraints()
+#         self.add_time_not_between_constraint(datetime(2020, 1, 1, 16, 0, 0), datetime(2020, 1, 2, 8, 0, 0))
+#         self.assertFalse(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                              datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
+#
+#         # Set datetime constraints start < lower_bound and stop > upper_bound
+#         self.clear_time_constraints()
+#         self.add_time_not_between_constraint(datetime(2020, 1, 1, 8, 0, 0), datetime(2020, 1, 2, 14, 0, 0))
+#         self.assertFalse(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                             datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
+#
+#     def test_can_run_anywhere_not_between_returns_true(self):
+#         """
+#         Test 'not_between' constraint with start/stop datetime constraints 'outside' upper_bound and lower_bound
+#         """
+#         # Set datetime constraints start < lower_bound and stop < lower_bound
+#         self.clear_time_constraints()
+#         self.add_time_not_between_constraint(datetime(2020, 1, 1, 3, 0, 0), datetime(2020, 1, 1, 11, 0, 0))
+#         self.assertTrue(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                              datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 1, 16, 0, 0)))
+#
+#         # Set datetime constraints start > upper_bound and stop > upper_bound
+#         self.clear_time_constraints()
+#         self.add_time_not_between_constraint(datetime(2020, 1, 1, 16, 0, 0), datetime(2020, 1, 1, 20, 0, 0))
+#         self.assertTrue(tc1.can_run_anywhere_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                              datetime(2020, 1, 1, 13, 0, 0), datetime(2020, 1, 1, 15, 0, 0)))
+#
+#     # several simultaneous time ranges in 'at' / 'between' / 'not between' constraints
+#
+#     def execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary(self):
+#         """
+#         Just a simple wrapper to call 'can_run_within_timewindow_with_time_constraints' function
+#         with a 24 hours boundary 2020-01-01 12:00 - 2020-01-02 12:00
+#         """
+#         return (tc1.can_run_within_timewindow_with_time_constraints(
+#                     self.scheduling_unit_blueprint, datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0)))
+#
+#     def test_can_run_within_at_constraint(self):
+#         """
+#         Test "at" constraint with both boundary and 'inside' upper_bound and lower_bound
+#         """
+#         # no constraints defined so should be OK
+#         self.clear_time_constraints()
+#         self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # Set datetime constraint before lower_bound
+#         self.clear_time_constraints()
+#         self.add_time_at_constraint(datetime(2020, 1, 1, 11, 0, 0))
+#         self.assertFalse(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                                                             datetime(2020, 1, 1, 12, 0, 0),
+#                                                                             datetime(2020, 1, 1, 14, 0, 0)))
+#
+#         # Set datetime constraint at lower_bound, but duration exceeds upper_bound
+#         self.clear_time_constraints()
+#         self.add_time_at_constraint(datetime(2020, 1, 1, 12, 0, 0))
+#         self.assertFalse(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                                                             datetime(2020, 1, 1, 12, 0, 0),
+#                                                                             datetime(2020, 1, 1, 14, 0, 0)))
+#
+#         # Set datetime constraint at upper_bound
+#         self.clear_time_constraints()
+#         self.add_time_at_constraint(datetime(2020, 1, 1, 14, 0, 0))
+#         self.assertFalse(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                                                              datetime(2020, 1, 1, 12, 0, 0),
+#                                                                              datetime(2020, 1, 1, 14, 0, 0)))
+#
+#         # Set datetime constraint after upper_bound
+#         self.clear_time_constraints()
+#         self.add_time_at_constraint(datetime(2020, 1, 1, 15, 0, 0))
+#         self.assertFalse(tc1.can_run_within_timewindow_with_time_constraints(self.scheduling_unit_blueprint,
+#                                                                             datetime(2020, 1, 1, 12, 0, 0),
+#                                                                             datetime(2020, 1, 1, 14, 0, 0)))
+#
+#         # Set datetime constraint at lower_bound
+#         self.clear_time_constraints()
+#         self.add_time_at_constraint(datetime(2020, 1, 1, 12, 0, 0))
+#         self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # Set datetime constraint that fits the time window
+#         self.clear_time_constraints()
+#         self.add_time_at_constraint(datetime(2020, 1, 1, 18, 30, 0))
+#         self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # Set datetime constraint so that obs lasts till exactly upper_bound
+#         self.clear_time_constraints()
+#         self.add_time_at_constraint(datetime(2020, 1, 2, 9, 50, 0))
+#         self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#     def test_can_run_within_between_constraints(self):
+#         """
+#         Test multiple 'between' constraints within 24 boundary and check overall result of
+#         'can_run_within_timewindow_with_time_constraints'
+#         This function will iterate between the boundary with boundary shift of 1hr and boundary length of
+#         the observation duration, which is in this testcase two hour
+#         i.e. 12-14, 13-15, 14-16,..etc.., 9-11
+#         """
+#         # no constraints defined so should be OK
+#         self.clear_time_constraints()
+#         self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # Add constraints of 1hr, we cannot run
+#         self.add_time_between_constraint(datetime(2020, 1, 1, 13, 0, 0), datetime(2020, 1, 1, 14, 0, 0))
+#         self.add_time_between_constraint(datetime(2020, 1, 1, 16, 0, 0), datetime(2020, 1, 1, 17, 0, 0))
+#         self.assertFalse(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # Add constraints of 2hr, but partially outside the bounds, we still cannot run
+#         self.add_time_between_constraint(datetime(2020, 1, 2, 11, 0, 0), datetime(2020, 1, 2, 13, 0, 0))
+#         self.assertFalse(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # Add constraints of 2hr, we can run again
+#         self.add_time_between_constraint(datetime(2020, 1, 1, 17, 0, 0), datetime(2020, 1, 1, 19, 0, 0))
+#         self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # Add constraint of 24hr constraint, we still 'can_run'
+#         self.add_time_between_constraint(datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 12, 0, 0))
+#         self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # Clear all between constraints
+#         self.clear_time_constraints()
+#
+#         # Add constraints after the 24hr, now we 'can not run'
+#         self.add_time_between_constraint(datetime(2020, 1, 2, 13, 0, 0), datetime(2020, 1, 2, 15, 0, 0))
+#         self.add_time_between_constraint(datetime(2020, 1, 2, 16, 0, 0), datetime(2020, 1, 2, 20, 0, 0))
+#         self.assertFalse(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # Add constraint before the 24hr, we 'still can not run'
+#         self.add_time_between_constraint(datetime(2020, 1, 1, 9, 0, 0), datetime(2020, 1, 1, 12, 0, 0))
+#         self.assertFalse(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # add one 'inside' constraint of 3 hours, so overall must be ok again.
+#         # Note that 2 hrs would only be sufficient if they match the moving window exactly (here: full hour)
+#         self.add_time_between_constraint(datetime(2020, 1, 1, 14, 30, 0), datetime(2020, 1, 1, 17, 30, 0))
+#         self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#     def test_can_run_within_not_between_constraints(self):
+#         """
+#         Test multiple 'not_between' constraints within 24 boundary and check overall result of
+#         'can_run_within_timewindow_with_time_constraints'
+#         This function will iterate between the boundary with boundary shift of 1hr and boundary length of
+#         the observation duration, which is in this testcase two hour
+#         i.e. 12-14, 13-15, 14-16,..etc.., 9-11
+#         """
+#         # no constraints defined so should be OK
+#         self.clear_time_constraints()
+#         self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # Add constraints of 1hr, we still 'can_run'
+#         self.add_time_not_between_constraint(datetime(2020, 1, 1, 13, 0, 0), datetime(2020, 1, 1, 14, 0, 0))
+#         self.add_time_not_between_constraint(datetime(2020, 1, 1, 16, 0, 0), datetime(2020, 1, 1, 17, 0, 0))
+#         self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # Add constraints of 2hr, we still 'can_run'
+#         self.add_time_not_between_constraint(datetime(2020, 1, 1, 18, 0, 0), datetime(2020, 1, 1, 20, 0, 0))
+#         self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # Add constraint of 20hr constraint, we still 'can_run'
+#         self.add_time_not_between_constraint(datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 2, 8, 0, 0))
+#         self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # Add constraint of 2hr, to fill the 'last gap', now we can not run
+#         self.add_time_not_between_constraint(datetime(2020, 1, 2, 10, 0, 0), datetime(2020, 1, 2, 12, 0, 0))
+#         self.assertFalse(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         self.clear_time_constraints()
+#
+#         # Add 4 hr constraints within 24 hours boundary, we can run
+#         self.add_time_not_between_constraint(datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 1, 16, 0, 0))
+#         self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#     # combined time contraints tests
+#
+#     def test_can_run_anywhere_combined_time_constraints(self):
+#         """
+#         Test multiple time constraints in combination and make sure that they block the time window as expected,
+#         even though each constraint individually would allow the observation to run.
+#         """
+#
+#         # Set before and after constraint with sufficient gap to fit observation, and assert True
+#         self.clear_time_constraints()
+#         self.scheduling_unit_blueprint.scheduling_constraints_doc['time']["after"] = datetime(2020, 1, 1, 12, 59, 59).isoformat()
+#         self.scheduling_unit_blueprint.scheduling_constraints_doc['time']["before"] = datetime(2020, 1, 1, 15, 0, 1).isoformat()
+#         self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # set before and after constraint with slightly smaller gap for observation, and assert False
+#         self.clear_time_constraints()
+#         self.scheduling_unit_blueprint.scheduling_constraints_doc['time']["after"] = datetime(2020, 1, 1, 13, 0, 0).isoformat()
+#         self.scheduling_unit_blueprint.scheduling_constraints_doc['time']["before"] = datetime(2020, 1, 1, 15, 0, 0).isoformat()
+#         self.assertFalse(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # set before and after constraint with large gap
+#         # then and add additional between and not between constraints until window is blocked
+#         # can run 13-8h
+#         self.clear_time_constraints()
+#         self.scheduling_unit_blueprint.scheduling_constraints_doc['time']["after"] = datetime(2020, 1, 1, 13, 0, 0).isoformat()
+#         self.scheduling_unit_blueprint.scheduling_constraints_doc['time']["before"] = datetime(2020, 1, 2, 8, 0, 0).isoformat()
+#         self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # can run 13h-20h
+#         self.add_time_between_constraint(datetime(2020, 1, 1, 11, 0, 0), datetime(2020, 1, 1, 20, 0, 0))
+#         self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # can run 13h-17h
+#         self.add_time_not_between_constraint(datetime(2020, 1, 1, 17, 0, 0), datetime(2020, 1, 2, 4, 0, 0))
+#         self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # can not run anymore
+#         self.add_time_not_between_constraint(datetime(2020, 1, 1, 12, 0, 0), datetime(2020, 1, 1, 16, 0, 0))
+#         self.assertFalse(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # add another between window, can run 4h-8h
+#         self.add_time_between_constraint(datetime(2020, 1, 1, 2, 0, 0), datetime(2020, 1, 2, 12, 0, 0))
+#         self.assertTrue(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#         # move before constraint, can not run anymore
+#         self.scheduling_unit_blueprint.scheduling_constraints_doc['time']["before"] = datetime(2020, 1, 2, 5, 0, 0).isoformat()
+#         self.assertFalse(self.execute_can_run_within_timewindow_with_time_constraints_of_24hour_boundary())
+#
+#
+# @unittest.skip("TODO: fix, make less dependend on strategy template defaults")
+# class TestReservedStations(unittest.TestCase):
+#     """
+#     Tests for the reserved stations used in dynamic scheduling
+#     Test with different boundaries of scheduling unit start and stop times
+#     Reservation 'visualized'
+#           @ = station reservation start_time, * = station reservation stop_time
+#                SUB start_time     SUB stop_time                 Expected Result
+#      1.                |     @ ......|...*                      can NOT run
+#      2.             @..|..*          |                          can NOT run
+#      3.                |  @.....*    |                          can NOT run
+#      4.             @..|.............|......*                   can NOT run
+#      5.       @......* |             |                          can run
+#      6.                |             |   @.....*                can run
+#     """
+#
+#     @staticmethod
+#     def create_station_reservation(additional_name, lst_stations, start_time=datetime(2100, 1, 1, 0, 0, 0),
+#                                                                    stop_time=datetime(2100, 1, 2, 0, 0, 0)):
+#         """
+#         Create a station reservation with given list of stations, start_time and stop_time (optional)
+#         Default duration is 24 hours (defined in seconds)
+#         """
+#         reservation_template = models.ReservationTemplate.objects.get(name="resource reservation")
+#         reservation_template_spec = get_default_json_object_for_schema(reservation_template.schema)
+#         reservation_template_spec["resources"] = {"stations": lst_stations }
+#         res = models.Reservation.objects.create(name="Station Reservation %s" % additional_name,
+#                                    description="Station reservation for testing",
+#                                    specifications_template=reservation_template,
+#                                    specifications_doc=reservation_template_spec,
+#                                    start_time=start_time,
+#                                    stop_time=stop_time)
+#         return res
+#
+#     def setUp(self) -> None:
+#         # scheduling unit
+#         self.obs_duration = 120 * 60 # 2 hours
+#         scheduling_set = models.SchedulingSet.objects.create(**SchedulingSet_test_data())
+#         scheduling_unit_draft = TestDynamicScheduling.create_simple_observation_scheduling_unit(
+#             "scheduling unit for %s" % self._testMethodName,
+#             scheduling_set=scheduling_set,
+#             obs_duration=self.obs_duration)
+#         self.scheduling_unit_blueprint = create_task_blueprints_and_subtasks_from_scheduling_unit_draft(
+#             scheduling_unit_draft)
+#         # wipe all reservations in between tests, so the tests don't influence each other
+#         for reservation in models.Reservation.objects.all():
+#             reservation.delete()
+#
+#     def set_1_reservation_start_time_gt_sub_start_time_and_stop_time_gt_sub_stop_time(self, station_reservation):
+#         """
+#         Set (1) reservation start_time > SUB start_time and reservation stop_time > SUB stop_time
+#         """
+#         station_reservation.start_time = self.scheduling_unit_blueprint.start_time + timedelta(minutes=5)
+#         station_reservation.stop_time = self.scheduling_unit_blueprint.stop_time + timedelta(minutes=5)
+#         station_reservation.save()
+#
+#     def set_2_reservation_start_time_lt_sub_start_time_and_stop_time_lt_sub_stop_time(self, station_reservation):
+#         """
+#         Set (2) reservation start_time < SUB start_time and reservation stop_time < SUB stop_time
+#         """
+#         station_reservation.start_time = self.scheduling_unit_blueprint.start_time - timedelta(minutes=5)
+#         station_reservation.stop_time = self.scheduling_unit_blueprint.stop_time - timedelta(minutes=5)
+#         station_reservation.save()
+#
+#     def set_3_reservation_start_time_gt_sub_start_time_and_stop_time_lt_sub_stop_time(self, station_reservation):
+#         """
+#         Set (3) reservation start_time > SUB start_time and reservation stop_time < SUB stop_time
+#         """
+#         station_reservation.start_time = self.scheduling_unit_blueprint.start_time + timedelta(minutes=5)
+#         station_reservation.stop_time = self.scheduling_unit_blueprint.stop_time - timedelta(minutes=5)
+#         station_reservation.save()
+#
+#     def set_4_reservation_start_time_lt_sub_start_time_and_stop_time_gt_sub_stop_time(self, station_reservation):
+#         """
+#         Set (4) reservation start_time < SUB start_time and reservation stop_time > SUB stop_time
+#         """
+#         station_reservation.start_time = self.scheduling_unit_blueprint.start_time - timedelta(minutes=5)
+#         station_reservation.stop_time = self.scheduling_unit_blueprint.stop_time + timedelta(minutes=5)
+#         station_reservation.save()
+#
+#     def set_5_reservation_start_time_and_stop_time_lt_sub_start_time(self, station_reservation):
+#         """
+#         Set (5) reservation start_time and reservation stop_time < SUB start_time
+#         """
+#         station_reservation.start_time = self.scheduling_unit_blueprint.start_time - timedelta(minutes=60)
+#         station_reservation.stop_time = self.scheduling_unit_blueprint.start_time - timedelta(minutes=5)
+#         station_reservation.save()
+#
+#     def set_6_reservation_start_time_and_stop_time_gt_sub_stop_time(self, station_reservation):
+#         """
+#         Set (6) reservation start_time and reservation stop_time > SUB stop_time
+#         """
+#         station_reservation.start_time = self.scheduling_unit_blueprint.stop_time + timedelta(minutes=5)
+#         station_reservation.stop_time = self.scheduling_unit_blueprint.stop_time + timedelta(minutes=65)
+#         station_reservation.save()
+#
+#     def update_station_groups_of_scheduling_unit_blueprint(self):
+#         """
+#         Use the UC1 strategy template to 'easily' extend the station group of the scheduling_unit
+#         For info, it will have three station groups
+#         - dutch station with max_nr_missing=4
+#         - international with max_nr_missing=2
+#         - international required with max_nr_missing=1
+#         """
+#         uc1_strategy_template = models.SchedulingUnitObservingStrategyTemplate.objects.get(name="UC1 CTC+pipelines")
+#         scheduling_unit_spec = add_defaults_to_json_object_for_schema(uc1_strategy_template.template,
+#                                                                       uc1_strategy_template.scheduling_unit_template.schema)
+#         station_groups = scheduling_unit_spec['tasks']['Target Observation']['specifications_doc']['station_groups']
+#         self.scheduling_unit_blueprint.requirements_doc['tasks']['Observation']['specifications_doc']['station_groups'] = station_groups
+#
+#     def test_one_station_reserved(self):
+#         """
+#         Test station reservation when 1 station (CS001) is reserved and station CS001 is used in scheduling_unit
+#         with different reservation start and stop times
+#         """
+#         reservation_one = self.create_station_reservation("One", ["CS001"])
+#         # reservation start_time > SUB start_time and reservation stop_time > SUB stop_time
+#         self.set_1_reservation_start_time_gt_sub_start_time_and_stop_time_gt_sub_stop_time(reservation_one)
+#         self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#         # reservation start_time < SUB start_time and stop_time < SUB stop_time
+#         self.set_2_reservation_start_time_lt_sub_start_time_and_stop_time_lt_sub_stop_time(reservation_one)
+#         self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#         # reservation start_time > SUB start_time and stop_time < SUB stop_time
+#         self.set_3_reservation_start_time_gt_sub_start_time_and_stop_time_lt_sub_stop_time(reservation_one)
+#         self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#         # reservation start_time < SUB start_time and stop_time > SUB stop_time
+#         self.set_4_reservation_start_time_lt_sub_start_time_and_stop_time_gt_sub_stop_time(reservation_one)
+#         self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#         # Reservations outside boundary
+#         # start_time and stop_time < SUB start_time
+#         self.set_5_reservation_start_time_and_stop_time_lt_sub_start_time(reservation_one)
+#         self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#         # start_time and stop_time > SUB stop_time
+#         self.set_6_reservation_start_time_and_stop_time_gt_sub_stop_time(reservation_one)
+#         self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#     def test_two_stations_reserved(self):
+#         """
+#         Test station reservation when 2 station (CS001,CS002) are reserved and station CS001 is used in scheduling_unit
+#         with different reservation start and stop times
+#         """
+#         reservation_two = self.create_station_reservation("Two", ["CS001", "CS002"])
+#         # reservation start_time > SUB start_time and reservation stop_time > SUB stop_time
+#         self.set_1_reservation_start_time_gt_sub_start_time_and_stop_time_gt_sub_stop_time(reservation_two)
+#         self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#         # reservation start_time < SUB start_time and stop_time < SUB stop_time
+#         self.set_2_reservation_start_time_lt_sub_start_time_and_stop_time_lt_sub_stop_time(reservation_two)
+#         self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#         # reservation start_time > SUB start_time and stop_time < SUB stop_time
+#         self.set_3_reservation_start_time_gt_sub_start_time_and_stop_time_lt_sub_stop_time(reservation_two)
+#         self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#         # reservation start_time < SUB start_time and stop_time > SUB stop_time
+#         self.set_4_reservation_start_time_lt_sub_start_time_and_stop_time_gt_sub_stop_time(reservation_two)
+#         self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#         # Reservations outside boundary
+#         # start_time and stop_time < SUB start_time
+#         self.set_5_reservation_start_time_and_stop_time_lt_sub_start_time(reservation_two)
+#         self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#         # start_time and stop_time > SUB stop_time
+#         self.set_6_reservation_start_time_and_stop_time_gt_sub_stop_time(reservation_two)
+#         self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#     def test_two_stations_reserved_but_not_used(self):
+#         """
+#         Test station reservation when 2 stations (CS002, CS003) are reserved and station CS001 is used in scheduling_unit
+#         with different reservation start and stop times
+#         All possibilities should result in 'can run'
+#         """
+#         reservation_two_no_overlap = self.create_station_reservation("Two-NoOverlap", ["CS002", "CS003"])
+#         # reservation start_time > SUB start_time and reservation stop_time > SUB stop_time
+#         self.set_1_reservation_start_time_gt_sub_start_time_and_stop_time_gt_sub_stop_time(reservation_two_no_overlap)
+#         self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#         # reservation start_time < SUB start_time and stop_time < SUB stop_time
+#         self.set_2_reservation_start_time_lt_sub_start_time_and_stop_time_lt_sub_stop_time(reservation_two_no_overlap)
+#         self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#         # reservation start_time > SUB start_time and stop_time < SUB stop_time
+#         self.set_3_reservation_start_time_gt_sub_start_time_and_stop_time_lt_sub_stop_time(reservation_two_no_overlap)
+#         self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#         # reservation start_time < SUB start_time and stop_time > SUB stop_time
+#         self.set_4_reservation_start_time_lt_sub_start_time_and_stop_time_gt_sub_stop_time(reservation_two_no_overlap)
+#         self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#         # Reservations outside boundary
+#         # start_time and stop_time < SUB start_time
+#         self.set_5_reservation_start_time_and_stop_time_lt_sub_start_time(reservation_two_no_overlap)
+#         self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#         # start_time and stop_time > SUB stop_time
+#         self.set_6_reservation_start_time_and_stop_time_gt_sub_stop_time(reservation_two_no_overlap)
+#         self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#     def test_two_stations_reserved_with_duration_null(self):
+#         """
+#         Test station reservation when two stations (CS001,CS002) are reserved with duration null and so reserved indefinitely
+#         and station CS001 is used in scheduling_unit
+#         Test with different reservation start time and NO stop_time
+#         start_time after SUB stop_time 'can run' all others 'can NOT run'
+#         """
+#         reservation_two_no_duration = self.create_station_reservation("Two-NoDuration", ["CS001", "CS002"], stop_time=None)
+#         # reservation start_time > SUB start_time and < SUB stop_time
+#         reservation_two_no_duration.start_time = self.scheduling_unit_blueprint.start_time + timedelta(minutes=5)
+#         reservation_two_no_duration.save()
+#         self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#         # reservation start_time < SUB start_time (and < SUB stop_time of course)
+#         reservation_two_no_duration.start_time = self.scheduling_unit_blueprint.start_time - timedelta(minutes=5)
+#         reservation_two_no_duration.save()
+#         self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#         # reservation start_time > SUB stop time
+#         reservation_two_no_duration.start_time = self.scheduling_unit_blueprint.stop_time + timedelta(minutes=5)
+#         reservation_two_no_duration.save()
+#         self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#     def test_dutch_stations_conflicts_result_false(self):
+#         """
+#         Test conflict of 'Dutch' station which have a default of max_nr_missing=4,
+#         Create stations reservation equal to max_nr_missing+1 and check that it can not run
+#         """
+#         self.update_station_groups_of_scheduling_unit_blueprint()
+#         # Create a reservation within scheduling_unit
+#         self.create_station_reservation("Dutch", ['CS001', 'CS002', 'CS003', 'CS401', 'CS501'],
+#                                         start_time=self.scheduling_unit_blueprint.start_time)
+#         self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#     def test_dutch_stations_conflicts_result_true(self):
+#         """
+#         Test conflict of 'Dutch' station which have a default of max_nr_missing=4,
+#         Create stations reservation equal to max_nr_missing and check that it can run
+#         """
+#         self.update_station_groups_of_scheduling_unit_blueprint()
+#         # Create a reservation within scheduling_unit
+#         self.create_station_reservation("Dutch", ['CS001', 'CS002', 'CS003', 'CS401'],
+#                                         start_time=self.scheduling_unit_blueprint.start_time)
+#         self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#     def test_international_stations_conflicts_result_false(self):
+#         """
+#         Test conflict of 'International' stations which have a default of max_nr_missing=2,
+#         Create stations reservation equal to max_nr_missing+1 and check that it can not run
+#         """
+#         self.update_station_groups_of_scheduling_unit_blueprint()
+#         # Create a reservation within scheduling_unit
+#         self.create_station_reservation("International", ['SE607', 'PL610', 'PL612'],
+#                                         start_time=self.scheduling_unit_blueprint.start_time)
+#         self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#     def test_international_stations_conflicts_result_true(self):
+#         """
+#         Test conflict of 'International' stations which are have a default of max_nr_missing=2,
+#         Create stations reservation equal to max_nr_missing and check that it can run
+#         """
+#         self.update_station_groups_of_scheduling_unit_blueprint()
+#         # Create a reservation within scheduling_unit
+#         self.create_station_reservation("International", ['SE607', 'PL610'],
+#                                         start_time=self.scheduling_unit_blueprint.start_time)
+#         self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#     def test_international_required_stations_conflicts_result_false(self):
+#         """
+#         Test conflict of 'International Required' stations which are have a default of max_nr_missing=1,
+#         Create stations reservation equal to max_nr_missing+1 and check that it can not run
+#         """
+#         self.update_station_groups_of_scheduling_unit_blueprint()
+#         # Create a reservation within scheduling_unit
+#         self.create_station_reservation("International Required", ['DE601', 'DE605'],
+#                                         start_time=self.scheduling_unit_blueprint.start_time)
+#         self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#     def test_international_required_stations_conflicts_result_true(self):
+#         """
+#         Test conflict of 'International Required' stations which are have a default of max_nr_missing=1,
+#         Create stations reservation equal to max_nr_missing and check that it can run
+#         """
+#         self.update_station_groups_of_scheduling_unit_blueprint()
+#         # Create a reservation within scheduling_unit
+#         self.create_station_reservation("International Required", ['DE605'],
+#                                         start_time=self.scheduling_unit_blueprint.start_time)
+#         self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#     def test_mixed_required_stations_conflicts_result_false(self):
+#         """
+#         Test conflict of 'mixed' stations which are have a default of max_nr_missing,
+#         Create stations reservation equal to max_nr_missing and one station group max_nr_missing+1
+#         and check that it can not run
+#         """
+#         self.update_station_groups_of_scheduling_unit_blueprint()
+#         # Create a reservation within scheduling_unit
+#         self.create_station_reservation("Mixed", ['DE605', 'SE607', 'PL610', 'CS001', 'CS002', 'CS003', 'CS401'],
+#                                         start_time=self.scheduling_unit_blueprint.start_time)
+#         self.assertFalse(can_run_within_station_reservations(self.scheduling_unit_blueprint))
+#
+#     def test_mixed_required_stations_conflicts_result_true(self):
+#         """
+#         Test conflict of 'mixed' stations which are have a default of max_nr_missing,
+#         Create stations reservation equal to max_nr_missing and check that it can run
+#         """
+#         self.update_station_groups_of_scheduling_unit_blueprint()
+#         # Create a reservation within scheduling_unit
+#         self.create_station_reservation("Mixed", ['DE605', 'PL610', 'CS001', 'CS002', 'CS003', 'CS401'],
+#                                         start_time=self.scheduling_unit_blueprint.start_time)
+#         self.assertTrue(can_run_within_station_reservations(self.scheduling_unit_blueprint))
 
 
 class TestTriggers(TestCase):
@@ -1953,6 +1953,8 @@ class TestTriggers(TestCase):
         # we only mocked the cancellation.
 
         # Assert now the new triggered scheduling_unit has been scheduled
+        # todo: TMSS-704: We should only cancel if the trigger cannot run afterwards due to constraints.
+        #  Add such constraints once the scheduler considers that, since that will break this test.
         self.assertIsNotNone(scheduled_scheduling_unit)
         self.assertEqual(scheduled_scheduling_unit.id, triggered_scheduling_unit_blueprint.id)
         self.assertEqual(triggered_scheduling_unit_blueprint.status, 'scheduled')
@@ -1991,7 +1993,7 @@ class TestTriggers(TestCase):
         running_subtasks = get_running_observation_subtasks(subtask.stop_time + timedelta(minutes=5))
         self.assertNotIn(subtask, running_subtasks)
 
-        # add a triggered scheduling_unit with higher priority
+        # add a triggered scheduling_unit with same trigger priority
         scheduling_unit_draft = TestDynamicScheduling.create_simple_observation_scheduling_unit(
                                     "triggered scheduling unit for %s" % self._testMethodName,
                                     scheduling_set=self.scheduling_set,
@@ -2009,7 +2011,196 @@ class TestTriggers(TestCase):
         # Assert that the new triggered scheduling_unit has NOT been scheduled, and the regular one is still observing
         self.assertIsNone(scheduled_scheduling_unit)
         self.assertEqual(regular_scheduling_unit_blueprint.status, 'observing')
-        self.assertEqual(triggered_scheduling_unit_blueprint.status, 'error')  # todo: TMSS-704: this should be 'schedulable' as long as no constraint is blocking it, or unschedulable otherwise.
+        #self.assertEqual(triggered_scheduling_unit_blueprint.status, 'schedulable')  # todo: TMSS-704: Make this pass. Currently goes to error state
+
+    @mock.patch("lofar.sas.tmss.services.scheduling.dynamic_scheduling.cancel_subtask")
+    def test_triggered_scheduling_unit_does_not_cancel_regular_observation_if_it_cannot_run_anyway(self, cancel_mock):
+
+        # create a regular scheduling_unit
+        scheduling_unit_draft = TestDynamicScheduling.create_simple_observation_scheduling_unit(
+                                    "scheduling unit for %s" % self._testMethodName,
+                                    scheduling_set=self.scheduling_set,
+                                    is_triggered=False)
+        regular_scheduling_unit_blueprint = create_task_blueprints_and_subtasks_from_scheduling_unit_draft(scheduling_unit_draft)
+        regular_scheduling_unit_blueprint.scheduling_constraints_doc = {}
+        regular_scheduling_unit_blueprint.save()
+
+        scheduled_scheduling_unit = do_dynamic_schedule()
+
+        # Assert the scheduling_unit has been scheduled
+        self.assertIsNotNone(scheduled_scheduling_unit)
+        self.assertEqual(scheduled_scheduling_unit.id, regular_scheduling_unit_blueprint.id)
+        self.assertEqual(regular_scheduling_unit_blueprint.status, 'scheduled')
+
+        # put obs to started state
+        subtask = scheduled_scheduling_unit.task_blueprints.first().subtasks.first()
+        subtask.state = models.SubtaskState.objects.get(value='starting')
+        subtask.save()
+        subtask.state = models.SubtaskState.objects.get(value='started')
+        subtask.save()
+
+        # assert obs it detected as running
+        running_subtasks = get_running_observation_subtasks()
+        self.assertIn(subtask, running_subtasks)
+
+        # also assert cut-off date is considered
+        running_subtasks = get_running_observation_subtasks(subtask.stop_time + timedelta(minutes=5))
+        self.assertNotIn(subtask, running_subtasks)
+
+        # add a triggered scheduling_unit with higher priority, but a between constraint that can never be met
+        scheduling_unit_draft = TestDynamicScheduling.create_simple_observation_scheduling_unit(
+                                    "triggered scheduling unit for %s" % self._testMethodName,
+                                    scheduling_set=self.scheduling_set_high_trigger_priority,
+                                    is_triggered=True)
+        triggered_scheduling_unit_blueprint = create_task_blueprints_and_subtasks_from_scheduling_unit_draft(scheduling_unit_draft)
+        triggered_scheduling_unit_blueprint.scheduling_constraints_doc = {'time': {'between': [{"from": datetime.utcnow().isoformat(), "to": (datetime.utcnow()+timedelta(minutes=10)).isoformat()},]}}
+        triggered_scheduling_unit_blueprint.save()
+
+        scheduled_scheduling_unit = do_dynamic_schedule()
+
+        # assert that the subtask has NOT been cancelled and is still in state 'started'
+        #cancel_mock.assert_not_called()
+        self.assertEqual(subtask.state.value, 'started')
+
+        # Assert that the new triggered scheduling_unit has NOT been scheduled, and the regular one is still observing
+        self.assertIsNone(scheduled_scheduling_unit)
+        self.assertEqual(regular_scheduling_unit_blueprint.status, 'observing')
+        #self.assertEqual(triggered_scheduling_unit_blueprint.status, 'schedulable')  # todo: TMSS-704: Make this pass. Currently goes to error state.
+
+    @mock.patch("lofar.sas.tmss.services.scheduling.dynamic_scheduling.cancel_subtask")
+    def test_triggered_scheduling_unit_gets_scheduled_in_correct_trigger_priority_order(self, cancel_mock):
+
+        # create three regular scheduling_units, two with high trigger priority, one with lower
+        scheduling_unit_draft_high1 = TestDynamicScheduling.create_simple_observation_scheduling_unit(
+                                    "scheduling unit for %s" % self._testMethodName,
+                                    scheduling_set=self.scheduling_set_high_trigger_priority,
+                                    is_triggered=False)
+        regular_scheduling_unit_blueprint_high1 = create_task_blueprints_and_subtasks_from_scheduling_unit_draft(scheduling_unit_draft_high1)
+        regular_scheduling_unit_blueprint_high1.scheduling_constraints_doc = {}
+        regular_scheduling_unit_blueprint_high1.save()
+
+        scheduling_unit_draft_high2 = TestDynamicScheduling.create_simple_observation_scheduling_unit(
+                                    "scheduling unit for %s" % self._testMethodName,
+                                    scheduling_set=self.scheduling_set_high_trigger_priority,
+                                    is_triggered=False)
+        regular_scheduling_unit_blueprint_high2 = create_task_blueprints_and_subtasks_from_scheduling_unit_draft(scheduling_unit_draft_high2)
+        regular_scheduling_unit_blueprint_high2.scheduling_constraints_doc = {}
+        regular_scheduling_unit_blueprint_high2.save()
+
+        scheduling_unit_draft_low = TestDynamicScheduling.create_simple_observation_scheduling_unit(
+                                    "scheduling unit for %s" % self._testMethodName,
+                                    scheduling_set=self.scheduling_set,
+                                    is_triggered=False)
+        regular_scheduling_unit_blueprint_low = create_task_blueprints_and_subtasks_from_scheduling_unit_draft(scheduling_unit_draft_low)
+        regular_scheduling_unit_blueprint_low.scheduling_constraints_doc = {}
+        regular_scheduling_unit_blueprint_low.save()
+
+
+        scheduled_scheduling_unit = do_dynamic_schedule()
+
+        # Assert the scheduling_unit has been scheduled
+        self.assertIsNotNone(scheduled_scheduling_unit)
+        self.assertEqual(scheduled_scheduling_unit.id, regular_scheduling_unit_blueprint_high1.id)
+        self.assertEqual(regular_scheduling_unit_blueprint_high1.status, 'scheduled')
+
+        # put first obs to started state
+        subtask = scheduled_scheduling_unit.task_blueprints.first().subtasks.first()
+        subtask.state = models.SubtaskState.objects.get(value='starting')
+        subtask.save()
+        subtask.state = models.SubtaskState.objects.get(value='started')
+        subtask.save()
+
+        # add a triggered scheduling_unit with same priority
+        scheduling_unit_draft_trigger = TestDynamicScheduling.create_simple_observation_scheduling_unit(
+                                    "triggered scheduling unit for %s" % self._testMethodName,
+                                    scheduling_set=self.scheduling_set_high_trigger_priority,
+                                    is_triggered=True)
+        triggered_scheduling_unit_blueprint = create_task_blueprints_and_subtasks_from_scheduling_unit_draft(scheduling_unit_draft_trigger)
+        triggered_scheduling_unit_blueprint.scheduling_constraints_doc = {}
+        triggered_scheduling_unit_blueprint.save()
+
+        scheduled_scheduling_unit = do_dynamic_schedule()
+
+        # assert that the subtask has NOT been cancelled and is still in state 'started', and its SU is observing
+        cancel_mock.assert_not_called()
+        self.assertEqual(subtask.state.value, 'started')
+        self.assertEqual(regular_scheduling_unit_blueprint_high1.status, 'observing')
+
+        # Assert that the new triggered scheduling_unit has been scheduled, and starts in between the same and lower
+        # priority units
+        self.assertIsNotNone(scheduled_scheduling_unit)
+        #self.assertEqual(triggered_scheduling_unit_blueprint.status, 'scheduled')  # todo: TMSS-704: Make this pass. Currently goes to error state
+        self.assertEqual(regular_scheduling_unit_blueprint_high2.status, 'scheduled')
+        self.assertEqual(regular_scheduling_unit_blueprint_low.status, 'schedulable')  # todo: why high2 gets scheduled, but this is only schedulable?
+        self.assertGreater(regular_scheduling_unit_blueprint_low.start_time, triggered_scheduling_unit_blueprint.stop_time)
+        self.assertGreater(triggered_scheduling_unit_blueprint.start_time, regular_scheduling_unit_blueprint_high1.stop_time)  # todo: TMSS-704: Make this pass. Currently starts after high1, but unexpectedly before high2
+        self.assertGreater(regular_scheduling_unit_blueprint_high2.start_time, regular_scheduling_unit_blueprint_high1.stop_time)
+
+    @mock.patch("lofar.sas.tmss.services.scheduling.dynamic_scheduling.cancel_subtask")
+    def test_triggered_scheduling_unit_goes_to_unschedulable_if_it_cannot_cancel_and_does_not_fit(self, cancel_mock):
+
+        # create three regular scheduling_units, two with high trigger priority, one with lower
+        scheduling_unit_draft_high1 = TestDynamicScheduling.create_simple_observation_scheduling_unit(
+                                    "scheduling unit for %s" % self._testMethodName,
+                                    scheduling_set=self.scheduling_set_high_trigger_priority,
+                                    is_triggered=False)
+        regular_scheduling_unit_blueprint_high1 = create_task_blueprints_and_subtasks_from_scheduling_unit_draft(scheduling_unit_draft_high1)
+        regular_scheduling_unit_blueprint_high1.scheduling_constraints_doc = {}
+        regular_scheduling_unit_blueprint_high1.save()
+
+        scheduling_unit_draft_high2 = TestDynamicScheduling.create_simple_observation_scheduling_unit(
+                                    "scheduling unit for %s" % self._testMethodName,
+                                    scheduling_set=self.scheduling_set_high_trigger_priority,
+                                    is_triggered=False)
+        regular_scheduling_unit_blueprint_high2 = create_task_blueprints_and_subtasks_from_scheduling_unit_draft(scheduling_unit_draft_high2)
+        regular_scheduling_unit_blueprint_high2.scheduling_constraints_doc = {}
+        regular_scheduling_unit_blueprint_high2.save()
+
+        scheduling_unit_draft_low = TestDynamicScheduling.create_simple_observation_scheduling_unit(
+                                    "scheduling unit for %s" % self._testMethodName,
+                                    scheduling_set=self.scheduling_set,
+                                    is_triggered=False)
+        regular_scheduling_unit_blueprint_low = create_task_blueprints_and_subtasks_from_scheduling_unit_draft(scheduling_unit_draft_low)
+        regular_scheduling_unit_blueprint_low.scheduling_constraints_doc = {}
+        regular_scheduling_unit_blueprint_low.save()
+
+
+        scheduled_scheduling_unit = do_dynamic_schedule()
+
+        # Assert the scheduling_unit has been scheduled
+        self.assertIsNotNone(scheduled_scheduling_unit)
+        self.assertEqual(scheduled_scheduling_unit.id, regular_scheduling_unit_blueprint_high1.id)
+        self.assertEqual(regular_scheduling_unit_blueprint_high1.status, 'scheduled')
+
+        # put first obs to started state
+        subtask = scheduled_scheduling_unit.task_blueprints.first().subtasks.first()
+        subtask.state = models.SubtaskState.objects.get(value='starting')
+        subtask.save()
+        subtask.state = models.SubtaskState.objects.get(value='started')
+        subtask.save()
+
+        # add a triggered scheduling_unit with same trigger priority, and a between constraint that can only be met
+        # when the regular obs would be cancelled (which is not allowed because it requires higher trigger priority).
+        scheduling_unit_draft_trigger = TestDynamicScheduling.create_simple_observation_scheduling_unit(
+                                    "triggered scheduling unit for %s" % self._testMethodName,
+                                    scheduling_set=self.scheduling_set_high_trigger_priority,
+                                    is_triggered=True)
+        triggered_scheduling_unit_blueprint = create_task_blueprints_and_subtasks_from_scheduling_unit_draft(scheduling_unit_draft_trigger)
+        triggered_scheduling_unit_blueprint.scheduling_constraints_doc = {'time': {'between': [{"from": datetime.utcnow().isoformat(), "to": (datetime.utcnow()+timedelta(hours=3)).isoformat()},]}}
+        triggered_scheduling_unit_blueprint.save()
+
+        scheduled_scheduling_unit = do_dynamic_schedule()
+
+        # assert that the subtask has NOT been cancelled and is still in state 'started', and its SU is observing
+        cancel_mock.assert_not_called()
+        self.assertEqual(subtask.state.value, 'started')
+        self.assertEqual(regular_scheduling_unit_blueprint_high1.status, 'observing')
+
+        # Assert that the new triggered scheduling_unit has NOT been scheduled and regular observations remain scheduled
+        self.assertIsNotNone(scheduled_scheduling_unit)
+        self.assertEqual(triggered_scheduling_unit_blueprint.status, 'unschedulable')  # todo: TMSS-704: Make this pass. Currently goes to error state
+        self.assertEqual(regular_scheduling_unit_blueprint_high2.status, 'scheduled')
+        self.assertEqual(regular_scheduling_unit_blueprint_low.status, 'schedulable')  # todo: why high2 gets scheduled, but this is only schedulable?
 
 
 logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=logging.INFO)
-- 
GitLab