full_check_locales = options.full_check_locales

    # Variables from release config
    retry(mercurial, args=(options.buildbot_configs, 'buildbot-configs'))
    update('buildbot-configs', revision=options.release_tag)
    release_config = validate(options)
    product_name = release_config['productName']
    staging_server = FTP_SERVER_TEMPLATE % release_config['stagingServer']
    aus_server_url = release_config['ausServerUrl']
    build_number = release_config['buildNumber']
    previous_releases_staging_server = FTP_SERVER_TEMPLATE % \
        release_config.get('previousReleasesStagingServer',
                           release_config['stagingServer'])

    # Current version data
    pc = PatcherConfig(open(options.config).read())
    app_name = pc['appName']
    to_version = pc['current-update']['to']
    to_ = makeReleaseRepackUrls(
        product_name, app_name, to_version, options.platform,
        locale='%locale%', signed=True, exclude_secondary=True
    ).values()[0]
    candidates_dir = makeCandidatesDir(
        product_name, to_version, build_number, ftp_root='/')
    to_path = "%s%s" % (candidates_dir, to_)

    partials = pc['current-update']['partials'].keys()
    # Exclude current version from update verify
    completes = pc.getFromVersions()

    uvc = UpdateVerifyConfig(product=app_name, platform=update_platform,
    full_check_locales = options.full_check_locales

    # Variables from release config
    retry(mercurial, args=(options.buildbot_configs, 'buildbot-configs'))
    update('buildbot-configs', revision=options.release_tag)
    release_config = validate(options)
    product_name = release_config['productName']
    staging_server = FTP_SERVER_TEMPLATE % release_config['stagingServer']
    aus_server_url = release_config['ausServerUrl']
    build_number = release_config['buildNumber']
    previous_releases_staging_server = FTP_SERVER_TEMPLATE % \
        release_config.get('previousReleasesStagingServer',
                           release_config['stagingServer'])

    # Current version data
    pc = PatcherConfig(open(options.config).read())
    partials = pc['current-update']['partials'].keys()
    app_name = pc['appName']
    to_version = pc['current-update']['to']
    to_ = makeReleaseRepackUrls(product_name,
                                app_name,
                                to_version,
                                options.platform,
                                locale='%locale%',
                                signed=True,
                                exclude_secondary=True).values()[0]
    candidates_dir = makeCandidatesDir(product_name,
                                       to_version,
                                       build_number,
                                       ftp_root='/')
    to_path = "%s%s" % (candidates_dir, to_)
    full_check_locales = options.full_check_locales

    # Variables from release config
    retry(mercurial, args=(options.buildbot_configs, 'buildbot-configs'))
    update('buildbot-configs', revision=options.release_tag)
    release_config = validate(options)
    product_name = release_config['productName']
    staging_server = FTP_SERVER_TEMPLATE % release_config['stagingServer']
    aus_server_url = release_config['ausServerUrl']
    build_number = release_config['buildNumber']
    previous_releases_staging_server = FTP_SERVER_TEMPLATE % \
        release_config.get('previousReleasesStagingServer',
                           release_config['stagingServer'])

    # Current version data
    pc = PatcherConfig(open(options.config).read())
    app_name = pc['appName']
    to_version = pc['current-update']['to']
    to_ = makeReleaseRepackUrls(
        product_name, app_name, to_version, options.platform,
        locale='%locale%', signed=True, exclude_secondary=True
    ).values()[0]
    candidates_dir = makeCandidatesDir(
        product_name, to_version, build_number, ftp_root='/')
    to_path = "%s%s" % (candidates_dir, to_)

    partials = pc['current-update']['partials'].keys()
    # Exclude current version from update verify
    completes = pc.getFromVersions()

    uvc = UpdateVerifyConfig(product=app_name, platform=update_platform,
    parser.add_argument("--previous-archive-prefix")
    parser.add_argument("--balrog-url", required=True)
    parser.add_argument("--build-number", required=True)
    args = parser.parse_args()
    logging.basicConfig(format="%(message)s", level=args.loglevel)

    ftp_platform = buildbot2ftp(args.platform)
    full_check_locales = args.full_check_locales
    product_name = args.product
    stage_product_name = args.stage_product or product_name
    prev_archive_prefix = args.previous_archive_prefix or args.archive_prefix
    aus_server_url = args.balrog_url
    build_number = args.build_number

    # Current version data
    pc = PatcherConfig(args.config.read())
    partials = pc['current-update']['partials'].keys()
    app_name = pc['appName']
    to_version = pc['current-update']['to']
    to_release = pc['release'][to_version]
    to_ = makeReleaseRepackUrls(
        product_name, app_name, to_version, args.platform,
        locale='%locale%', signed=True, exclude_secondary=True
    ).values()[0]
    candidates_dir = makeCandidatesDir(
        stage_product_name, to_version, build_number, ftp_root='/')
    to_path = "%s%s" % (candidates_dir, to_)

    uvc = UpdateVerifyConfig(
        product=app_name, channel=args.update_verify_channel,
        aus_server=aus_server_url, to=to_path,
 def setUp(self):
     self.pc = PatcherConfig()
                        dest="updater_platform",
                        default=None)
    args = parser.parse_args()
    logging.basicConfig(format="%(message)s", level=args.loglevel)

    ftp_platform = buildbot2ftp(args.platform)
    full_check_locales = args.full_check_locales
    product_name = args.product
    stage_product_name = args.stage_product or product_name
    prev_archive_prefix = args.previous_archive_prefix or args.archive_prefix
    aus_server_url = args.balrog_url
    build_number = args.build_number
    updater_platform = args.updater_platform

    # Current version data
    pc = PatcherConfig(args.config.read())
    partials = pc['current-update']['partials'].keys()
    app_name = pc['appName']
    to_version = pc['current-update']['to']
    to_release = pc['release'][to_version]
    to_ = makeReleaseRepackUrls(product_name,
                                app_name,
                                to_version,
                                args.platform,
                                locale='%locale%',
                                signed=True,
                                exclude_secondary=True).values()[0]
    candidates_dir = makeCandidatesDir(stage_product_name,
                                       to_version,
                                       build_number,
                                       ftp_root='/')
class TestPatcherConfig(unittest.TestCase):
    config = path.join(path.dirname(__file__), "sample-patcher-config.cfg")
    badConfig = path.join(path.dirname(__file__), "bad-patcher-config.cfg")

    def _parse(self, section):
        return ApacheConfParser(section, infile=False).nodes[0].body.nodes

    def setUp(self):
        self.pc = PatcherConfig()

    def testGetUpdatePaths(self):
        expected = (
            ('11.0', 'mac', 'en-US', ('betatest', 'releasetest', 'release'),
             ('complete', )),
            ('11.0', 'mac', 'ja-JP-mac', ('betatest', 'releasetest',
                                          'release'), ('complete', )),
            ('11.0', 'mac', 'zu', ('betatest', 'releasetest', 'release'),
             ('complete', )),
            ('11.0', 'win32', 'en-US', ('betatest', 'releasetest', 'release'),
             ('complete', )),
            ('11.0', 'win32', 'ja', ('betatest', 'releasetest', 'release'),
             ('complete', )),
            ('11.0', 'win32', 'zu', ('betatest', 'releasetest', 'release'),
             ('complete', )),
            ('12.0', 'mac', 'en-US', ('betatest', 'releasetest', 'release'),
             ('complete', 'partial')),
            ('12.0', 'mac', 'ja-JP-mac', ('betatest', 'releasetest',
                                          'release'), ('complete', 'partial')),
            ('12.0', 'mac', 'zu', ('betatest', 'releasetest', 'release'),
             ('complete', 'partial')),
            ('12.0', 'win32', 'en-US', ('betatest', 'releasetest', 'release'),
             ('complete', 'partial')),
            ('12.0', 'win32', 'ja', ('betatest', 'releasetest', 'release'),
             ('complete', 'partial')),
            ('12.0', 'win32', 'zu', ('betatest', 'releasetest', 'release'),
             ('complete', 'partial')),
            ('13.0', 'mac', 'en-US', ('betatest', 'releasetest', 'release'),
             ('complete', 'partial')),
            ('13.0', 'mac', 'ja-JP-mac', ('betatest', 'releasetest',
                                          'release'), ('complete', 'partial')),
            ('13.0', 'win32', 'en-US', ('betatest', 'releasetest', 'release'),
             ('complete', 'partial')),
            ('13.0', 'win32', 'ja', ('betatest', 'releasetest', 'release'),
             ('complete', 'partial')),
        )
        got = []
        # getUpdatePaths is a generator, so we need to store the results before
        # comparison
        for path in samplePatcherConfigObj.getUpdatePaths():
            got.append(path)
        self.assertEquals(sorted(got), sorted(expected))

    def testGetUpdatePathsNone(self):
        got = []
        for path in self.pc.getUpdatePaths():
            got.append(path)
        self.assertEquals(got, [])

    def testReadXml(self):
        self.pc.readXml(open(self.config).read())
        self.assertEquals(self.pc, samplePatcherConfigObj)

    def testReadXmlMultipleCurrentUpdate(self):
        bad = open(self.badConfig).read()
        self.assertRaises(PatcherConfigError, self.pc.readXml, bad)

    def testParsePastUpdate(self):
        expected = ['11.0', '12.0', ['betatest', 'releasetest']]
        got = self.pc.parsePastUpdate(
            ['11.0', '12.0', 'betatest', 'releasetest'])
        self.assertEquals(got, expected)

    def testParsePastUpdateOneChannel(self):
        expected = ['11.0', '12.0', ['betatest']]
        got = self.pc.parsePastUpdate(['11.0', '12.0', 'betatest'])
        self.assertEquals(got, expected)

    def testParsePastUpdateNoChannels(self):
        self.assertRaises(PatcherConfigError, self.pc.parsePastUpdate,
                          ['11.0', '12.0'])

    def testParseCurrentUpdate(self):
        dom = self._parse("""\
<current-update>
    channel   release
    <complete>
        path    %platform%.%locale%.complete.mar
    </complete>
    details   https://details
    from   13.0
    <partials>
        <12.0>
            betatest-url http://%platform%.%locale%.12.0.partial.mar
            path %platform%.%locale%.12.0.partial.mar
            url http://%bouncer-platform%.%locale%.12.0.partial
        </12.0>
        <13.0>
            betatest-url http://%platform%.%locale%.13.0.partial.mar
            path %platform%.%locale%.13.0.partial.mar
            url http://%bouncer-platform%.%locale%.13.0.partial
        </13.0>
    </partials>
    testchannel   betatest releasetest
    to   13.0.1
</current-update>
""")
        expected = {
            'channel': ['release'],
            'details': 'https://details',
            'from': '13.0',
            'testchannel': ['betatest', 'releasetest'],
            'to': '13.0.1',
            'complete': {
                'path': '%platform%.%locale%.complete.mar',
            },
            'partials': {
                '12.0': {
                    'betatest-url':
                    'http://%platform%.%locale%.12.0.partial.mar',
                    'path': '%platform%.%locale%.12.0.partial.mar',
                    'url': 'http://%bouncer-platform%.%locale%.12.0.partial',
                },
                '13.0': {
                    'betatest-url':
                    'http://%platform%.%locale%.13.0.partial.mar',
                    'path': '%platform%.%locale%.13.0.partial.mar',
                    'url': 'http://%bouncer-platform%.%locale%.13.0.partial',
                }
            },
        }
        got = self.pc.parseCurrentUpdate(dom)
        self.assertEquals(got, expected)

    def testParseCurrentUpdateWithForce(self):
        dom = self._parse("""\
<current-update>
    channel   release
    <complete>
        path    %platform%.%locale%.complete.mar
    </complete>
    details   https://details
    from   13.0
    testchannel   betatest releasetest
    to   13.0.1
    force foo
    force bar
</current-update>
""")
        expected = {
            'channel': ['release'],
            'details': 'https://details',
            'from': '13.0',
            'testchannel': ['betatest', 'releasetest'],
            'to': '13.0.1',
            'complete': {
                'path': '%platform%.%locale%.complete.mar',
            },
            'force': ['foo', 'bar'],
        }
        got = self.pc.parseCurrentUpdate(dom)
        self.assertEquals(got, expected)

    def testParseCurrentUpdateMultipleComplete(self):
        dom = self._parse("""\
<current-update>
    channel   release
    <complete>
        path    %platform%.%locale%.complete.mar
    </complete>
    details   https://details
    from   13.0
    <complete>
        path    %platform%.%locale%.partial.mar
    </complete>
    testchannel   betatest releasetest
    to   13.0.1
</current-update>
""")
        self.assertRaises(PatcherConfigError, self.pc.parseCurrentUpdate, dom)

    def testParseRelease(self):
        dom = self._parse("""\
<11.0>
    checksumsurl http://%platform%.%locale%.checksum
    completemarurl  http://%platform%.%locale%.complete
    <exceptions>
        ja   win32, linux-i686
        ja-JP-mac   mac
    </exceptions>
    extension-version   11.0
    locales   de en-US ja ja-JP-mac zu
    mar-channel-ids   firefox-mozilla-beta,firefox-mozilla-release
    <platforms>
        linux-i686 12345
        mac   12345
        win32   12345
    </platforms>
    prettyVersion   11.0
    schema   2
    version   11.0
</11.0>
""")
        expected = {
            'checksumsurl': 'http://%platform%.%locale%.checksum',
            'completemarurl': 'http://%platform%.%locale%.complete',
            'extension-version': '11.0',
            'locales': ['de', 'en-US', 'ja', 'ja-JP-mac', 'zu'],
            'mar-channel-ids': 'firefox-mozilla-beta,firefox-mozilla-release',
            'prettyVersion': '11.0',
            'schema': 2,
            'version': '11.0',
            'exceptions': {
                'ja': ['win32', 'linux-i686'],
                'ja-JP-mac': ['mac'],
            },
            'platforms': {
                'linux-i686': 12345,
                'mac': 12345,
                'win32': 12345,
            },
        }
        got = self.pc.parseRelease(dom)
        self.assertEquals(got, expected)

    def testParseReleaseMultipleNodesSameVersion(self):
        dom = self._parse("""\
<11.0>
version   11.0
version   12.0
</11.0>
""")
        self.assertRaises(PatcherConfigError, self.pc.parseRelease, dom)

    def testAddPastUpdate(self):
        self.pc.addPastUpdate(['1', '2', ['test']])
        self.assertEquals(self.pc['past-update'], [['1', '2', ['test']]])

    def testAddDuplicatePastUpdate(self):
        self.pc['past-update'] = [['1', '2', ['abc']]]
        self.assertRaises(PatcherConfigError, self.pc.addPastUpdate,
                          ['1', '2', ['test']])

    def testAddDuplicatePastUpdate2(self):
        self.pc['past-update'] = [['1', '2', ['abc']]]
        self.assertRaises(PatcherConfigError, self.pc.addPastUpdate,
                          ['1', '3', ['test']])

    def testAddRelease(self):
        self.pc.addRelease('3.0', {
            'schema': 2,
            'version': '3.0',
        })
        self.assertEquals(self.pc['release'],
                          {'3.0': {
                              'schema': 2,
                              'version': '3.0'
                          }})

    def testAddDuplicateRelease(self):
        self.pc['release']['2.0'] = {}
        self.assertRaises(PatcherConfigError, self.pc.addRelease, '2.0', {})

    def testGetUrlComplete(self):
        pc = samplePatcherConfigObj
        with mock.patch.dict('release.platforms.ftp_bouncer_platform_map',
                             {'p': 'pp'}):
            got = pc.getUrl('12.0', 'p', 'l', 'complete', 'release')
            self.assertEquals(got, 'http://pp.l.complete')

    def testGetUrlCompleteOverride(self):
        pc = samplePatcherConfigObj
        got = pc.getUrl('13.0', 'p', 'l', 'complete', 'betatest')
        self.assertEquals(got, 'http://p.l.complete.mar')

    def testGetUrlPartial(self):
        pc = samplePatcherConfigObj
        got = pc.getUrl('12.0', 'p', 'l', 'partial', 'releasetest')
        self.assertEquals(got, 'http://p.l.12.0.partial')

    def testGetUrlNonExistentPartial(self):
        pc = samplePatcherConfigObj
        self.assertRaises(PatcherConfigError, pc.getUrl, '15.0', 'p', 'l',
                          'partial', 'a')

    def testGetPathComplete(self):
        pc = samplePatcherConfigObj
        got = pc.getPath('11.0', 'p', 'l', 'complete')
        self.assertEquals(got, 'p.l.complete.mar')

    def testGetPathPartial(self):
        pc = samplePatcherConfigObj
        got = pc.getPath('12.0', 'p', 'l', 'partial')
        self.assertEquals(got, 'p.l.12.0.partial.mar')

    def testGetOptionalAttrsSchema1(self):
        pc = samplePatcherConfigObj
        self.assertEquals(pc.getOptionalAttrs('11.0', 'en-US'), {})

    def testGetOptionalAttrsSchema2(self):
        pc = samplePatcherConfigObj
        self.assertEquals(pc.getOptionalAttrs('12.0', 'en-US'),
                          {'actions': ['silent']})

    def testGetOptionalAttrsSchema2WrongLocale(self):
        pc = samplePatcherConfigObj
        self.assertEquals(pc.getOptionalAttrs('12.0', 'de'), {})

    def testGetFromVersions(self):
        pc = samplePatcherConfigObj
        self.assertEquals(sorted(pc.getFromVersions()),
                          ['11.0', '12.0', '13.0'])
from os import path
import unittest

import mock

from apache_conf_parser import ApacheConfParser

from release.updates.patcher import substitutePath, PatcherConfig, PatcherConfigError

samplePatcherConfigObj = PatcherConfig()
samplePatcherConfigObj['appName'] = 'Firefox'
samplePatcherConfigObj['current-update'] = {
    'channel': ['release'],
    'testchannel': ['betatest', 'releasetest'],
    'details': 'https://details',
    'from': '13.0',
    'to': '13.0.1',
    'actions': ['silent'],
    'action-locales': ['en-US'],
    'complete': {
        'betatest-url': 'http://%platform%.%locale%.complete.mar',
        'path': '%platform%.%locale%.complete.mar',
        'url': 'http://%bouncer-platform%.%locale%.complete',
    },
    'partials': {
        '12.0': {
            'betatest-url': 'http://%platform%.%locale%.12.0.partial.mar',
            'path': '%platform%.%locale%.12.0.partial.mar',
            'url': 'http://%bouncer-platform%.%locale%.12.0.partial',
        },
        '13.0': {
 def setUp(self):
     self.pc = PatcherConfig()
class TestPatcherConfig(unittest.TestCase):
    config = path.join(path.dirname(__file__), "sample-patcher-config.cfg")
    badConfig = path.join(path.dirname(__file__), "bad-patcher-config.cfg")

    def _parse(self, section):
        return ApacheConfParser(section, infile=False).nodes[0].body.nodes

    def setUp(self):
        self.pc = PatcherConfig()

    def testGetUpdatePaths(self):
        expected = (
            ('11.0', 'mac', 'en-US', ('betatest',
             'releasetest', 'release'), ('complete',)),
            ('11.0', 'mac', 'ja-JP-mac', ('betatest',
             'releasetest', 'release'), ('complete',)),
            ('11.0', 'mac', 'zu', ('betatest', 'releasetest',
             'release'), ('complete',)),
            ('11.0', 'win32', 'en-US', ('betatest',
             'releasetest', 'release'), ('complete',)),
            ('11.0', 'win32', 'ja', ('betatest', 'releasetest',
             'release'), ('complete',)),
            ('11.0', 'win32', 'zu', ('betatest', 'releasetest',
             'release'), ('complete',)),
            ('12.0', 'mac', 'en-US', ('betatest',
             'releasetest', 'release'), ('complete', 'partial')),
            ('12.0', 'mac', 'ja-JP-mac', ('betatest',
             'releasetest', 'release'), ('complete', 'partial')),
            ('12.0', 'mac', 'zu', ('betatest', 'releasetest',
             'release'), ('complete', 'partial')),
            ('12.0', 'win32', 'en-US', ('betatest',
             'releasetest', 'release'), ('complete', 'partial')),
            ('12.0', 'win32', 'ja', ('betatest', 'releasetest',
             'release'), ('complete', 'partial')),
            ('12.0', 'win32', 'zu', ('betatest', 'releasetest',
             'release'), ('complete', 'partial')),
            ('13.0', 'mac', 'en-US', ('betatest',
             'releasetest', 'release'), ('complete', 'partial')),
            ('13.0', 'mac', 'ja-JP-mac', ('betatest',
             'releasetest', 'release'), ('complete', 'partial')),
            ('13.0', 'win32', 'en-US', ('betatest',
             'releasetest', 'release'), ('complete', 'partial')),
            ('13.0', 'win32', 'ja', ('betatest', 'releasetest',
             'release'), ('complete', 'partial')),
            ('13.0', 'win64', 'en-US', ('betatest',
             'releasetest', 'release'), ('complete', 'partial')),
            ('13.0', 'win64', 'ja', ('betatest', 'releasetest',
             'release'), ('complete', 'partial')),
        )
        got = []
        # getUpdatePaths is a generator, so we need to store the results before
        # comparison
        for path in samplePatcherConfigObj.getUpdatePaths():
            got.append(path)
        self.assertEquals(sorted(got), sorted(expected))

    def testGetUpdatePathsNone(self):
        got = []
        for path in self.pc.getUpdatePaths():
            got.append(path)
        self.assertEquals(got, [])

    def testReadXml(self):
        self.pc.readXml(open(self.config).read())
        self.assertEquals(self.pc, samplePatcherConfigObj)

    def testReadXmlMultipleCurrentUpdate(self):
        bad = open(self.badConfig).read()
        self.assertRaises(PatcherConfigError, self.pc.readXml, bad)

    def testParsePastUpdate(self):
        expected = ['11.0', '12.0', ['betatest', 'releasetest']]
        got = self.pc.parsePastUpdate(
            ['11.0', '12.0', 'betatest', 'releasetest'])
        self.assertEquals(got, expected)

    def testParsePastUpdateOneChannel(self):
        expected = ['11.0', '12.0', ['betatest']]
        got = self.pc.parsePastUpdate(['11.0', '12.0', 'betatest'])
        self.assertEquals(got, expected)

    def testParsePastUpdateNoChannels(self):
        self.assertRaises(
            PatcherConfigError, self.pc.parsePastUpdate, ['11.0', '12.0'])

    def testParseCurrentUpdate(self):
        dom = self._parse("""\
<current-update>
    channel   release
    <complete>
        path    %platform%.%locale%.complete.mar
    </complete>
    details   https://details
    from   13.0
    <partials>
        <12.0>
            betatest-url http://%platform%.%locale%.12.0.partial.mar
            path %platform%.%locale%.12.0.partial.mar
            url http://%bouncer-platform%.%locale%.12.0.partial
        </12.0>
        <13.0>
            betatest-url http://%platform%.%locale%.13.0.partial.mar
            path %platform%.%locale%.13.0.partial.mar
            url http://%bouncer-platform%.%locale%.13.0.partial
        </13.0>
    </partials>
    testchannel   betatest releasetest
    to   13.0.1
</current-update>
""")
        expected = {
            'channel': ['release'],
            'details': 'https://details',
            'from': '13.0',
            'testchannel': ['betatest', 'releasetest'],
            'to': '13.0.1',
            'complete': {
                'path': '%platform%.%locale%.complete.mar',
            },
            'partials': {
                '12.0': {
                    'betatest-url': 'http://%platform%.%locale%.12.0.partial.mar',
                    'path': '%platform%.%locale%.12.0.partial.mar',
                    'url': 'http://%bouncer-platform%.%locale%.12.0.partial',
                },
                '13.0': {
                    'betatest-url': 'http://%platform%.%locale%.13.0.partial.mar',
                    'path': '%platform%.%locale%.13.0.partial.mar',
                    'url': 'http://%bouncer-platform%.%locale%.13.0.partial',
                }
            },
        }
        got = self.pc.parseCurrentUpdate(dom)
        self.assertEquals(got, expected)

    def testParseCurrentUpdateWithForce(self):
        dom = self._parse("""\
<current-update>
    channel   release
    <complete>
        path    %platform%.%locale%.complete.mar
    </complete>
    details   https://details
    from   13.0
    testchannel   betatest releasetest
    to   13.0.1
    force foo
    force bar
</current-update>
""")
        expected = {
            'channel': ['release'],
            'details': 'https://details',
            'from': '13.0',
            'testchannel': ['betatest', 'releasetest'],
            'to': '13.0.1',
            'complete': {
                'path': '%platform%.%locale%.complete.mar',
            },
            'force': ['foo', 'bar'],
        }
        got = self.pc.parseCurrentUpdate(dom)
        self.assertEquals(got, expected)

    def testParseCurrentUpdateMultipleComplete(self):
        dom = self._parse("""\
<current-update>
    channel   release
    <complete>
        path    %platform%.%locale%.complete.mar
    </complete>
    details   https://details
    from   13.0
    <complete>
        path    %platform%.%locale%.partial.mar
    </complete>
    testchannel   betatest releasetest
    to   13.0.1
</current-update>
""")
        self.assertRaises(PatcherConfigError, self.pc.parseCurrentUpdate, dom)

    def testParseRelease(self):
        dom = self._parse("""\
<11.0>
    checksumsurl http://%platform%.%locale%.checksum
    completemarurl  http://%platform%.%locale%.complete
    <exceptions>
        ja   win32, linux-i686
        ja-JP-mac   mac
    </exceptions>
    extension-version   11.0
    locales   de en-US ja ja-JP-mac zu
    mar-channel-ids   firefox-mozilla-beta,firefox-mozilla-release
    <platforms>
        linux-i686 12345
        mac   12345
        win32   12345
    </platforms>
    prettyVersion   11.0
    schema   2
    version   11.0
</11.0>
""")
        expected = {
            'checksumsurl': 'http://%platform%.%locale%.checksum',
            'completemarurl': 'http://%platform%.%locale%.complete',
            'extension-version': '11.0',
            'locales': ['de', 'en-US', 'ja', 'ja-JP-mac', 'zu'],
            'mar-channel-ids': 'firefox-mozilla-beta,firefox-mozilla-release',
            'prettyVersion': '11.0',
            'schema': 2,
            'version': '11.0',
            'exceptions': {
                'ja': ['win32', 'linux-i686'],
                'ja-JP-mac': ['mac'],
            },
            'platforms': {
                'linux-i686': 12345,
                'mac': 12345,
                'win32': 12345,
            },
        }
        got = self.pc.parseRelease(dom)
        self.assertEquals(got, expected)

    def testParseReleaseMultipleNodesSameVersion(self):
        dom = self._parse("""\
<11.0>
version   11.0
version   12.0
</11.0>
""")
        self.assertRaises(PatcherConfigError, self.pc.parseRelease, dom)

    def testAddPastUpdate(self):
        self.pc.addPastUpdate(['1', '2', ['test']])
        self.assertEquals(self.pc['past-update'], [['1', '2', ['test']]])

    def testAddDuplicatePastUpdate(self):
        self.pc['past-update'] = [['1', '2', ['abc']]]
        self.assertRaises(
            PatcherConfigError, self.pc.addPastUpdate, ['1', '2', ['test']])

    def testAddDuplicatePastUpdate2(self):
        self.pc['past-update'] = [['1', '2', ['abc']]]
        self.assertRaises(
            PatcherConfigError, self.pc.addPastUpdate, ['1', '3', ['test']])

    def testAddRelease(self):
        self.pc.addRelease('3.0', {
            'schema': 2,
            'version': '3.0',
        })
        self.assertEquals(
            self.pc['release'], {'3.0': {'schema': 2, 'version': '3.0'}})

    def testAddDuplicateRelease(self):
        self.pc['release']['2.0'] = {}
        self.assertRaises(PatcherConfigError, self.pc.addRelease, '2.0', {})

    def testGetUrlComplete(self):
        pc = samplePatcherConfigObj
        with mock.patch.dict('release.platforms.ftp_bouncer_platform_map', {'p': 'pp'}):
            got = pc.getUrl('12.0', 'p', 'l', 'complete', 'release')
            self.assertEquals(got, 'http://pp.l.complete')

    def testGetUrlCompleteOverride(self):
        pc = samplePatcherConfigObj
        got = pc.getUrl('13.0', 'p', 'l', 'complete', 'betatest')
        self.assertEquals(got, 'http://p.l.complete.mar')

    def testGetUrlPartial(self):
        pc = samplePatcherConfigObj
        got = pc.getUrl('12.0', 'p', 'l', 'partial', 'releasetest')
        self.assertEquals(got, 'http://p.l.12.0.partial')

    def testGetUrlNonExistentPartial(self):
        pc = samplePatcherConfigObj
        self.assertRaises(
            PatcherConfigError, pc.getUrl, '15.0', 'p', 'l', 'partial', 'a')

    def testGetPathComplete(self):
        pc = samplePatcherConfigObj
        got = pc.getPath('11.0', 'p', 'l', 'complete')
        self.assertEquals(got, 'p.l.complete.mar')

    def testGetPathPartial(self):
        pc = samplePatcherConfigObj
        got = pc.getPath('12.0', 'p', 'l', 'partial')
        self.assertEquals(got, 'p.l.12.0.partial.mar')

    def testGetOptionalAttrsSchema1(self):
        pc = samplePatcherConfigObj
        self.assertEquals(pc.getOptionalAttrs('11.0', 'en-US'), {})

    def testGetOptionalAttrsSchema2(self):
        pc = samplePatcherConfigObj
        self.assertEquals(pc.getOptionalAttrs('12.0', 'en-US'), {'actions': ['silent']})

    def testGetOptionalAttrsSchema2WrongLocale(self):
        pc = samplePatcherConfigObj
        self.assertEquals(pc.getOptionalAttrs('12.0', 'de'), {})

    def testGetFromVersions(self):
        pc = samplePatcherConfigObj
        self.assertEquals(
            sorted(pc.getFromVersions()), ['11.0', '12.0', '13.0'])
Пример #11
0
        "-v", "--verbose", dest="verbose", default=False, action="store_true")

    options, args = parser.parse_args()

    if not options.config:
        print >>sys.stderr, "Required option --config not present"
        sys.exit(1)

    log_level = logging.INFO
    if options.verbose:
        log_level = logging.DEBUG
    logging.basicConfig(level=log_level, format="%(asctime)s - %(levelname)s - %(name)s.%(funcName)s#%(lineno)s: %(message)s")
    log = logging.getLogger()

    hashType = options.hashType.lower()
    pc = PatcherConfig(open(options.config).read())
    appName = pc['appName']
    version = pc['current-update']['to']
    appVersion = pc['release'][version]['extension-version']
    prettyVersion = pc['release'][version]['prettyVersion']

    # We end up using most checksums many times so we keep an in-memory
    # cache of them to speed things up. We also keep an on-disk cache
    # of the downloaded .checksums files in checksumsDir to speed things up
    # if we have to re-run the script for some reason.
    checksums = {}
    checksumsDir = options.checksumsDir
    if not path.exists(checksumsDir):
        mkdir(checksumsDir)

    def cacheChecksums(platform, locale, sums):