blob: 07261d8ed2ef3e5739a94baa808ebb9929103a6d [file] [log] [blame]
Chris Sosa47a7d4e2012-03-28 11:26:55 -07001#!/usr/bin/python
2#
3# Copyright (c) 2012 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"""Unit tests for devserver_util module."""
8
9import mox
10import os
11import shutil
12import tempfile
13import unittest
14
Chris Masone816e38c2012-05-02 12:22:36 -070015import downloadable_artifact
Chris Sosa47a7d4e2012-03-28 11:26:55 -070016import devserver
17import devserver_util
18import downloader
19
20
21# Fake Dev Server Layout:
22TEST_LAYOUT = {
23 'test-board-1': ['R17-1413.0.0-a1-b1346', 'R17-18.0.0-a1-b1346'],
24 'test-board-2': ['R16-2241.0.0-a0-b2', 'R17-2.0.0-a1-b1346'],
25 'test-board-3': []
26}
27
28
Chris Masone816e38c2012-05-02 12:22:36 -070029class DownloaderTestBase(mox.MoxTestBase):
Chris Sosa47a7d4e2012-03-28 11:26:55 -070030
31 def setUp(self):
32 mox.MoxTestBase.setUp(self)
33 self._work_dir = tempfile.mkdtemp('downloader-test')
34 self.build = 'R17-1413.0.0-a1-b1346'
35 self.archive_url_prefix = (
36 'gs://chromeos-image-archive/x86-mario-release/' + self.build)
37
38 def tearDown(self):
Gilad Arnold0b8c3f32012-09-19 14:35:44 -070039 shutil.rmtree(self._work_dir, ignore_errors=True)
Chris Sosa47a7d4e2012-03-28 11:26:55 -070040
Chris Sosaf0975642012-06-29 13:53:42 -070041 def _CommonDownloaderSetup(self, ignore_background=False):
Chris Sosa47a7d4e2012-03-28 11:26:55 -070042 """Common code to downloader tests.
43
Chris Masone816e38c2012-05-02 12:22:36 -070044 Mocks out key devserver_util module methods, creates mock artifacts
45 and sets appropriate expectations.
Chris Sosa47a7d4e2012-03-28 11:26:55 -070046
Chris Sosaf0975642012-06-29 13:53:42 -070047 @ignore_background Indicate that background artifacts should be ignored.
48
Chris Masone816e38c2012-05-02 12:22:36 -070049 @return iterable of artifact objects with appropriate expectations.
Chris Sosa47a7d4e2012-03-28 11:26:55 -070050 """
51 board = 'x86-mario-release'
52 self.mox.StubOutWithMock(devserver_util, 'AcquireLock')
53 self.mox.StubOutWithMock(devserver_util, 'GatherArtifactDownloads')
54 self.mox.StubOutWithMock(devserver_util, 'ReleaseLock')
55 self.mox.StubOutWithMock(tempfile, 'mkdtemp')
56
Chris Masone816e38c2012-05-02 12:22:36 -070057 devserver_util.AcquireLock(
58 static_dir=self._work_dir,
59 tag=self._ClassUnderTest().GenerateLockTag(board, self.build)
60 ).AndReturn(self._work_dir)
Chris Sosa47a7d4e2012-03-28 11:26:55 -070061
Chris Masone816e38c2012-05-02 12:22:36 -070062 tempfile.mkdtemp(suffix=mox.IgnoreArg()).AndReturn(self._work_dir)
Chris Sosaf0975642012-06-29 13:53:42 -070063 return self._GenerateArtifacts(ignore_background)
Chris Masone816e38c2012-05-02 12:22:36 -070064
65 def _CreateArtifactDownloader(self, artifacts):
66 """Create and return a Downloader of the appropriate type.
67
68 The returned downloader will expect to download and stage the
69 DownloadableArtifacts listed in [artifacts].
70
71 @param artifacts: iterable of DownloadableArtifacts.
72 @return instance of downloader.Downloader or subclass.
73 """
74 raise NotImplementedError()
75
76 def _ClassUnderTest(self):
77 """Return class object of the type being tested.
78
79 @return downloader.Downloader class object, or subclass.
80 """
81 raise NotImplementedError()
82
Chris Sosaf0975642012-06-29 13:53:42 -070083 def _GenerateArtifacts(self, ignore_background):
Chris Masone816e38c2012-05-02 12:22:36 -070084 """Instantiate artifact mocks and set expectations on them.
85
Chris Sosaf0975642012-06-29 13:53:42 -070086 @ignore_background Indicate that background artifacts should be ignored.
87 This gets passed by CommonDownloaderSetup.
88
Chris Masone816e38c2012-05-02 12:22:36 -070089 @return iterable of artifact objects with appropriate expectations.
90 """
91 raise NotImplementedError()
92
93
94class DownloaderTest(DownloaderTestBase):
95 """Unit tests for downloader.Downloader.
96
97 setUp() and tearDown() inherited from DownloaderTestBase.
98 """
99
100 def _CreateArtifactDownloader(self, artifacts):
101 d = downloader.Downloader(self._work_dir)
102 self.mox.StubOutWithMock(d, 'GatherArtifactDownloads')
103 d.GatherArtifactDownloads(
104 self._work_dir, self.archive_url_prefix, self.build,
105 self._work_dir).AndReturn(artifacts)
106 return d
107
108 def _ClassUnderTest(self):
109 return downloader.Downloader
110
Chris Sosaf0975642012-06-29 13:53:42 -0700111 def _GenerateArtifacts(self, ignore_background):
Chris Masone816e38c2012-05-02 12:22:36 -0700112 """Instantiate artifact mocks and set expectations on them.
113
114 Sets up artifacts and sets up expectations for synchronous artifacts to
115 be downloaded first.
116
Chris Sosaf0975642012-06-29 13:53:42 -0700117 @ignore_background If True, doesn't use mocks for download/stage methods.
118
Chris Masone816e38c2012-05-02 12:22:36 -0700119 @return iterable of artifact objects with appropriate expectations.
120 """
121 artifacts = []
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700122 for index in range(5):
Chris Masone816e38c2012-05-02 12:22:36 -0700123 artifact = self.mox.CreateMock(downloadable_artifact.DownloadableArtifact)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700124 # Make every other artifact synchronous.
125 if index % 2 == 0:
126 artifact.Synchronous = lambda: True
Chris Masone816e38c2012-05-02 12:22:36 -0700127 artifact.Download()
128 artifact.Stage()
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700129 else:
130 artifact.Synchronous = lambda: False
Chris Sosaf0975642012-06-29 13:53:42 -0700131 if ignore_background:
132 artifact.Download = lambda: None
133 artifact.Stage = lambda: None
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700134
135 artifacts.append(artifact)
136
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700137 return artifacts
138
139 def testDownloaderSerially(self):
140 """Runs through the standard downloader workflow with no backgrounding."""
141 artifacts = self._CommonDownloaderSetup()
142
143 # Downloads non-synchronous artifacts second.
144 for index, artifact in enumerate(artifacts):
145 if index % 2 != 0:
146 artifact.Download()
147 artifact.Stage()
148
Chris Masone816e38c2012-05-02 12:22:36 -0700149 d = self._CreateArtifactDownloader(artifacts)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700150 self.mox.ReplayAll()
Chris Masone816e38c2012-05-02 12:22:36 -0700151 self.assertEqual(d.Download(self.archive_url_prefix, background=False),
152 'Success')
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700153 self.mox.VerifyAll()
154
155 def testDownloaderInBackground(self):
156 """Runs through the standard downloader workflow with backgrounding."""
Chris Sosaf0975642012-06-29 13:53:42 -0700157 artifacts = self._CommonDownloaderSetup(ignore_background=True)
Chris Masone816e38c2012-05-02 12:22:36 -0700158 d = self._CreateArtifactDownloader(artifacts)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700159 self.mox.ReplayAll()
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700160 d.Download(self.archive_url_prefix, background=True)
161 self.assertEqual(d.GetStatusOfBackgroundDownloads(), 'Success')
162 self.mox.VerifyAll()
163
164 def testInteractionWithDevserver(self):
Chris Sosa9164ca32012-03-28 11:04:50 -0700165 """Tests interaction between the downloader and devserver methods."""
Chris Sosaf0975642012-06-29 13:53:42 -0700166 artifacts = self._CommonDownloaderSetup(ignore_background=True)
Chris Masone816e38c2012-05-02 12:22:36 -0700167 devserver_util.GatherArtifactDownloads(
168 self._work_dir, self.archive_url_prefix, self.build,
169 self._work_dir).AndReturn(artifacts)
170
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700171 class FakeUpdater():
172 static_dir = self._work_dir
173
174 devserver.updater = FakeUpdater()
175
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700176 self.mox.ReplayAll()
177 dev = devserver.DevServerRoot()
178 status = dev.download(archive_url=self.archive_url_prefix)
179 self.assertTrue(status, 'Success')
180 status = dev.wait_for_status(archive_url=self.archive_url_prefix)
181 self.assertTrue(status, 'Success')
182 self.mox.VerifyAll()
183
Chris Sosa9164ca32012-03-28 11:04:50 -0700184 def testBuildStaged(self):
185 """Test whether we can correctly check if a build is previously staged."""
Yu-Ju Hongd49d7f42012-06-25 12:23:11 -0700186 base_url = 'gs://chrome-awesome/'
187 build_dir = 'x86-awesome-release/R99-1234.0-r1'
188 archive_url = base_url + build_dir
189 archive_url_non_staged = base_url + 'x86-awesome-release/R99-1234.0-r2'
Chris Sosa9164ca32012-03-28 11:04:50 -0700190 # Create the directory to reflect staging.
Yu-Ju Hongd49d7f42012-06-25 12:23:11 -0700191 os.makedirs(os.path.join(self._work_dir, build_dir))
Chris Sosa9164ca32012-03-28 11:04:50 -0700192
193 self.assertTrue(downloader.Downloader.BuildStaged(archive_url,
194 self._work_dir))
Alex Millera44d5022012-07-27 11:34:16 -0700195 self.assertTrue(os.path.exists(
196 os.path.join(os.path.join(self._work_dir, build_dir),
197 downloader.Downloader._TIMESTAMP_FILENAME)))
Chris Sosa9164ca32012-03-28 11:04:50 -0700198 self.assertFalse(downloader.Downloader.BuildStaged(archive_url_non_staged,
199 self._work_dir))
Yu-Ju Hongd49d7f42012-06-25 12:23:11 -0700200 def testTrybotBuildStaged(self):
201 """Test whether a previous staged trybot-build can be corrected detected"""
202 base_url = 'gs://chrome-awesome/'
203 build_dir = 'trybot/date/x86-awesome-release/R99-1234.0-r1'
204 archive_url = base_url + build_dir
205 archive_url_non_staged = base_url + 'x86-awesome-release/R99-1234.0-r2'
206 # Create the directory to reflect staging.
207 os.makedirs(os.path.join(self._work_dir, build_dir))
Chris Sosa9164ca32012-03-28 11:04:50 -0700208
Yu-Ju Hongd49d7f42012-06-25 12:23:11 -0700209 self.assertTrue(downloader.Downloader.BuildStaged(archive_url,
210 self._work_dir))
211 self.assertFalse(downloader.Downloader.BuildStaged(archive_url_non_staged,
212 self._work_dir))
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700213
Chris Masone816e38c2012-05-02 12:22:36 -0700214class SymbolDownloaderTest(DownloaderTestBase):
215 """Unit tests for downloader.SymbolDownloader.
216
217 setUp() and tearDown() inherited from DownloaderTestBase.
218 """
219
220 def _CreateArtifactDownloader(self, artifacts):
221 d = downloader.SymbolDownloader(self._work_dir)
222 self.mox.StubOutWithMock(d, 'GatherArtifactDownloads')
223 d.GatherArtifactDownloads(
224 self._work_dir, self.archive_url_prefix, '',
225 self._work_dir).AndReturn(artifacts)
226 return d
227
228 def _ClassUnderTest(self):
229 return downloader.SymbolDownloader
230
Chris Sosaf0975642012-06-29 13:53:42 -0700231 def _GenerateArtifacts(self, unused_ignore_background):
Chris Masone816e38c2012-05-02 12:22:36 -0700232 """Instantiate artifact mocks and set expectations on them.
233
234 Sets up a DebugTarball and sets up expectation that it will be
235 downloaded and staged.
236
237 @return iterable of one artifact object with appropriate expectations.
238 """
239 artifact = self.mox.CreateMock(downloadable_artifact.DownloadableArtifact)
240 artifact.Synchronous = lambda: True
241 artifact.Download()
242 artifact.Stage()
243 return [artifact]
244
245 def testDownloaderSerially(self):
246 """Runs through the symbol downloader workflow."""
247 d = self._CreateArtifactDownloader(self._CommonDownloaderSetup())
248
249 self.mox.ReplayAll()
250 self.assertEqual(d.Download(self.archive_url_prefix), 'Success')
251 self.mox.VerifyAll()
252
253
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700254if __name__ == '__main__':
255 unittest.main()