xref: /aosp_15_r20/external/autotest/database/database_connection_unittest.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
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