http://scons.tigris.org/issues/show_bug.cgi?id=2329
[scons.git] / src / engine / SCons / TaskmasterTests.py
index f3cb5f02a863bf8e95fc553edd3b10be53eecedf..65d10b59ebafc032c02e60ca424363a709d31156 100644 (file)
@@ -46,6 +46,7 @@ class Node:
         self.scanned = 0
         self.scanner = None
         self.targets = [self]
+        self.prerequisites = []
         class Builder:
             def targets(self, node):
                 return node.targets
@@ -54,27 +55,44 @@ class Node:
         self.csig = None
         self.state = SCons.Node.no_state
         self.prepared = None
-        self.waiting_parents = []
+        self.ref_count = 0
+        self.waiting_parents = set()
+        self.waiting_s_e = set()
         self.side_effect = 0
         self.side_effects = []
         self.alttargets = []
         self.postprocessed = None
         self._bsig_val = None
         self._current_val = 0
+        self.always_build = None
 
     def disambiguate(self):
         return self
 
+    def push_to_cache(self):
+        pass
+
     def retrieve_from_cache(self):
         global cache_text
         if self.cached:
             cache_text.append(self.name + " retrieved")
         return self.cached
 
+    def make_ready(self):
+        pass
+
+    def prepare(self):
+        self.prepared = 1
+
     def build(self):
         global built_text
         built_text = self.name + " built"
 
+    def built(self):
+        global built_text
+        if not self.cached:
+            built_text = built_text + " really"
+
     def has_builder(self):
         return not self.builder is None
 
@@ -84,17 +102,10 @@ class Node:
     def alter_targets(self):
         return self.alttargets, None
 
-    def built(self):
-        global built_text
-        built_text = built_text + " really"
-
     def visited(self):
         global visited_nodes
         visited_nodes.append(self.name)
 
-    def prepare(self):
-        self.prepared = 1
-
     def children(self):
         if not self.scanned:
             self.scan()
@@ -109,14 +120,13 @@ class Node:
 
     def scanner_key(self):
         return self.name
-  
+
     def add_to_waiting_parents(self, node):
-        self.waiting_parents.append(node)
-  
-    def call_for_all_waiting_parents(self, func):
-        func(self)
-        for parent in self.waiting_parents:
-            parent.call_for_all_waiting_parents(func)
+        wp = self.waiting_parents
+        if node in wp:
+            return 0
+        wp.add(node)
+        return 1
 
     def get_state(self):
         return self.state
@@ -136,18 +146,11 @@ class Node:
     def store_bsig(self):
         pass
 
-    def calculator(self):
-        class Calc:
-            def bsig(self, node):
-                return node._bsig_val
-            def current(self, node, sig):
-                return node._current_val
-        return Calc()
-
-    def current(self, calc=None):
-        if calc is None:
-            calc = self.calculator()
-        return calc.current(self, calc.bsig(self))
+    def is_pseudo_derived(self):
+        pass
+
+    def is_up_to_date(self):
+        return self._current_val
     
     def depends_on(self, nodes):
         for node in nodes:
@@ -160,6 +163,29 @@ class Node:
 
     def postprocess(self):
         self.postprocessed = 1
+        self.waiting_parents = set()
+
+    def get_executor(self):
+        if not hasattr(self, 'executor'):
+            class Executor:
+                def prepare(self):
+                    pass
+                def get_action_targets(self):
+                    return self.targets
+                def get_all_targets(self):
+                    return self.targets
+                def get_all_children(self):
+                    result = []
+                    for node in self.targets:
+                        result.extend(node.children())
+                    return result
+                def get_all_prerequisites(self):
+                    return []
+                def get_action_side_effects(self):
+                    return []
+            self.executor = Executor()
+            self.executor.targets = self.targets
+        return self.executor
 
 class OtherError(Exception):
     pass
@@ -181,12 +207,12 @@ class TaskmasterTestCase(unittest.TestCase):
         t.prepare()
         t.execute()
         t = tm.next_task()
-        assert t == None
+        assert t is None
 
         n1 = Node("n1")
         n2 = Node("n2")
         n3 = Node("n3", [n1, n2])
-        
+
         tm = SCons.Taskmaster.Taskmaster([n3])
 
         t = tm.next_task()
@@ -194,20 +220,23 @@ class TaskmasterTestCase(unittest.TestCase):
         t.execute()
         assert built_text == "n1 built", built_text
         t.executed()
