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