blob: 56df93c8832dac305486eb950eb6495d3d1036d9 [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
Gilad Arnold5174ca22012-09-12 10:49:09 -070057 lock_tag = self._ClassUnderTest().GenerateLockTag(board, self.build)
Chris Masone816e38c2012-05-02 12:22:36 -070058 devserver_util.AcquireLock(
59 static_dir=self._work_dir,
Gilad Arnold5174ca22012-09-12 10:49:09 -070060 tag=lock_tag).AndReturn(self._work_dir)
61 devserver_util.ReleaseLock(
62 static_dir=self._work_dir,
63 tag=lock_tag)
Chris Sosa47a7d4e2012-03-28 11:26:55 -070064
Chris Masone816e38c2012-05-02 12:22:36 -070065 tempfile.mkdtemp(suffix=mox.IgnoreArg()).AndReturn(self._work_dir)
Chris Sosaf0975642012-06-29 13:53:42 -070066 return self._GenerateArtifacts(ignore_background)
Chris Masone816e38c2012-05-02 12:22:36 -070067
68 def _CreateArtifactDownloader(self, artifacts):
69 """Create and return a Downloader of the appropriate type.
70
71 The returned downloader will expect to download and stage the
72 DownloadableArtifacts listed in [artifacts].
73
74 @param artifacts: iterable of DownloadableArtifacts.
75 @return instance of downloader.Downloader or subclass.
76 """
77 raise NotImplementedError()
78
79 def _ClassUnderTest(self):
80 """Return class object of the type being tested.
81
82 @return downloader.Downloader class object, or subclass.
83 """
84 raise NotImplementedError()
85
Chris Sosaf0975642012-06-29 13:53:42 -070086 def _GenerateArtifacts(self, ignore_background):
Chris Masone816e38c2012-05-02 12:22:36 -070087 """Instantiate artifact mocks and set expectations on them.
88
Chris Sosaf0975642012-06-29 13:53:42 -070089 @ignore_background Indicate that background artifacts should be ignored.
90 This gets passed by CommonDownloaderSetup.
91
Chris Masone816e38c2012-05-02 12:22:36 -070092 @return iterable of artifact objects with appropriate expectations.
93 """
94 raise NotImplementedError()
95
96
97class DownloaderTest(DownloaderTestBase):
98 """Unit tests for downloader.Downloader.
99
100 setUp() and tearDown() inherited from DownloaderTestBase.
101 """
102
103 def _CreateArtifactDownloader(self, artifacts):
104 d = downloader.Downloader(self._work_dir)
105 self.mox.StubOutWithMock(d, 'GatherArtifactDownloads')
106 d.GatherArtifactDownloads(
107 self._work_dir, self.archive_url_prefix, self.build,
108 self._work_dir).AndReturn(artifacts)
109 return d
110
111 def _ClassUnderTest(self):
112 return downloader.Downloader
113
Chris Sosaf0975642012-06-29 13:53:42 -0700114 def _GenerateArtifacts(self, ignore_background):
Chris Masone816e38c2012-05-02 12:22:36 -0700115 """Instantiate artifact mocks and set expectations on them.
116
117 Sets up artifacts and sets up expectations for synchronous artifacts to
118 be downloaded first.
119
Chris Sosaf0975642012-06-29 13:53:42 -0700120 @ignore_background If True, doesn't use mocks for download/stage methods.
121
Chris Masone816e38c2012-05-02 12:22:36 -0700122 @return iterable of artifact objects with appropriate expectations.
123 """
124 artifacts = []
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700125 for index in range(5):
Chris Masone816e38c2012-05-02 12:22:36 -0700126 artifact = self.mox.CreateMock(downloadable_artifact.DownloadableArtifact)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700127 # Make every other artifact synchronous.
128 if index % 2 == 0:
129 artifact.Synchronous = lambda: True
Chris Masone816e38c2012-05-02 12:22:36 -0700130 artifact.Download()
131 artifact.Stage()
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700132 else:
133 artifact.Synchronous = lambda: False
Chris Sosaf0975642012-06-29 13:53:42 -0700134 if ignore_background:
135 artifact.Download = lambda: None
136 artifact.Stage = lambda: None
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700137
138 artifacts.append(artifact)
139
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700140 return artifacts
141
142 def testDownloaderSerially(self):
143 """Runs through the standard downloader workflow with no backgrounding."""
144 artifacts = self._CommonDownloaderSetup()
145
146 # Downloads non-synchronous artifacts second.
147 for index, artifact in enumerate(artifacts):
148 if index % 2 != 0:
149 artifact.Download()
150 artifact.Stage()
151
Chris Masone816e38c2012-05-02 12:22:36 -0700152 d = self._CreateArtifactDownloader(artifacts)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700153 self.mox.ReplayAll()
Chris Masone816e38c2012-05-02 12:22:36 -0700154 self.assertEqual(d.Download(self.archive_url_prefix, background=False),
155 'Success')
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700156 self.mox.VerifyAll()
157
158 def testDownloaderInBackground(self):
159 """Runs through the standard downloader workflow with backgrounding."""
Chris Sosaf0975642012-06-29 13:53:42 -0700160 artifacts = self._CommonDownloaderSetup(ignore_background=True)
Chris Masone816e38c2012-05-02 12:22:36 -0700161 d = self._CreateArtifactDownloader(artifacts)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700162 self.mox.ReplayAll()
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700163 d.Download(self.archive_url_prefix, background=True)
164 self.assertEqual(d.GetStatusOfBackgroundDownloads(), 'Success')
165 self.mox.VerifyAll()
166
167 def testInteractionWithDevserver(self):
Chris Sosa9164ca32012-03-28 11:04:50 -0700168 """Tests interaction between the downloader and devserver methods."""
Chris Sosaf0975642012-06-29 13:53:42 -0700169 artifacts = self._CommonDownloaderSetup(ignore_background=True)
Chris Masone816e38c2012-05-02 12:22:36 -0700170 devserver_util.GatherArtifactDownloads(
171 self._work_dir, self.archive_url_prefix, self.build,
172 self._work_dir).AndReturn(artifacts)
173
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700174 class FakeUpdater():
175 static_dir = self._work_dir
176
177 devserver.updater = FakeUpdater()
178
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700179 self.mox.ReplayAll()
180 dev = devserver.DevServerRoot()
181 status = dev.download(archive_url=self.archive_url_prefix)
182 self.assertTrue(status, 'Success')
183 status = dev.wait_for_status(archive_url=self.archive_url_prefix)
184 self.assertTrue(status, 'Success')
185 self.mox.VerifyAll()
186
Chris Sosa9164ca32012-03-28 11:04:50 -0700187 def testBuildStaged(self):
188 """Test whether we can correctly check if a build is previously staged."""
Yu-Ju Hongd49d7f42012-06-25 12:23:11 -0700189 base_url = 'gs://chrome-awesome/'
190 build_dir = 'x86-awesome-release/R99-1234.0-r1'
191 archive_url = base_url + build_dir
192 archive_url_non_staged = base_url + 'x86-awesome-release/R99-1234.0-r2'
Chris Sosa9164ca32012-03-28 11:04:50 -0700193 # Create the directory to reflect staging.
Yu-Ju Hongd49d7f42012-06-25 12:23:11 -0700194 os.makedirs(os.path.join(self._work_dir, build_dir))
Chris Sosa9164ca32012-03-28 11:04:50 -0700195
196 self.assertTrue(downloader.Downloader.BuildStaged(archive_url,
197 self._work_dir))
Alex Millera44d5022012-07-27 11:34:16 -0700198 self.assertTrue(os.path.exists(
199 os.path.join(os.path.join(self._work_dir, build_dir),
200 downloader.Downloader._TIMESTAMP_FILENAME)))
Chris Sosa9164ca32012-03-28 11:04:50 -0700201 self.assertFalse(downloader.Downloader.BuildStaged(archive_url_non_staged,
202 self._work_dir))
Yu-Ju Hongd49d7f42012-06-25 12:23:11 -0700203 def testTrybotBuildStaged(self):
204 """Test whether a previous staged trybot-build can be corrected detected"""
205 base_url = 'gs://chrome-awesome/'
206 build_dir = 'trybot/date/x86-awesome-release/R99-1234.0-r1'
207 archive_url = base_url + build_dir
208 archive_url_non_staged = base_url + 'x86-awesome-release/R99-1234.0-r2'
209 # Create the directory to reflect staging.
210 os.makedirs(os.path.join(self._work_dir, build_dir))
Chris Sosa9164ca32012-03-28 11:04:50 -0700211
Yu-Ju Hongd49d7f42012-06-25 12:23:11 -0700212 self.assertTrue(downloader.Downloader.BuildStaged(archive_url,
213 self._work_dir))
214 self.assertFalse(downloader.Downloader.BuildStaged(archive_url_non_staged,
215 self._work_dir))
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700216
Chris Masone816e38c2012-05-02 12:22:36 -0700217class SymbolDownloaderTest(DownloaderTestBase):
218 """Unit tests for downloader.SymbolDownloader.
219
220 setUp() and tearDown() inherited from DownloaderTestBase.
221 """
222
223 def _CreateArtifactDownloader(self, artifacts):
224 d = downloader.SymbolDownloader(self._work_dir)
225 self.mox.StubOutWithMock(d, 'GatherArtifactDownloads')
226 d.GatherArtifactDownloads(
227 self._work_dir, self.archive_url_prefix, '',
228 self._work_dir).AndReturn(artifacts)
229 return d
230
231 def _ClassUnderTest(self):
232 return downloader.SymbolDownloader
233
Chris Sosaf0975642012-06-29 13:53:42 -0700234 def _GenerateArtifacts(self, unused_ignore_background):
Chris Masone816e38c2012-05-02 12:22:36 -0700235 """Instantiate artifact mocks and set expectations on them.
236
237 Sets up a DebugTarball and sets up expectation that it will be
238 downloaded and staged.
239
240 @return iterable of one artifact object with appropriate expectations.
241 """
242 artifact = self.mox.CreateMock(downloadable_artifact.DownloadableArtifact)
243 artifact.Synchronous = lambda: True
244 artifact.Download()
245 artifact.Stage()
246 return [artifact]
247
248 def testDownloaderSerially(self):
249 """Runs through the symbol downloader workflow."""
250 d = self._CreateArtifactDownloader(self._CommonDownloaderSetup())
251
252 self.mox.ReplayAll()
253 self.assertEqual(d.Download(self.archive_url_prefix), 'Success')
254 self.mox.VerifyAll()
255
256
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700257if __name__ == '__main__':
258 unittest.main()