1#!/usr/bin/python
2
3__author__ = """Ashwin Ganti (aganti@google.com)"""
4
5import os, sys, socket, errno, unittest, threading
6from time import time, sleep
7import common
8from autotest_lib.client.common_lib import error, barrier, base_barrier
9from autotest_lib.client.common_lib.test_utils import mock
10
11
12class listen_server_test(unittest.TestCase):
13
14    def test_init(self):
15        server = barrier.listen_server()
16        server.close()
17
18
19    def test_close(self):
20        server = barrier.listen_server()
21        # cannot bind on the same port again
22        self.assertRaises(socket.error, barrier.listen_server)
23        server.close()
24        # now we can
25        server = barrier.listen_server()
26        server.close()
27
28
29class barrier_test(unittest.TestCase):
30
31    def setUp(self):
32        self.god = mock.mock_god()
33        self.god.mock_io()
34
35
36    def tearDown(self):
37        self.god.unmock_io()
38
39
40    def test_initialize(self):
41        b = barrier.barrier('127.0.0.1#', 'testtag', 100, 11921)
42        self.assertEqual(b._hostid, '127.0.0.1#')
43        self.assertEqual(b._tag, 'testtag')
44        self.assertEqual(b._timeout_secs, 100)
45        self.assertEqual(b._port, 11921)
46
47
48    def test_get_host_from_id(self):
49        hostname = base_barrier.get_host_from_id('my_host')
50        self.assertEqual(hostname, 'my_host')
51
52        hostname = base_barrier.get_host_from_id('my_host#')
53        self.assertEqual(hostname, 'my_host')
54
55        self.assertRaises(error.BarrierError,
56                          base_barrier.get_host_from_id, '#my_host')
57
58
59    def test_update_timeout(self):
60        b = barrier.barrier('127.0.0.1#', 'update', 100)
61        b._update_timeout(120)
62        self.assertEqual(b._timeout_secs, 120)
63
64
65    def test_remaining(self):
66        b = barrier.barrier('127.0.0.1#', 'remain', 100)
67        remain = b._remaining()
68        self.assertEqual(remain, 100)
69
70
71    def test_master_welcome_garbage(self):
72        b = barrier.barrier('127.0.0.1#', 'garbage', 100)
73        waiting_before = dict(b._waiting)
74        seen_before = b._seen
75
76        sender, receiver = socket.socketpair()
77        try:
78            sender.send('GET /foobar?p=-1 HTTP/1.0\r\n\r\n')
79            # This should not raise an exception.
80            b._master_welcome((receiver, 'fakeaddr'))
81
82            self.assertEqual(waiting_before, b._waiting)
83            self.assertEqual(seen_before, b._seen)
84
85            sender, receiver = socket.socketpair()
86            sender.send('abcdefg\x00\x01\x02\n'*5)
87            # This should not raise an exception.
88            b._master_welcome((receiver, 'fakeaddr'))
89
90            self.assertEqual(waiting_before, b._waiting)
91            self.assertEqual(seen_before, b._seen)
92        finally:
93            sender.close()
94            receiver.close()
95
96
97    def test_rendezvous_basic(self):
98        # Basic rendezvous testing
99        self.rendezvous_test(60, port=11920)
100
101
102    def test_rendezvous_timeout(self):
103        # The rendezvous should time out here and throw a
104        # BarrierError since we are specifying a timeout of 0
105        self.assertRaises(error.BarrierError,
106                          self.rendezvous_test, 0, port=11921)
107
108
109    def test_rendezvous_abort_ok(self):
110        # Test with abort flag set to not abort.
111        self.rendezvous_test(60, port=11920,
112                             test_abort=True, abort=False)
113
114
115    def test_rendezvous_abort(self):
116        # The rendezvous should abort here and throw a
117        # BarrierError since we are asking to abort
118        self.assertRaises(error.BarrierError,
119                          self.rendezvous_test, 0, port=11921,
120                          test_abort=True, abort=True)
121
122
123    def test_rendezvous_servers_basic(self):
124        # The rendezvous should time out here and throw a
125        # BarrierError since we are specifying a timeout of 0
126        self.rendezvous_test(60, port=11921,
127                             rendezvous_servers=True)
128
129
130    def test_rendezvous_servers_timeout(self):
131        # The rendezvous should time out here and throw a
132        # BarrierError since we are specifying a timeout of 0
133        self.assertRaises(error.BarrierError,
134                          self.rendezvous_test, 0, port=11922,
135                          rendezvous_servers=True)
136
137
138    def test_rendezvous_servers_abort_ok(self):
139        # Test with abort flag set to not abort.
140        self.rendezvous_test(60, port=11920, rendezvous_servers=True,
141                             test_abort=True, abort=False)
142
143
144    def test_rendezvous_servers_abort(self):
145        # The rendezvous should abort here and throw a
146        # BarrierError since we are asking to abort
147        self.assertRaises(error.BarrierError,
148                          self.rendezvous_test, 0, port=11922,
149                          rendezvous_servers=True,
150                          test_abort=True, abort=True)
151
152
153    # Internal utility function (not a unit test)
154    def rendezvous_test(self, timeout, port=11922,
155                        rendezvous_servers=False, test_abort=False,
156                        abort=False, listen_server=None):
157        if listen_server:
158            port = None
159
160        def _rdv(addr):
161            b1 = barrier.barrier(addr, "test_meeting", timeout, port,
162                                 listen_server=listen_server)
163            if not rendezvous_servers:
164                if test_abort:
165                    b1.rendezvous('127.0.0.1#0', '127.0.0.1#1', abort=abort)
166                else:
167                    b1.rendezvous('127.0.0.1#0', '127.0.0.1#1')
168            else:
169                if test_abort:
170                    b1.rendezvous_servers('127.0.0.1#0', '127.0.0.1#1',
171                                          abort=abort)
172                else:
173                    b1.rendezvous_servers('127.0.0.1#0', '127.0.0.1#1')
174
175
176        def _thread_rdv(addr):
177            # We need to ignore the exception on one side.
178            try:
179                _rdv(addr)
180            except error.BarrierError:
181                pass
182
183        client = threading.Thread(target=_thread_rdv,
184                                  args=('127.0.0.1#0',))
185        client.start()
186        _rdv('127.0.0.1#1')
187        client.join()
188
189
190    def test_reusing_listen_server(self):
191        """
192        Test that reusing the same listen server object works.
193        """
194        server = barrier.listen_server()
195        self.rendezvous_test(10, listen_server=server)
196        self.rendezvous_test(10, listen_server=server)
197        self.rendezvous_test(10, listen_server=server)
198
199
200if __name__ == "__main__":
201    unittest.main()
202