| 
9 | 9 |     Host your_hostname localhost 127.0.0.*  | 
10 | 10 |       StrictHostKeyChecking no  | 
11 | 11 |       LogLevel ERROR  | 
 | 12 | +
  | 
 | 13 | +The hostname mock command available in tests/bin needs to be  | 
 | 14 | +used on the remote nodes (tests/bin added to PATH in .bashrc).  | 
12 | 15 | """  | 
13 | 16 | 
 
  | 
14 | 17 | import logging  | 
 | 
18 | 21 | import warnings  | 
19 | 22 | 
 
  | 
20 | 23 | from ClusterShell.NodeSet import NodeSet  | 
 | 24 | +from ClusterShell.Propagation import RouteResolvingError  | 
 | 25 | +from ClusterShell.Event import EventHandler  | 
21 | 26 | from ClusterShell.Task import task_self, task_terminate, task_wait  | 
22 | 27 | from ClusterShell.Task import Task, task_cleanup  | 
23 | 28 | from ClusterShell.Topology import TopologyGraph  | 
 | 
36 | 41 | NODE_FOREIGN = '127.0.0.5'  | 
37 | 42 | 
 
  | 
38 | 43 | 
 
  | 
39 |  | -class TEventHandlerBase(object):  | 
 | 44 | +class TEventHandlerBase(EventHandler):  | 
40 | 45 |     """Base Test class for EventHandler"""  | 
41 | 46 | 
 
  | 
42 | 47 |     def __init__(self):  | 
@@ -103,6 +108,16 @@ def ev_close(self, worker, timedout):  | 
103 | 108 |         if timedout:  | 
104 | 109 |             self.ev_timedout_cnt += 1  | 
105 | 110 | 
 
  | 
 | 111 | +class TRoutingEventHandler(TEventHandler):  | 
 | 112 | +    """Test Routing Event Handler"""  | 
 | 113 | + | 
 | 114 | +    def __init__(self):  | 
 | 115 | +        TEventHandler.__init__(self)  | 
 | 116 | +        self.routing_events = []  | 
 | 117 | + | 
 | 118 | +    def _ev_routing(self, worker, arg):  | 
 | 119 | +        self.routing_events.append((worker, arg))  | 
 | 120 | + | 
106 | 121 | 
 
  | 
107 | 122 | class TreeWorkerTestBase(unittest.TestCase):  | 
108 | 123 |     """  | 
@@ -348,6 +363,38 @@ def test_tree_run_event(self):  | 
348 | 363 |         self.assertEqual(teh.ev_close_cnt, 1)  | 
349 | 364 |         self.assertEqual(teh.last_read, b'Lorem Ipsum')  | 
350 | 365 | 
 
  | 
 | 366 | +    def test_tree_run_event_multiple(self):  | 
 | 367 | +        """test multiple tree runs with EventHandler (1.8+)"""  | 
 | 368 | +        # Test for GH#566  | 
 | 369 | +        teh = TEventHandler()  | 
 | 370 | +        self.task.run('echo Lorem Ipsum Unum', nodes=NODE_DISTANT, handler=teh)  | 
 | 371 | +        self.assertEqual(teh.ev_start_cnt, 1)  | 
 | 372 | +        self.assertEqual(teh.ev_pickup_cnt, 1)  | 
 | 373 | +        self.assertEqual(teh.ev_read_cnt, 1)  | 
 | 374 | +        self.assertEqual(teh.ev_written_cnt, 0)  | 
 | 375 | +        self.assertEqual(teh.ev_hup_cnt, 1)  | 
 | 376 | +        self.assertEqual(teh.ev_timedout_cnt, 0)  | 
 | 377 | +        self.assertEqual(teh.ev_close_cnt, 1)  | 
 | 378 | +        self.assertEqual(teh.last_read, b'Lorem Ipsum Unum')  | 
 | 379 | +        self.task.run('echo Lorem Ipsum Duo', nodes=NODE_DISTANT, handler=teh)  | 
 | 380 | +        self.assertEqual(teh.ev_start_cnt, 2)  | 
 | 381 | +        self.assertEqual(teh.ev_pickup_cnt, 2)  | 
 | 382 | +        self.assertEqual(teh.ev_read_cnt, 2)  | 
 | 383 | +        self.assertEqual(teh.ev_written_cnt, 0)  | 
 | 384 | +        self.assertEqual(teh.ev_hup_cnt, 2)  | 
 | 385 | +        self.assertEqual(teh.ev_timedout_cnt, 0)  | 
 | 386 | +        self.assertEqual(teh.ev_close_cnt, 2)  | 
 | 387 | +        self.assertEqual(teh.last_read, b'Lorem Ipsum Duo')  | 
 | 388 | +        self.task.run('echo Lorem Ipsum Tres', nodes=NODE_DISTANT, handler=teh)  | 
 | 389 | +        self.assertEqual(teh.ev_start_cnt, 3)  | 
 | 390 | +        self.assertEqual(teh.ev_pickup_cnt, 3)  | 
 | 391 | +        self.assertEqual(teh.ev_read_cnt, 3)  | 
 | 392 | +        self.assertEqual(teh.ev_written_cnt, 0)  | 
 | 393 | +        self.assertEqual(teh.ev_hup_cnt, 3)  | 
 | 394 | +        self.assertEqual(teh.ev_timedout_cnt, 0)  | 
 | 395 | +        self.assertEqual(teh.ev_close_cnt, 3)  | 
 | 396 | +        self.assertEqual(teh.last_read, b'Lorem Ipsum Tres')  | 
 | 397 | + | 
