blob: 7ec883a4a4ad92e0597f45e64768349f0473a883 [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
Gilad Arnoldc65330c2012-09-20 15:17:48 -07007"""Unit tests for downloader module."""
Chris Sosa47a7d4e2012-03-28 11:26:55 -07008
Chris Sosa47a7d4e2012-03-28 11:26:55 -07009import os
10import shutil
11import tempfile
12import unittest
13
Gilad Arnoldabb352e2012-09-23 01:24:27 -070014import mox
15
Gilad Arnoldc65330c2012-09-20 15:17:48 -070016import build_artifact
17import common_util
Chris Sosa47a7d4e2012-03-28 11:26:55 -070018import devserver
Chris Sosa47a7d4e2012-03-28 11:26:55 -070019import 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 12:22:36 -070030class DownloaderTestBase(mox.MoxTestBase):
Chris Sosa47a7d4e2012-03-28 11:26:55 -070031
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 14:35:44 -070040 shutil.rmtree(self._work_dir, ignore_errors=True)
Chris Sosa47a7d4e2012-03-28 11:26:55 -070041
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
Gilad Arnoldc65330c2012-09-20 15:17:48 -070045 Mocks out key util module methods, creates mock artifacts and sets
46 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'
Gilad Arnoldc65330c2012-09-20 15:17:48 -070053 self.mox.StubOutWithMock(common_util, 'AcquireLock')
54 self.mox.StubOutWithMock(common_util, 'GatherArtifactDownloads')
55 self.mox.StubOutWithMock(common_util, 'ReleaseLock')
Chris Sosa47a7d4e2012-03-28 11:26:55 -070056 self.mox.StubOutWithMock(tempfile, 'mkdtemp')
57
Gilad Arnold5174ca22012-09-12 10:49:09 -070058 lock_tag = self._ClassUnderTest().GenerateLockTag(board, self.build)
Gilad Arnoldc65330c2012-09-20 15:17:48 -070059 common_util.AcquireLock(
Chris Masone816e38c2012-05-02 12:22:36 -070060 static_dir=self._work_dir,
Gilad Arnold5174ca22012-09-12 10:49:09 -070061 tag=lock_tag).AndReturn(self._work_dir)
Gilad Arnoldc65330c2012-09-20 15:17:48 -070062 common_util.ReleaseLock(static_dir=self._work_dir, tag=lock_tag)
Chris Sosa47a7d4e2012-03-28 11:26:55 -070063
Chris Masone816e38c2012-05-02 12:22:36 -070064 tempfile.mkdtemp(suffix=mox.IgnoreArg()).AndReturn(self._work_dir)
Chris Sosaf0975642012-06-29 13:53:42 -070065 return self._GenerateArtifacts(ignore_background)
Chris Masone816e38c2012-05-02 12:22:36 -070066
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 15:17:48 -070071 Artifacts listed in [artifacts].
Chris Masone816e38c2012-05-02 12:22:36 -070072
Gilad Arnoldc65330c2012-09-20 15:17:48 -070073 @param artifacts: iterable of Artifacts.
Chris Masone816e38c2012-05-02 12:22:36 -070074 @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 13:53:42 -070085 def _GenerateArtifacts(self, ignore_background):
Chris Masone816e38c2012-05-02 12:22:36 -070086 """Instantiate artifact mocks and set expectations on them.
87
Chris Sosaf0975642012-06-29 13:53:42 -070088 @ignore_background Indicate that background artifacts should be ignored.
89 This gets passed by CommonDownloaderSetup.
90
Chris Masone816e38c2012-05-02 12:22:36 -070091 @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 10:49:40 -0700106 self._work_dir, self.archive_url_prefix, self._work_dir,
107 self.build).AndReturn(artifacts)
Chris Masone816e38c2012-05-02 12:22:36 -0700108 return d
109
110 def _ClassUnderTest(self):
111 return downloader.Downloader
112
Chris Sosaf0975642012-06-29 13:53:42 -0700113 def _GenerateArtifacts(self, ignore_background):
Chris Masone816e38c2012-05-02 12:22:36 -0700114 """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 13:53:42 -0700119 @ignore_background If True, doesn't use mocks for download/stage methods.
120
Chris Masone816e38c2012-05-02 12:22:36 -0700121 @return iterable of artifact objects with appropriate expectations.
122 """
123 artifacts = []
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700124 for index in range(5):
Gilad Arnoldc65330c2012-09-20 15:17:48 -0700125 artifact = self.mox.CreateMock(build_artifact.BuildArtifact)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700126 # Make every other artifact synchronous.
127 if index % 2 == 0:
128 artifact.Synchronous = lambda: True
Chris Masone816e38c2012-05-02 12:22:36 -0700129 artifact.Download()
130 artifact.Stage()
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700131 else:
132 artifact.Synchronous = lambda: False
Chris Sosaf0975642012-06-29 13:53:42 -0700133 if ignore_background:
134 artifact.Download = lambda: None
135 artifact.Stage = lambda: None
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700136
137 artifacts.append(artifact)
138
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700139 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 12:22:36 -0700151 d = self._CreateArtifactDownloader(artifacts)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700152 self.mox.ReplayAll()
Chris Masone816e38c2012-05-02 12:22:36 -0700153 self.assertEqual(d.Download(self.archive_url_prefix, background=False),
154 'Success')
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700155 self.mox.VerifyAll()
156
157 def testDownloaderInBackground(self):
158 """Runs through the standard downloader workflow with backgrounding."""
Chris Sosaf0975642012-06-29 13:53:42 -0700159 artifacts = self._CommonDownloaderSetup(ignore_background=True)
Chris Masone816e38c2012-05-02 12:22:36 -0700160 d = self._CreateArtifactDownloader(artifacts)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700161 self.mox.ReplayAll()
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700162 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 11:04:50 -0700167 """Tests interaction between the downloader and devserver methods."""
Chris Sosaf0975642012-06-29 13:53:42 -0700168 artifacts = self._CommonDownloaderSetup(ignore_background=True)
Gilad Arnoldc65330c2012-09-20 15:17:48 -0700169 common_util.GatherArtifactDownloads(
Gilad Arnold6f99b982012-09-12 10:49:40 -0700170 self._work_dir, self.archive_url_prefix, self._work_dir,
171 self.build).AndReturn(artifacts)
Chris Masone816e38c2012-05-02 12:22:36 -0700172
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700173 class FakeUpdater():
174 static_dir = self._work_dir
175
176 devserver.updater = FakeUpdater()
177
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700178 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 11:04:50 -0700186 def testBuildStaged(self):
187 """Test whether we can correctly check if a build is previously staged."""
Yu-Ju Hongd49d7f42012-06-25 12:23:11 -0700188 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 11:04:50 -0700192 # Create the directory to reflect staging.
Yu-Ju Hongd49d7f42012-06-25 12:23:11 -0700193 os.makedirs(os.path.join(self._work_dir, build_dir))
Chris Sosa9164ca32012-03-28 11:04:50 -0700194
195 self.assertTrue(downloader.Downloader.BuildStaged(archive_url,
196 self._work_dir))
Alex Millera44d5022012-07-27 11:34:16 -0700197 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 11:04:50 -0700200 self.assertFalse(downloader.Downloader.BuildStaged(archive_url_non_staged,
201 self._work_dir))
Yu-Ju Hongd49d7f42012-06-25 12:23:11 -0700202 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 11:04:50 -0700210
Yu-Ju Hongd49d7f42012-06-25 12:23:11 -0700211 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 11:26:55 -0700215
Chris Masone816e38c2012-05-02 12:22:36 -0700216class 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 10:49:40 -0700226 self._work_dir, self.archive_url_prefix,
Chris Masone816e38c2012-05-02 12:22:36 -0700227 self._work_dir).AndReturn(artifacts)
228 return d
229
230 def _ClassUnderTest(self):
231 return downloader.SymbolDownloader
232
Chris Sosaf0975642012-06-29 13:53:42 -0700233 def _GenerateArtifacts(self, unused_ignore_background):
Chris Masone816e38c2012-05-02 12:22:36 -0700234 """Instantiate artifact mocks and set expectations on them.
235
Gilad Arnoldc65330c2012-09-20 15:17:48 -0700236 Sets up a DebugTarballBuildArtifact and sets up expectation that it will be
Chris Masone816e38c2012-05-02 12:22:36 -0700237 downloaded and staged.
238
239 @return iterable of one artifact object with appropriate expectations.
240 """
Gilad Arnoldc65330c2012-09-20 15:17:48 -0700241 artifact = self.mox.CreateMock(build_artifact.BuildArtifact)
Chris Masone816e38c2012-05-02 12:22:36 -0700242 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 11:26:55 -0700256if __name__ == '__main__':
257 unittest.main()