blob: b49e0d830642936d12cf5df70b90d0c89368aa48 [file] [log] [blame]
Keyar Hood1a3c8dd2013-05-29 17:41:50 -07001#!/usr/bin/python
2#
3# Copyright (c) 2013 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
Keyar Hood708f1fb2013-08-12 14:32:39 -07007import datetime, unittest
Keyar Hood1a3c8dd2013-05-29 17:41:50 -07008
9import mox
10
Keyar Hood788e4982013-06-18 14:34:28 -070011import common
12# This must come before the import of complete_failures in order to use the
13# in memory database.
14from autotest_lib.frontend import setup_django_readonly_environment
15from autotest_lib.frontend import setup_test_environment
16import complete_failures
Keyar Hood1a3c8dd2013-05-29 17:41:50 -070017from autotest_lib.client.common_lib import mail
Keyar Hood788e4982013-06-18 14:34:28 -070018from autotest_lib.frontend.tko import models
19from django import test
Keyar Hood1a3c8dd2013-05-29 17:41:50 -070020
21
Keyar Hood788e4982013-06-18 14:34:28 -070022GOOD_STATUS_IDX = 6
Keyar Hood788e4982013-06-18 14:34:28 -070023
Keyar Hoode7b11842013-06-25 15:41:59 -070024# See complte_failurs_functional_tests.py for why we need this.
25class MockDatetime(datetime.datetime):
26 """Used to mock out parts of datetime.datetime."""
27 pass
28
29
Keyar Hood1a3c8dd2013-05-29 17:41:50 -070030class EmailAboutTestFailureTests(mox.MoxTestBase):
31 """
Keyar Hood3d807682013-07-01 15:13:05 -070032 Tests that emails are sent about failed tests.
Keyar Hood1a3c8dd2013-05-29 17:41:50 -070033 """
34 def setUp(self):
35 super(EmailAboutTestFailureTests, self).setUp()
36
37 # We need to mock out the send function in all tests or else the
38 # emails will be sent out during tests.
39 self.mox.StubOutWithMock(mail, 'send')
40
Keyar Hoode7b11842013-06-25 15:41:59 -070041 self._orig_too_long = complete_failures._DAYS_TO_BE_FAILING_TOO_LONG
Keyar Hood1a3c8dd2013-05-29 17:41:50 -070042
43
44 def tearDown(self):
Keyar Hoode7b11842013-06-25 15:41:59 -070045 complete_failures._DAYS_TO_BE_FAILING_TOO_LONG = self._orig_too_long
Keyar Hood788e4982013-06-18 14:34:28 -070046 super(EmailAboutTestFailureTests, self).tearDown()
Keyar Hood1a3c8dd2013-05-29 17:41:50 -070047
48
Keyar Hood708f1fb2013-08-12 14:32:39 -070049 def test_email_sent_about_all_failed_tests(self):
50 """Test that the email report mentions all the failed_tests."""
Keyar Hood1a3c8dd2013-05-29 17:41:50 -070051 complete_failures._DAYS_TO_BE_FAILING_TOO_LONG = 60
52
53 mail.send(
54 'chromeos-test-health@google.com',
55 ['chromeos-lab-infrastructure@google.com'],
56 [],
57 'Long Failing Tests',
Keyar Hooda3564712013-07-29 17:15:50 -070058 '1/1 tests have been failing for at least %d days.\n'
59 'They are the following:\n\ntest'
Keyar Hood1a3c8dd2013-05-29 17:41:50 -070060 % complete_failures._DAYS_TO_BE_FAILING_TOO_LONG)
61
Keyar Hood708f1fb2013-08-12 14:32:39 -070062 failures = ['test']
63 all_tests = set(failures)
Keyar Hood1a3c8dd2013-05-29 17:41:50 -070064
Keyar Hood1a3c8dd2013-05-29 17:41:50 -070065 self.mox.ReplayAll()
Keyar Hood708f1fb2013-08-12 14:32:39 -070066 complete_failures.email_about_test_failure(failures, all_tests)
Keyar Hooda3564712013-07-29 17:15:50 -070067
68
69 def test_email_has_test_names_sorted_alphabetically(self):
70 """Test that the email report has entries sorted alphabetically."""
71 complete_failures._DAYS_TO_BE_FAILING_TOO_LONG = 60
72
73 mail.send(
74 'chromeos-test-health@google.com',
75 ['chromeos-lab-infrastructure@google.com'],
76 [],
77 'Long Failing Tests',
78 '2/2 tests have been failing for at least %d days.\n'
79 'They are the following:\n\ntest1\ntest2'
80 % complete_failures._DAYS_TO_BE_FAILING_TOO_LONG)
81
82 # We use an OrderedDict to gurantee that the elements would be out of
83 # order if we did a simple traversal.
Keyar Hood708f1fb2013-08-12 14:32:39 -070084 failures = ['test2', 'test1']
85 all_tests = set(failures)
Keyar Hooda3564712013-07-29 17:15:50 -070086
Keyar Hooda3564712013-07-29 17:15:50 -070087 self.mox.ReplayAll()
Keyar Hood708f1fb2013-08-12 14:32:39 -070088 complete_failures.email_about_test_failure(failures, all_tests)
Keyar Hooda3564712013-07-29 17:15:50 -070089
90
91 def test_email_count_of_total_number_of_tests(self):
92 """Test that the email report displays total number of tests."""
93 complete_failures._DAYS_TO_BE_FAILING_TOO_LONG = 60
94
95 mail.send(
96 'chromeos-test-health@google.com',
97 ['chromeos-lab-infrastructure@google.com'],
98 [],
99 'Long Failing Tests',
100 '1/2 tests have been failing for at least %d days.\n'
101 'They are the following:\n\ntest'
102 % complete_failures._DAYS_TO_BE_FAILING_TOO_LONG)
103
Keyar Hood708f1fb2013-08-12 14:32:39 -0700104 failures = ['test']
105 all_tests = set(failures) | {'not_failure'}
Keyar Hooda3564712013-07-29 17:15:50 -0700106
Keyar Hooda3564712013-07-29 17:15:50 -0700107 self.mox.ReplayAll()
Keyar Hood708f1fb2013-08-12 14:32:39 -0700108 complete_failures.email_about_test_failure(failures, all_tests)
Keyar Hood788e4982013-06-18 14:34:28 -0700109
110
Keyar Hood005539d2013-06-24 14:27:57 -0700111class IsValidTestNameTests(test.TestCase):
112 """Tests the is_valid_test_name function."""
113
114 def test_returns_true_for_valid_test_name(self):
115 """Test that a valid test name returns True."""
116 name = 'TestName.TestName'
117 self.assertTrue(complete_failures.is_valid_test_name(name))
118
119
120 def test_returns_false_if_name_has_slash_in_it(self):
121 """Test that a name with a slash in it returns False."""
122 name = 'path/to/test'
123 self.assertFalse(complete_failures.is_valid_test_name(name))
124
125
126 def test_returns_false_for_try_new_image_entries(self):
127 """Test that a name that starts with try_new_image returns False."""
128 name = 'try_new_image-blah'
129 self.assertFalse(complete_failures.is_valid_test_name(name))
130
131
Keyar Hood0f26dba2013-07-18 17:49:32 -0700132class PrepareLastPassesTests(test.TestCase):
133 """Tests the prepare_last_passes function."""
Keyar Hood788e4982013-06-18 14:34:28 -0700134
135 def setUp(self):
Keyar Hood0f26dba2013-07-18 17:49:32 -0700136 super(PrepareLastPassesTests, self).setUp()
Keyar Hood788e4982013-06-18 14:34:28 -0700137
138 def tearDown(self):
Keyar Hood0f26dba2013-07-18 17:49:32 -0700139 super(PrepareLastPassesTests, self).tearDown()
Keyar Hood788e4982013-06-18 14:34:28 -0700140
Keyar Hood005539d2013-06-24 14:27:57 -0700141 def test_does_not_return_invalid_test_names(self):
142 """Tests that tests with invalid test names are not returned."""
Keyar Hood0f26dba2013-07-18 17:49:32 -0700143 results = complete_failures.prepare_last_passes(['invalid_test/name'])
Keyar Hood005539d2013-06-24 14:27:57 -0700144
Keyar Hood0f26dba2013-07-18 17:49:32 -0700145 self.assertEqual(results, {})
Keyar Hood005539d2013-06-24 14:27:57 -0700146
Keyar Hood005539d2013-06-24 14:27:57 -0700147
Keyar Hoode7b11842013-06-25 15:41:59 -0700148class GetRecentlyRanTestNamesTests(mox.MoxTestBase, test.TestCase):
149 """Tests the get_recently_ran_test_names function."""
Keyar Hood788e4982013-06-18 14:34:28 -0700150
151 def setUp(self):
Keyar Hoode7b11842013-06-25 15:41:59 -0700152 super(GetRecentlyRanTestNamesTests, self).setUp()
153 self.mox.StubOutWithMock(MockDatetime, 'today')
154 self.datetime = datetime.datetime
155 datetime.datetime = MockDatetime
Keyar Hood788e4982013-06-18 14:34:28 -0700156 setup_test_environment.set_up()
Keyar Hoode7b11842013-06-25 15:41:59 -0700157 self._orig_cutoff = complete_failures._DAYS_NOT_RUNNING_CUTOFF
Keyar Hood788e4982013-06-18 14:34:28 -0700158
159
160 def tearDown(self):
Keyar Hoode7b11842013-06-25 15:41:59 -0700161 datetime.datetime = self.datetime
162 complete_failures._DAYS_NOT_RUNNING_CUTOFF = self._orig_cutoff
Keyar Hood788e4982013-06-18 14:34:28 -0700163 setup_test_environment.tear_down()
Keyar Hoode7b11842013-06-25 15:41:59 -0700164 super(GetRecentlyRanTestNamesTests, self).tearDown()
Keyar Hood788e4982013-06-18 14:34:28 -0700165
166
Keyar Hoode7b11842013-06-25 15:41:59 -0700167 def test_return_all_recently_ran_tests(self):
Keyar Hood788e4982013-06-18 14:34:28 -0700168 """Test that the function does as it says it does."""
Keyar Hood005539d2013-06-24 14:27:57 -0700169 job = models.Job(job_idx=1)
170 kernel = models.Kernel(kernel_idx=1)
171 machine = models.Machine(machine_idx=1)
172 success_status = models.Status(status_idx=GOOD_STATUS_IDX)
Keyar Hood788e4982013-06-18 14:34:28 -0700173
Keyar Hoode7b11842013-06-25 15:41:59 -0700174 recent = models.Test(job=job, status=success_status,
175 kernel=kernel, machine=machine,
176 test='recent',
177 started_time=self.datetime(2012, 1, 1))
178 recent.save()
179 old = models.Test(job=job, status=success_status,
180 kernel=kernel, machine=machine,
181 test='old',
182 started_time=self.datetime(2011, 1, 2))
183 old.save()
Keyar Hood788e4982013-06-18 14:34:28 -0700184
Keyar Hoode7b11842013-06-25 15:41:59 -0700185 datetime.datetime.today().AndReturn(self.datetime(2012, 1, 4))
186 complete_failures._DAYS_NOT_RUNNING_CUTOFF = 60
Keyar Hood788e4982013-06-18 14:34:28 -0700187
Keyar Hoode7b11842013-06-25 15:41:59 -0700188 self.mox.ReplayAll()
189 results = complete_failures.get_recently_ran_test_names()
190
191 self.assertEqual(set(results), set(['recent']))
Keyar Hood788e4982013-06-18 14:34:28 -0700192
193
194 def test_returns_no_duplicate_names(self):
195 """Test that each test name appears only once."""
Keyar Hood005539d2013-06-24 14:27:57 -0700196 job = models.Job(job_idx=1)
197 kernel = models.Kernel(kernel_idx=1)
198 machine = models.Machine(machine_idx=1)
199 success_status = models.Status(status_idx=GOOD_STATUS_IDX)
Keyar Hood788e4982013-06-18 14:34:28 -0700200
Keyar Hood005539d2013-06-24 14:27:57 -0700201 test = models.Test(job=job, status=success_status,
202 kernel=kernel, machine=machine,
203 test='test',
Keyar Hoode7b11842013-06-25 15:41:59 -0700204 started_time=self.datetime(2012, 1, 1))
Keyar Hood788e4982013-06-18 14:34:28 -0700205 test.save()
Keyar Hood005539d2013-06-24 14:27:57 -0700206 duplicate = models.Test(job=job, status=success_status,
207 kernel=kernel, machine=machine,
208 test='test',
Keyar Hoode7b11842013-06-25 15:41:59 -0700209 started_time=self.datetime(2012, 1, 2))
Keyar Hood788e4982013-06-18 14:34:28 -0700210 duplicate.save()
211
Keyar Hoode7b11842013-06-25 15:41:59 -0700212 datetime.datetime.today().AndReturn(self.datetime(2012, 1, 3))
213 complete_failures._DAYS_NOT_RUNNING_CUTOFF = 60
214
215 self.mox.ReplayAll()
216 results = complete_failures.get_recently_ran_test_names()
Keyar Hood788e4982013-06-18 14:34:28 -0700217
218 self.assertEqual(len(results), 1)
219
220
221class GetTestsToAnalyzeTests(mox.MoxTestBase):
222 """Tests the get_tests_to_analyze function."""
223
Keyar Hoode7b11842013-06-25 15:41:59 -0700224 def test_returns_recent_test_names(self):
Keyar Hood788e4982013-06-18 14:34:28 -0700225 """Test should return all the test names in the database."""
Keyar Hood788e4982013-06-18 14:34:28 -0700226
Keyar Hooda3564712013-07-29 17:15:50 -0700227 recent_tests = {'passing_test', 'failing_test'}
228 last_passes = {'passing_test': datetime.datetime(2012, 1 ,1),
229 'old_passing_test': datetime.datetime(2011, 1, 1)}
230
231 results = complete_failures.get_tests_to_analyze(recent_tests,
232 last_passes)
Keyar Hood788e4982013-06-18 14:34:28 -0700233
Keyar Hoode7b11842013-06-25 15:41:59 -0700234 self.assertEqual(results,
235 {'passing_test': datetime.datetime(2012, 1, 1),
236 'failing_test': datetime.datetime.min})
Keyar Hood788e4982013-06-18 14:34:28 -0700237
238
239 def test_returns_failing_tests_with_min_datetime(self):
240 """Test that never-passed tests are paired with datetime.min."""
Keyar Hood788e4982013-06-18 14:34:28 -0700241
Keyar Hooda3564712013-07-29 17:15:50 -0700242 recent_tests = {'test'}
243 last_passes = {}
Keyar Hood788e4982013-06-18 14:34:28 -0700244
245 self.mox.ReplayAll()
Keyar Hooda3564712013-07-29 17:15:50 -0700246 results = complete_failures.get_tests_to_analyze(recent_tests,
247 last_passes)
Keyar Hood788e4982013-06-18 14:34:28 -0700248
249 self.assertEqual(results, {'test': datetime.datetime.min})
Keyar Hood1a3c8dd2013-05-29 17:41:50 -0700250
251
Keyar Hood708f1fb2013-08-12 14:32:39 -0700252class FilterOutGoodTestsTests(mox.MoxTestBase):
253 """Tests the filter_our_good_tests function."""
254
255 def setUp(self):
256 super(FilterOutGoodTestsTests, self).setUp()
257 self.mox.StubOutWithMock(MockDatetime, 'today')
258 self.datetime = datetime.datetime
259 datetime.datetime = MockDatetime
260 self._orig_too_long = complete_failures._DAYS_TO_BE_FAILING_TOO_LONG
261
262
263 def tearDown(self):
264 datetime.datetime = self.datetime
265 complete_failures._DAYS_TO_BE_FAILING_TOO_LONG = self._orig_too_long
266 super(FilterOutGoodTestsTests, self).tearDown()
267
268
269 def test_remove_all_tests_that_have_passed_recently_enough(self):
270 """Test that all recently passing tests are not returned."""
271
272 complete_failures._DAYS_TO_BE_FAILING_TOO_LONG = 10
273 datetime.datetime.today().AndReturn(self.datetime(2012, 1, 21))
274
275 self.mox.ReplayAll()
276 result = complete_failures.filter_out_good_tests(
277 {'test': self.datetime(2012, 1, 20)})
278
279 self.assertEqual(result, [])
280
281
282 def test_keep_all_tests_that_have_not_passed_recently_enough(self):
283 """Test that the tests that have not recently passed are returned."""
284
285 complete_failures._DAYS_TO_BE_FAILING_TOO_LONG = 10
286 datetime.datetime.today().AndReturn(self.datetime(2012, 1, 21))
287
288 self.mox.ReplayAll()
289 result = complete_failures.filter_out_good_tests(
290 {'test': self.datetime(2012, 1, 10)})
291
292 self.assertEqual(result, ['test'])
293
294
Keyar Hood1a3c8dd2013-05-29 17:41:50 -0700295if __name__ == '__main__':
296 unittest.main()