xref: /aosp_15_r20/external/autotest/tko/site_parse_unittest.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1*9c5db199SXin Li# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2*9c5db199SXin Li# Use of this source code is governed by a BSD-style license that can be
3*9c5db199SXin Li# found in the LICENSE file.
4*9c5db199SXin Li#
5*9c5db199SXin Li
6*9c5db199SXin Li#pylint: disable-msg=C0111
7*9c5db199SXin Li
8*9c5db199SXin Liimport os
9*9c5db199SXin Liimport shutil
10*9c5db199SXin Liimport tempfile
11*9c5db199SXin Liimport unittest
12*9c5db199SXin Lifrom unittest.mock import patch
13*9c5db199SXin Lifrom six.moves import reload_module as reload
14*9c5db199SXin Li
15*9c5db199SXin Liimport common
16*9c5db199SXin Li
17*9c5db199SXin Lifrom django.conf import settings
18*9c5db199SXin Lifrom autotest_lib.client.common_lib import global_config
19*9c5db199SXin Lifrom autotest_lib.frontend import database_settings_helper
20*9c5db199SXin Lifrom autotest_lib.frontend import setup_django_environment
21*9c5db199SXin Lifrom autotest_lib.frontend import setup_test_environment
22*9c5db199SXin Lifrom autotest_lib.frontend.afe import frontend_test_utils
23*9c5db199SXin Lifrom autotest_lib.frontend.afe import models as django_afe_models
24*9c5db199SXin Lifrom autotest_lib.frontend.tko import models as django_tko_models
25*9c5db199SXin Lifrom autotest_lib.tko import db as tko_db
26*9c5db199SXin Lifrom autotest_lib.tko.site_parse import StackTrace
27*9c5db199SXin Li
28*9c5db199SXin Li# Have to import this after setup_django_environment and setup_test_environment.
29*9c5db199SXin Li# It creates a database connection, so the mocking has to be done first.
30*9c5db199SXin Lifrom django.db import connections
31*9c5db199SXin Li
32*9c5db199SXin Liclass stack_trace_test(unittest.TestCase):
33*9c5db199SXin Li
34*9c5db199SXin Li
35*9c5db199SXin Li    def setUp(self):
36*9c5db199SXin Li        setup_test_environment.set_up()
37*9c5db199SXin Li        self._fake_results = tempfile.mkdtemp()
38*9c5db199SXin Li        self._cros_src_dir = global_config.global_config.get_config_value(
39*9c5db199SXin Li            'CROS', 'source_tree', default=None)
40*9c5db199SXin Li
41*9c5db199SXin Li        if not self._cros_src_dir:
42*9c5db199SXin Li            self.fail('No ChromeOS source tree defined in global_config.ini')
43*9c5db199SXin Li
44*9c5db199SXin Li        self._stack_trace = StackTrace(
45*9c5db199SXin Li            self._fake_results, self._cros_src_dir)
46*9c5db199SXin Li
47*9c5db199SXin Li        self._cache_dir = os.path.join(
48*9c5db199SXin Li            self._cros_src_dir, 'chroot', self._stack_trace._CACHE_DIR)
49*9c5db199SXin Li
50*9c5db199SXin Li        # Ensure we don't obliterate a live cache directory by accident.
51*9c5db199SXin Li        if os.path.exists(self._cache_dir):
52*9c5db199SXin Li            self.fail(
53*9c5db199SXin Li                'Symbol cache directory already exists. Cowardly refusing to'
54*9c5db199SXin Li                ' run. Please remove this directory manually to continue.')
55*9c5db199SXin Li
56*9c5db199SXin Li
57*9c5db199SXin Li    def tearDown(self):
58*9c5db199SXin Li        setup_test_environment.tear_down()
59*9c5db199SXin Li        shutil.rmtree(self._fake_results)
60*9c5db199SXin Li        if os.path.exists(self._cache_dir):
61*9c5db199SXin Li            shutil.rmtree(self._cache_dir)
62*9c5db199SXin Li
63*9c5db199SXin Li
64*9c5db199SXin Li    def _setup_basic_cache(self,
65*9c5db199SXin Li                           job_name='x86-alex-r16-R16-1166.0.0-a1-b1118_bvt',
66*9c5db199SXin Li                           mkdir=True):
67*9c5db199SXin Li        # Ensure cache directory is present.
68*9c5db199SXin Li        self._stack_trace._get_cache_dir()
69*9c5db199SXin Li        board, rev, version = self._stack_trace._parse_job_name(job_name)
70*9c5db199SXin Li
71*9c5db199SXin Li        symbols_dir = os.path.join(
72*9c5db199SXin Li            self._cache_dir, '-'.join([board, rev, version]))
73*9c5db199SXin Li        if mkdir:
74*9c5db199SXin Li            os.mkdir(symbols_dir)
75*9c5db199SXin Li
76*9c5db199SXin Li        chroot_symbols_dir = os.sep + os.path.relpath(
77*9c5db199SXin Li            symbols_dir, self._stack_trace._chroot_dir)
78*9c5db199SXin Li
79*9c5db199SXin Li        return job_name, symbols_dir, chroot_symbols_dir
80*9c5db199SXin Li
81*9c5db199SXin Li
82*9c5db199SXin Li    def test_get_job_name(self):
83*9c5db199SXin Li        job_name = 'x86-alex-r16-R16-1166.0.0-a1-b1118_regression'
84*9c5db199SXin Li        with open(os.path.join(self._fake_results, 'keyval'), 'w') as f:
85*9c5db199SXin Li            f.write('label=%s' % job_name)
86*9c5db199SXin Li
87*9c5db199SXin Li        self.assertEqual(self._stack_trace._get_job_name(), job_name)
88*9c5db199SXin Li
89*9c5db199SXin Li
90*9c5db199SXin Li    def test_parse_3_tuple_job_name(self):
91*9c5db199SXin Li        job_name = 'x86-alex-r16-R16-1166.0.0-a1-b1118_regression'
92*9c5db199SXin Li        board, rev, version = self._stack_trace._parse_job_name(job_name)
93*9c5db199SXin Li        self.assertEqual(board, 'x86-alex')
94*9c5db199SXin Li        self.assertEqual(rev, 'r16')
95*9c5db199SXin Li        self.assertEqual(version, '1166.0.0')
96*9c5db199SXin Li
97*9c5db199SXin Li
98*9c5db199SXin Li    def test_parse_4_tuple_job_name(self):
99*9c5db199SXin Li        job_name = 'x86-mario-r15-0.15.1011.74-a1-b61_bvt'
100*9c5db199SXin Li        board, rev, version = self._stack_trace._parse_job_name(job_name)
101*9c5db199SXin Li        self.assertEqual(board, 'x86-mario')
102*9c5db199SXin Li        self.assertEqual(rev, 'r15')
103*9c5db199SXin Li        self.assertEqual(version, '0.15.1011.74')
104*9c5db199SXin Li
105*9c5db199SXin Li
106*9c5db199SXin Li    def test_parse_4_tuple_au_job_name(self):
107*9c5db199SXin Li        job_name = 'x86-alex-r15-0.15.1011.81_to_0.15.1011.82-a1-b69_mton_au'
108*9c5db199SXin Li        board, rev, version = self._stack_trace._parse_job_name(job_name)
109*9c5db199SXin Li        self.assertEqual(board, 'x86-alex')
110*9c5db199SXin Li        self.assertEqual(rev, 'r15')
111*9c5db199SXin Li        self.assertEqual(version, '0.15.1011.82')
112*9c5db199SXin Li
113*9c5db199SXin Li
114*9c5db199SXin Li    def test_parse_3_tuple_au_job_name(self):
115*9c5db199SXin Li        job_name = 'x86-alex-r16-1165.0.0_to_R16-1166.0.0-a1-b69_mton_au'
116*9c5db199SXin Li        board, rev, version = self._stack_trace._parse_job_name(job_name)
117*9c5db199SXin Li        self.assertEqual(board, 'x86-alex')
118*9c5db199SXin Li        self.assertEqual(rev, 'r16')
119*9c5db199SXin Li        self.assertEqual(version, '1166.0.0')
120*9c5db199SXin Li
121*9c5db199SXin Li
122*9c5db199SXin Liclass database_selection_test(unittest.TestCase,
123*9c5db199SXin Li                              frontend_test_utils.FrontendTestMixin):
124*9c5db199SXin Li
125*9c5db199SXin Li    def setUp(self):
126*9c5db199SXin Li        super(database_selection_test, self).setUp()
127*9c5db199SXin Li        self._frontend_common_setup(fill_data=False)
128*9c5db199SXin Li
129*9c5db199SXin Li
130*9c5db199SXin Li    def tearDown(self):
131*9c5db199SXin Li        super(database_selection_test, self).tearDown()
132*9c5db199SXin Li        self._frontend_common_teardown()
133*9c5db199SXin Li        global_config.global_config.reset_config_values()
134*9c5db199SXin Li
135*9c5db199SXin Li
136*9c5db199SXin Li    def assertQueries(self, database, assert_in, assert_not_in):
137*9c5db199SXin Li        assert_in_found = False
138*9c5db199SXin Li        for query in connections[database].queries:
139*9c5db199SXin Li            sql = query['sql']
140*9c5db199SXin Li            # Ignore CREATE TABLE statements as they are always executed
141*9c5db199SXin Li            if 'INSERT INTO' in sql or 'SELECT' in sql:
142*9c5db199SXin Li                self.assertNotIn(assert_not_in, sql)
143*9c5db199SXin Li                if assert_in in sql:
144*9c5db199SXin Li                    assert_in_found = True
145*9c5db199SXin Li        self.assertTrue(assert_in_found)
146*9c5db199SXin Li
147*9c5db199SXin Li
148*9c5db199SXin Li    def testDjangoModels(self):
149*9c5db199SXin Li        # If DEBUG=False connection.query will be empty
150*9c5db199SXin Li        settings.DEBUG = True
151*9c5db199SXin Li
152*9c5db199SXin Li        afe_job = django_afe_models.Job.objects.create(created_on='2014-08-12')
153*9c5db199SXin Li        # Machine has less dependencies than tko Job so it's easier to create
154*9c5db199SXin Li        tko_job = django_tko_models.Machine.objects.create()
155*9c5db199SXin Li
156*9c5db199SXin Li        django_afe_models.Job.objects.get(pk=afe_job.id)
157*9c5db199SXin Li        django_tko_models.Machine.objects.get(pk=tko_job.pk)
158*9c5db199SXin Li
159*9c5db199SXin Li        self.assertQueries('global', 'tko_machines', 'afe_jobs')
160*9c5db199SXin Li        self.assertQueries('default', 'afe_jobs', 'tko_machines')
161*9c5db199SXin Li
162*9c5db199SXin Li        # Avoid unnecessary debug output from other tests
163*9c5db199SXin Li        settings.DEBUG = True
164*9c5db199SXin Li
165*9c5db199SXin Li
166*9c5db199SXin Li    def testRunOnShardWithoutGlobalConfigsFails(self):
167*9c5db199SXin Li        global_config.global_config.override_config_value(
168*9c5db199SXin Li                'SHARD', 'shard_hostname', 'host1')
169*9c5db199SXin Li        from autotest_lib.frontend import settings
170*9c5db199SXin Li        # settings module was already loaded during the imports of this file,
171*9c5db199SXin Li        # so before the configuration setting was made, therefore reload it:
172*9c5db199SXin Li        reload(database_settings_helper)
173*9c5db199SXin Li        self.assertRaises(global_config.ConfigError,
174*9c5db199SXin Li                          reload, settings)
175*9c5db199SXin Li
176*9c5db199SXin Li
177*9c5db199SXin Li    def testRunOnMainWithoutGlobalConfigsWorks(self):
178*9c5db199SXin Li        global_config.global_config.override_config_value(
179*9c5db199SXin Li                'SHARD', 'shard_hostname', '')
180*9c5db199SXin Li        from autotest_lib.frontend import settings
181*9c5db199SXin Li        # settings module was already loaded during the imports of this file,
182*9c5db199SXin Li        # so before the configuration setting was made, therefore reload it:
183*9c5db199SXin Li        reload(database_settings_helper)
184*9c5db199SXin Li        reload(settings)
185*9c5db199SXin Li
186*9c5db199SXin Li
187*9c5db199SXin Li    def testTkoDatabase(self):
188*9c5db199SXin Li        global_host = 'GLOBAL_HOST'
189*9c5db199SXin Li        global_user = 'GLOBAL_USER'
190*9c5db199SXin Li        global_db = 'GLOBAL_DB'
191*9c5db199SXin Li        global_pw = 'GLOBAL_PW'
192*9c5db199SXin Li        global_port = ''
193*9c5db199SXin Li        local_host = 'LOCAL_HOST'
194*9c5db199SXin Li
195*9c5db199SXin Li        global_config.global_config.override_config_value(
196*9c5db199SXin Li                'AUTOTEST_WEB', 'global_db_type', '')
197*9c5db199SXin Li
198*9c5db199SXin Li        global_config.global_config.override_config_value(
199*9c5db199SXin Li                'AUTOTEST_WEB', 'global_db_host', global_host)
200*9c5db199SXin Li        global_config.global_config.override_config_value(
201*9c5db199SXin Li                'AUTOTEST_WEB', 'global_db_database', global_db)
202*9c5db199SXin Li        global_config.global_config.override_config_value(
203*9c5db199SXin Li                'AUTOTEST_WEB', 'global_db_user', global_user)
204*9c5db199SXin Li        global_config.global_config.override_config_value(
205*9c5db199SXin Li                'AUTOTEST_WEB', 'global_db_password', global_pw)
206*9c5db199SXin Li        global_config.global_config.override_config_value(
207*9c5db199SXin Li                'AUTOTEST_WEB', 'host', local_host)
208*9c5db199SXin Li
209*9c5db199SXin Li        class ConnectCalledException(Exception):
210*9c5db199SXin Li            pass
211*9c5db199SXin Li
212*9c5db199SXin Li        # We're only interested in the parameters connect is called with here.
213*9c5db199SXin Li        # Take the fast path out so we don't have to mock all the other calls
214*9c5db199SXin Li        # that will later be made on the connection
215*9c5db199SXin Li        def fake_connect(*args, **kwargs):
216*9c5db199SXin Li            raise ConnectCalledException
217*9c5db199SXin Li
218*9c5db199SXin Li        tko_db.db_sql.connect = None
219*9c5db199SXin Li        patcher = patch.object(tko_db.db_sql, 'connect')
220*9c5db199SXin Li        mock = patcher.start()
221*9c5db199SXin Li        self.addCleanup(patcher.stop)
222*9c5db199SXin Li
223*9c5db199SXin Li        mock.side_effect = fake_connect
224*9c5db199SXin Li        self.assertRaises(ConnectCalledException, tko_db.db_sql)
225*9c5db199SXin Li
226*9c5db199SXin Li        mock.assert_called_with(global_host, global_db, global_user, global_pw,
227*9c5db199SXin Li                                global_port)
228*9c5db199SXin Li
229*9c5db199SXin Li
230*9c5db199SXin Liif __name__ == "__main__":
231*9c5db199SXin Li    unittest.main()
232