blob: 0a4e4ed0081472a292154a28b0ab90143942b3b8 [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):
39 if os.path.exists(self._work_dir):
40 shutil.rmtree(self._work_dir)
41
Chris Sosaf0975642012-06-29 13:53:42 -070042 def _CommonDownloaderSetup(self, ignore_background=False):
Chris Sosa47a7d4e2012-03-28 11:26:55 -070043 """Common code to downloader tests.
44
Chris Masone816e38c2012-05-02 12:22:36 -070045 Mocks out key devserver_util module methods, creates mock artifacts
46 and sets appropriate expectations.
Chris Sosa47a7d4e2012-03-28 11:26:55 -070047
Chris Sosaf0975642012-06-29 13:53:42 -070048 @ignore_background Indicate that background artifacts should be ignored.
49
Chris Masone816e38c2012-05-02 12:22:36 -070050 @return iterable of artifact objects with appropriate expectations.
Chris Sosa47a7d4e2012-03-28 11:26:55 -070051 """
52 board = 'x86-mario-release'
53 self.mox.StubOutWithMock(devserver_util, 'AcquireLock')
54 self.mox.StubOutWithMock(devserver_util, 'GatherArtifactDownloads')
55 self.mox.StubOutWithMock(devserver_util, 'ReleaseLock')
56 self.mox.StubOutWithMock(tempfile, 'mkdtemp')
57
Chris Masone816e38c2012-05-02 12:22:36 -070058 devserver_util.AcquireLock(
59 static_dir=self._work_dir,
60 tag=self._ClassUnderTest().GenerateLockTag(board, self.build)
61 ).AndReturn(self._work_dir)
Chris Sosa47a7d4e2012-03-28 11:26:55 -070062
Chris Masone816e38c2012-05-02 12:22:36 -070063 tempfile.mkdtemp(suffix=mox.IgnoreArg()).AndReturn(self._work_dir)
Chris Sosaf0975642012-06-29 13:53:42 -070064 return self._GenerateArtifacts(ignore_background)
Chris Masone816e38c2012-05-02 12:22:36 -070065
66 def _CreateArtifactDownloader(self, artifacts):
67 """Create and return a Downloader of the appropriate type.
68
69 The returned downloader will expect to download and stage the
70 DownloadableArtifacts listed in [artifacts].
71
72 @param artifacts: iterable of DownloadableArtifacts.
73 @return instance of downloader.Downloader or subclass.
74 """
75 raise NotImplementedError()
76
77 def _ClassUnderTest(self):
78 """Return class object of the type being tested.
79
80 @return downloader.Downloader class object, or subclass.
81 """
82 raise NotImplementedError()
83
Chris Sosaf0975642012-06-29 13:53:42 -070084 def _GenerateArtifacts(self, ignore_background):
Chris Masone816e38c2012-05-02 12:22:36 -070085 """Instantiate artifact mocks and set expectations on them.
86
Chris Sosaf0975642012-06-29 13:53:42 -070087 @ignore_background Indicate that background artifacts should be ignored.
88 This gets passed by CommonDownloaderSetup.
89
Chris Masone816e38c2012-05-02 12:22:36 -070090 @return iterable of artifact objects with appropriate expectations.
91 """
92 raise NotImplementedError()
93
94
95class DownloaderTest(DownloaderTestBase):
96 """Unit tests for downloader.Downloader.
97
98 setUp() and tearDown() inherited from DownloaderTestBase.
99 """
100
101 def _CreateArtifactDownloader(self, artifacts):
102 d = downloader.Downloader(self._work_dir)
103 self.mox.StubOutWithMock(d, 'GatherArtifactDownloads')
104 d.GatherArtifactDownloads(
105 self._work_dir, self.archive_url_prefix, self.build,
106 self._work_dir).AndReturn(artifacts)
107 return d
108
109 def _ClassUnderTest(self):
110 return downloader.Downloader
111
Chris Sosaf0975642012-06-29 13:53:42 -0700112 def _GenerateArtifacts(self, ignore_background):
Chris Masone816e38c2012-05-02 12:22:36 -0700113 """Instantiate artifact mocks and set expectations on them.
114
115 Sets up artifacts and sets up expectations for synchronous artifacts to
116 be downloaded first.
117
Chris Sosaf0975642012-06-29 13:53:42 -0700118 @ignore_background If True, doesn't use mocks for download/stage methods.
119
Chris Masone816e38c2012-05-02 12:22:36 -0700120 @return iterable of artifact objects with appropriate expectations.
121 """
122 artifacts = []
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700123 for index in range(5):
Chris Masone816e38c2012-05-02 12:22:36 -0700124 artifact = self.mox.CreateMock(downloadable_artifact.DownloadableArtifact)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700125 # Make every other artifact synchronous.
126 if index % 2 == 0:
127 artifact.Synchronous = lambda: True
Chris Masone816e38c2012-05-02 12:22:36 -0700128 artifact.Download()
129 artifact.Stage()
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700130 else:
131 artifact.Synchronous = lambda: False
Chris Sosaf0975642012-06-29 13:53:42 -0700132 if ignore_background:
133 artifact.Download = lambda: None
134 artifact.Stage = lambda: None
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700135
136 artifacts.append(artifact)
137
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700138 return artifacts
139
140 def testDownloaderSerially(self):
141 """Runs through the standard downloader workflow with no backgrounding."""
142 artifacts = self._CommonDownloaderSetup()
143
144 # Downloads non-synchronous artifacts second.
145 for index, artifact in enumerate(artifacts):
146 if index % 2 != 0:
147 artifact.Download()
148 artifact.Stage()
149
Chris Masone816e38c2012-05-02 12:22:36 -0700150 d = self._CreateArtifactDownloader(artifacts)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700151 self.mox.ReplayAll()
Chris Masone816e38c2012-05-02 12:22:36 -0700152 self.assertEqual(d.Download(self.archive_url_prefix, background=False),
153 'Success')
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700154 self.mox.VerifyAll()
155
156 def testDownloaderInBackground(self):
157 """Runs through the standard downloader workflow with backgrounding."""
Chris Sosaf0975642012-06-29 13:53:42 -0700158 artifacts = self._CommonDownloaderSetup(ignore_background=True)
Chris Masone816e38c2012-05-02 12:22:36 -0700159 d = self._CreateArtifactDownloader(artifacts)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700160 self.mox.ReplayAll()
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700161 d.Download(self.archive_url_prefix, background=True)
162 self.assertEqual(d.GetStatusOfBackgroundDownloads(), 'Success')
163 self.mox.VerifyAll()
164
165 def testInteractionWithDevserver(self):
Chris Sosa9164ca32012-03-28 11:04:50 -0700166 """Tests interaction between the downloader and devserver methods."""
Chris Sosaf0975642012-06-29 13:53:42 -0700167 artifacts = self._CommonDownloaderSetup(ignore_background=True)
Chris Masone816e38c2012-05-02 12:22:36 -0700168 devserver_util.GatherArtifactDownloads(
169 self._work_dir, self.archive_url_prefix, self.build,
170 self._work_dir).AndReturn(artifacts)
171
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700172 class FakeUpdater():
173 static_dir = self._work_dir
174
175 devserver.updater = FakeUpdater()
176
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700177 self.mox.ReplayAll()
178 dev = devserver.DevServerRoot()
179 status = dev.download(archive_url=self.archive_url_prefix)
180 self.assertTrue(status, 'Success')
181 status = dev.wait_for_status(archive_url=self.archive_url_prefix)
182 self.assertTrue(status, 'Success')
183 self.mox.VerifyAll()
184
Chris Sosa9164ca32012-03-28 11:04:50 -0700185 def testBuildStaged(self):
186 """Test whether we can correctly check if a build is previously staged."""
Yu-Ju Hongd49d7f42012-06-25 12:23:11 -0700187 base_url = 'gs://chrome-awesome/'
188 build_dir = 'x86-awesome-release/R99-1234.0-r1'
189 archive_url = base_url + build_dir
190 archive_url_non_staged = base_url + 'x86-awesome-release/R99-1234.0-r2'
Chris Sosa9164ca32012-03-28 11:04:50 -0700191 # Create the directory to reflect staging.
Yu-Ju Hongd49d7f42012-06-25 12:23:11 -0700192 os.makedirs(os.path.join(self._work_dir, build_dir))
Chris Sosa9164ca32012-03-28 11:04:50 -0700193
194 self.assertTrue(downloader.Downloader.BuildStaged(archive_url,
195 self._work_dir))
Alex Millera44d5022012-07-27 11:34:16 -0700196 self.assertTrue(os.path.exists(
197 os.path.join(os.path.join(self._work_dir, build_dir),
198 downloader.Downloader._TIMESTAMP_FILENAME)))
Chris Sosa9164ca32012-03-28 11:04:50 -0700199 self.assertFalse(downloader.Downloader.BuildStaged(archive_url_non_staged,
200 self._work_dir))
Yu-Ju Hongd49d7f42012-06-25 12:23:11 -0700201 def testTrybotBuildStaged(self):
202 """Test whether a previous staged trybot-build can be corrected detected"""
203 base_url = 'gs://chrome-awesome/'
204 build_dir = 'trybot/date/x86-awesome-release/R99-1234.0-r1'
205 archive_url = base_url + build_dir
206 archive_url_non_staged = base_url + 'x86-awesome-release/R99-1234.0-r2'
207 # Create the directory to reflect staging.
208 os.makedirs(os.path.join(self._work_dir, build_dir))
Chris Sosa9164ca32012-03-28 11:04:50 -0700209
Yu-Ju Hongd49d7f42012-06-25 12:23:11 -0700210 self.assertTrue(downloader.Downloader.BuildStaged(archive_url,
211 self._work_dir))
212 self.assertFalse(downloader.Downloader.BuildStaged(archive_url_non_staged,
213 self._work_dir))
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700214
Chris Masone816e38c2012-05-02 12:22:36 -0700215class SymbolDownloaderTest(DownloaderTestBase):
216 """Unit tests for downloader.SymbolDownloader.
217
218 setUp() and tearDown() inherited from DownloaderTestBase.
219 """
220
221 def _CreateArtifactDownloader(self, artifacts):
222 d = downloader.SymbolDownloader(self._work_dir)
223 self.mox.StubOutWithMock(d, 'GatherArtifactDownloads')
224 d.GatherArtifactDownloads(
225 self._work_dir, self.archive_url_prefix, '',
226 self._work_dir).AndReturn(artifacts)
227 return d
228
229 def _ClassUnderTest(self):
230 return downloader.SymbolDownloader
231
Chris Sosaf0975642012-06-29 13:53:42 -0700232 def _GenerateArtifacts(self, unused_ignore_background):
Chris Masone816e38c2012-05-02 12:22:36 -0700233 """Instantiate artifact mocks and set expectations on them.
234
235 Sets up a DebugTarball and sets up expectation that it will be
236 downloaded and staged.
237
238 @return iterable of one artifact object with appropriate expectations.
239 """
240 artifact = self.mox.CreateMock(downloadable_artifact.DownloadableArtifact)
241 artifact.Synchronous = lambda: True
242 artifact.Download()
243 artifact.Stage()
244 return [artifact]
245
246 def testDownloaderSerially(self):
247 """Runs through the symbol downloader workflow."""
248 d = self._CreateArtifactDownloader(self._CommonDownloaderSetup())
249
250 self.mox.ReplayAll()
251 self.assertEqual(d.Download(self.archive_url_prefix), 'Success')
252 self.mox.VerifyAll()
253
254
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700255if __name__ == '__main__':
256 unittest.main()