blob: 447082505ff55ff292dcaf9c7359b26ab37c0117 [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 build_artifact module.
Chris Sosa47a7d4e2012-03-28 11:26:55 -07008
9These unit tests take tarball from google storage locations to fully test
Chris Sosa76e44b92013-01-31 12:11:38 -080010the artifact download process. Please make sure to set up your boto file.
Chris Sosa47a7d4e2012-03-28 11:26:55 -070011"""
12
Chris Sosa47a7d4e2012-03-28 11:26:55 -070013import os
Gilad Arnold1638d822013-11-07 23:38:16 -080014import random
Chris Sosa47a7d4e2012-03-28 11:26:55 -070015import shutil
16import subprocess
17import tempfile
18import unittest
19
Gilad Arnoldabb352e2012-09-23 01:24:27 -070020import mox
21
Gilad Arnoldc65330c2012-09-20 15:17:48 -070022import build_artifact
Gilad Arnold1638d822013-11-07 23:38:16 -080023import devserver_constants
Chris Sosa47a7d4e2012-03-28 11:26:55 -070024
Gilad Arnoldabb352e2012-09-23 01:24:27 -070025
Chris Sosa76e44b92013-01-31 12:11:38 -080026_VERSION = 'R26-3646.0.0-rc1'
Chris Sosa47a7d4e2012-03-28 11:26:55 -070027_TEST_GOLO_ARCHIVE = (
Chris Sosa76e44b92013-01-31 12:11:38 -080028 'gs://chromeos-image-archive/x86-generic-chromium-pfq/R26-3646.0.0-rc1')
Dan Shi6e50c722013-08-19 15:05:06 -070029_TEST_NON_EXISTING_GOLO_ARCHIVE = (
30 'gs://chromeos-image-archive/x86-generic-chromium-pfq/R26-no_such_build')
Chris Sosa76e44b92013-01-31 12:11:38 -080031
Gilad Arnold1638d822013-11-07 23:38:16 -080032_TEST_GOLO_ARCHIVE_TEST_TARBALL_CONTENT = [
33 'autotest/test_suites/control.PGO_record',
34 'autotest/test_suites/control.au',
35 'autotest/test_suites/control.audio',
36 'autotest/test_suites/control.browsertests',
37 'autotest/test_suites/control.bvt',
38 'autotest/test_suites/control.dummy',
39 'autotest/test_suites/control.enterprise',
40 'autotest/test_suites/control.enterprise_enroll',
41 'autotest/test_suites/control.faft_dev',
42 'autotest/test_suites/control.faft_ec',
43 'autotest/test_suites/control.faft_normal',
44 'autotest/test_suites/control.graphics',
45 'autotest/test_suites/control.graphicsGLES',
46 'autotest/test_suites/control.hwqual',
47 'autotest/test_suites/control.kernel_daily_benchmarks',
48 'autotest/test_suites/control.kernel_daily_regression',
49 'autotest/test_suites/control.kernel_per-build_benchmarks',
50 'autotest/test_suites/control.kernel_per-build_regression',
51 'autotest/test_suites/control.kernel_weekly_regression',
52 'autotest/test_suites/control.link_perf',
53 'autotest/test_suites/control.network3g',
54 'autotest/test_suites/control.network3g_gobi',
55 'autotest/test_suites/control.network_wifi',
56 'autotest/test_suites/control.onccell',
57 'autotest/test_suites/control.pagecycler',
58 'autotest/test_suites/control.perfalerts',
59 'autotest/test_suites/control.power_build',
60 'autotest/test_suites/control.power_daily',
61 'autotest/test_suites/control.power_requirements',
62 'autotest/test_suites/control.pyauto',
63 'autotest/test_suites/control.pyauto_basic',
64 'autotest/test_suites/control.pyauto_endurance',
65 'autotest/test_suites/control.pyauto_perf',
66 'autotest/test_suites/control.regression',
67 'autotest/test_suites/control.security',
68 'autotest/test_suites/control.servo',
69 'autotest/test_suites/control.smoke',
70 'autotest/test_suites/control.sync',
71 'autotest/test_suites/control.vda',
72 'autotest/test_suites/control.video',
73 'autotest/test_suites/control.webrtc',
74 'autotest/test_suites/control.wificell',
75 'autotest/test_suites/control.wifichaos',
76 'autotest/test_suites/dependency_info',
77 'autotest/test_suites/dev_harness.py',
78]
79
80_TEST_GOLO_ARCHIVE_IMAGE_ZIPFILE_CONTENT = [
81 'au-generator.zip',
82 'boot.config',
83 'boot.desc',
84 'chromiumos_qemu_image.bin',
85 'chromiumos_test_image.bin',
86 'config.txt',
87 'mount_image.sh',
88 'oem.image',
89 'pack_partitions.sh',
90 'umount_image.sh',
91 'unpack_partitions.sh',
92]
93
94
Chris Sosa76e44b92013-01-31 12:11:38 -080095# Different as the above does not have deltas (for smaller artifacts).
96_DELTA_VERSION = 'R26-3645.0.0'
97_TEST_GOLO_FOR_DELTAS = (
98 'gs://chromeos-image-archive/x86-mario-release/R26-3645.0.0')
Yu-Ju Honge61cbe92012-07-10 14:10:26 -070099
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700100
Chris Sosa76e44b92013-01-31 12:11:38 -0800101# pylint: disable=W0212
Gilad Arnoldc65330c2012-09-20 15:17:48 -0700102class BuildArtifactTest(mox.MoxTestBase):
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700103
104 def setUp(self):
105 mox.MoxTestBase.setUp(self)
Chris Sosa76e44b92013-01-31 12:11:38 -0800106 self.work_dir = tempfile.mkdtemp('build_artifact_unittest')
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700107
108 def tearDown(self):
109 shutil.rmtree(self.work_dir)
110
Gilad Arnold1638d822013-11-07 23:38:16 -0800111 def _CheckMarker(self, marker_file, installed_files):
112 with open(os.path.join(self.work_dir, marker_file)) as f:
113 self.assertItemsEqual(installed_files, [line.strip() for line in f])
114
Yu-Ju Hong5d5bf0d2014-02-11 21:38:20 -0800115 def testBundledArtifactTypes(self):
116 """Tests that all known bundled artifacts are either zip or tar files."""
117 known_names = ['zip', '.tgz', '.tar', 'tar.bz2', 'tar.xz', 'tar.gz']
118 for d in build_artifact.ARTIFACT_IMPLEMENTATION_MAP.values():
119 if d.artifact_class == build_artifact.BundledBuildArtifact:
120 for name in known_names:
121 if d.name.endswith(name):
122 break
123 else:
124 self.assertTrue('False')
125
Chris Sosa76e44b92013-01-31 12:11:38 -0800126 def testProcessBuildArtifact(self):
127 """Processes a real tarball from GSUtil and stages it."""
Gilad Arnoldc65330c2012-09-20 15:17:48 -0700128 artifact = build_artifact.BuildArtifact(
Chris Sosa76e44b92013-01-31 12:11:38 -0800129 self.work_dir,
130 _TEST_GOLO_ARCHIVE, build_artifact.TEST_SUITES_FILE, _VERSION)
131 artifact.Process(False)
Gilad Arnold1638d822013-11-07 23:38:16 -0800132 self.assertItemsEqual(
133 artifact.installed_files,
134 [os.path.join(self.work_dir, build_artifact.TEST_SUITES_FILE)])
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700135 self.assertTrue(os.path.exists(os.path.join(
Chris Sosa76e44b92013-01-31 12:11:38 -0800136 self.work_dir, build_artifact.TEST_SUITES_FILE)))
Gilad Arnold1638d822013-11-07 23:38:16 -0800137 self._CheckMarker(artifact.marker_name, artifact.installed_files)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700138
Chris Sosa76e44b92013-01-31 12:11:38 -0800139 def testProcessTarball(self):
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700140 """Downloads a real tarball and untars it."""
Yu-Ju Hong5d5bf0d2014-02-11 21:38:20 -0800141 artifact = build_artifact.BundledBuildArtifact(
Chris Sosa76e44b92013-01-31 12:11:38 -0800142 self.work_dir, _TEST_GOLO_ARCHIVE, build_artifact.TEST_SUITES_FILE,
143 _VERSION)
Gilad Arnold1638d822013-11-07 23:38:16 -0800144 expected_installed_files = [
145 os.path.join(self.work_dir, filename)
146 for filename in ([build_artifact.TEST_SUITES_FILE] +
147 _TEST_GOLO_ARCHIVE_TEST_TARBALL_CONTENT)]
Chris Sosa76e44b92013-01-31 12:11:38 -0800148 artifact.Process(False)
Gilad Arnold1638d822013-11-07 23:38:16 -0800149 self.assertItemsEqual(artifact.installed_files, expected_installed_files)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700150 self.assertTrue(os.path.isdir(os.path.join(
Chris Sosa76e44b92013-01-31 12:11:38 -0800151 self.work_dir, 'autotest', 'test_suites')))
Gilad Arnold1638d822013-11-07 23:38:16 -0800152 self._CheckMarker(artifact.marker_name, artifact.installed_files)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700153
Chris Sosa76e44b92013-01-31 12:11:38 -0800154 def testProcessTarballWithFile(self):
155 """Downloads a real tarball and only untars one file from it."""
156 file_to_download = 'autotest/test_suites/control.au'
Yu-Ju Hong5d5bf0d2014-02-11 21:38:20 -0800157 artifact = build_artifact.BundledBuildArtifact(
Chris Sosa76e44b92013-01-31 12:11:38 -0800158 self.work_dir, _TEST_GOLO_ARCHIVE, build_artifact.TEST_SUITES_FILE,
Gilad Arnold1638d822013-11-07 23:38:16 -0800159 _VERSION, files_to_extract=[file_to_download])
160 expected_installed_files = [
161 os.path.join(self.work_dir, filename)
162 for filename in [build_artifact.TEST_SUITES_FILE] + [file_to_download]]
Chris Sosa76e44b92013-01-31 12:11:38 -0800163 artifact.Process(False)
Gilad Arnold1638d822013-11-07 23:38:16 -0800164 self.assertItemsEqual(artifact.installed_files, expected_installed_files)
Chris Sosa76e44b92013-01-31 12:11:38 -0800165 self.assertTrue(os.path.exists(os.path.join(
166 self.work_dir, file_to_download)))
Gilad Arnold1638d822013-11-07 23:38:16 -0800167 self._CheckMarker(artifact.marker_name, artifact.installed_files)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700168
joychen0a8e34e2013-06-24 17:58:36 -0700169 def testDownloadAutotest(self):
Yu-Ju Honge61cbe92012-07-10 14:10:26 -0700170 """Downloads a real autotest tarball for test."""
Gilad Arnoldc65330c2012-09-20 15:17:48 -0700171 self.mox.StubOutWithMock(build_artifact.AutotestTarballBuildArtifact,
Chris Sosa76e44b92013-01-31 12:11:38 -0800172 '_Extract')
173 artifact = build_artifact.AutotestTarballBuildArtifact(
174 self.work_dir, _TEST_GOLO_ARCHIVE, build_artifact.AUTOTEST_FILE,
Yu-Ju Hong5d5bf0d2014-02-11 21:38:20 -0800175 _VERSION, files_to_extract=None, exclude=['autotest/test_suites'])
Chris Sosa76e44b92013-01-31 12:11:38 -0800176
joychen0a8e34e2013-06-24 17:58:36 -0700177 install_dir = self.work_dir
178 artifact.staging_dir = install_dir
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700179 self.mox.StubOutWithMock(subprocess, 'check_call')
joychen0a8e34e2013-06-24 17:58:36 -0700180 subprocess.check_call(mox.In('autotest/utils/packager.py'), cwd=install_dir)
Gilad Arnold02dc6552013-11-14 11:27:54 -0800181 self.mox.StubOutWithMock(artifact, '_WaitForArtifactToExist')
Yu-Ju Hong5d5bf0d2014-02-11 21:38:20 -0800182 self.mox.StubOutWithMock(artifact, '_UpdateName')
183 artifact._WaitForArtifactToExist(artifact.name, 1)
184 artifact._UpdateName(mox.IgnoreArg())
Gilad Arnold1638d822013-11-07 23:38:16 -0800185 artifact._Download()
186 artifact._Extract()
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700187 self.mox.ReplayAll()
Gilad Arnold1638d822013-11-07 23:38:16 -0800188 artifact.Process(True)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700189 self.mox.VerifyAll()
Gilad Arnold1638d822013-11-07 23:38:16 -0800190 self.assertItemsEqual(artifact.installed_files, [])
Chris Sosa76e44b92013-01-31 12:11:38 -0800191 self.assertTrue(os.path.isdir(
192 os.path.join(self.work_dir, 'autotest', 'packages')))
Gilad Arnold1638d822013-11-07 23:38:16 -0800193 self._CheckMarker(artifact.marker_name, [])
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700194
Gilad Arnoldc65330c2012-09-20 15:17:48 -0700195 def testAUTestPayloadBuildArtifact(self):
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700196 """Downloads a real tarball and treats it like an AU payload."""
Gilad Arnoldc65330c2012-09-20 15:17:48 -0700197 artifact = build_artifact.AUTestPayloadBuildArtifact(
Chris Sosa76e44b92013-01-31 12:11:38 -0800198 self.work_dir, _TEST_GOLO_ARCHIVE, build_artifact.TEST_SUITES_FILE,
199 _VERSION)
Gilad Arnold1638d822013-11-07 23:38:16 -0800200 expected_installed_files = [
201 os.path.join(self.work_dir, devserver_constants.UPDATE_FILE)]
Chris Sosa76e44b92013-01-31 12:11:38 -0800202 artifact.Process(False)
Gilad Arnold1638d822013-11-07 23:38:16 -0800203 self.assertItemsEqual(artifact.installed_files, expected_installed_files)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700204 self.assertTrue(os.path.exists(os.path.join(
Gilad Arnold1638d822013-11-07 23:38:16 -0800205 self.work_dir, devserver_constants.UPDATE_FILE)))
206 self._CheckMarker(artifact.marker_name, artifact.installed_files)
Chris Sosa76e44b92013-01-31 12:11:38 -0800207
208 def testDeltaPayloadsArtifact(self):
209 """Downloads delta paylaods from test bucket."""
210 artifact = build_artifact.DeltaPayloadsArtifact(
Gilad Arnold950569b2013-08-27 14:38:01 -0700211 self.work_dir, _TEST_GOLO_FOR_DELTAS, 'DONTCARE', _DELTA_VERSION)
Gilad Arnold1638d822013-11-07 23:38:16 -0800212 delta_installed_files = ('update.gz', 'stateful.tgz')
Chris Sosa76e44b92013-01-31 12:11:38 -0800213 nton_dir = os.path.join(self.work_dir, 'au', '%s_nton' % _DELTA_VERSION)
214 mton_dir = os.path.join(self.work_dir, 'au', '%s_mton' % _DELTA_VERSION)
Gilad Arnold1638d822013-11-07 23:38:16 -0800215 expected_installed_files = ([os.path.join(nton_dir, filename)
216 for filename in delta_installed_files] +
217 [os.path.join(mton_dir, filename)
218 for filename in delta_installed_files])
219 artifact.Process(False)
220 self.assertItemsEqual(artifact.installed_files, expected_installed_files)
Chris Sosa76e44b92013-01-31 12:11:38 -0800221 self.assertTrue(os.path.exists(os.path.join(nton_dir, 'update.gz')))
222 self.assertTrue(os.path.exists(os.path.join(mton_dir, 'update.gz')))
Gilad Arnold1638d822013-11-07 23:38:16 -0800223 self._CheckMarker(artifact.marker_name, artifact.installed_files)
Chris Sosa76e44b92013-01-31 12:11:38 -0800224
225 def testImageUnzip(self):
226 """Downloads and stages a zip file and extracts a test image."""
Gilad Arnold1638d822013-11-07 23:38:16 -0800227 files_to_extract = ['chromiumos_test_image.bin']
Yu-Ju Hong5d5bf0d2014-02-11 21:38:20 -0800228 artifact = build_artifact.BundledBuildArtifact(
Chris Sosa76e44b92013-01-31 12:11:38 -0800229 self.work_dir, _TEST_GOLO_ARCHIVE, build_artifact.IMAGE_FILE,
Gilad Arnold1638d822013-11-07 23:38:16 -0800230 _VERSION, files_to_extract=files_to_extract)
231 expected_installed_files = [
232 os.path.join(self.work_dir, filename)
233 for filename in [build_artifact.IMAGE_FILE] + files_to_extract]
Chris Sosa76e44b92013-01-31 12:11:38 -0800234 artifact.Process(False)
Gilad Arnold1638d822013-11-07 23:38:16 -0800235 self.assertItemsEqual(expected_installed_files, artifact.installed_files)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700236 self.assertTrue(os.path.exists(os.path.join(
Chris Sosa76e44b92013-01-31 12:11:38 -0800237 self.work_dir, 'chromiumos_test_image.bin')))
Gilad Arnold1638d822013-11-07 23:38:16 -0800238 self._CheckMarker(artifact.marker_name, artifact.installed_files)
Chris Sosa76e44b92013-01-31 12:11:38 -0800239
240 def testImageUnzipWithExcludes(self):
241 """Downloads and stages a zip file while excluding all large files."""
Yu-Ju Hong5d5bf0d2014-02-11 21:38:20 -0800242 artifact = build_artifact.BundledBuildArtifact(
Chris Sosa76e44b92013-01-31 12:11:38 -0800243 self.work_dir, _TEST_GOLO_ARCHIVE, build_artifact.IMAGE_FILE,
Gilad Arnold950569b2013-08-27 14:38:01 -0700244 _VERSION, exclude=['*.bin'])
Gilad Arnold1638d822013-11-07 23:38:16 -0800245 expected_extracted_files = [
246 filename for filename in _TEST_GOLO_ARCHIVE_IMAGE_ZIPFILE_CONTENT
247 if not filename.endswith('.bin')]
248 expected_installed_files = [
249 os.path.join(self.work_dir, filename)
250 for filename in [build_artifact.IMAGE_FILE] + expected_extracted_files]
Chris Sosa76e44b92013-01-31 12:11:38 -0800251 artifact.Process(False)
Gilad Arnold1638d822013-11-07 23:38:16 -0800252 self.assertItemsEqual(expected_installed_files, artifact.installed_files)
Chris Sosa76e44b92013-01-31 12:11:38 -0800253 self.assertFalse(os.path.exists(os.path.join(
254 self.work_dir, 'chromiumos_test_image.bin')))
Gilad Arnold1638d822013-11-07 23:38:16 -0800255 self._CheckMarker(artifact.marker_name, artifact.installed_files)
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700256
Chris Sosa6b0c6172013-08-05 17:01:33 -0700257 def testArtifactFactory(self):
258 """Tests that BuildArtifact logic works for both named and file artifacts.
259 """
260 name_artifact = 'test_suites' # This file is in every real GS dir.
261 file_artifact = 'metadata.json' # This file is in every real GS dir.
262 factory = build_artifact.ArtifactFactory(self.work_dir, _TEST_GOLO_ARCHIVE,
263 [name_artifact], [file_artifact],
264 _VERSION)
265 artifacts = factory.RequiredArtifacts()
266 self.assertEqual(len(artifacts), 2)
Gilad Arnold1638d822013-11-07 23:38:16 -0800267 expected_installed_files_0 = [
268 os.path.join(self.work_dir, filename) for filename
269 in ([build_artifact.TEST_SUITES_FILE] +
270 _TEST_GOLO_ARCHIVE_TEST_TARBALL_CONTENT)]
271 expected_installed_files_1 = [os.path.join(self.work_dir, file_artifact)]
Chris Sosa6b0c6172013-08-05 17:01:33 -0700272 artifacts[0].Process(False)
273 artifacts[1].Process(False)
Gilad Arnold1638d822013-11-07 23:38:16 -0800274 self.assertItemsEqual(artifacts[0].installed_files,
275 expected_installed_files_0)
276 self.assertItemsEqual(artifacts[1].installed_files,
277 expected_installed_files_1)
Chris Sosa6b0c6172013-08-05 17:01:33 -0700278 # Test suites directory exists.
279 self.assertTrue(os.path.exists(os.path.join(
280 self.work_dir, 'autotest', 'test_suites')))
281 # File artifact was staged.
282 self.assertTrue(os.path.exists(os.path.join(self.work_dir,
283 file_artifact)))
Gilad Arnold1638d822013-11-07 23:38:16 -0800284 self._CheckMarker(artifacts[0].marker_name, artifacts[0].installed_files)
285 self._CheckMarker(artifacts[1].marker_name, artifacts[1].installed_files)
Chris Sosa6b0c6172013-08-05 17:01:33 -0700286
Dan Shi6e50c722013-08-19 15:05:06 -0700287 def testProcessBuildArtifactWithException(self):
288 """Test processing a non-existing artifact from GSUtil."""
289 artifact = build_artifact.BuildArtifact(
290 self.work_dir, _TEST_NON_EXISTING_GOLO_ARCHIVE,
291 build_artifact.TEST_SUITES_FILE, _VERSION)
292 try:
293 artifact.Process(False)
294 except Exception as e:
295 expected_exception = e
296 exception = artifact.GetException()
297 self.assertEqual(str(exception), str(expected_exception))
298
Gilad Arnold1638d822013-11-07 23:38:16 -0800299 def testArtifactStaged(self):
300 """Tests the artifact staging verification logic."""
Yu-Ju Hong5d5bf0d2014-02-11 21:38:20 -0800301 artifact = build_artifact.BundledBuildArtifact(
Gilad Arnold1638d822013-11-07 23:38:16 -0800302 self.work_dir, _TEST_GOLO_ARCHIVE, build_artifact.TEST_SUITES_FILE,
303 _VERSION)
304 expected_installed_files = [
305 os.path.join(self.work_dir, filename)
306 for filename in ([build_artifact.TEST_SUITES_FILE] +
307 _TEST_GOLO_ARCHIVE_TEST_TARBALL_CONTENT)]
308 artifact.Process(False)
309
310 # Check that it works when all files are there.
311 self.assertTrue(artifact.ArtifactStaged())
312
313 # Remove an arbitrary file among the ones staged, ensure the check fails
314 # and that the marker files is removed.
315 os.remove(random.choice(expected_installed_files))
316 self.assertTrue(os.path.exists(os.path.join(self.work_dir,
317 artifact.marker_name)))
318 self.assertFalse(artifact.ArtifactStaged())
319 self.assertFalse(os.path.exists(os.path.join(self.work_dir,
320 artifact.marker_name)))
321
Chris Sosa47a7d4e2012-03-28 11:26:55 -0700322
323if __name__ == '__main__':
324 unittest.main()