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