+        t.postprocess()
 
         t = tm.next_task()
         t.prepare()
         t.execute()
         assert built_text == "n2 built", built_text
         t.executed()
+        t.postprocess()
 
         t = tm.next_task()
         t.prepare()
         t.execute()
         assert built_text == "n3 built", built_text
         t.executed()
+        t.postprocess()
 
-        assert tm.next_task() == None
+        assert tm.next_task() is None
 
         built_text = "up to date: "
         top_node = n3
@@ -236,20 +265,23 @@ class TaskmasterTestCase(unittest.TestCase):
         t.execute()
         assert built_text == "n1 up-to-date", built_text
         t.executed()
+        t.postprocess()
 
         t = tm.next_task()
         t.prepare()
         t.execute()
         assert built_text == "n2 up-to-date", built_text
         t.executed()
+        t.postprocess()
 
         t = tm.next_task()
         t.prepare()
         t.execute()
         assert built_text == "n3 up-to-date top", built_text
         t.executed()
+        t.postprocess()
 
-        assert tm.next_task() == None
+        assert tm.next_task() is None
 
 
         n1 = Node("n1")
@@ -259,55 +291,47 @@ class TaskmasterTestCase(unittest.TestCase):
         n5 = Node("n5", [n3, n4])
         tm = SCons.Taskmaster.Taskmaster([n5])
 
-        assert not tm.is_blocked()
-        
         t1 = tm.next_task()
         assert t1.get_target() == n1
-        assert not tm.is_blocked()
-        
+
         t2 = tm.next_task()
         assert t2.get_target() == n2
-        assert not tm.is_blocked()
 
         t4 = tm.next_task()
         assert t4.get_target() == n4
-        assert tm.is_blocked()
         t4.executed()
-        assert tm.is_blocked()
-        
+        t4.postprocess()
+
         t1.executed()
-        assert tm.is_blocked()
+        t1.postprocess()
         t2.executed()
-        assert not tm.is_blocked()
+        t2.postprocess()
         t3 = tm.next_task()
         assert t3.get_target() == n3
-        assert tm.is_blocked()
 
         t3.executed()
-        assert not tm.is_blocked()
+        t3.postprocess()
         t5 = tm.next_task()
         assert t5.get_target() == n5, t5.get_target()
-        assert tm.is_blocked()  # still executing t5
         t5.executed()
-        assert not tm.is_blocked()
+        t5.postprocess()
+
+        assert tm.next_task() is None
 
-        assert tm.next_task() == None
 
-        
         n4 = Node("n4")
         n4.set_state(SCons.Node.executed)
         tm = SCons.Taskmaster.Taskmaster([n4])
-        assert tm.next_task() == None
+        assert tm.next_task() is None
 
         n1 = Node("n1")
         n2 = Node("n2", [n1])
         tm = SCons.Taskmaster.Taskmaster([n2,n2])
         t = tm.next_task()
-        assert tm.is_blocked()
         t.executed()
-        assert not tm.is_blocked()
+        t.postprocess()
         t = tm.next_task()
-        assert tm.next_task() == None
+        assert tm.next_task() is None
 
 
         n1 = Node("n1")
@@ -318,15 +342,18 @@ class TaskmasterTestCase(unittest.TestCase):
         target = t.get_target()
         assert target == n1, target
         t.executed()
+        t.postprocess()
         t = tm.next_task()
         target = t.get_target()
         assert target == n2, target
         t.executed()
+        t.postprocess()
         t = tm.next_task()
         target = t.get_target()
         assert target == n3, target
         t.executed()
-        assert tm.next_task() == None
+        t.postprocess()
+        assert tm.next_task() is None
 
         n1 = Node("n1")
         n2 = Node("n2")
@@ -339,23 +366,27 @@ class TaskmasterTestCase(unittest.TestCase):
         t = tm.next_task()
         assert t.get_target() == n1
         t.executed()
+        t.postprocess()
         t = tm.next_task()
         assert t.get_target() == n2
         t.executed()
+        t.postprocess()
         t = tm.next_task()
         assert t.get_target() == n3
         t.executed()
+        t.postprocess()
         t = tm.next_task()
         assert t.get_target() == n4
         t.executed()
-        assert tm.next_task() == None
+        t.postprocess()
+        assert tm.next_task() is None
         assert scan_called == 4, scan_called
 
         tm = SCons.Taskmaster.Taskmaster([n5])
         t = tm.next_task()
         assert t.get_target() == n5, t.get_target()
         t.executed()
