#!/usr/bin/python # # Copyright (c) 2013 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import datetime, unittest import mox import common # This must come before the import of complete_failures in order to use the # in memory database. from autotest_lib.frontend import setup_django_readonly_environment from autotest_lib.frontend import setup_test_environment import complete_failures from autotest_lib.client.common_lib import mail from autotest_lib.frontend.tko import models from django import test GOOD_STATUS_IDX = 6 # See complte_failurs_functional_tests.py for why we need this. class MockDatetime(datetime.datetime): """Used to mock out parts of datetime.datetime.""" pass class EmailAboutTestFailureTests(mox.MoxTestBase): """ Tests that emails are sent about failed tests. """ def setUp(self): super(EmailAboutTestFailureTests, self).setUp() # We need to mock out the send function in all tests or else the # emails will be sent out during tests. self.mox.StubOutWithMock(mail, 'send') self._orig_too_long = complete_failures._DAYS_TO_BE_FAILING_TOO_LONG def tearDown(self): complete_failures._DAYS_TO_BE_FAILING_TOO_LONG = self._orig_too_long super(EmailAboutTestFailureTests, self).tearDown() def test_email_sent_about_all_failed_tests(self): """Test that the email report mentions all the failed_tests.""" complete_failures._DAYS_TO_BE_FAILING_TOO_LONG = 60 mail.send( 'chromeos-test-health@google.com', ['chromeos-lab-infrastructure@google.com'], [], 'Long Failing Tests', '1/1 tests have been failing for at least %d days.\n' 'They are the following:\n\ntest' % complete_failures._DAYS_TO_BE_FAILING_TOO_LONG) failures = ['test'] all_tests = set(failures) self.mox.ReplayAll() complete_failures.email_about_test_failure(failures, all_tests) def test_email_has_test_names_sorted_alphabetically(self): """Test that the email report has entries sorted alphabetically.""" complete_failures._DAYS_TO_BE_FAILING_TOO_LONG = 60 mail.send( 'chromeos-test-health@google.com', ['chromeos-lab-infrastructure@google.com'], [], 'Long Failing Tests', '2/2 tests have been failing for at least %d days.\n' 'They are the following:\n\ntest1\ntest2' % complete_failures._DAYS_TO_BE_FAILING_TOO_LONG) # We use an OrderedDict to gurantee that the elements would be out of # order if we did a simple traversal. failures = ['test2', 'test1'] all_tests = set(failures) self.mox.ReplayAll() complete_failures.email_about_test_failure(failures, all_tests) def test_email_count_of_total_number_of_tests(self): """Test that the email report displays total number of tests.""" complete_failures._DAYS_TO_BE_FAILING_TOO_LONG = 60 mail.send( 'chromeos-test-health@google.com', ['chromeos-lab-infrastructure@google.com'], [], 'Long Failing Tests', '1/2 tests have been failing for at least %d days.\n' 'They are the following:\n\ntest' % complete_failures._DAYS_TO_BE_FAILING_TOO_LONG) failures = ['test'] all_tests = set(failures) | {'not_failure'} self.mox.ReplayAll() complete_failures.email_about_test_failure(failures, all_tests) class IsValidTestNameTests(test.TestCase): """Tests the is_valid_test_name function.""" def test_returns_true_for_valid_test_name(self): """Test that a valid test name returns True.""" name = 'TestName.TestName' self.assertTrue(complete_failures.is_valid_test_name(name)) def test_returns_false_if_name_has_slash_in_it(self): """Test that a name with a slash in it returns False.""" name = 'path/to/test' self.assertFalse(complete_failures.is_valid_test_name(name)) def test_returns_false_for_try_new_image_entries(self): """Test that a name that starts with try_new_image returns False.""" name = 'try_new_image-blah' self.assertFalse(complete_failures.is_valid_test_name(name)) class PrepareLastPassesTests(test.TestCase): """Tests the prepare_last_passes function.""" def setUp(self): super(PrepareLastPassesTests, self).setUp() def tearDown(self): super(PrepareLastPassesTests, self).tearDown() def test_does_not_return_invalid_test_names(self): """Tests that tests with invalid test names are not returned.""" results = complete_failures.prepare_last_passes(['invalid_test/name']) self.assertEqual(results, {}) class GetRecentlyRanTestNamesTests(mox.MoxTestBase, test.TestCase): """Tests the get_recently_ran_test_names function.""" def setUp(self): super(GetRecentlyRanTestNamesTests, self).setUp() self.mox.StubOutWithMock(MockDatetime, 'today') self.datetime = datetime.datetime datetime.datetime = MockDatetime setup_test_environment.set_up() self._orig_cutoff = complete_failures._DAYS_NOT_RUNNING_CUTOFF def tearDown(self): datetime.datetime = self.datetime complete_failures._DAYS_NOT_RUNNING_CUTOFF = self._orig_cutoff setup_test_environment.tear_down() super(GetRecentlyRanTestNamesTests, self).tearDown() def test_return_all_recently_ran_tests(self): """Test that the function does as it says it does.""" job = models.Job(job_idx=1) kernel = models.Kernel(kernel_idx=1) machine = models.Machine(machine_idx=1) success_status = models.Status(status_idx=GOOD_STATUS_IDX) recent = models.Test(job=job, status=success_status, kernel=kernel, machine=machine, test='recent', started_time=self.datetime(2012, 1, 1)) recent.save() old = models.Test(job=job, status=success_status, kernel=kernel, machine=machine, test='old', started_time=self.datetime(2011, 1, 2)) old.save() datetime.datetime.today().AndReturn(self.datetime(2012, 1, 4)) complete_failures._DAYS_NOT_RUNNING_CUTOFF = 60 self.mox.ReplayAll() results = complete_failures.get_recently_ran_test_names() self.assertEqual(set(results), set(['recent'])) def test_returns_no_duplicate_names(self): """Test that each test name appears only once.""" job = models.Job(job_idx=1) kernel = models.Kernel(kernel_idx=1) machine = models.Machine(machine_idx=1) success_status = models.Status(status_idx=GOOD_STATUS_IDX) test = models.Test(job=job, status=success_status, kernel=kernel, machine=machine, test='test', started_time=self.datetime(2012, 1, 1)) test.save() duplicate = models.Test(job=job, status=success_status, kernel=kernel, machine=machine, test='test', started_time=self.datetime(2012, 1, 2)) duplicate.save() datetime.datetime.today().AndReturn(self.datetime(2012, 1, 3)) complete_failures._DAYS_NOT_RUNNING_CUTOFF = 60 self.mox.ReplayAll() results = complete_failures.get_recently_ran_test_names() self.assertEqual(len(results), 1) class GetTestsToAnalyzeTests(mox.MoxTestBase): """Tests the get_tests_to_analyze function.""" def test_returns_recent_test_names(self): """Test should return all the test names in the database.""" recent_tests = {'passing_test', 'failing_test'} last_passes = {'passing_test': datetime.datetime(2012, 1 ,1), 'old_passing_test': datetime.datetime(2011, 1, 1)} results = complete_failures.get_tests_to_analyze(recent_tests, last_passes) self.assertEqual(results, {'passing_test': datetime.datetime(2012, 1, 1), 'failing_test': datetime.datetime.min}) def test_returns_failing_tests_with_min_datetime(self): """Test that never-passed tests are paired with datetime.min.""" recent_tests = {'test'} last_passes = {} self.mox.ReplayAll() results = complete_failures.get_tests_to_analyze(recent_tests, last_passes) self.assertEqual(results, {'test': datetime.datetime.min}) class FilterOutGoodTestsTests(mox.MoxTestBase): """Tests the filter_our_good_tests function.""" def setUp(self): super(FilterOutGoodTestsTests, self).setUp() self.mox.StubOutWithMock(MockDatetime, 'today') self.datetime = datetime.datetime datetime.datetime = MockDatetime self._orig_too_long = complete_failures._DAYS_TO_BE_FAILING_TOO_LONG def tearDown(self): datetime.datetime = self.datetime complete_failures._DAYS_TO_BE_FAILING_TOO_LONG = self._orig_too_long super(FilterOutGoodTestsTests, self).tearDown() def test_remove_all_tests_that_have_passed_recently_enough(self): """Test that all recently passing tests are not returned.""" complete_failures._DAYS_TO_BE_FAILING_TOO_LONG = 10 datetime.datetime.today().AndReturn(self.datetime(2012, 1, 21)) self.mox.ReplayAll() result = complete_failures.filter_out_good_tests( {'test': self.datetime(2012, 1, 20)}) self.assertEqual(result, []) def test_keep_all_tests_that_have_not_passed_recently_enough(self): """Test that the tests that have not recently passed are returned.""" complete_failures._DAYS_TO_BE_FAILING_TOO_LONG = 10 datetime.datetime.today().AndReturn(self.datetime(2012, 1, 21)) self.mox.ReplayAll() result = complete_failures.filter_out_good_tests( {'test': self.datetime(2012, 1, 10)}) self.assertEqual(result, ['test']) if __name__ == '__main__': unittest.main()