351 | 398 |     def test_tree_run_event_timeout(self):  | 
352 | 399 |         """test tree run with EventHandler (1.8+) with timeout"""  | 
353 | 400 |         teh = TEventHandler()  | 
@@ -713,6 +760,17 @@ def ev_hup(self, worker, node, rc):  | 
713 | 760 |         self.assertEqual(teh.ev_close_cnt, 1)  | 
714 | 761 |         self.assertEqual(teh.last_read, None)  | 
715 | 762 | 
 
  | 
 | 763 | +    def test_tree_gateway_bogus_single(self):  | 
 | 764 | +        """test tree run with bogus single gateway"""  | 
 | 765 | +        # Part of GH#566  | 
 | 766 | +        teh = TEventHandler()  | 
 | 767 | +        os.environ['CLUSTERSHELL_GW_PYTHON_EXECUTABLE'] = '/test/bogus'  | 
 | 768 | +        try:  | 
 | 769 | +            self.assertRaises(RouteResolvingError, self.task.run, 'echo Lorem Ipsum',  | 
 | 770 | +                              nodes=NODE_DISTANT, handler=teh)  | 
 | 771 | +        finally:  | 
 | 772 | +            del os.environ['CLUSTERSHELL_GW_PYTHON_EXECUTABLE']  | 
 | 773 | + | 
716 | 774 | 
 
  | 
717 | 775 | @unittest.skipIf(HOSTNAME == 'localhost', "does not work with hostname set to 'localhost'")  | 
718 | 776 | class TreeWorkerGW2Test(TreeWorkerTestBase):  | 
@@ -858,3 +916,24 @@ def test_tree_run_gw2f1_write_distant(self):  | 
858 | 916 |     def test_tree_run_gw2f1_write_distant2_mt(self):  | 
859 | 917 |         """test tree run with write(), 1/2 gateways, distant 2 targets, separate thread"""  | 
860 | 918 |         self._tree_run_write(NODE_DISTANT2, separate_thread=True)  | 
 | 919 | + | 
 | 920 | +    def test_tree_run_gw2f1_reroute(self):  | 
 | 921 | +        """test tree run with reroute event, 1/2 gateways"""  | 
 | 922 | +        teh = TRoutingEventHandler()  | 
 | 923 | +        self.task.run('echo Lorem Ipsum', nodes=NODE_DISTANT2, handler=teh)  | 
 | 924 | +        self.assertEqual(len(teh.routing_events), 1)  | 
 | 925 | +        worker, arg = teh.routing_events[0]  | 
 | 926 | +        self.assertEqual(worker.command, "echo Lorem Ipsum")  | 
 | 927 | +        self.assertEqual(arg["event"], "reroute")  | 
 | 928 | +        self.assertIn(arg["targets"], NodeSet(NODE_DISTANT2))  | 
 | 929 | +        # event handler checks  | 
 | 930 | +        self.assertEqual(teh.ev_start_cnt, 1)  | 
 | 931 | +        self.assertEqual(teh.ev_pickup_cnt, 2)  | 
 | 932 | +        # read_cnt += 1 for gateway error on stderr (so currently not fully  | 
 | 933 | +        # transparent to the user)  | 
 | 934 | +        self.assertEqual(teh.ev_read_cnt, 3)  | 
 | 935 | +        self.assertEqual(teh.ev_written_cnt, 0)  | 
 | 936 | +        self.assertEqual(teh.ev_hup_cnt, 2)  | 
 | 937 | +        self.assertEqual(teh.ev_timedout_cnt, 0)  | 
 | 938 | +        self.assertEqual(teh.ev_close_cnt, 1)  | 
 | 939 | +        self.assertEqual(teh.last_read, b'Lorem Ipsum')  | 
0 commit comments