-        assert tm.next_task() == None
+        assert tm.next_task() is None
         assert scan_called == 5, scan_called
 
         n1 = Node("n1")
@@ -368,28 +399,26 @@ class TaskmasterTestCase(unittest.TestCase):
         tm = SCons.Taskmaster.Taskmaster([n1,n2,n3,n4,n5])
         t = tm.next_task()
         assert t.get_target() == n1
-        assert n4.state == SCons.Node.executing
-        assert tm.is_blocked()
+        assert n4.state == SCons.Node.executing, n4.state
         t.executed()
-        assert not tm.is_blocked()
+        t.postprocess()
         t = tm.next_task()
         assert t.get_target() == n2
-        assert tm.is_blocked()
         t.executed()
+        t.postprocess()
         t = tm.next_task()
         assert t.get_target() == n3
-        assert tm.is_blocked()
         t.executed()
+        t.postprocess()
         t = tm.next_task()
         assert t.get_target() == n4
-        assert tm.is_blocked()
         t.executed()
+        t.postprocess()
         t = tm.next_task()
         assert t.get_target() == n5
-        assert tm.is_blocked()  # still executing n5
         assert not tm.next_task()
         t.executed()
-        assert not tm.is_blocked()
+        t.postprocess()
 
         n1 = Node("n1")
         n2 = Node("n2")
@@ -402,31 +431,40 @@ class TaskmasterTestCase(unittest.TestCase):
         t = tm.next_task()
         assert t.get_target() == n3, t.get_target()
         t.executed()
+        t.postprocess()
         t = tm.next_task()
         assert t.get_target() == n2, t.get_target()
         t.executed()
+        t.postprocess()
         t = tm.next_task()
         assert t.get_target() == n1, t.get_target()
         t.executed()
+        t.postprocess()
         t = tm.next_task()
         assert t.get_target() == n4, t.get_target()
         t.executed()
+        t.postprocess()
 
         n5 = Node("n5")
         n6 = Node("n6")
         n7 = Node("n7")
         n6.alttargets = [n7]
+
         tm = SCons.Taskmaster.Taskmaster([n5])
         t = tm.next_task()
         assert t.get_target() == n5
         t.executed()
+        t.postprocess()
+
         tm = SCons.Taskmaster.Taskmaster([n6])
         t = tm.next_task()
         assert t.get_target() == n7
         t.executed()
+        t.postprocess()
         t = tm.next_task()
         assert t.get_target() == n6
         t.executed()
+        t.postprocess()
 
         n1 = Node("n1")
         n2 = Node("n2", [n1])
@@ -441,9 +479,10 @@ class TaskmasterTestCase(unittest.TestCase):
         tm = SCons.Taskmaster.Taskmaster([n1])
         t = tm.next_task()
         t.executed()
+        t.postprocess()
 
         s = n1.get_state()
-        assert s == SCons.Node.up_to_date, s
+        assert s == SCons.Node.executed, s
         s = n2.get_state()
         assert s == SCons.Node.executed, s
 
@@ -467,7 +506,10 @@ class TaskmasterTestCase(unittest.TestCase):
         n3 = Node("n3")
         c4 = Node("c4")
         c4._current_val = 1
