timed_event_unittest.py revision e8bebaf10711ca802d40c0b7f412e3910999159e
1fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone#!/usr/bin/python
2fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone#
3fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
4fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone# Use of this source code is governed by a BSD-style license that can be
5fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone# found in the LICENSE file.
6fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
72d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone"""Unit tests for site_utils/timed_event.py."""
8fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
993f51d4da152538007d5b44a2dc9d2bbb1fe3429Chris Masoneimport datetime, logging, mox, unittest
10fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
1193f51d4da152538007d5b44a2dc9d2bbb1fe3429Chris Masoneimport base_event, deduping_scheduler, forgiving_config_parser
1293f51d4da152538007d5b44a2dc9d2bbb1fe3429Chris Masoneimport manifest_versions, task, timed_event
13fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
14fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
15013859b492bf4f5b304e31be3300789443eee33eChris Masoneclass TimedEventTestBase(mox.MoxTestBase):
16013859b492bf4f5b304e31be3300789443eee33eChris Masone    """Base class for TimedEvent unit test classes."""
17fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
18fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
19fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def setUp(self):
20013859b492bf4f5b304e31be3300789443eee33eChris Masone        super(TimedEventTestBase, self).setUp()
212d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        self.mox.StubOutWithMock(timed_event.TimedEvent, '_now')
225bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone        self.mv = self.mox.CreateMock(manifest_versions.ManifestVersions)
23fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
24fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
25fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def BaseTime(self):
26013859b492bf4f5b304e31be3300789443eee33eChris Masone        """Return the TimedEvent trigger-time as a datetime instance."""
27fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        raise NotImplementedError()
28fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
29fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
305bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone    def CreateEvent(self):
31013859b492bf4f5b304e31be3300789443eee33eChris Masone        """Return an instance of the TimedEvent subclass being tested."""
32fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        raise NotImplementedError()
33fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
34fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
35fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def TimeBefore(self, now):
36fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        """Return a datetime that's before |now|."""
37fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        raise NotImplementedError()
38fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
39fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
40fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def TimeLaterThan(self, now):
41fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        """Return a datetime that's later than |now|."""
42fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        raise NotImplementedError()
43fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
44fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
45fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def doTestDeadlineInFuture(self):
46fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        fake_now = self.TimeBefore(self.BaseTime())
472d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        timed_event.TimedEvent._now().MultipleTimes().AndReturn(fake_now)
48fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.mox.ReplayAll()
49fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
505bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone        t = self.CreateEvent()  # Deadline gets set for a future time.
512d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        self.assertFalse(t.ShouldHandle())
52fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.mox.VerifyAll()
53fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
54fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.mox.ResetAll()
55fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        fake_now = self.TimeLaterThan(fake_now)  # Jump past that future time.
562d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        timed_event.TimedEvent._now().MultipleTimes().AndReturn(fake_now)
57fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.mox.ReplayAll()
582d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        self.assertTrue(t.ShouldHandle())
59fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
60fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
61fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def doTestDeadlineIsNow(self):
62fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        """We happened to create the trigger at the exact right time."""
632d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        timed_event.TimedEvent._now().MultipleTimes().AndReturn(self.BaseTime())
64fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.mox.ReplayAll()
655bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone        to_test = self.CreateEvent()
662d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        self.assertTrue(to_test.ShouldHandle())
67fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
68fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
69fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def doTestTOCTOU(self):
70fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        """Even if deadline passes during initialization, trigger must fire."""
71fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        init_now = self.BaseTime() - datetime.timedelta(seconds=1)
72fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        fire_now = self.BaseTime() + datetime.timedelta(seconds=1)
732d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        timed_event.TimedEvent._now().AndReturn(init_now)
742d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        timed_event.TimedEvent._now().AndReturn(fire_now)
75fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.mox.ReplayAll()
76fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
775bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone        t = self.CreateEvent()  # Deadline gets set for later tonight...
78fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        # ...but has passed by the time we get around to firing.
792d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        self.assertTrue(t.ShouldHandle())
80fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
81fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
82e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone    def doTestDeadlineUpdate(self, days_to_jump):
83e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        fake_now = self.TimeBefore(self.BaseTime())
84e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        timed_event.TimedEvent._now().MultipleTimes().AndReturn(fake_now)
85e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        self.mox.ReplayAll()
86e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone
87e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        nightly = self.CreateEvent()  # Deadline gets set for tonight.
88e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        self.assertFalse(nightly.ShouldHandle())
89e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        self.mox.VerifyAll()
90e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone
91e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        self.mox.ResetAll()
92e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        fake_now = self.TimeLaterThan(self.BaseTime())  # Jump past deadline.
93e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        timed_event.TimedEvent._now().MultipleTimes().AndReturn(fake_now)
94e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        self.mox.ReplayAll()
95e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone
96e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        self.assertTrue(nightly.ShouldHandle())
97e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        nightly.UpdateCriteria()  # Deadline moves to tomorrow night
98e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        self.assertFalse(nightly.ShouldHandle())
99e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        self.mox.VerifyAll()
100e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone
101e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        self.mox.ResetAll()
102e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        fake_now += datetime.timedelta(days=days_to_jump)  # Jump past deadline.
103e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        timed_event.TimedEvent._now().MultipleTimes().AndReturn(fake_now)
104e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        self.mox.ReplayAll()
105e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        self.assertTrue(nightly.ShouldHandle())
106e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone
107e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone
1085bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone    def doTestGetBranchBuilds(self, days):
1095bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone        board = 'faux_board'
1105bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone        branch_manifests = {('factory','16'): ['last16'],
1115bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone                            ('release','17'): ['first17', 'last17']}
11293f51d4da152538007d5b44a2dc9d2bbb1fe3429Chris Masone        self.mv.ManifestsSinceDays(days, board).AndReturn(branch_manifests)
1135bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone        timed_event.TimedEvent._now().MultipleTimes().AndReturn(self.BaseTime())
1145bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone        self.mox.ReplayAll()
1155bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone
116d17d185d7abd68584f3756a89a7475a5b6109f34Chris Masone        branch_builds = self.CreateEvent().GetBranchBuildsForBoard(board)
1175bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone        for (type, milestone), manifests in branch_manifests.iteritems():
1185bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone            build = None
11967f06d6003bb11f03f925810272f595d79dce44aChris Masone            if type in task.BARE_BRANCHES:
1209ee3eca81228c4479e4b1b0af11d9b69547b1ca7Chris Masone                self.assertEquals(len(branch_builds[type]), 1)
1219ee3eca81228c4479e4b1b0af11d9b69547b1ca7Chris Masone                build = branch_builds[type][0]
1225bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone                self.assertTrue(build.startswith('%s-%s' % (board, type)))
1235bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone            else:
1249ee3eca81228c4479e4b1b0af11d9b69547b1ca7Chris Masone                self.assertEquals(len(branch_builds[milestone]), 1)
1259ee3eca81228c4479e4b1b0af11d9b69547b1ca7Chris Masone                build = branch_builds[milestone][0]
1265bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone                self.assertTrue(build.startswith('%s-release' % board))
1279ee3eca81228c4479e4b1b0af11d9b69547b1ca7Chris Masone            self.assertTrue('R%s-%s' % (milestone, manifests[-1]) in build)
1285bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone
1295bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone
130013859b492bf4f5b304e31be3300789443eee33eChris Masoneclass NightlyTest(TimedEventTestBase):
131fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    """Unit tests for Weekly.
132fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
133fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    @var _HOUR: The time of night to use in these unit tests.
134fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    """
135fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
1362d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone    _HOUR = 20
137fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
138fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
139fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def setUp(self):
140fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        super(NightlyTest, self).setUp()
141fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
142fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
143fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def BaseTime(self):
144fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        return datetime.datetime(2012, 1, 1, self._HOUR)
145fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
146fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
1475bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone    def CreateEvent(self):
1482d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        """Return an instance of timed_event.Nightly."""
14993f51d4da152538007d5b44a2dc9d2bbb1fe3429Chris Masone        return timed_event.Nightly(self.mv, False, self._HOUR)
1502d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone
1512d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone
1522d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone    def testCreateFromConfig(self):
1532d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        """Test that creating from config is equivalent to using constructor."""
1542d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        config = forgiving_config_parser.ForgivingConfigParser()
15593f51d4da152538007d5b44a2dc9d2bbb1fe3429Chris Masone        section = base_event.SectionName(timed_event.Nightly.KEYWORD)
1562d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        config.add_section(section)
1572d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        config.set(section, 'hour', '%d' % self._HOUR)
1582d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone
1592d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        timed_event.TimedEvent._now().MultipleTimes().AndReturn(self.BaseTime())
1602d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        self.mox.ReplayAll()
1612d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone
16293f51d4da152538007d5b44a2dc9d2bbb1fe3429Chris Masone        self.assertEquals(self.CreateEvent(),
16393f51d4da152538007d5b44a2dc9d2bbb1fe3429Chris Masone                          timed_event.Nightly.CreateFromConfig(config, self.mv))
1642d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone
1652d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone
1662d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone    def testCreateFromEmptyConfig(self):
1672d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        """Test that creating from empty config uses defaults."""
1682d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        config = forgiving_config_parser.ForgivingConfigParser()
1692d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone
1702d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        timed_event.TimedEvent._now().MultipleTimes().AndReturn(self.BaseTime())
1712d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        self.mox.ReplayAll()
1722d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone
1732d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        self.assertEquals(
17493f51d4da152538007d5b44a2dc9d2bbb1fe3429Chris Masone            timed_event.Nightly(self.mv, False,
17593f51d4da152538007d5b44a2dc9d2bbb1fe3429Chris Masone                                timed_event.Nightly._DEFAULT_HOUR),
17693f51d4da152538007d5b44a2dc9d2bbb1fe3429Chris Masone            timed_event.Nightly.CreateFromConfig(config, self.mv))
177fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
178fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
179fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def testDeadlineInPast(self):
180fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        """Ensure we work if the deadline aready passed today."""
181fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        fake_now = self.BaseTime() + datetime.timedelta(hours=1)
1822d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        timed_event.TimedEvent._now().MultipleTimes().AndReturn(fake_now)
183fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.mox.ReplayAll()
184fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
1855bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone        nightly = self.CreateEvent()  # Deadline gets set for tomorrow night.
1862d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        self.assertFalse(nightly.ShouldHandle())
187fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.mox.VerifyAll()
188fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
189fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.mox.ResetAll()
190fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        fake_now += datetime.timedelta(days=1)  # Jump to tomorrow night.
1912d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        timed_event.TimedEvent._now().MultipleTimes().AndReturn(fake_now)
192fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.mox.ReplayAll()
1932d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        self.assertTrue(nightly.ShouldHandle())
194fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
195fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
196fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def TimeBefore(self, now):
197fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        return now - datetime.timedelta(hours=1)
198fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
199fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
200fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def TimeLaterThan(self, now):
201fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        return now + datetime.timedelta(hours=2)
202fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
203fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
204fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def testDeadlineInFuture(self):
205fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        """Ensure we work if the deadline is later today."""
206fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.doTestDeadlineInFuture()
207fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
208fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
209fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def testDeadlineIsNow(self):
210fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        """We happened to create the trigger at the exact right time."""
211fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.doTestDeadlineIsNow()
212fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
213fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
214fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def testTOCTOU(self):
215fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        """Even if deadline passes during initialization, trigger must fire."""
216fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.doTestTOCTOU()
217fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
218fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
219e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone    def testDeadlineUpdate(self):
220e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        """Ensure we update the deadline correctly."""
221e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        self.doTestDeadlineUpdate(days_to_jump=1)
222e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone
223e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone
2245bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone    def testGetBranchBuilds(self):
2255bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone        """Ensure Nightly gets most recent builds in last day."""
2265bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone        self.doTestGetBranchBuilds(days=1)
2275bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone
2285bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone
229013859b492bf4f5b304e31be3300789443eee33eChris Masoneclass WeeklyTest(TimedEventTestBase):
230fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    """Unit tests for Weekly.
231fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
232fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    @var _DAY: The day of the week to use in these unit tests.
233fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    @var _HOUR: The time of night to use in these unit tests.
234fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    """
235fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
236fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    _DAY = 5
2372d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone    _HOUR = 22
238fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
239fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
240fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def setUp(self):
241fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        super(WeeklyTest, self).setUp()
242fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
243fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
244fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def BaseTime(self):
245fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        basetime = datetime.datetime(2012, 1, 1, self._HOUR)
246fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        basetime += datetime.timedelta(self._DAY-basetime.weekday())
247fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        return basetime
248fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
249fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
2505bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone    def CreateEvent(self):
2512d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        """Return an instance of timed_event.Weekly."""
25293f51d4da152538007d5b44a2dc9d2bbb1fe3429Chris Masone        return timed_event.Weekly(self.mv, False, self._DAY, self._HOUR)
2532d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone
2542d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone
2552d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone    def testCreateFromConfig(self):
2562d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        """Test that creating from config is equivalent to using constructor."""
2572d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        config = forgiving_config_parser.ForgivingConfigParser()
25893f51d4da152538007d5b44a2dc9d2bbb1fe3429Chris Masone        section = base_event.SectionName(timed_event.Weekly.KEYWORD)
2592d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        config.add_section(section)
2602d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        config.set(section, 'day', '%d' % self._DAY)
2612d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        config.set(section, 'hour', '%d' % self._HOUR)
2622d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone
2632d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        timed_event.TimedEvent._now().MultipleTimes().AndReturn(self.BaseTime())
2642d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        self.mox.ReplayAll()
2652d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone
26693f51d4da152538007d5b44a2dc9d2bbb1fe3429Chris Masone        self.assertEquals(self.CreateEvent(),
26793f51d4da152538007d5b44a2dc9d2bbb1fe3429Chris Masone                          timed_event.Weekly.CreateFromConfig(config, self.mv))
268fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
269fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
270fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def testDeadlineInPast(self):
271fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        """Ensure we work if the deadline already passed this week."""
272fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        fake_now = self.BaseTime() + datetime.timedelta(days=1)
2732d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        timed_event.TimedEvent._now().MultipleTimes().AndReturn(fake_now)
274fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.mox.ReplayAll()
275fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
2765bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone        weekly = self.CreateEvent()  # Deadline gets set for next week.
2772d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        self.assertFalse(weekly.ShouldHandle())
278fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.mox.VerifyAll()
279fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
280fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.mox.ResetAll()
281fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        fake_now += datetime.timedelta(days=1)  # Jump to tomorrow.
2822d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        timed_event.TimedEvent._now().MultipleTimes().AndReturn(fake_now)
283fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.mox.ReplayAll()
2842d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        self.assertFalse(weekly.ShouldHandle())
285fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.mox.VerifyAll()
286fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
287fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.mox.ResetAll()
288fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        fake_now += datetime.timedelta(days=7)  # Jump to next week.
2892d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        timed_event.TimedEvent._now().MultipleTimes().AndReturn(fake_now)
290fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.mox.ReplayAll()
2912d61ca263d3e571b19604ea4c9d7b55d83c28405Chris Masone        self.assertTrue(weekly.ShouldHandle())
292fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
293fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
294fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def TimeBefore(self, now):
295fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        return now - datetime.timedelta(days=1)
296fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
297fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
298fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def TimeLaterThan(self, now):
299fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        return now + datetime.timedelta(days=2)
300fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
301fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
302fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def testDeadlineInFuture(self):
303fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        """Ensure we work if the deadline is later this week."""
304fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.doTestDeadlineInFuture()
305fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
306fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
307fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def testDeadlineIsNow(self):
308fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        """We happened to create the trigger at the exact right time."""
309fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.doTestDeadlineIsNow()
310fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
311fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
312fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone    def testTOCTOU(self):
313fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        """Even if deadline passes during initialization, trigger must fire."""
314fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone        self.doTestTOCTOU()
315fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
316fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone
317e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone    def testDeadlineUpdate(self):
318e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        """Ensure we update the deadline correctly."""
319e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone        self.doTestDeadlineUpdate(days_to_jump=7)
320e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone
321e8bebaf10711ca802d40c0b7f412e3910999159eChris Masone
3225bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone    def testGetBranchBuilds(self):
3235bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone        """Ensure Weekly gets most recent builds in last 7 days."""
3245bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone        self.doTestGetBranchBuilds(days=7)
3255bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone
3265bde7dc7d8b0608feb43491d5ac648d11c890f54Chris Masone
327fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masoneif __name__ == '__main__':
328fad911ada4f6126280765f15204eaf8b3b4bc437Chris Masone  unittest.main()
329