1*9c5db199SXin Li#!/usr/bin/python3 2*9c5db199SXin Li 3*9c5db199SXin Liimport unittest, time 4*9c5db199SXin Liimport common 5*9c5db199SXin Lifrom autotest_lib.client.common_lib import global_config 6*9c5db199SXin Lifrom autotest_lib.client.common_lib.test_utils import mock 7*9c5db199SXin Lifrom autotest_lib.database import database_connection 8*9c5db199SXin Li 9*9c5db199SXin Li_CONFIG_SECTION = 'AUTOTEST_WEB' 10*9c5db199SXin Li_HOST = 'myhost' 11*9c5db199SXin Li_USER = 'myuser' 12*9c5db199SXin Li_PASS = 'mypass' 13*9c5db199SXin Li_DB_NAME = 'mydb' 14*9c5db199SXin Li_DB_TYPE = 'mydbtype' 15*9c5db199SXin Li 16*9c5db199SXin Li_CONNECT_KWARGS = dict(host=_HOST, username=_USER, password=_PASS, 17*9c5db199SXin Li db_name=_DB_NAME) 18*9c5db199SXin Li_RECONNECT_DELAY = 10 19*9c5db199SXin Li 20*9c5db199SXin Liclass FakeDatabaseError(Exception): 21*9c5db199SXin Li pass 22*9c5db199SXin Li 23*9c5db199SXin Li 24*9c5db199SXin Liclass DatabaseConnectionTest(unittest.TestCase): 25*9c5db199SXin Li def setUp(self): 26*9c5db199SXin Li self.god = mock.mock_god() 27*9c5db199SXin Li self.god.stub_function(time, 'sleep') 28*9c5db199SXin Li 29*9c5db199SXin Li 30*9c5db199SXin Li def tearDown(self): 31*9c5db199SXin Li global_config.global_config.reset_config_values() 32*9c5db199SXin Li self.god.unstub_all() 33*9c5db199SXin Li 34*9c5db199SXin Li 35*9c5db199SXin Li def _get_database_connection(self, config_section=_CONFIG_SECTION): 36*9c5db199SXin Li if config_section == _CONFIG_SECTION: 37*9c5db199SXin Li self._override_config() 38*9c5db199SXin Li db = database_connection.DatabaseConnection(config_section) 39*9c5db199SXin Li 40*9c5db199SXin Li self._fake_backend = self.god.create_mock_class( 41*9c5db199SXin Li database_connection._GenericBackend, 'fake_backend') 42*9c5db199SXin Li for exception in database_connection._DB_EXCEPTIONS: 43*9c5db199SXin Li setattr(self._fake_backend, exception, FakeDatabaseError) 44*9c5db199SXin Li self._fake_backend.rowcount = 0 45*9c5db199SXin Li 46*9c5db199SXin Li def get_fake_backend(db_type): 47*9c5db199SXin Li self._db_type = db_type 48*9c5db199SXin Li return self._fake_backend 49*9c5db199SXin Li self.god.stub_with(db, '_get_backend', get_fake_backend) 50*9c5db199SXin Li 51*9c5db199SXin Li db.reconnect_delay_sec = _RECONNECT_DELAY 52*9c5db199SXin Li return db 53*9c5db199SXin Li 54*9c5db199SXin Li 55*9c5db199SXin Li def _override_config(self): 56*9c5db199SXin Li c = global_config.global_config 57*9c5db199SXin Li c.override_config_value(_CONFIG_SECTION, 'host', _HOST) 58*9c5db199SXin Li c.override_config_value(_CONFIG_SECTION, 'user', _USER) 59*9c5db199SXin Li c.override_config_value(_CONFIG_SECTION, 'password', _PASS) 60*9c5db199SXin Li c.override_config_value(_CONFIG_SECTION, 'database', _DB_NAME) 61*9c5db199SXin Li c.override_config_value(_CONFIG_SECTION, 'db_type', _DB_TYPE) 62*9c5db199SXin Li 63*9c5db199SXin Li 64*9c5db199SXin Li def test_connect(self): 65*9c5db199SXin Li db = self._get_database_connection(config_section=None) 66*9c5db199SXin Li self._fake_backend.connect.expect_call(**_CONNECT_KWARGS) 67*9c5db199SXin Li 68*9c5db199SXin Li db.connect(db_type=_DB_TYPE, host=_HOST, username=_USER, 69*9c5db199SXin Li password=_PASS, db_name=_DB_NAME) 70*9c5db199SXin Li 71*9c5db199SXin Li self.assertEquals(self._db_type, _DB_TYPE) 72*9c5db199SXin Li self.god.check_playback() 73*9c5db199SXin Li 74*9c5db199SXin Li 75*9c5db199SXin Li def test_global_config(self): 76*9c5db199SXin Li db = self._get_database_connection() 77*9c5db199SXin Li self._fake_backend.connect.expect_call(**_CONNECT_KWARGS) 78*9c5db199SXin Li 79*9c5db199SXin Li db.connect() 80*9c5db199SXin Li 81*9c5db199SXin Li self.assertEquals(self._db_type, _DB_TYPE) 82*9c5db199SXin Li self.god.check_playback() 83*9c5db199SXin Li 84*9c5db199SXin Li 85*9c5db199SXin Li def _expect_reconnect(self, fail=False): 86*9c5db199SXin Li self._fake_backend.disconnect.expect_call() 87*9c5db199SXin Li call = self._fake_backend.connect.expect_call(**_CONNECT_KWARGS) 88*9c5db199SXin Li if fail: 89*9c5db199SXin Li call.and_raises(FakeDatabaseError()) 90*9c5db199SXin Li 91*9c5db199SXin Li 92*9c5db199SXin Li def _expect_fail_and_reconnect(self, num_reconnects, fail_last=False): 93*9c5db199SXin Li self._fake_backend.connect.expect_call(**_CONNECT_KWARGS).and_raises( 94*9c5db199SXin Li FakeDatabaseError()) 95*9c5db199SXin Li for i in range(num_reconnects): 96*9c5db199SXin Li time.sleep.expect_call(_RECONNECT_DELAY) 97*9c5db199SXin Li if i < num_reconnects - 1: 98*9c5db199SXin Li self._expect_reconnect(fail=True) 99*9c5db199SXin Li else: 100*9c5db199SXin Li self._expect_reconnect(fail=fail_last) 101*9c5db199SXin Li 102*9c5db199SXin Li 103*9c5db199SXin Li def test_connect_retry(self): 104*9c5db199SXin Li db = self._get_database_connection() 105*9c5db199SXin Li self._expect_fail_and_reconnect(1) 106*9c5db199SXin Li 107*9c5db199SXin Li db.connect() 108*9c5db199SXin Li self.god.check_playback() 109*9c5db199SXin Li 110*9c5db199SXin Li self._fake_backend.disconnect.expect_call() 111*9c5db199SXin Li self._expect_fail_and_reconnect(0) 112*9c5db199SXin Li self.assertRaises(FakeDatabaseError, db.connect, 113*9c5db199SXin Li try_reconnecting=False) 114*9c5db199SXin Li self.god.check_playback() 115*9c5db199SXin Li 116*9c5db199SXin Li db.reconnect_enabled = False 117*9c5db199SXin Li self._fake_backend.disconnect.expect_call() 118*9c5db199SXin Li self._expect_fail_and_reconnect(0) 119*9c5db199SXin Li self.assertRaises(FakeDatabaseError, db.connect) 120*9c5db199SXin Li self.god.check_playback() 121*9c5db199SXin Li 122*9c5db199SXin Li 123*9c5db199SXin Li def test_max_reconnect(self): 124*9c5db199SXin Li db = self._get_database_connection() 125*9c5db199SXin Li db.max_reconnect_attempts = 5 126*9c5db199SXin Li self._expect_fail_and_reconnect(5, fail_last=True) 127*9c5db199SXin Li 128*9c5db199SXin Li self.assertRaises(FakeDatabaseError, db.connect) 129*9c5db199SXin Li self.god.check_playback() 130*9c5db199SXin Li 131*9c5db199SXin Li 132*9c5db199SXin Li def test_reconnect_forever(self): 133*9c5db199SXin Li db = self._get_database_connection() 134*9c5db199SXin Li db.max_reconnect_attempts = database_connection.RECONNECT_FOREVER 135*9c5db199SXin Li self._expect_fail_and_reconnect(30) 136*9c5db199SXin Li 137*9c5db199SXin Li db.connect() 138*9c5db199SXin Li self.god.check_playback() 139*9c5db199SXin Li 140*9c5db199SXin Li 141*9c5db199SXin Li def _simple_connect(self, db): 142*9c5db199SXin Li self._fake_backend.connect.expect_call(**_CONNECT_KWARGS) 143*9c5db199SXin Li db.connect() 144*9c5db199SXin Li self.god.check_playback() 145*9c5db199SXin Li 146*9c5db199SXin Li 147*9c5db199SXin Li def test_disconnect(self): 148*9c5db199SXin Li db = self._get_database_connection() 149*9c5db199SXin Li self._simple_connect(db) 150*9c5db199SXin Li self._fake_backend.disconnect.expect_call() 151*9c5db199SXin Li 152*9c5db199SXin Li db.disconnect() 153*9c5db199SXin Li self.god.check_playback() 154*9c5db199SXin Li 155*9c5db199SXin Li 156*9c5db199SXin Li def test_execute(self): 157*9c5db199SXin Li db = self._get_database_connection() 158*9c5db199SXin Li self._simple_connect(db) 159*9c5db199SXin Li params = object() 160*9c5db199SXin Li self._fake_backend.execute.expect_call('query', params) 161*9c5db199SXin Li 162*9c5db199SXin Li db.execute('query', params) 163*9c5db199SXin Li self.god.check_playback() 164*9c5db199SXin Li 165*9c5db199SXin Li 166*9c5db199SXin Li def test_execute_retry(self): 167*9c5db199SXin Li db = self._get_database_connection() 168*9c5db199SXin Li self._simple_connect(db) 169*9c5db199SXin Li self._fake_backend.execute.expect_call('query', None).and_raises( 170*9c5db199SXin Li FakeDatabaseError()) 171*9c5db199SXin Li self._expect_reconnect() 172*9c5db199SXin Li self._fake_backend.execute.expect_call('query', None) 173*9c5db199SXin Li 174*9c5db199SXin Li db.execute('query') 175*9c5db199SXin Li self.god.check_playback() 176*9c5db199SXin Li 177*9c5db199SXin Li self._fake_backend.execute.expect_call('query', None).and_raises( 178*9c5db199SXin Li FakeDatabaseError()) 179*9c5db199SXin Li self.assertRaises(FakeDatabaseError, db.execute, 'query', 180*9c5db199SXin Li try_reconnecting=False) 181*9c5db199SXin Li 182*9c5db199SXin Li 183*9c5db199SXin Liif __name__ == '__main__': 184*9c5db199SXin Li unittest.main() 185