-        tm = SCons.Taskmaster.Taskmaster(targets = [n1, c2, n3, c4],
+        a5 = Node("a5")
+        a5._current_val = 1
+        a5.always_build = 1
+        tm = SCons.Taskmaster.Taskmaster(targets = [n1, c2, n3, c4, a5],
                                          tasker = TaskGen)
 
         del ood[:]
@@ -486,6 +528,9 @@ class TaskmasterTestCase(unittest.TestCase):
         t = tm.next_task()
         assert ood == [], ood
 
+        del ood[:]
+        t = tm.next_task()
+        assert ood == [a5], ood
 
     def test_make_ready_exception(self):
         """Test handling exceptions from Task.make_ready()
@@ -590,56 +635,19 @@ class TaskmasterTestCase(unittest.TestCase):
 
     def test_cycle_detection(self):
         """Test detecting dependency cycles
-
         """
         n1 = Node("n1")
         n2 = Node("n2", [n1])
         n3 = Node("n3", [n2])
         n1.kids = [n3]
 
+        tm = SCons.Taskmaster.Taskmaster([n3])
         try:
-            tm = SCons.Taskmaster.Taskmaster([n3])
             t = tm.next_task()
         except SCons.Errors.UserError, e:
             assert str(e) == "Dependency cycle: n3 -> n1 -> n2 -> n3", str(e)
         else:
-            assert 0
-        
-    def test_is_blocked(self):
-        """Test whether a task is blocked
-
-        Both default and overridden in a subclass.
-        """
-        tm = SCons.Taskmaster.Taskmaster()
-        assert not tm.is_blocked()
-
-        class MyTM(SCons.Taskmaster.Taskmaster):
-            def _find_next_ready_node(self):
-                self.ready = 1
-        tm = MyTM()
-        assert not tm.is_blocked()
-
-        class MyTM(SCons.Taskmaster.Taskmaster):
-            def _find_next_ready_node(self):
-                self.ready = None
-                self.pending = []
-                self.executing = []
-        tm = MyTM()
-        assert not tm.is_blocked()
-
-        class MyTM(SCons.Taskmaster.Taskmaster):
-            def _find_next_ready_node(self):
-                self.ready = None
-                self.pending = [1]
-        tm = MyTM()
-        assert tm.is_blocked()
-
-        class MyTM(SCons.Taskmaster.Taskmaster):
-            def _find_next_ready_node(self):
-                self.ready = None
-                self.executing = [1]
-        tm = MyTM()
-        assert tm.is_blocked()
+            assert 'Did not catch expected UserError'
 
     def test_next_top_level_candidate(self):
         """Test the next_top_level_candidate() method
@@ -650,9 +658,9 @@ class TaskmasterTestCase(unittest.TestCase):
 
         tm = SCons.Taskmaster.Taskmaster([n3])
         t = tm.next_task()
-        assert tm.executing == [n1], tm.executing
+        assert t.targets == [n1], t.targets
         t.fail_stop()
-        assert t.targets == [n3], t.targets
+        assert t.targets == [n3], list(map(str, t.targets))
         assert t.top == 1, t.top
 
     def test_stop(self):
@@ -665,13 +673,14 @@ class TaskmasterTestCase(unittest.TestCase):
         n1 = Node("n1")
         n2 = Node("n2")
         n3 = Node("n3", [n1, n2])
-        
+
         tm = SCons.Taskmaster.Taskmaster([n3])
         t = tm.next_task()
         t.prepare()
         t.execute()
         assert built_text == "n1 built", built_text
         t.executed()
+        t.postprocess()
         assert built_text == "n1 built really", built_text
 
         tm.stop()
@@ -696,16 +705,6 @@ class TaskmasterTestCase(unittest.TestCase):
         assert built_text == "MyTM.stop()"
         assert tm.next_task() is None
 
-    def test_failed(self):
-        """Test when a task has failed
-        """
-        n1 = Node("n1")
-        tm = SCons.Taskmaster.Taskmaster([n1])
-        t = tm.next_task()
-        assert tm.executing == [n1], tm.executing
-        tm.failed(n1)
-        assert tm.executing == [], tm.executing
-
     def test_executed(self):
         """Test when a task has been executed
         """
@@ -724,7 +723,7 @@ class TaskmasterTestCase(unittest.TestCase):
         s = n1.get_state()
         assert s == SCons.Node.executed, s
         assert built_text == "xxx really", built_text
-        assert visited_nodes == [], visited_nodes
+        assert visited_nodes == ['n1'], visited_nodes
 
         n2 = Node("n2")
         tm = SCons.Taskmaster.Taskmaster([n2])
@@ -755,11 +754,10 @@ class TaskmasterTestCase(unittest.TestCase):
         assert s == SCons.Node.up_to_date, s
         s = n4.get_state()
         assert s == SCons.Node.executed, s
-        assert visited_nodes == ['n3'], visited_nodes
+        assert visited_nodes == ['n3', 'n4'], visited_nodes
 
     def test_prepare(self):
         """Test preparation of multiple Nodes for a task
-
         """
         n1 = Node("n1")
         n2 = Node("n2")
@@ -771,7 +769,7 @@ class TaskmasterTestCase(unittest.TestCase):
         # set it up by having something that approximates a real Builder
         # return this list--but that's more work than is probably
         # warranted right now.
-        t.targets = [n1, n2]
+        n1.get_executor().targets = [n1, n2]
         t.prepare()
         assert n1.prepared
         assert n2.prepared
@@ -782,7 +780,7 @@ class TaskmasterTestCase(unittest.TestCase):
         t = tm.next_task()
         # More bogus reaching in and setting the targets.
         n3.set_state(SCons.Node.up_to_date)
-        t.targets = [n3, n4]
+        n3.get_executor().targets = [n3, n4]
         t.prepare()
         assert n3.prepared
         assert n4.prepared
@@ -818,11 +816,11 @@ class TaskmasterTestCase(unittest.TestCase):
 
         n6.side_effects = [ n8 ]
         n7.side_effects = [ n9, n10 ]
-        
+
         tm = SCons.Taskmaster.Taskmaster([n6, n7])
         t = tm.next_task()
         # More bogus reaching in and setting the targets.
-        t.targets = [n6, n7]
+        n6.get_executor().targets = [n6, n7]
         t.prepare()
         assert n6.prepared
         assert n7.prepared
@@ -830,9 +828,36 @@ class TaskmasterTestCase(unittest.TestCase):
         assert n9.prepared
         assert n10.prepared
 
+        # Make sure we call an Executor's prepare() method.
+        class ExceptionExecutor:
+            def prepare(self):
+                raise Exception, "Executor.prepare() exception"
+            def get_all_targets(self):
+                return self.nodes
+            def get_all_children(self):
+                result = []
+                for node in self.nodes:
+                    result.extend(node.children())
+                return result
+            def get_all_prerequisites(self):
+                return []
+            def get_action_side_effects(self):
+                return []
+
+        n11 = Node("n11")
+        n11.executor = ExceptionExecutor()
+        n11.executor.nodes = [n11]
+        tm = SCons.Taskmaster.Taskmaster([n11])
+        t = tm.next_task()
+        try:
+            t.prepare()
+        except Exception, e:
+            assert str(e) == "Executor.prepare() exception", e
+        else:
+            raise AssertionError, "did not catch expected exception"
+
     def test_execute(self):
         """Test executing a task
-
         """
         global built_text
         global cache_text
@@ -882,12 +907,10 @@ class TaskmasterTestCase(unittest.TestCase):
             t.execute()
         except SCons.Errors.BuildError, e:
             assert e.node == n4, e.node
-            assert e.errstr == "Exception", e.errstr
-            assert len(e.args) == 3, `e.args`
-            assert e.args[0] == OtherError, e.args[0]
-            assert isinstance(e.args[1], OtherError), type(e.args[1])
+            assert e.errstr == "OtherError : ", e.errstr
+            assert len(e.exc_info) == 3, e.exc_info
             exc_traceback = sys.exc_info()[2]
-            assert type(e.args[2]) == type(exc_traceback), e.args[2]
+            assert isinstance(e.exc_info[2], type(exc_traceback)), e.exc_info[2]
         else:
             raise TestFailed, "did not catch expected BuildError"
 
@@ -955,37 +978,46 @@ class TaskmasterTestCase(unittest.TestCase):
         ]
         assert str(exc_value) in exception_values, exc_value
 
