blob: b9a1c8599fdd42a907346fdd5c81992a19586227 [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
42 def _CommonDownloaderSetup(self):
43 """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 Masone816e38c2012-05-02 12:22:36 -070048 @return iterable of artifact objects with appropriate expectations.
Chris Sosa47a7d4e2012-03-28 11:26:55 -070049 """
50 board = 'x86-mario-release'
51 self.mox.StubOutWithMock(devserver_util, 'AcquireLock')
52 self.mox.StubOutWithMock(devserver_util, 'GatherArtifactDownloads')
53 self.mox.StubOutWithMock(devserver_util, 'ReleaseLock')
54 self.mox.StubOutWithMock(tempfile, 'mkdtemp')
55
Chris Masone816e38c2012-05-02 12:22:36 -070056 devserver_util.AcquireLock(
57 static_dir=self._work_dir,
58 tag=self._ClassUnderTest().GenerateLockTag(board, self.build)
59 ).AndReturn(self._work_dir)
Chris Sosa47a7d4e2012-03-28 11:26:55 -070060
Chris Masone816e38c2012-05-02 12:22:36 -070061 tempfile.mkdtemp(suffix=mox.IgnoreArg()).AndReturn(self._work_dir)
62 return self._GenerateArtifacts()
63
64 def _CreateArtifactDownloader(self, artifacts):
65 """Create and return a Downloader of the appropriate type.
66
67 The returned downloader will expect to download and stage the
68 DownloadableArtifacts listed in [artifacts].
69
70 @param artifacts: iterable of DownloadableArtifacts.
71 @return instance of downloader.Downloader or subclass.
72 """
73 raise NotImplementedError()
74
75 def _ClassUnderTest(self):
76 """Return class object of the type being tested.
77
78 @return downloader.Downloader class object, or subclass.
79 """
80 raise NotImplementedError()
81
82 def _GenerateArtifacts(self):
83 """Instantiate artifact mocks and set expectations on them.
84
85 @return iterable of artifact objects with appropriate expectations.
86 """
87 raise NotImplementedError()
88
89
90class DownloaderTest(DownloaderTestBase):
91 """Unit tests for downloader.Downloader.
92
93 setUp() and tearDown() inherited from DownloaderTestBase.
94 """
95
96 def _CreateArtifactDownloader(self, artifacts):
97 d = downloader.Downloader(self._work_dir)
98 self.mox.StubOutWithMock(d, 'GatherArtifactDownloads')
99 d.GatherArtifactDownloads(
100 self._work_dir, self.archive_url_prefix, self.build,
101 self._work_dir).AndReturn(artifacts)
102 return d
103
104 def _ClassUnderTest(self):
105 return downloader.Downloader
106
107 def _GenerateArtifacts(self):
108 """Instantiate artifact mocks and set expectations on them.
109
110 Sets up artifacts and sets up expectations for synchronous artifacts to
111 be downloaded first.
112
113 @return iterable of artifact objects with appropriate expectations.
114 """
115 artifacts = []
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700116 for index in range(5):
Chris Masone816e38c2012-05-02 12:22:36 -0700117 artifact = self.mox.CreateMock(downloadable_artifact.DownloadableArtifact)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700118 # Make every other artifact synchronous.
119 if index % 2 == 0:
120 artifact.Synchronous = lambda: True
Chris Masone816e38c2012-05-02 12:22:36 -0700121 artifact.Download()
122 artifact.Stage()
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700123 else:
124 artifact.Synchronous = lambda: False
125
126 artifacts.append(artifact)
127
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700128 return artifacts
129
130 def testDownloaderSerially(self):
131 """Runs through the standard downloader workflow with no backgrounding."""
132 artifacts = self._CommonDownloaderSetup()
133
134 # Downloads non-synchronous artifacts second.
135 for index, artifact in enumerate(artifacts):
136 if index % 2 != 0:
137 artifact.Download()
138 artifact.Stage()
139
Chris Masone816e38c2012-05-02 12:22:36 -0700140 d = self._CreateArtifactDownloader(artifacts)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700141 self.mox.ReplayAll()
Chris Masone816e38c2012-05-02 12:22:36 -0700142 self.assertEqual(d.Download(self.archive_url_prefix, background=False),
143 'Success')
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700144 self.mox.VerifyAll()
145
146 def testDownloaderInBackground(self):
147 """Runs through the standard downloader workflow with backgrounding."""
148 artifacts = self._CommonDownloaderSetup()
149
150 # Downloads non-synchronous artifacts second.
151 for index, artifact in enumerate(artifacts):
152 if index % 2 != 0:
153 artifact.Download()
154 artifact.Stage()
155
Chris Masone816e38c2012-05-02 12:22:36 -0700156 d = self._CreateArtifactDownloader(artifacts)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700157 self.mox.ReplayAll()
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700158 d.Download(self.archive_url_prefix, background=True)
159 self.assertEqual(d.GetStatusOfBackgroundDownloads(), 'Success')
160 self.mox.VerifyAll()
161
162 def testInteractionWithDevserver(self):
Chris Sosa9164ca32012-03-28 11:04:50 -0700163 """Tests interaction between the downloader and devserver methods."""
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700164 artifacts = self._CommonDownloaderSetup()
Chris Masone816e38c2012-05-02 12:22:36 -0700165 devserver_util.GatherArtifactDownloads(
166 self._work_dir, self.archive_url_prefix, self.build,
167 self._work_dir).AndReturn(artifacts)
168
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700169 class FakeUpdater():
170 static_dir = self._work_dir
171
172 devserver.updater = FakeUpdater()
173
174 # Downloads non-synchronous artifacts second.
175 for index, artifact in enumerate(artifacts):
176 if index % 2 != 0:
177 artifact.Download()
178 artifact.Stage()
179
180 self.mox.ReplayAll()
181 dev = devserver.DevServerRoot()
182 status = dev.download(archive_url=self.archive_url_prefix)
183 self.assertTrue(status, 'Success')
184 status = dev.wait_for_status(archive_url=self.archive_url_prefix)
185 self.assertTrue(status, 'Success')
186 self.mox.VerifyAll()
187
Chris Sosa9164ca32012-03-28 11:04:50 -0700188 def testBuildStaged(self):
189 """Test whether we can correctly check if a build is previously staged."""
Yu-Ju Hongd49d7f42012-06-25 12:23:11 -0700190 base_url = 'gs://chrome-awesome/'
191 build_dir = 'x86-awesome-release/R99-1234.0-r1'
192 archive_url = base_url + build_dir
193 archive_url_non_staged = base_url + 'x86-awesome-release/R99-1234.0-r2'
Chris Sosa9164ca32012-03-28 11:04:50 -0700194 # Create the directory to reflect staging.
Yu-Ju Hongd49d7f42012-06-25 12:23:11 -0700195 os.makedirs(os.path.join(self._work_dir, build_dir))
Chris Sosa9164ca32012-03-28 11:04:50 -0700196
197 self.assertTrue(downloader.Downloader.BuildStaged(archive_url,
198 self._work_dir))
199 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
232 def _GenerateArtifacts(self):
233 """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()