15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/env python
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import copy
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import datetime
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import hashlib
97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport logging
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import posixpath
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import subprocess
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import tempfile
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import unittest
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import urlparse
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BUILD_TOOLS_DIR = os.path.dirname(SCRIPT_DIR)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sys.path.append(BUILD_TOOLS_DIR)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import manifest_util
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import update_nacl_manifest
24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)from update_nacl_manifest import CANARY_BUNDLE_NAME, BIONIC_CANARY_BUNDLE_NAME
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)HTTPS_BASE_URL = 'https://storage.googleapis.com' \
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    '/nativeclient_mirror/nacl/nacl_sdk/'
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OS_CR = ('cros',)
31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)OS_L = ('linux',)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OS_M = ('mac',)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OS_ML = ('mac', 'linux')
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OS_MW = ('mac', 'win')
35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)OS_LW = ('linux', 'win')
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OS_MLW = ('mac', 'linux', 'win')
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)OS_ALL = ('all',)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)POST_STABLE = 'post_stable'
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)STABLE = 'stable'
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BETA = 'beta'
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEV = 'dev'
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CANARY = 'canary'
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def GetArchiveURL(basename, version):
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return urlparse.urljoin(HTTPS_BASE_URL, posixpath.join(version, basename))
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def GetPlatformArchiveUrl(host_os, version):
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  basename = 'naclsdk_%s.tar.bz2' % (host_os,)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return GetArchiveURL(basename, version)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)def GetBionicArchiveUrl(version):
55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  basename = 'naclsdk_bionic.tar.bz2'
56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return GetArchiveURL(basename, version)
57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def MakeGsUrl(rel_path):
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return update_nacl_manifest.GS_BUCKET_PATH + rel_path
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetPathFromGsUrl(url):
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert url.startswith(update_nacl_manifest.GS_BUCKET_PATH)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return url[len(update_nacl_manifest.GS_BUCKET_PATH):]
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetPathFromHttpsUrl(url):
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert url.startswith(HTTPS_BASE_URL)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return url[len(HTTPS_BASE_URL):]
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def MakeArchive(url, host_os):
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  archive = manifest_util.Archive(host_os)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  archive.url = url
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # dummy values that won't succeed if we ever use them, but will pass
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # validation. :)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  archive.checksum = {'sha1': 'foobar'}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  archive.size = 1
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return archive
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def MakePlatformArchive(host_os, version):
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return MakeArchive(GetPlatformArchiveUrl(host_os, version), host_os)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)def MakeBionicArchive(host_os, version):
88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return MakeArchive(GetBionicArchiveUrl(version), host_os)
89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def MakeNonPlatformArchive(basename, version):
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return MakeArchive(GetArchiveURL(basename, version), 'all')
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def MakeNonPepperBundle(name, with_archives=False):
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bundle = manifest_util.Bundle(name)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bundle.version = 1
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bundle.revision = 1
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bundle.description = 'Dummy bundle'
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bundle.recommended = 'yes'
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bundle.stability = 'stable'
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if with_archives:
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for host_os in OS_MLW:
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      archive = manifest_util.Archive(host_os)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      archive.url = 'http://example.com'
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      archive.checksum = {'sha1': 'blah'}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      archive.size = 2
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bundle.AddArchive(archive)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bundle
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)def MakePepperBundle(major_version, revision=0, version=None, stability='dev',
114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                     bundle_name=None):
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert (version is None or
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          version.split('.')[0] == 'trunk' or
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          version.split('.')[0] == str(major_version))
118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if not bundle_name:
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bundle_name = 'pepper_' + str(major_version)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bundle = manifest_util.Bundle(bundle_name)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bundle.version = major_version
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bundle.revision = revision
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bundle.description = 'Chrome %s bundle, revision %s' % (major_version,
125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                          revision)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bundle.repath = 'pepper_' + str(major_version)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bundle.recommended = 'no'
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bundle.stability = stability
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return bundle
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def MakePlatformBundle(major_version, revision=0, version=None, host_oses=None,
134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       stability='dev'):
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bundle = MakePepperBundle(major_version, revision, version, stability)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if host_oses:
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for host_os in host_oses:
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bundle.AddArchive(MakePlatformArchive(host_os, version))
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bundle
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)def MakeBionicBundle(major_version, revision=0, version=None, host_oses=None):
145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  bundle = MakePepperBundle(major_version, revision, version, 'dev')
146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if host_oses:
148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    for host_os in host_oses:
149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      bundle.AddArchive(MakeBionicArchive(host_os, version))
150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return bundle
152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MakeManifest(manifest_util.SDKManifest):
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self, *args):
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    manifest_util.SDKManifest.__init__(self)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for bundle in args:
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.AddBundle(bundle)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def AddBundle(self, bundle):
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.MergeBundle(bundle, allow_existing=False)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MakeHistory(object):
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self):
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # used for a dummy timestamp
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.datetime = datetime.datetime.utcnow()
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history = []
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Add(self, host_oses, channel, version):
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for host_os in host_oses:
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      timestamp = self.datetime.strftime('%Y-%m-%d %H:%M:%S.%f')
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.history.append((host_os, channel, version, timestamp))
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.datetime += datetime.timedelta(0, -3600) # one hour earlier
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.datetime += datetime.timedelta(-1) # one day earlier
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MakeFiles(dict):
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def AddOnlineManifest(self, manifest_string):
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self['naclsdk_manifest2.json'] = manifest_string
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Add(self, bundle, add_archive_for_os=OS_MLW, add_json_for_os=OS_MLW):
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for archive in bundle.GetArchives():
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not archive.host_os in add_archive_for_os:
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self.AddArchive(bundle, archive, archive.host_os in add_json_for_os)
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def AddArchive(self, bundle, archive, add_json=True):
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    path = GetPathFromHttpsUrl(archive.url)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self[path] = 'My Dummy archive'
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if add_json:
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      # add .json manifest snippet, it should look like a normal Bundle, but
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      # only has one archive.
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new_bundle = manifest_util.Bundle('')
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new_bundle.CopyFrom(bundle)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      del new_bundle.archives[:]
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new_bundle.AddArchive(archive)
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self[path + '.json'] = new_bundle.GetDataAsString()
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestDelegate(update_nacl_manifest.Delegate):
2056d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  def __init__(self, manifest, history, files):
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.manifest = manifest
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history = history
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.files = files
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.dryrun = 0
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.called_gsutil_cp = False
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.called_sendmail = False
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetRepoManifest(self):
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self.manifest
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetHistory(self):
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self.history
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GsUtil_ls(self, url):
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    path = GetPathFromGsUrl(url)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = []
2226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    for filename in self.files.iterkeys():
2236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      if not filename.startswith(path):
2246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        continue
2256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      # Find the first slash after the prefix (path).
2276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      # +1, because if the slash is directly after path, then we want to find
2286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      # the following slash anyway.
2296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      slash = filename.find('/', len(path) + 1)
2306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      if slash != -1:
2326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        filename = filename[:slash]
2336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      result.append(MakeGsUrl(filename))
2356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    # Remove dupes.
2376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return list(set(result))
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GsUtil_cat(self, url):
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    path = GetPathFromGsUrl(url)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if path not in self.files:
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise subprocess.CalledProcessError(1, 'gsutil cat %s' % (url,))
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self.files[path]
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GsUtil_cp(self, src, dest, stdin=None):
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.called_gsutil_cp = True
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dest_path = GetPathFromGsUrl(dest)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if src == '-':
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.files[dest_path] = stdin
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      src_path = GetPathFromGsUrl(src)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if src_path not in self.files:
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        raise subprocess.CalledProcessError(1, 'gsutil cp %s %s' % (src, dest))
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.files[dest_path] = self.files[src_path]
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  def SendMail(self, subject, text):
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.called_sendmail = True
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Shorthand for premade bundles/versions
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)V18_0_1025_163 = '18.0.1025.163'
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)V18_0_1025_175 = '18.0.1025.175'
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)V18_0_1025_184 = '18.0.1025.184'
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)V19_0_1084_41 = '19.0.1084.41'
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)V19_0_1084_67 = '19.0.1084.67'
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)V21_0_1145_0 = '21.0.1145.0'
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)V21_0_1166_0 = '21.0.1166.0'
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)V26_0_1386_0 = '26.0.1386.0'
269424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)V26_0_1386_1 = '26.0.1386.1'
270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)V37_0_2054_0 = '37.0.2054.0'
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)VTRUNK_140819 = 'trunk.140819'
272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)VTRUNK_277776 = 'trunk.277776'
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)B18_0_1025_163_MLW = MakePlatformBundle(18, 132135, V18_0_1025_163, OS_MLW)
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)B18_0_1025_184_MLW = MakePlatformBundle(18, 134900, V18_0_1025_184, OS_MLW)
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)B18_NONE = MakePlatformBundle(18)
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)B19_0_1084_41_MLW = MakePlatformBundle(19, 134854, V19_0_1084_41, OS_MLW)
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)B19_0_1084_67_MLW = MakePlatformBundle(19, 142000, V19_0_1084_67, OS_MLW)
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)B19_NONE = MakePlatformBundle(19)
279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)BCANARY_NONE = MakePepperBundle(0, stability=CANARY,
280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                bundle_name=CANARY_BUNDLE_NAME)
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)B21_0_1145_0_MLW = MakePlatformBundle(21, 138079, V21_0_1145_0, OS_MLW)
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)B21_0_1166_0_MW = MakePlatformBundle(21, 140819, V21_0_1166_0, OS_MW)
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)B26_NONE = MakePlatformBundle(26)
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)B26_0_1386_0_MLW = MakePlatformBundle(26, 177362, V26_0_1386_0, OS_MLW)
285424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)B26_0_1386_1_MLW = MakePlatformBundle(26, 177439, V26_0_1386_1, OS_MLW)
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)BTRUNK_140819_MLW = MakePlatformBundle(21, 140819, VTRUNK_140819, OS_MLW)
287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)BBIONIC_NONE = MakePepperBundle(0, stability=CANARY,
288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                bundle_name=BIONIC_CANARY_BUNDLE_NAME)
289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)BBIONIC_TRUNK_277776 = MakeBionicBundle(37, 277776, VTRUNK_277776, OS_L)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NON_PEPPER_BUNDLE_NOARCHIVES = MakeNonPepperBundle('foo')
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NON_PEPPER_BUNDLE_ARCHIVES = MakeNonPepperBundle('bar', with_archives=True)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestUpdateManifest(unittest.TestCase):
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def setUp(self):
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history = MakeHistory()
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.files = MakeFiles()
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.version_mapping = {}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.delegate = None
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.uploaded_manifest = None
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.manifest = None
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _MakeDelegate(self):
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.delegate = TestDelegate(self.manifest, self.history.history,
3056d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        self.files)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _Run(self, host_oses, extra_archives=None, fixed_bundle_versions=None):
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    update_nacl_manifest.Run(self.delegate, host_oses, extra_archives,
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             fixed_bundle_versions)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _HasUploadedManifest(self):
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 'naclsdk_manifest2.json' in self.files
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _ReadUploadedManifest(self):
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.uploaded_manifest = manifest_util.SDKManifest()
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.uploaded_manifest.LoadDataFromString(
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.files['naclsdk_manifest2.json'])
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  def _AssertUploadedManifestHasBundle(self, bundle, stability,
320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                       bundle_name=None):
321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if not bundle_name:
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bundle_name = bundle.name
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uploaded_manifest_bundle = self.uploaded_manifest.GetBundle(bundle_name)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Bundles that we create in the test (and in the manifest snippets) have
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # their stability set to "dev". update_nacl_manifest correctly updates it.
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # So we have to force the stability of |bundle| so they compare equal.
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_bundle = copy.copy(bundle)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_bundle.stability = stability
330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if bundle_name:
331f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      test_bundle.name = bundle_name
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(uploaded_manifest_bundle, test_bundle)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _AddCsvHistory(self, history):
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    import csv
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    import cStringIO
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    history_stream = cStringIO.StringIO(history)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.history = [(platform, channel, version, date)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for platform, channel, version, date in csv.reader(history_stream)]
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testNoUpdateNeeded(self):
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(B18_0_1025_163_MLW)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._MakeDelegate()
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._Run(OS_MLW)
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertFalse(self._HasUploadedManifest())
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Add another bundle, make sure it still doesn't update
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest.AddBundle(B19_0_1084_41_MLW)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._Run(OS_MLW)
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertFalse(self._HasUploadedManifest())
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testSimpleUpdate(self):
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(B18_NONE)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_MLW, BETA, V18_0_1025_163)
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B18_0_1025_163_MLW)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._MakeDelegate()
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._Run(OS_MLW)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._ReadUploadedManifest()
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testOnePlatformHasNewerRelease(self):
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(B18_NONE)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_M, BETA, V18_0_1025_175)  # Mac has newer version
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_MLW, BETA, V18_0_1025_163)
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B18_0_1025_163_MLW)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._MakeDelegate()
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._Run(OS_MLW)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._ReadUploadedManifest()
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testMultipleMissingPlatformsInHistory(self):
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(B18_NONE)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_ML, BETA, V18_0_1025_184)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_M, BETA, V18_0_1025_175)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_MLW, BETA, V18_0_1025_163)
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B18_0_1025_163_MLW)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._MakeDelegate()
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._Run(OS_MLW)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._ReadUploadedManifest()
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testUpdateOnlyOneBundle(self):
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(B18_NONE, B19_0_1084_41_MLW)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_MLW, BETA, V18_0_1025_163)
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B18_0_1025_163_MLW)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._MakeDelegate()
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._Run(OS_MLW)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._ReadUploadedManifest()
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self._AssertUploadedManifestHasBundle(B19_0_1084_41_MLW, DEV)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(len(self.uploaded_manifest.GetBundles()), 2)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testUpdateTwoBundles(self):
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(B18_NONE, B19_NONE)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_MLW, DEV, V19_0_1084_41)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_MLW, BETA, V18_0_1025_163)
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B18_0_1025_163_MLW)
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B19_0_1084_41_MLW)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._MakeDelegate()
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._Run(OS_MLW)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._ReadUploadedManifest()
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self._AssertUploadedManifestHasBundle(B19_0_1084_41_MLW, DEV)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(len(self.uploaded_manifest.GetBundles()), 2)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testUpdateWithMissingPlatformsInArchives(self):
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(B18_NONE)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_MLW, BETA, V18_0_1025_184)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_MLW, BETA, V18_0_1025_163)
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B18_0_1025_184_MLW, add_archive_for_os=OS_M)
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B18_0_1025_163_MLW)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._MakeDelegate()
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._Run(OS_MLW)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._ReadUploadedManifest()
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testUpdateWithMissingManifestSnippets(self):
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(B18_NONE)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_MLW, BETA, V18_0_1025_184)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_MLW, BETA, V18_0_1025_163)
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B18_0_1025_184_MLW, add_json_for_os=OS_ML)
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B18_0_1025_163_MLW)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._MakeDelegate()
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._Run(OS_MLW)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._ReadUploadedManifest()
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testRecommendedIsStable(self):
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for channel in STABLE, BETA, DEV, CANARY:
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.setUp()
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      bundle = copy.deepcopy(B18_NONE)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.manifest = MakeManifest(bundle)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.history.Add(OS_MLW, channel, V18_0_1025_163)
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      self.files.Add(B18_0_1025_163_MLW)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self._MakeDelegate()
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self._Run(OS_MLW)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self._ReadUploadedManifest()
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uploaded_bundle = self.uploaded_manifest.GetBundle('pepper_18')
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if channel == STABLE:
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.assertEqual(uploaded_bundle.recommended, 'yes')
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.assertEqual(uploaded_bundle.recommended, 'no')
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testNoUpdateWithNonPepperBundle(self):
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.manifest = MakeManifest(NON_PEPPER_BUNDLE_NOARCHIVES,
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        B18_0_1025_163_MLW)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._MakeDelegate()
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._Run(OS_MLW)
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertFalse(self._HasUploadedManifest())
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testUpdateWithHistoryWithExtraneousPlatforms(self):
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(B18_NONE)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_ML, BETA, V18_0_1025_184)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_CR, BETA, V18_0_1025_184)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_CR, BETA, V18_0_1025_175)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_MLW, BETA, V18_0_1025_163)
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B18_0_1025_163_MLW)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._MakeDelegate()
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._Run(OS_MLW)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._ReadUploadedManifest()
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testSnippetWithStringRevisionAndVersion(self):
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # This test exists because some manifest snippets were uploaded with
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # strings for their revisions and versions. I want to make sure the
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # resulting manifest is still consistent with the old format.
474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(B18_NONE)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_MLW, BETA, V18_0_1025_163)
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bundle_string_revision = MakePlatformBundle('18', '1234', V18_0_1025_163,
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                OS_MLW)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.files.Add(bundle_string_revision)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._MakeDelegate()
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._Run(OS_MLW)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._ReadUploadedManifest()
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uploaded_bundle = self.uploaded_manifest.GetBundle(
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bundle_string_revision.name)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(uploaded_bundle.revision, 1234)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(uploaded_bundle.version, 18)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testUpdateCanary(self):
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(copy.deepcopy(BCANARY_NONE))
4896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    self.files.Add(BTRUNK_140819_MLW)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._MakeDelegate()
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._Run(OS_MLW)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._ReadUploadedManifest()
4936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    self._AssertUploadedManifestHasBundle(BTRUNK_140819_MLW, CANARY,
494f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                          bundle_name=CANARY_BUNDLE_NAME)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testCanaryShouldOnlyUseCanaryVersions(self):
497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    canary_bundle = copy.deepcopy(BCANARY_NONE)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.manifest = MakeManifest(canary_bundle)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_MW, CANARY, V21_0_1166_0)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_MW, BETA, V19_0_1084_41)
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B19_0_1084_41_MLW)
502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.version_mapping[V21_0_1166_0] = VTRUNK_140819
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._MakeDelegate()
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertRaises(Exception, self._Run, OS_MLW)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testExtensionWorksAsBz2(self):
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Allow old bundles with just .bz2 extension to work
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(B18_NONE)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.history.Add(OS_MLW, BETA, V18_0_1025_163)
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bundle = copy.deepcopy(B18_0_1025_163_MLW)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    archive_url = bundle.GetArchive('mac').url
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bundle.GetArchive('mac').url = archive_url.replace('.tar', '')
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.files.Add(bundle)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._MakeDelegate()
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._Run(OS_MLW)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._ReadUploadedManifest()
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._AssertUploadedManifestHasBundle(bundle, BETA)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testOnlyOneStableBundle(self):
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    # Make sure that any bundle that has an older version than STABLE is marked
522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    # as POST_STABLE, even if the last version we found was BETA, DEV, etc.
523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for channel in STABLE, BETA, DEV, CANARY:
524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      self.setUp()
525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      self.manifest = MakeManifest(B18_NONE, B19_NONE)
526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      self.history.Add(OS_MLW, channel, V18_0_1025_163)
527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      self.history.Add(OS_MLW, STABLE, V19_0_1084_41)
528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      self.files.Add(B18_0_1025_163_MLW)
529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      self.files.Add(B19_0_1084_41_MLW)
530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      self._MakeDelegate()
531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      self._Run(OS_MLW)
532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      self._ReadUploadedManifest()
533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      p18_bundle = self.uploaded_manifest.GetBundle(B18_NONE.name)
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      self.assertEqual(p18_bundle.stability, POST_STABLE)
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      self.assertEqual(p18_bundle.recommended, 'no')
536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      p19_bundle = self.uploaded_manifest.GetBundle(B19_NONE.name)
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      self.assertEqual(p19_bundle.stability, STABLE)
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      self.assertEqual(p19_bundle.recommended, 'yes')
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testDontPushIfNoChange(self):
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # Make an online manifest that already has this bundle.
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    online_manifest = MakeManifest(B18_0_1025_163_MLW)
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.files.AddOnlineManifest(online_manifest.GetDataAsString())
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(B18_NONE)
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.history.Add(OS_MLW, DEV, V18_0_1025_163)
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B18_0_1025_163_MLW)
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._MakeDelegate()
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._Run(OS_MLW)
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertFalse(self.delegate.called_gsutil_cp)
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testDontPushIfRollback(self):
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # Make an online manifest that has a newer bundle
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    online_manifest = MakeManifest(B18_0_1025_184_MLW)
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.files.AddOnlineManifest(online_manifest.GetDataAsString())
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(B18_NONE)
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.history.Add(OS_MLW, DEV, V18_0_1025_163)
560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B18_0_1025_163_MLW)
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._MakeDelegate()
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._Run(OS_MLW)
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertFalse(self.delegate.called_gsutil_cp)
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testRunWithFixedBundleVersions(self):
567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(B18_NONE)
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.history.Add(OS_MLW, BETA, V18_0_1025_163)
569c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B18_0_1025_163_MLW)
570c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B18_0_1025_184_MLW)
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._MakeDelegate()
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._Run(OS_MLW, None, [('pepper_18', '18.0.1025.184')])
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._ReadUploadedManifest()
575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self._AssertUploadedManifestHasBundle(B18_0_1025_184_MLW, BETA)
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testRunWithMissingFixedBundleVersions(self):
579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(B18_NONE)
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.history.Add(OS_MLW, BETA, V18_0_1025_163)
581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B18_0_1025_163_MLW)
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._MakeDelegate()
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._Run(OS_MLW, None, [('pepper_18', '18.0.1025.184')])
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # Nothing should be uploaded if the user gives a missing fixed version.
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertFalse(self.delegate.called_gsutil_cp)
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testDontIncludeRandomBundles(self):
589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(B26_NONE)
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.history.Add(OS_MLW, BETA, V26_0_1386_0)
591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B26_0_1386_0_MLW)
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    some_other_bundle = MakePepperBundle(26, 1, V26_0_1386_0, BETA)
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    some_other_archive = MakeNonPlatformArchive('some_other.tar.bz2',
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                V26_0_1386_0)
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    some_other_bundle.AddArchive(some_other_archive)
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.files.AddArchive(some_other_bundle, some_other_archive)
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._MakeDelegate()
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._Run(OS_MLW)
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._ReadUploadedManifest()
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uploaded_bundle = self.uploaded_manifest.GetBundle('pepper_26')
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertEqual(1, len(uploaded_bundle.GetHostOSArchives()))
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testNaclportsBundle(self):
606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(B26_NONE)
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.history.Add(OS_MLW, BETA, V26_0_1386_0)
608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B26_0_1386_0_MLW)
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # NaclPorts "bundle".
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    naclports_bundle = MakePepperBundle(26, 1, V26_0_1386_0, BETA)
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    naclports_archive = MakeNonPlatformArchive('naclports.tar.bz2',
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                               V26_0_1386_0)
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    naclports_bundle.AddArchive(naclports_archive)
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.files.AddArchive(naclports_bundle, naclports_archive)
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._MakeDelegate()
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._Run(OS_MLW, [('naclports.tar.bz2', '26.0.1386.0')])
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._ReadUploadedManifest()
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uploaded_bundle = self.uploaded_manifest.GetBundle('pepper_26')
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertEqual(2, len(uploaded_bundle.GetHostOSArchives()))
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testKeepBundleOrder(self):
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # This is a regression test: when a bundle is skipped (because it isn't
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # newer than the online bundle), it was added to the end of the list.
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # Make an online manifest that already has B18.
629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    online_manifest = MakeManifest(B18_0_1025_163_MLW)
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.files.AddOnlineManifest(online_manifest.GetDataAsString())
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(B18_NONE, B19_NONE)
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.history.Add(OS_MLW, STABLE, V18_0_1025_163)
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.history.Add(OS_MLW, STABLE, V19_0_1084_41)
635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B18_0_1025_163_MLW)
636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.Add(B19_0_1084_41_MLW)
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._MakeDelegate()
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._Run(OS_MLW)
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._ReadUploadedManifest()
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # Bundle 18 should be before bundle 19.
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bundles = self.uploaded_manifest.GetBundles()
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertEqual(2, len(bundles))
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertEqual('pepper_18', bundles[0].name)
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertEqual('pepper_19', bundles[1].name)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  def testBundleWithoutHistoryUsesOnline(self):
649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    online_manifest = MakeManifest(B18_0_1025_163_MLW)
650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.files.AddOnlineManifest(online_manifest.GetDataAsString())
651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
652c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(B18_NONE)
653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self._MakeDelegate()
655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    # This should not raise.
656c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self._Run(OS_MLW)
657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self._ReadUploadedManifest()
658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    # But it should have sent an email nagging the users to lock this bundle
660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    # manually.
661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.assertTrue(self.delegate.called_sendmail)
662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    uploaded_bundle = self.uploaded_manifest.GetBundle('pepper_18')
664c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.assertEqual(uploaded_bundle, B18_0_1025_163_MLW)
665c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
666c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  def testBundleWithoutHistoryOrOnlineRaises(self):
667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.manifest = MakeManifest(B18_NONE)
668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self._MakeDelegate()
669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.assertRaises(update_nacl_manifest.UnknownLockedBundleException,
670c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      self._Run, OS_MLW)
671c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
672f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  def testUpdateBionic(self):
673f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    bionic_bundle = copy.deepcopy(BBIONIC_NONE)
674f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    self.manifest = MakeManifest(bionic_bundle)
675f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    self.history.Add(OS_MW, CANARY, V37_0_2054_0)
676f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    self.files.Add(BBIONIC_TRUNK_277776)
677f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    self.version_mapping[V37_0_2054_0] = VTRUNK_277776
678f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    self._MakeDelegate()
679f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    self._Run(OS_MLW)
680f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    self._ReadUploadedManifest()
681f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    self._AssertUploadedManifestHasBundle(BBIONIC_TRUNK_277776, CANARY,
682f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                          bundle_name=BIONIC_CANARY_BUNDLE_NAME)
683f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestUpdateVitals(unittest.TestCase):
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def setUp(self):
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    f = tempfile.NamedTemporaryFile('w', prefix="test_update_nacl_manifest")
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.test_file = f.name
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    f.close()
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_data = "Some test data"
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.sha1 = hashlib.sha1(test_data).hexdigest()
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.data_len = len(test_data)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    with open(self.test_file, 'w') as f:
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      f.write(test_data)
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def tearDown(self):
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os.remove(self.test_file)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testUpdateVitals(self):
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    archive = manifest_util.Archive(manifest_util.GetHostOS())
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    path = os.path.abspath(self.test_file)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if sys.platform == 'win32':
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # On Windows, the path must start with three slashes, i.e.
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # (file:///C:\whatever)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      path = '/' + path
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    archive.url = 'file://' + path
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bundle = MakePlatformBundle(18)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bundle.AddArchive(archive)
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    manifest = MakeManifest(bundle)
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    archive = manifest.GetBundles()[0]['archives'][0]
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertTrue('size' not in archive)
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertTrue('checksum' not in archive)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertRaises(manifest_util.Error, manifest.Validate)
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    manifest.Validate(add_missing_info=True)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(archive['size'], self.data_len)
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(archive['checksum']['sha1'], self.sha1)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if __name__ == '__main__':
7246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  logging.basicConfig(level=logging.CRITICAL)
7256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  # Uncomment the following line to enable more debugging info.
7266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  # logging.getLogger('update_nacl_manifest').setLevel(logging.INFO)
7276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sys.exit(unittest.main())
729