-        t.exception_set(("exception 1", None))
+        class Exception1(Exception):
+            pass
+
+        t.exception_set((Exception1, None))
         try:
             t.exception_raise()
         except:
             exc_type, exc_value = sys.exc_info()[:2]
-            assert exc_type == "exception 1", exc_type
-            assert exc_value is None, exc_value
+            assert exc_type == Exception1, exc_type
+            assert str(exc_value) == '', exc_value
         else:
             assert 0, "did not catch expected exception"
 
-        t.exception_set(("exception 2", "xyzzy"))
+        class Exception2(Exception):
+            pass
+
+        t.exception_set((Exception2, "xyzzy"))
         try:
             t.exception_raise()
         except:
             exc_type, exc_value = sys.exc_info()[:2]
-            assert exc_type == "exception 2", exc_type
-            assert exc_value == "xyzzy", exc_value
+            assert exc_type == Exception2, exc_type
+            assert str(exc_value) == "xyzzy", exc_value
         else:
             assert 0, "did not catch expected exception"
 
+        class Exception3(Exception):
+            pass
+
         try:
             1/0
         except:
             tb = sys.exc_info()[2]
-        t.exception_set(("exception 3", "arg", tb))
+        t.exception_set((Exception3, "arg", tb))
         try:
             t.exception_raise()
         except:
             exc_type, exc_value, exc_tb = sys.exc_info()
