Keyar Hood | 1a3c8dd | 2013-05-29 17:41:50 -0700 | [diff] [blame^] | 1 | #!/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 | |
| 7 | import datetime, unittest |
| 8 | |
| 9 | import mox |
| 10 | |
| 11 | import common, complete_failures |
| 12 | from autotest_lib.client.common_lib import mail |
| 13 | |
| 14 | |
| 15 | class EmailAboutTestFailureTests(mox.MoxTestBase): |
| 16 | """ |
| 17 | Test the core logic of the comlete_failures.py script. |
| 18 | |
| 19 | The core logic is to send emails only if we have not yet done so for a |
| 20 | given test before and to take actions if the test has been failing for |
| 21 | long enough. |
| 22 | |
| 23 | """ |
| 24 | def setUp(self): |
| 25 | super(EmailAboutTestFailureTests, self).setUp() |
| 26 | |
| 27 | # We need to mock out the send function in all tests or else the |
| 28 | # emails will be sent out during tests. |
| 29 | self.mox.StubOutWithMock(mail, 'send') |
| 30 | |
| 31 | self._orignal_too_late = complete_failures._DAYS_TO_BE_FAILING_TOO_LONG |
| 32 | |
| 33 | |
| 34 | def tearDown(self): |
| 35 | complete_failures._DAYS_TO_BE_FAILING_TOO_LONG = self._orignal_too_late |
| 36 | |
| 37 | |
| 38 | def test_deal_with_new_failing_test(self): |
| 39 | """ |
| 40 | Test adding a failing test to the storage. |
| 41 | |
| 42 | We expect the email sending code to be called if it is added. |
| 43 | |
| 44 | """ |
| 45 | # We will want to keep all the datetime logic intact and so we need to |
| 46 | # keep a reference to the unmocked datetime. |
| 47 | self.datetime = datetime.datetime |
| 48 | self.mox.StubOutWithMock(datetime, 'datetime') |
| 49 | datetime.datetime.today().AndReturn(self.datetime(2012, 1, 1)) |
| 50 | complete_failures._DAYS_TO_BE_FAILING_TOO_LONG = 60 |
| 51 | |
| 52 | mail.send( |
| 53 | 'chromeos-test-health@google.com', |
| 54 | ['chromeos-lab-infrastructure@google.com'], |
| 55 | [], |
| 56 | 'Long Failing Tests', |
| 57 | 'The following tests have been failing for at ' |
| 58 | 'least %i days:\n\ntest' |
| 59 | % complete_failures._DAYS_TO_BE_FAILING_TOO_LONG) |
| 60 | |
| 61 | storage = {} |
| 62 | |
| 63 | # The ReplayAll is required or else a mox object sneaks its way into |
| 64 | # the storage object somehow. |
| 65 | self.mox.ReplayAll() |
| 66 | complete_failures.email_about_test_failure( |
| 67 | {'test': datetime.datetime.min}, storage) |
| 68 | |
| 69 | self.assertEqual(storage['test'], self.datetime(2012, 1, 1)) |
| 70 | self.mox.VerifyAll() |
| 71 | |
| 72 | |
| 73 | def test_remove_test_if_it_has_succeeded_recently_enough(self): |
| 74 | """Test that we remove a passing test from the storage object.""" |
| 75 | storage = {'test': datetime.datetime(2012, 1, 1)} |
| 76 | complete_failures._DAYS_TO_BE_FAILING_TOO_LONG = 60 |
| 77 | today = datetime.datetime(2012, 4, 10) |
| 78 | safe_date = datetime.datetime(2012, 4, 9) |
| 79 | |
| 80 | self.mox.StubOutWithMock(datetime, 'datetime') |
| 81 | datetime.datetime.today().AndReturn(today) |
| 82 | |
| 83 | self.mox.ReplayAll() |
| 84 | complete_failures.email_about_test_failure({'test': safe_date}, storage) |
| 85 | |
| 86 | self.assertTrue('test' not in storage) |
| 87 | self.mox.VerifyAll() |
| 88 | |
| 89 | |
| 90 | def test_no_crashing_on_test_that_has_never_failed_for_too_long(self): |
| 91 | """Test that we do not crash for tests that have always passed.""" |
| 92 | storage = {} |
| 93 | complete_failures._DAYS_TO_BE_FAILING_TOO_LONG = 60 |
| 94 | today = datetime.datetime(2012,4,10) |
| 95 | safe_date = datetime.datetime(2012,4,9) |
| 96 | |
| 97 | self.mox.StubOutWithMock(datetime, 'datetime') |
| 98 | datetime.datetime.today().AndReturn(today) |
| 99 | |
| 100 | self.mox.ReplayAll() |
| 101 | complete_failures.email_about_test_failure({'test': safe_date}, storage) |
| 102 | |
| 103 | self.assertTrue('test' not in storage) |
| 104 | self.mox.VerifyAll() |
| 105 | |
| 106 | |
| 107 | def test_do_not_send_email_if_test_already_in_storage(self): |
| 108 | """Test only send emails on newly problematic tests.""" |
| 109 | storage = {'test': datetime.datetime(2012, 1, 1)} |
| 110 | self.datetime = datetime.datetime |
| 111 | self.mox.StubOutWithMock(datetime, 'datetime') |
| 112 | datetime.datetime.today().AndReturn(self.datetime(2012, 1, 1)) |
| 113 | |
| 114 | self.mox.ReplayAll() |
| 115 | complete_failures.email_about_test_failure( |
| 116 | {'test': datetime.datetime.min}, storage) |
| 117 | |
| 118 | self.mox.VerifyAll() |
| 119 | |
| 120 | |
| 121 | def test_do_not_delete_if_still_failing(self): |
| 122 | """Test that an old failing test is not removed from storage.""" |
| 123 | # We will want to keep all the datetime logic intact and so we need to |
| 124 | # keep a reference to the unmocked datetime. |
| 125 | self.datetime = datetime.datetime |
| 126 | today = datetime.datetime(2012, 1, 1) |
| 127 | self.mox.StubOutWithMock(datetime, 'datetime') |
| 128 | datetime.datetime.today().AndReturn(today) |
| 129 | |
| 130 | storage = {'test': datetime.datetime.min} |
| 131 | |
| 132 | # The ReplayAll is required or else a mox object sneaks its way into |
| 133 | # the storage object somehow. |
| 134 | self.mox.ReplayAll() |
| 135 | complete_failures.email_about_test_failure( |
| 136 | {'test': datetime.datetime.min}, storage) |
| 137 | |
| 138 | self.assertTrue('test' in storage) |
| 139 | self.mox.VerifyAll() |
| 140 | |
| 141 | |
| 142 | if __name__ == '__main__': |
| 143 | unittest.main() |