blob: 7ec883a4a4ad92e0597f45e64768349f0473a883 [file] [log] [blame]
Chris Sosa47a7d4e2012-03-28 18:26:551#!/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
Gilad Arnoldc65330c2012-09-20 22:17:487"""Unit tests for downloader module."""
Chris Sosa47a7d4e2012-03-28 18:26:558
Chris Sosa47a7d4e2012-03-28 18:26:559import os
10import shutil
11import tempfile
12import unittest
13
Gilad Arnoldabb352e2012-09-23 08:24:2714import mox
15
Gilad Arnoldc65330c2012-09-20 22:17:4816import build_artifact
17import common_util
Chris Sosa47a7d4e2012-03-28 18:26:5518import devserver
Chris Sosa47a7d4e2012-03-28 18:26:5519import downloader
20
21
22# Fake Dev Server Layout:
23TEST_LAYOUT = {
24 'test-board-1': ['R17-1413.0.0-a1-b1346', 'R17-18.0.0-a1-b1346'],
25 'test-board-2': ['R16-2241.0.0-a0-b2', 'R17-2.0.0-a1-b1346'],
26 'test-board-3': []
27}
28
29
Chris Masone816e38c2012-05-02 19:22:3630class DownloaderTestBase(mox.MoxTestBase):
Chris Sosa47a7d4e2012-03-28 18:26:5531
32 def setUp(self):
33 mox.MoxTestBase.setUp(self)
34 self._work_dir = tempfile.mkdtemp('downloader-test')
35 self.build = 'R17-1413.0.0-a1-b1346'
36 self.archive_url_prefix = (
37 'gs://chromeos-image-archive/x86-mario-release/' + self.build)
38
39 def tearDown(self):
Gilad Arnold0b8c3f32012-09-19 21:35:4440 shutil.rmtree(self._work_dir, ignore_errors=True)
Chris Sosa47a7d4e2012-03-28 18:26:5541
Chris Sosaf0975642012-06-29 20:53:4242 def _CommonDownloaderSetup(self, ignore_background=False):
Chris Sosa47a7d4e2012-03-28 18:26:5543 """Common code to downloader tests.
44
Gilad Arnoldc65330c2012-09-20 22:17:4845 Mocks out key util module methods, creates mock artifacts and sets
46 appropriate expectations.
Chris Sosa47a7d4e2012-03-28 18:26:5547
Chris Sosaf0975642012-06-29 20:53:4248 @ignore_background Indicate that background artifacts should be ignored.
49
Chris Masone816e38c2012-05-02 19:22:3650 @return iterable of artifact objects with appropriate expectations.
Chris Sosa47a7d4e2012-03-28 18:26:5551 """
52 board = 'x86-mario-release'
Gilad Arnoldc65330c2012-09-20 22:17:4853 self.mox.StubOutWithMock(common_util, 'AcquireLock')
54 self.mox.StubOutWithMock(common_util, 'GatherArtifactDownloads')
55 self.mox.StubOutWithMock(common_util, 'ReleaseLock')
Chris Sosa47a7d4e2012-03-28 18:26:5556 self.mox.StubOutWithMock(tempfile, 'mkdtemp')
57
Gilad Arnold5174ca22012-09-12 17:49:0958 lock_tag = self._ClassUnderTest().GenerateLockTag(board, self.build)
Gilad Arnoldc65330c2012-09-20 22:17:4859 common_util.AcquireLock(
Chris Masone816e38c2012-05-02 19:22:3660 static_dir=self._work_dir,
Gilad Arnold5174ca22012-09-12 17:49:0961 tag=lock_tag).AndReturn(self._work_dir)
Gilad Arnoldc65330c2012-09-20 22:17:4862 common_util.ReleaseLock(static_dir=self._work_dir, tag=lock_tag)
Chris Sosa47a7d4e2012-03-28 18:26:5563
Chris Masone816e38c2012-05-02 19:22:3664 tempfile.mkdtemp(suffix=mox.IgnoreArg()).AndReturn(self._work_dir)
Chris Sosaf0975642012-06-29 20:53:4265 return self._GenerateArtifacts(ignore_background)
Chris Masone816e38c2012-05-02 19:22:3666
67 def _CreateArtifactDownloader(self, artifacts):
68 """Create and return a Downloader of the appropriate type.
69
70 The returned downloader will expect to download and stage the
Gilad Arnoldc65330c2012-09-20 22:17:4871 Artifacts listed in [artifacts].
Chris Masone816e38c2012-05-02 19:22:3672
Gilad Arnoldc65330c2012-09-20 22:17:4873 @param artifacts: iterable of Artifacts.
Chris Masone816e38c2012-05-02 19:22:3674 @return instance of downloader.Downloader or subclass.
75 """
76 raise NotImplementedError()
77
78 def _ClassUnderTest(self):
79 """Return class object of the type being tested.
80
81 @return downloader.Downloader class object, or subclass.
82 """
83 raise NotImplementedError()
84
Chris Sosaf0975642012-06-29 20:53:4285 def _GenerateArtifacts(self, ignore_background):
Chris Masone816e38c2012-05-02 19:22:3686 """Instantiate artifact mocks and set expectations on them.
87
Chris Sosaf0975642012-06-29 20:53:4288 @ignore_background Indicate that background artifacts should be ignored.
89 This gets passed by CommonDownloaderSetup.
90
Chris Masone816e38c2012-05-02 19:22:3691 @return iterable of artifact objects with appropriate expectations.
92 """
93 raise NotImplementedError()
94
95
96class DownloaderTest(DownloaderTestBase):
97 """Unit tests for downloader.Downloader.
98
99 setUp() and tearDown() inherited from DownloaderTestBase.
100 """
101
102 def _CreateArtifactDownloader(self, artifacts):
103 d = downloader.Downloader(self._work_dir)
104 self.mox.StubOutWithMock(d, 'GatherArtifactDownloads')
105 d.GatherArtifactDownloads(
Gilad Arnold6f99b982012-09-12 17:49:40106 self._work_dir, self.archive_url_prefix, self._work_dir,
107 self.build).AndReturn(artifacts)
Chris Masone816e38c2012-05-02 19:22:36108 return d
109
110 def _ClassUnderTest(self):
111 return downloader.Downloader
112
Chris Sosaf0975642012-06-29 20:53:42113 def _GenerateArtifacts(self, ignore_background):
Chris Masone816e38c2012-05-02 19:22:36114 """Instantiate artifact mocks and set expectations on them.
115
116 Sets up artifacts and sets up expectations for synchronous artifacts to
117 be downloaded first.
118
Chris Sosaf0975642012-06-29 20:53:42119 @ignore_background If True, doesn't use mocks for download/stage methods.
120
Chris Masone816e38c2012-05-02 19:22:36121 @return iterable of artifact objects with appropriate expectations.
122 """
123 artifacts = []
Chris Sosa47a7d4e2012-03-28 18:26:55124 for index in range(5):
Gilad Arnoldc65330c2012-09-20 22:17:48125 artifact = self.mox.CreateMock(build_artifact.BuildArtifact)
Chris Sosa47a7d4e2012-03-28 18:26:55126 # Make every other artifact synchronous.
127 if index % 2 == 0:
128 artifact.Synchronous = lambda: True
Chris Masone816e38c2012-05-02 19:22:36129 artifact.Download()
130 artifact.Stage()
Chris Sosa47a7d4e2012-03-28 18:26:55131 else:
132 artifact.Synchronous = lambda: False
Chris Sosaf0975642012-06-29 20:53:42133 if ignore_background:
134 artifact.Download = lambda: None
135 artifact.Stage = lambda: None
Chris Sosa47a7d4e2012-03-28 18:26:55136
137 artifacts.append(artifact)
138
Chris Sosa47a7d4e2012-03-28 18:26:55139 return artifacts
140
141 def testDownloaderSerially(self):
142 """Runs through the standard downloader workflow with no backgrounding."""
143 artifacts = self._CommonDownloaderSetup()
144
145 # Downloads non-synchronous artifacts second.
146 for index, artifact in enumerate(artifacts):
147 if index % 2 != 0:
148 artifact.Download()
149 artifact.Stage()
150
Chris Masone816e38c2012-05-02 19:22:36151 d = self._CreateArtifactDownloader(artifacts)
Chris Sosa47a7d4e2012-03-28 18:26:55152 self.mox.ReplayAll()
Chris Masone816e38c2012-05-02 19:22:36153 self.assertEqual(d.Download(self.archive_url_prefix, background=False),
154 'Success')
Chris Sosa47a7d4e2012-03-28 18:26:55155 self.mox.VerifyAll()
156
157 def testDownloaderInBackground(self):
158 """Runs through the standard downloader workflow with backgrounding."""
Chris Sosaf0975642012-06-29 20:53:42159 artifacts = self._CommonDownloaderSetup(ignore_background=True)
Chris Masone816e38c2012-05-02 19:22:36160 d = self._CreateArtifactDownloader(artifacts)
Chris Sosa47a7d4e2012-03-28 18:26:55161 self.mox.ReplayAll()
Chris Sosa47a7d4e2012-03-28 18:26:55162 d.Download(self.archive_url_prefix, background=True)
163 self.assertEqual(d.GetStatusOfBackgroundDownloads(), 'Success')
164 self.mox.VerifyAll()
165
166 def testInteractionWithDevserver(self):
Chris Sosa9164ca32012-03-28 18:04:50167 """Tests interaction between the downloader and devserver methods."""
Chris Sosaf0975642012-06-29 20:53:42168 artifacts = self._CommonDownloaderSetup(ignore_background=True)
Gilad Arnoldc65330c2012-09-20 22:17:48169 common_util.GatherArtifactDownloads(
Gilad Arnold6f99b982012-09-12 17:49:40170 self._work_dir, self.archive_url_prefix, self._work_dir,
171 self.build).AndReturn(artifacts)
Chris Masone816e38c2012-05-02 19:22:36172
Chris Sosa47a7d4e2012-03-28 18:26:55173 class FakeUpdater():
174 static_dir = self._work_dir
175
176 devserver.updater = FakeUpdater()
177
Chris Sosa47a7d4e2012-03-28 18:26:55178 self.mox.ReplayAll()
179 dev = devserver.DevServerRoot()
180 status = dev.download(archive_url=self.archive_url_prefix)
181 self.assertTrue(status, 'Success')
182 status = dev.wait_for_status(archive_url=self.archive_url_prefix)
183 self.assertTrue(status, 'Success')
184 self.mox.VerifyAll()
185
Chris Sosa9164ca32012-03-28 18:04:50186 def testBuildStaged(self):
187 """Test whether we can correctly check if a build is previously staged."""
Yu-Ju Hongd49d7f42012-06-25 19:23:11188 base_url = 'gs://chrome-awesome/'
189 build_dir = 'x86-awesome-release/R99-1234.0-r1'
190 archive_url = base_url + build_dir
191 archive_url_non_staged = base_url + 'x86-awesome-release/R99-1234.0-r2'
Chris Sosa9164ca32012-03-28 18:04:50192 # Create the directory to reflect staging.
Yu-Ju Hongd49d7f42012-06-25 19:23:11193 os.makedirs(os.path.join(self._work_dir, build_dir))
Chris Sosa9164ca32012-03-28 18:04:50194
195 self.assertTrue(downloader.Downloader.BuildStaged(archive_url,
196 self._work_dir))
Alex Millera44d5022012-07-27 18:34:16197 self.assertTrue(os.path.exists(
198 os.path.join(os.path.join(self._work_dir, build_dir),
199 downloader.Downloader._TIMESTAMP_FILENAME)))
Chris Sosa9164ca32012-03-28 18:04:50200 self.assertFalse(downloader.Downloader.BuildStaged(archive_url_non_staged,
201 self._work_dir))
Yu-Ju Hongd49d7f42012-06-25 19:23:11202 def testTrybotBuildStaged(self):
203 """Test whether a previous staged trybot-build can be corrected detected"""
204 base_url = 'gs://chrome-awesome/'
205 build_dir = 'trybot/date/x86-awesome-release/R99-1234.0-r1'
206 archive_url = base_url + build_dir
207 archive_url_non_staged = base_url + 'x86-awesome-release/R99-1234.0-r2'
208 # Create the directory to reflect staging.
209 os.makedirs(os.path.join(self._work_dir, build_dir))
Chris Sosa9164ca32012-03-28 18:04:50210
Yu-Ju Hongd49d7f42012-06-25 19:23:11211 self.assertTrue(downloader.Downloader.BuildStaged(archive_url,
212 self._work_dir))
213 self.assertFalse(downloader.Downloader.BuildStaged(archive_url_non_staged,
214 self._work_dir))
Chris Sosa47a7d4e2012-03-28 18:26:55215
Chris Masone816e38c2012-05-02 19:22:36216class SymbolDownloaderTest(DownloaderTestBase):
217 """Unit tests for downloader.SymbolDownloader.
218
219 setUp() and tearDown() inherited from DownloaderTestBase.
220 """
221
222 def _CreateArtifactDownloader(self, artifacts):
223 d = downloader.SymbolDownloader(self._work_dir)
224 self.mox.StubOutWithMock(d, 'GatherArtifactDownloads')
225 d.GatherArtifactDownloads(
Gilad Arnold6f99b982012-09-12 17:49:40226 self._work_dir, self.archive_url_prefix,
Chris Masone816e38c2012-05-02 19:22:36227 self._work_dir).AndReturn(artifacts)
228 return d
229
230 def _ClassUnderTest(self):
231 return downloader.SymbolDownloader
232
Chris Sosaf0975642012-06-29 20:53:42233 def _GenerateArtifacts(self, unused_ignore_background):
Chris Masone816e38c2012-05-02 19:22:36234 """Instantiate artifact mocks and set expectations on them.
235
Gilad Arnoldc65330c2012-09-20 22:17:48236 Sets up a DebugTarballBuildArtifact and sets up expectation that it will be
Chris Masone816e38c2012-05-02 19:22:36237 downloaded and staged.
238
239 @return iterable of one artifact object with appropriate expectations.
240 """
Gilad Arnoldc65330c2012-09-20 22:17:48241 artifact = self.mox.CreateMock(build_artifact.BuildArtifact)
Chris Masone816e38c2012-05-02 19:22:36242 artifact.Synchronous = lambda: True
243 artifact.Download()
244 artifact.Stage()
245 return [artifact]
246
247 def testDownloaderSerially(self):
248 """Runs through the symbol downloader workflow."""
249 d = self._CreateArtifactDownloader(self._CommonDownloaderSetup())
250
251 self.mox.ReplayAll()
252 self.assertEqual(d.Download(self.archive_url_prefix), 'Success')
253 self.mox.VerifyAll()
254
255
Chris Sosa47a7d4e2012-03-28 18:26:55256if __name__ == '__main__':
257 unittest.main()