-            assert exc_type == 'exception 3', exc_type
-            assert exc_value == "arg", exc_value
+            assert exc_type == Exception3, exc_type
+            assert str(exc_value) == "arg", exc_value
             import traceback
             x = traceback.extract_tb(tb)[-1]
             y = traceback.extract_tb(exc_tb)[-1]
@@ -993,23 +1025,8 @@ class TaskmasterTestCase(unittest.TestCase):
         else:
             assert 0, "did not catch expected exception"
 
-        t.exception_set(("exception 4", "XYZZY"))
-        def fw_exc(exc):
-            raise 'exception_forwarded', exc
-        tm.exception_raise = fw_exc 
-        try:
-            t.exception_raise()
-        except:
-            exc_type, exc_value = sys.exc_info()[:2]
-            assert exc_type == 'exception_forwarded', exc_type
-            assert exc_value[0] == "exception 4", exc_value[0]
-            assert exc_value[1] == "XYZZY", exc_value[1]
-        else:
-            assert 0, "did not catch expected exception"
-
     def test_postprocess(self):
         """Test postprocessing targets to give them a chance to clean up
-        
         """
         n1 = Node("n1")
         tm = SCons.Taskmaster.Taskmaster([n1])
@@ -1047,29 +1064,63 @@ class TaskmasterTestCase(unittest.TestCase):
         t = tm.next_task()
         t.prepare()
         t.execute()
+        t.postprocess()
         n1.set_state(SCons.Node.executed)
         t = tm.next_task()
         t.prepare()
         t.execute()
+        t.postprocess()
+        n2.set_state(SCons.Node.executed)
+        t = tm.next_task()
+        t.prepare()
+        t.execute()
+        t.postprocess()
         t = tm.next_task()
+        assert t is None
 
         value = trace.getvalue()
         expect = """\
-Taskmaster: 'n1': children:
-    []
-    evaluating
-Taskmaster: 'n1': already handled
-Taskmaster: 'n3': children:
-    ['n1', 'n2']
-    waiting on unstarted children:
-    ['n2']
-Taskmaster: 'n2': children:
-    []
-    evaluating
-Taskmaster: 'n3': children:
-    ['n1', 'n2']
-    waiting on unfinished children:
-    ['n2']
+
+Taskmaster: Looking for a node to evaluate
+Taskmaster:     Considering node <no_state   0   'n1'> and its children:
+Taskmaster: Evaluating <pending    0   'n1'>
+
+Task.make_ready_current(): node <pending    0   'n1'>
+Task.prepare():      node <executing  0   'n1'>
+Task.execute():      node <executing  0   'n1'>
+Task.postprocess():  node <executing  0   'n1'>
+
+Taskmaster: Looking for a node to evaluate
+Taskmaster:     Considering node <executed   0   'n1'> and its children:
+Taskmaster:        already handled (executed)
+Taskmaster:     Considering node <no_state   0   'n3'> and its children:
+Taskmaster:        <executed   0   'n1'>
+Taskmaster:        <no_state   0   'n2'>
+Taskmaster:      adjusted ref count: <pending    1   'n3'>, child 'n2'
+Taskmaster:     Considering node <no_state   0   'n2'> and its children:
+Taskmaster: Evaluating <pending    0   'n2'>
+
+Task.make_ready_current(): node <pending    0   'n2'>
+Task.prepare():      node <executing  0   'n2'>
+Task.execute():      node <executing  0   'n2'>
+Task.postprocess():  node <executing  0   'n2'>
+Task.postprocess():  removing <executing  0   'n2'>
+Task.postprocess():  adjusted parent ref count <pending    0   'n3'>
+
+Taskmaster: Looking for a node to evaluate
+Taskmaster:     Considering node <pending    0   'n3'> and its children:
+Taskmaster:        <executed   0   'n1'>
+Taskmaster:        <executed   0   'n2'>
+Taskmaster: Evaluating <pending    0   'n3'>
+
+Task.make_ready_current(): node <pending    0   'n3'>
+Task.prepare():      node <executing  0   'n3'>
+Task.execute():      node <executing  0   'n3'>
+Task.postprocess():  node <executing  0   'n3'>
+
+Taskmaster: Looking for a node to evaluate
+Taskmaster: No candidate anymore.
+
 """
         assert value == expect, value
 
@@ -1079,3 +1130,9 @@ if __name__ == "__main__":
     suite = unittest.makeSuite(TaskmasterTestCase, 'test_')
     if not unittest.TextTestRunner().run(suite).wasSuccessful():
         sys.exit(1)
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4: