Implement OCSP stapling in Windows BoringSSL port.
[chromium-blink-merge.git] / native_client_sdk / src / build_tools / tests / update_nacl_manifest_test.py
blobc2ef9da8006facfa890d3946059b28d935898f3f
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 import copy
7 import datetime
8 import hashlib
9 import logging
10 import os
11 import posixpath
12 import subprocess
13 import sys
14 import tempfile
15 import unittest
16 import urlparse
18 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
19 BUILD_TOOLS_DIR = os.path.dirname(SCRIPT_DIR)
21 sys.path.append(BUILD_TOOLS_DIR)
22 import manifest_util
23 import update_nacl_manifest
24 from update_nacl_manifest import CANARY_BUNDLE_NAME, BIONIC_CANARY_BUNDLE_NAME
27 HTTPS_BASE_URL = 'https://storage.googleapis.com' \
28 '/nativeclient_mirror/nacl/nacl_sdk/'
30 OS_CR = ('cros',)
31 OS_L = ('linux',)
32 OS_M = ('mac',)
33 OS_ML = ('mac', 'linux')
34 OS_MW = ('mac', 'win')
35 OS_LW = ('linux', 'win')
36 OS_MLW = ('mac', 'linux', 'win')
37 OS_ALL = ('all',)
38 POST_STABLE = 'post_stable'
39 STABLE = 'stable'
40 BETA = 'beta'
41 DEV = 'dev'
42 CANARY = 'canary'
45 def GetArchiveURL(basename, version):
46 return urlparse.urljoin(HTTPS_BASE_URL, posixpath.join(version, basename))
49 def GetPlatformArchiveUrl(host_os, version):
50 basename = 'naclsdk_%s.tar.bz2' % (host_os,)
51 return GetArchiveURL(basename, version)
54 def GetBionicArchiveUrl(version):
55 basename = 'naclsdk_bionic.tar.bz2'
56 return GetArchiveURL(basename, version)
59 def MakeGsUrl(rel_path):
60 return update_nacl_manifest.GS_BUCKET_PATH + rel_path
63 def GetPathFromGsUrl(url):
64 assert url.startswith(update_nacl_manifest.GS_BUCKET_PATH)
65 return url[len(update_nacl_manifest.GS_BUCKET_PATH):]
68 def GetPathFromHttpsUrl(url):
69 assert url.startswith(HTTPS_BASE_URL)
70 return url[len(HTTPS_BASE_URL):]
73 def MakeArchive(url, host_os):
74 archive = manifest_util.Archive(host_os)
75 archive.url = url
76 # dummy values that won't succeed if we ever use them, but will pass
77 # validation. :)
78 archive.checksum = {'sha1': 'foobar'}
79 archive.size = 1
80 return archive
83 def MakePlatformArchive(host_os, version):
84 return MakeArchive(GetPlatformArchiveUrl(host_os, version), host_os)
87 def MakeBionicArchive(host_os, version):
88 return MakeArchive(GetBionicArchiveUrl(version), host_os)
91 def MakeNonPlatformArchive(basename, version):
92 return MakeArchive(GetArchiveURL(basename, version), 'all')
95 def MakeNonPepperBundle(name, with_archives=False):
96 bundle = manifest_util.Bundle(name)
97 bundle.version = 1
98 bundle.revision = 1
99 bundle.description = 'Dummy bundle'
100 bundle.recommended = 'yes'
101 bundle.stability = 'stable'
103 if with_archives:
104 for host_os in OS_MLW:
105 archive = manifest_util.Archive(host_os)
106 archive.url = 'http://example.com'
107 archive.checksum = {'sha1': 'blah'}
108 archive.size = 2
109 bundle.AddArchive(archive)
110 return bundle
113 def MakePepperBundle(major_version, revision=0, version=None, stability='dev',
114 bundle_name=None):
115 assert (version is None or
116 version.split('.')[0] == 'trunk' or
117 version.split('.')[0] == str(major_version))
118 if not bundle_name:
119 bundle_name = 'pepper_' + str(major_version)
121 bundle = manifest_util.Bundle(bundle_name)
122 bundle.version = major_version
123 bundle.revision = revision
124 bundle.description = 'Chrome %s bundle, revision %s' % (major_version,
125 revision)
126 bundle.repath = 'pepper_' + str(major_version)
127 bundle.recommended = 'no'
128 bundle.stability = stability
130 return bundle
133 def MakePlatformBundle(major_version, revision=0, version=None, host_oses=None,
134 stability='dev'):
135 bundle = MakePepperBundle(major_version, revision, version, stability)
137 if host_oses:
138 for host_os in host_oses:
139 bundle.AddArchive(MakePlatformArchive(host_os, version))
141 return bundle
144 def MakeBionicBundle(major_version, revision=0, version=None, host_oses=None):
145 bundle = MakePepperBundle(major_version, revision, version, 'dev')
147 if host_oses:
148 for host_os in host_oses:
149 bundle.AddArchive(MakeBionicArchive(host_os, version))
151 return bundle
154 class MakeManifest(manifest_util.SDKManifest):
155 def __init__(self, *args):
156 manifest_util.SDKManifest.__init__(self)
158 for bundle in args:
159 self.AddBundle(bundle)
161 def AddBundle(self, bundle):
162 self.MergeBundle(bundle, allow_existing=False)
165 class MakeHistory(object):
166 def __init__(self):
167 # used for a dummy timestamp
168 self.datetime = datetime.datetime.utcnow()
169 self.history = []
171 def Add(self, host_oses, channel, version):
172 for host_os in host_oses:
173 timestamp = self.datetime.strftime('%Y-%m-%d %H:%M:%S.%f')
174 self.history.append((host_os, channel, version, timestamp))
175 self.datetime += datetime.timedelta(0, -3600) # one hour earlier
176 self.datetime += datetime.timedelta(-1) # one day earlier
179 class MakeFiles(dict):
180 def AddOnlineManifest(self, manifest_string):
181 self['naclsdk_manifest2.json'] = manifest_string
183 def Add(self, bundle, add_archive_for_os=OS_MLW, add_json_for_os=OS_MLW):
184 for archive in bundle.GetArchives():
185 if not archive.host_os in add_archive_for_os:
186 continue
188 self.AddArchive(bundle, archive, archive.host_os in add_json_for_os)
190 def AddArchive(self, bundle, archive, add_json=True):
191 path = GetPathFromHttpsUrl(archive.url)
192 self[path] = 'My Dummy archive'
194 if add_json:
195 # add .json manifest snippet, it should look like a normal Bundle, but
196 # only has one archive.
197 new_bundle = manifest_util.Bundle('')
198 new_bundle.CopyFrom(bundle)
199 del new_bundle.archives[:]
200 new_bundle.AddArchive(archive)
201 self[path + '.json'] = new_bundle.GetDataAsString()
204 class TestDelegate(update_nacl_manifest.Delegate):
205 def __init__(self, manifest, history, files):
206 self.manifest = manifest
207 self.history = history
208 self.files = files
209 self.dryrun = 0
210 self.called_gsutil_cp = False
211 self.called_sendmail = False
213 def GetRepoManifest(self):
214 return self.manifest
216 def GetHistory(self):
217 return self.history
219 def GsUtil_ls(self, url):
220 path = GetPathFromGsUrl(url)
221 result = []
222 for filename in self.files.iterkeys():
223 if not filename.startswith(path):
224 continue
226 # Find the first slash after the prefix (path).
227 # +1, because if the slash is directly after path, then we want to find
228 # the following slash anyway.
229 slash = filename.find('/', len(path) + 1)
231 if slash != -1:
232 filename = filename[:slash]
234 result.append(MakeGsUrl(filename))
236 # Remove dupes.
237 return list(set(result))
239 def GsUtil_cat(self, url):
240 path = GetPathFromGsUrl(url)
241 if path not in self.files:
242 raise subprocess.CalledProcessError(1, 'gsutil cat %s' % (url,))
243 return self.files[path]
245 def GsUtil_cp(self, src, dest, stdin=None):
246 self.called_gsutil_cp = True
247 dest_path = GetPathFromGsUrl(dest)
248 if src == '-':
249 self.files[dest_path] = stdin
250 else:
251 src_path = GetPathFromGsUrl(src)
252 if src_path not in self.files:
253 raise subprocess.CalledProcessError(1, 'gsutil cp %s %s' % (src, dest))
254 self.files[dest_path] = self.files[src_path]
256 def SendMail(self, subject, text):
257 self.called_sendmail = True
260 # Shorthand for premade bundles/versions
261 V18_0_1025_163 = '18.0.1025.163'
262 V18_0_1025_175 = '18.0.1025.175'
263 V18_0_1025_184 = '18.0.1025.184'
264 V19_0_1084_41 = '19.0.1084.41'
265 V19_0_1084_67 = '19.0.1084.67'
266 V21_0_1145_0 = '21.0.1145.0'
267 V21_0_1166_0 = '21.0.1166.0'
268 V26_0_1386_0 = '26.0.1386.0'
269 V26_0_1386_1 = '26.0.1386.1'
270 V37_0_2054_0 = '37.0.2054.0'
271 VTRUNK_140819 = 'trunk.140819'
272 VTRUNK_277776 = 'trunk.277776'
273 B18_0_1025_163_MLW = MakePlatformBundle(18, 132135, V18_0_1025_163, OS_MLW)
274 B18_0_1025_184_MLW = MakePlatformBundle(18, 134900, V18_0_1025_184, OS_MLW)
275 B18_NONE = MakePlatformBundle(18)
276 B19_0_1084_41_MLW = MakePlatformBundle(19, 134854, V19_0_1084_41, OS_MLW)
277 B19_0_1084_67_MLW = MakePlatformBundle(19, 142000, V19_0_1084_67, OS_MLW)
278 B19_NONE = MakePlatformBundle(19)
279 BCANARY_NONE = MakePepperBundle(0, stability=CANARY,
280 bundle_name=CANARY_BUNDLE_NAME)
281 B21_0_1145_0_MLW = MakePlatformBundle(21, 138079, V21_0_1145_0, OS_MLW)
282 B21_0_1166_0_MW = MakePlatformBundle(21, 140819, V21_0_1166_0, OS_MW)
283 B26_NONE = MakePlatformBundle(26)
284 B26_0_1386_0_MLW = MakePlatformBundle(26, 177362, V26_0_1386_0, OS_MLW)
285 B26_0_1386_1_MLW = MakePlatformBundle(26, 177439, V26_0_1386_1, OS_MLW)
286 BTRUNK_140819_MLW = MakePlatformBundle(21, 140819, VTRUNK_140819, OS_MLW)
287 BBIONIC_NONE = MakePepperBundle(0, stability=CANARY,
288 bundle_name=BIONIC_CANARY_BUNDLE_NAME)
289 BBIONIC_TRUNK_277776 = MakeBionicBundle(37, 277776, VTRUNK_277776, OS_L)
290 NON_PEPPER_BUNDLE_NOARCHIVES = MakeNonPepperBundle('foo')
291 NON_PEPPER_BUNDLE_ARCHIVES = MakeNonPepperBundle('bar', with_archives=True)
294 class TestUpdateManifest(unittest.TestCase):
295 def setUp(self):
296 self.history = MakeHistory()
297 self.files = MakeFiles()
298 self.version_mapping = {}
299 self.delegate = None
300 self.uploaded_manifest = None
301 self.manifest = None
303 def _MakeDelegate(self):
304 self.delegate = TestDelegate(self.manifest, self.history.history,
305 self.files)
307 def _Run(self, host_oses, extra_archives=None, fixed_bundle_versions=None):
308 update_nacl_manifest.Run(self.delegate, host_oses, extra_archives,
309 fixed_bundle_versions)
311 def _HasUploadedManifest(self):
312 return 'naclsdk_manifest2.json' in self.files
314 def _ReadUploadedManifest(self):
315 self.uploaded_manifest = manifest_util.SDKManifest()
316 self.uploaded_manifest.LoadDataFromString(
317 self.files['naclsdk_manifest2.json'])
319 def _AssertUploadedManifestHasBundle(self, bundle, stability,
320 bundle_name=None):
321 if not bundle_name:
322 bundle_name = bundle.name
324 uploaded_manifest_bundle = self.uploaded_manifest.GetBundle(bundle_name)
325 # Bundles that we create in the test (and in the manifest snippets) have
326 # their stability set to "dev". update_nacl_manifest correctly updates it.
327 # So we have to force the stability of |bundle| so they compare equal.
328 test_bundle = copy.copy(bundle)
329 test_bundle.stability = stability
330 if bundle_name:
331 test_bundle.name = bundle_name
332 self.assertEqual(uploaded_manifest_bundle, test_bundle)
334 def _AddCsvHistory(self, history):
335 import csv
336 import cStringIO
337 history_stream = cStringIO.StringIO(history)
338 self.history.history = [(platform, channel, version, date)
339 for platform, channel, version, date in csv.reader(history_stream)]
341 def testNoUpdateNeeded(self):
342 self.manifest = MakeManifest(B18_0_1025_163_MLW)
343 self._MakeDelegate()
344 self._Run(OS_MLW)
345 self.assertFalse(self._HasUploadedManifest())
347 # Add another bundle, make sure it still doesn't update
348 self.manifest.AddBundle(B19_0_1084_41_MLW)
349 self._Run(OS_MLW)
350 self.assertFalse(self._HasUploadedManifest())
352 def testSimpleUpdate(self):
353 self.manifest = MakeManifest(B18_NONE)
354 self.history.Add(OS_MLW, BETA, V18_0_1025_163)
355 self.files.Add(B18_0_1025_163_MLW)
356 self._MakeDelegate()
357 self._Run(OS_MLW)
358 self._ReadUploadedManifest()
359 self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
360 self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
362 def testOnePlatformHasNewerRelease(self):
363 self.manifest = MakeManifest(B18_NONE)
364 self.history.Add(OS_M, BETA, V18_0_1025_175) # Mac has newer version
365 self.history.Add(OS_MLW, BETA, V18_0_1025_163)
366 self.files.Add(B18_0_1025_163_MLW)
367 self._MakeDelegate()
368 self._Run(OS_MLW)
369 self._ReadUploadedManifest()
370 self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
371 self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
373 def testMultipleMissingPlatformsInHistory(self):
374 self.manifest = MakeManifest(B18_NONE)
375 self.history.Add(OS_ML, BETA, V18_0_1025_184)
376 self.history.Add(OS_M, BETA, V18_0_1025_175)
377 self.history.Add(OS_MLW, BETA, V18_0_1025_163)
378 self.files.Add(B18_0_1025_163_MLW)
379 self._MakeDelegate()
380 self._Run(OS_MLW)
381 self._ReadUploadedManifest()
382 self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
383 self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
385 def testUpdateOnlyOneBundle(self):
386 self.manifest = MakeManifest(B18_NONE, B19_0_1084_41_MLW)
387 self.history.Add(OS_MLW, BETA, V18_0_1025_163)
388 self.files.Add(B18_0_1025_163_MLW)
389 self._MakeDelegate()
390 self._Run(OS_MLW)
391 self._ReadUploadedManifest()
392 self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
393 self._AssertUploadedManifestHasBundle(B19_0_1084_41_MLW, DEV)
394 self.assertEqual(len(self.uploaded_manifest.GetBundles()), 2)
396 def testUpdateTwoBundles(self):
397 self.manifest = MakeManifest(B18_NONE, B19_NONE)
398 self.history.Add(OS_MLW, DEV, V19_0_1084_41)
399 self.history.Add(OS_MLW, BETA, V18_0_1025_163)
400 self.files.Add(B18_0_1025_163_MLW)
401 self.files.Add(B19_0_1084_41_MLW)
402 self._MakeDelegate()
403 self._Run(OS_MLW)
404 self._ReadUploadedManifest()
405 self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
406 self._AssertUploadedManifestHasBundle(B19_0_1084_41_MLW, DEV)
407 self.assertEqual(len(self.uploaded_manifest.GetBundles()), 2)
409 def testUpdateWithMissingPlatformsInArchives(self):
410 self.manifest = MakeManifest(B18_NONE)
411 self.history.Add(OS_MLW, BETA, V18_0_1025_184)
412 self.history.Add(OS_MLW, BETA, V18_0_1025_163)
413 self.files.Add(B18_0_1025_184_MLW, add_archive_for_os=OS_M)
414 self.files.Add(B18_0_1025_163_MLW)
415 self._MakeDelegate()
416 self._Run(OS_MLW)
417 self._ReadUploadedManifest()
418 self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
419 self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
421 def testUpdateWithMissingManifestSnippets(self):
422 self.manifest = MakeManifest(B18_NONE)
423 self.history.Add(OS_MLW, BETA, V18_0_1025_184)
424 self.history.Add(OS_MLW, BETA, V18_0_1025_163)
425 self.files.Add(B18_0_1025_184_MLW, add_json_for_os=OS_ML)
426 self.files.Add(B18_0_1025_163_MLW)
427 self._MakeDelegate()
428 self._Run(OS_MLW)
429 self._ReadUploadedManifest()
430 self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
431 self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
433 def testRecommendedIsStable(self):
434 for channel in STABLE, BETA, DEV, CANARY:
435 self.setUp()
436 bundle = copy.deepcopy(B18_NONE)
437 self.manifest = MakeManifest(bundle)
438 self.history.Add(OS_MLW, channel, V18_0_1025_163)
439 self.files.Add(B18_0_1025_163_MLW)
440 self._MakeDelegate()
441 self._Run(OS_MLW)
442 self._ReadUploadedManifest()
443 self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
444 uploaded_bundle = self.uploaded_manifest.GetBundle('pepper_18')
445 if channel == STABLE:
446 self.assertEqual(uploaded_bundle.recommended, 'yes')
447 else:
448 self.assertEqual(uploaded_bundle.recommended, 'no')
450 def testNoUpdateWithNonPepperBundle(self):
451 self.manifest = MakeManifest(NON_PEPPER_BUNDLE_NOARCHIVES,
452 B18_0_1025_163_MLW)
453 self._MakeDelegate()
454 self._Run(OS_MLW)
455 self.assertFalse(self._HasUploadedManifest())
457 def testUpdateWithHistoryWithExtraneousPlatforms(self):
458 self.manifest = MakeManifest(B18_NONE)
459 self.history.Add(OS_ML, BETA, V18_0_1025_184)
460 self.history.Add(OS_CR, BETA, V18_0_1025_184)
461 self.history.Add(OS_CR, BETA, V18_0_1025_175)
462 self.history.Add(OS_MLW, BETA, V18_0_1025_163)
463 self.files.Add(B18_0_1025_163_MLW)
464 self._MakeDelegate()
465 self._Run(OS_MLW)
466 self._ReadUploadedManifest()
467 self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
468 self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
470 def testSnippetWithStringRevisionAndVersion(self):
471 # This test exists because some manifest snippets were uploaded with
472 # strings for their revisions and versions. I want to make sure the
473 # resulting manifest is still consistent with the old format.
474 self.manifest = MakeManifest(B18_NONE)
475 self.history.Add(OS_MLW, BETA, V18_0_1025_163)
476 bundle_string_revision = MakePlatformBundle('18', '1234', V18_0_1025_163,
477 OS_MLW)
478 self.files.Add(bundle_string_revision)
479 self._MakeDelegate()
480 self._Run(OS_MLW)
481 self._ReadUploadedManifest()
482 uploaded_bundle = self.uploaded_manifest.GetBundle(
483 bundle_string_revision.name)
484 self.assertEqual(uploaded_bundle.revision, 1234)
485 self.assertEqual(uploaded_bundle.version, 18)
487 def testUpdateCanary(self):
488 self.manifest = MakeManifest(copy.deepcopy(BCANARY_NONE))
489 self.files.Add(BTRUNK_140819_MLW)
490 self._MakeDelegate()
491 self._Run(OS_MLW)
492 self._ReadUploadedManifest()
493 self._AssertUploadedManifestHasBundle(BTRUNK_140819_MLW, CANARY,
494 bundle_name=CANARY_BUNDLE_NAME)
496 def testCanaryShouldOnlyUseCanaryVersions(self):
497 canary_bundle = copy.deepcopy(BCANARY_NONE)
498 self.manifest = MakeManifest(canary_bundle)
499 self.history.Add(OS_MW, CANARY, V21_0_1166_0)
500 self.history.Add(OS_MW, BETA, V19_0_1084_41)
501 self.files.Add(B19_0_1084_41_MLW)
502 self.version_mapping[V21_0_1166_0] = VTRUNK_140819
503 self._MakeDelegate()
504 self.assertRaises(Exception, self._Run, OS_MLW)
506 def testExtensionWorksAsBz2(self):
507 # Allow old bundles with just .bz2 extension to work
508 self.manifest = MakeManifest(B18_NONE)
509 self.history.Add(OS_MLW, BETA, V18_0_1025_163)
510 bundle = copy.deepcopy(B18_0_1025_163_MLW)
511 archive_url = bundle.GetArchive('mac').url
512 bundle.GetArchive('mac').url = archive_url.replace('.tar', '')
513 self.files.Add(bundle)
514 self._MakeDelegate()
515 self._Run(OS_MLW)
516 self._ReadUploadedManifest()
517 self._AssertUploadedManifestHasBundle(bundle, BETA)
518 self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
520 def testOnlyOneStableBundle(self):
521 # Make sure that any bundle that has an older version than STABLE is marked
522 # as POST_STABLE, even if the last version we found was BETA, DEV, etc.
523 for channel in STABLE, BETA, DEV, CANARY:
524 self.setUp()
525 self.manifest = MakeManifest(B18_NONE, B19_NONE)
526 self.history.Add(OS_MLW, channel, V18_0_1025_163)
527 self.history.Add(OS_MLW, STABLE, V19_0_1084_41)
528 self.files.Add(B18_0_1025_163_MLW)
529 self.files.Add(B19_0_1084_41_MLW)
530 self._MakeDelegate()
531 self._Run(OS_MLW)
532 self._ReadUploadedManifest()
533 p18_bundle = self.uploaded_manifest.GetBundle(B18_NONE.name)
534 self.assertEqual(p18_bundle.stability, POST_STABLE)
535 self.assertEqual(p18_bundle.recommended, 'no')
536 p19_bundle = self.uploaded_manifest.GetBundle(B19_NONE.name)
537 self.assertEqual(p19_bundle.stability, STABLE)
538 self.assertEqual(p19_bundle.recommended, 'yes')
540 def testDontPushIfNoChange(self):
541 # Make an online manifest that already has this bundle.
542 online_manifest = MakeManifest(B18_0_1025_163_MLW)
543 self.files.AddOnlineManifest(online_manifest.GetDataAsString())
545 self.manifest = MakeManifest(B18_NONE)
546 self.history.Add(OS_MLW, DEV, V18_0_1025_163)
547 self.files.Add(B18_0_1025_163_MLW)
549 self._MakeDelegate()
550 self._Run(OS_MLW)
551 self.assertFalse(self.delegate.called_gsutil_cp)
553 def testDontPushIfRollback(self):
554 # Make an online manifest that has a newer bundle
555 online_manifest = MakeManifest(B18_0_1025_184_MLW)
556 self.files.AddOnlineManifest(online_manifest.GetDataAsString())
558 self.manifest = MakeManifest(B18_NONE)
559 self.history.Add(OS_MLW, DEV, V18_0_1025_163)
560 self.files.Add(B18_0_1025_163_MLW)
562 self._MakeDelegate()
563 self._Run(OS_MLW)
564 self.assertFalse(self.delegate.called_gsutil_cp)
566 def testRunWithFixedBundleVersions(self):
567 self.manifest = MakeManifest(B18_NONE)
568 self.history.Add(OS_MLW, BETA, V18_0_1025_163)
569 self.files.Add(B18_0_1025_163_MLW)
570 self.files.Add(B18_0_1025_184_MLW)
572 self._MakeDelegate()
573 self._Run(OS_MLW, None, [('pepper_18', '18.0.1025.184')])
574 self._ReadUploadedManifest()
575 self._AssertUploadedManifestHasBundle(B18_0_1025_184_MLW, BETA)
576 self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
578 def testRunWithMissingFixedBundleVersions(self):
579 self.manifest = MakeManifest(B18_NONE)
580 self.history.Add(OS_MLW, BETA, V18_0_1025_163)
581 self.files.Add(B18_0_1025_163_MLW)
583 self._MakeDelegate()
584 self._Run(OS_MLW, None, [('pepper_18', '18.0.1025.184')])
585 # Nothing should be uploaded if the user gives a missing fixed version.
586 self.assertFalse(self.delegate.called_gsutil_cp)
588 def testDontIncludeRandomBundles(self):
589 self.manifest = MakeManifest(B26_NONE)
590 self.history.Add(OS_MLW, BETA, V26_0_1386_0)
591 self.files.Add(B26_0_1386_0_MLW)
593 some_other_bundle = MakePepperBundle(26, 1, V26_0_1386_0, BETA)
594 some_other_archive = MakeNonPlatformArchive('some_other.tar.bz2',
595 V26_0_1386_0)
596 some_other_bundle.AddArchive(some_other_archive)
597 self.files.AddArchive(some_other_bundle, some_other_archive)
599 self._MakeDelegate()
600 self._Run(OS_MLW)
601 self._ReadUploadedManifest()
602 uploaded_bundle = self.uploaded_manifest.GetBundle('pepper_26')
603 self.assertEqual(1, len(uploaded_bundle.GetHostOSArchives()))
605 def testNaclportsBundle(self):
606 self.manifest = MakeManifest(B26_NONE)
607 self.history.Add(OS_MLW, BETA, V26_0_1386_0)
608 self.files.Add(B26_0_1386_0_MLW)
610 # NaclPorts "bundle".
611 naclports_bundle = MakePepperBundle(26, 1, V26_0_1386_0, BETA)
612 naclports_archive = MakeNonPlatformArchive('naclports.tar.bz2',
613 V26_0_1386_0)
614 naclports_bundle.AddArchive(naclports_archive)
615 self.files.AddArchive(naclports_bundle, naclports_archive)
617 self._MakeDelegate()
618 self._Run(OS_MLW, [('naclports.tar.bz2', '26.0.1386.0')])
619 self._ReadUploadedManifest()
621 uploaded_bundle = self.uploaded_manifest.GetBundle('pepper_26')
622 self.assertEqual(2, len(uploaded_bundle.GetHostOSArchives()))
624 def testKeepBundleOrder(self):
625 # This is a regression test: when a bundle is skipped (because it isn't
626 # newer than the online bundle), it was added to the end of the list.
628 # Make an online manifest that already has B18.
629 online_manifest = MakeManifest(B18_0_1025_163_MLW)
630 self.files.AddOnlineManifest(online_manifest.GetDataAsString())
632 self.manifest = MakeManifest(B18_NONE, B19_NONE)
633 self.history.Add(OS_MLW, STABLE, V18_0_1025_163)
634 self.history.Add(OS_MLW, STABLE, V19_0_1084_41)
635 self.files.Add(B18_0_1025_163_MLW)
636 self.files.Add(B19_0_1084_41_MLW)
638 self._MakeDelegate()
639 self._Run(OS_MLW)
640 self._ReadUploadedManifest()
642 # Bundle 18 should be before bundle 19.
643 bundles = self.uploaded_manifest.GetBundles()
644 self.assertEqual(2, len(bundles))
645 self.assertEqual('pepper_18', bundles[0].name)
646 self.assertEqual('pepper_19', bundles[1].name)
648 def testBundleWithoutHistoryUsesOnline(self):
649 online_manifest = MakeManifest(B18_0_1025_163_MLW)
650 self.files.AddOnlineManifest(online_manifest.GetDataAsString())
652 self.manifest = MakeManifest(B18_NONE)
654 self._MakeDelegate()
655 # This should not raise.
656 self._Run(OS_MLW)
657 self._ReadUploadedManifest()
659 # But it should have sent an email nagging the users to lock this bundle
660 # manually.
661 self.assertTrue(self.delegate.called_sendmail)
663 uploaded_bundle = self.uploaded_manifest.GetBundle('pepper_18')
664 self.assertEqual(uploaded_bundle, B18_0_1025_163_MLW)
666 def testBundleWithoutHistoryOrOnlineRaises(self):
667 self.manifest = MakeManifest(B18_NONE)
668 self._MakeDelegate()
669 self.assertRaises(update_nacl_manifest.UnknownLockedBundleException,
670 self._Run, OS_MLW)
672 def testUpdateBionic(self):
673 bionic_bundle = copy.deepcopy(BBIONIC_NONE)
674 self.manifest = MakeManifest(bionic_bundle)
675 self.history.Add(OS_MW, CANARY, V37_0_2054_0)
676 self.files.Add(BBIONIC_TRUNK_277776)
677 self.version_mapping[V37_0_2054_0] = VTRUNK_277776
678 self._MakeDelegate()
679 self._Run(OS_MLW)
680 self._ReadUploadedManifest()
681 self._AssertUploadedManifestHasBundle(BBIONIC_TRUNK_277776, CANARY,
682 bundle_name=BIONIC_CANARY_BUNDLE_NAME)
685 class TestUpdateVitals(unittest.TestCase):
686 def setUp(self):
687 f = tempfile.NamedTemporaryFile('w', prefix="test_update_nacl_manifest")
688 self.test_file = f.name
689 f.close()
690 test_data = "Some test data"
691 self.sha1 = hashlib.sha1(test_data).hexdigest()
692 self.data_len = len(test_data)
693 with open(self.test_file, 'w') as f:
694 f.write(test_data)
696 def tearDown(self):
697 os.remove(self.test_file)
699 def testUpdateVitals(self):
700 archive = manifest_util.Archive(manifest_util.GetHostOS())
701 path = os.path.abspath(self.test_file)
702 if sys.platform == 'win32':
703 # On Windows, the path must start with three slashes, i.e.
704 # (file:///C:\whatever)
705 path = '/' + path
706 archive.url = 'file://' + path
708 bundle = MakePlatformBundle(18)
709 bundle.AddArchive(archive)
710 manifest = MakeManifest(bundle)
711 archive = manifest.GetBundles()[0]['archives'][0]
713 self.assertTrue('size' not in archive)
714 self.assertTrue('checksum' not in archive)
715 self.assertRaises(manifest_util.Error, manifest.Validate)
717 manifest.Validate(add_missing_info=True)
719 self.assertEqual(archive['size'], self.data_len)
720 self.assertEqual(archive['checksum']['sha1'], self.sha1)
723 if __name__ == '__main__':
724 logging.basicConfig(level=logging.CRITICAL)
725 # Uncomment the following line to enable more debugging info.
726 # logging.getLogger('update_nacl_manifest').setLevel(logging.INFO)
728 sys.exit(unittest.main())