1#!/usr/bin/python
2# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import mox
7import socket
8import unittest
9
10import frontend_server
11from rpm_infrastructure_exception import RPMInfrastructureException
12
13import common
14from autotest_lib.site_utils.rpm_control_system import utils
15
16
17FAKE_DISPATCHER_URI1 = 'http://fake_dispatcher:1'
18FAKE_DISPATCHER_URI2 = 'http://fake_dispatcher:2'
19UNREACHABLE_SERVER_MSG = 'Server Unreachable'
20DUT_HOSTNAME = 'chromeos-rack8e-hostbs1'
21POWERUNIT_HOSTNAME = 'chromeos-rack8e-rpm1'
22OUTLET = '.A100'
23NEW_STATE = 'ON'
24FAKE_ERRNO = 1
25
26
27class TestFrontendServer(mox.MoxTestBase):
28    """Test frontend_server."""
29
30
31    def setUp(self):
32        super(TestFrontendServer, self).setUp()
33        self.frontend = frontend_server.RPMFrontendServer()
34        self.frontend._rpm_info[DUT_HOSTNAME] = utils.PowerUnitInfo(
35                device_hostname=DUT_HOSTNAME,
36                powerunit_type=utils.PowerUnitInfo.POWERUNIT_TYPES.RPM,
37                powerunit_hostname=POWERUNIT_HOSTNAME,
38                outlet=OUTLET, hydra_hostname=None)
39        self.xmlrpc_mock = self.mox.CreateMockAnything()
40        frontend_server.xmlrpclib.ServerProxy = self.mox.CreateMockAnything()
41        frontend_server.xmlrpclib.ServerProxy(FAKE_DISPATCHER_URI1,
42                allow_none=True).AndReturn(self.xmlrpc_mock)
43
44
45    def testNoRegisteredDispatchers(self):
46        """ Queue request with no dispatchers. Should fail. """
47        self.mox.ResetAll()
48        self.assertRaises(RPMInfrastructureException,
49                          self.frontend.queue_request, DUT_HOSTNAME, NEW_STATE)
50
51
52    def testSuccessfullyQueueRequest(self):
53        """
54        Queue request with at least one dispatcher.
55
56        Expects the request to succeed.
57        """
58        self.xmlrpc_mock.queue_request(
59                self.frontend._rpm_info[DUT_HOSTNAME],
60                NEW_STATE).AndReturn(True)
61        self.mox.ReplayAll()
62        self.frontend.register_dispatcher(FAKE_DISPATCHER_URI1)
63        self.assertTrue(self.frontend.queue_request(DUT_HOSTNAME, NEW_STATE))
64        self.mox.VerifyAll()
65
66
67    def testFailedQueueRequest(self):
68        """
69        Queue request with at least one dispatcher.
70
71        Expects the request to fail.
72        """
73        self.xmlrpc_mock.queue_request(
74                self.frontend._rpm_info[DUT_HOSTNAME],
75                NEW_STATE).AndReturn(False)
76        self.mox.ReplayAll()
77        self.frontend.register_dispatcher(FAKE_DISPATCHER_URI1)
78        self.assertFalse(self.frontend.queue_request(DUT_HOSTNAME, NEW_STATE))
79        self.mox.VerifyAll()
80
81
82    def testAllDispatchersUnregistered(self):
83        """
84        Queue request before and after a dispatcher unregisters.
85
86        queue_request should return True then False.
87        """
88        self.xmlrpc_mock.queue_request(
89                self.frontend._rpm_info[DUT_HOSTNAME],
90                NEW_STATE).AndReturn(True)
91        self.mox.ReplayAll()
92        self.frontend.register_dispatcher(FAKE_DISPATCHER_URI1)
93        self.assertTrue(self.frontend.queue_request(DUT_HOSTNAME, NEW_STATE))
94        self.frontend.unregister_dispatcher(FAKE_DISPATCHER_URI1)
95        self.assertRaises(RPMInfrastructureException,
96                          self.frontend.queue_request, DUT_HOSTNAME, NEW_STATE)
97        self.mox.VerifyAll()
98
99
100    def testUnreachableDispatcherServer(self):
101        """
102        Make sure that if the dispatch server is unreachable and raises an error
103        that we retry the call which will fail because there is no other servers
104        available.
105
106        The call to queue_request will raise a socket.error, and then it should
107        return False as there is no other dispatch servers available.
108        """
109        self.xmlrpc_mock.queue_request(
110                self.frontend._rpm_info[DUT_HOSTNAME], NEW_STATE).AndRaise(
111                socket.error(FAKE_ERRNO, UNREACHABLE_SERVER_MSG))
112        frontend_server.xmlrpclib.ServerProxy(
113                FAKE_DISPATCHER_URI1,
114                allow_none=True).AndReturn(
115                self.xmlrpc_mock)
116        self.xmlrpc_mock.is_up().AndRaise(
117                socket.error(FAKE_ERRNO, UNREACHABLE_SERVER_MSG))
118        self.mox.ReplayAll()
119        self.frontend.register_dispatcher(FAKE_DISPATCHER_URI1)
120        self.assertRaises(RPMInfrastructureException,
121                          self.frontend.queue_request, DUT_HOSTNAME, NEW_STATE)
122        self.mox.VerifyAll()
123
124
125    def testUnreachableDispatcherServerWithBackup(self):
126        """
127        Make sure that if the dispatch server is unreachable and raises an error
128        that we retry the call with a different dispatch server (if it's
129        available).
130
131        The first call to queue_request will raise a socket.error, however it
132        should make a second attempt that should be successful.
133        """
134        self.xmlrpc_mock.queue_request(
135                self.frontend._rpm_info[DUT_HOSTNAME], NEW_STATE).AndRaise(
136                socket.error(FAKE_ERRNO,UNREACHABLE_SERVER_MSG))
137        frontend_server.xmlrpclib.ServerProxy(
138                mox.IgnoreArg(), allow_none=True).MultipleTimes(3).AndReturn(
139                        self.xmlrpc_mock)
140        self.xmlrpc_mock.is_up().AndRaise(
141                socket.error(FAKE_ERRNO, UNREACHABLE_SERVER_MSG))
142        self.xmlrpc_mock.is_up().AndReturn(True)
143        self.xmlrpc_mock.queue_request(
144                self.frontend._rpm_info[DUT_HOSTNAME], NEW_STATE).AndReturn(True)
145        self.mox.ReplayAll()
146        self.frontend.register_dispatcher(FAKE_DISPATCHER_URI1)
147        self.frontend.register_dispatcher(FAKE_DISPATCHER_URI2)
148        self.assertTrue(self.frontend.queue_request(DUT_HOSTNAME, NEW_STATE))
149        self.mox.VerifyAll()
150
151
152if __name__ == '__main__':
153    unittest.main()
154