Example #1
0
    def test_reset_orphaned_builds(self):
        BuildConfig(self.env, 'test').insert()
        platform = TargetPlatform(self.env, config='test', name='Foo')
        platform.insert()
        build1 = Build(self.env,
                       config='test',
                       platform=platform.id,
                       rev=123,
                       rev_time=42,
                       status=Build.IN_PROGRESS,
                       slave='heinz',
                       started=time.time() - 600)  # Started ten minutes ago
        build1.insert()

        build2 = Build(self.env,
                       config='test',
                       platform=platform.id,
                       rev=124,
                       rev_time=42,
                       status=Build.IN_PROGRESS,
                       slave='heinz',
                       started=time.time() - 60)  # Started a minute ago
        build2.insert()

        queue = BuildQueue(self.env, timeout=300)  # 5 minutes timeout
        build = queue.reset_orphaned_builds()
        self.assertEqual(Build.PENDING,
                         Build.fetch(self.env, build1.id).status)
        self.assertEqual(Build.IN_PROGRESS,
                         Build.fetch(self.env, build2.id).status)
Example #2
0
    def test_view_config(self):
        config = BuildConfig(self.env, name='test', path='trunk')
        config.insert()
        platform = TargetPlatform(self.env, config='test', name='any')
        platform.insert()

        PermissionSystem(self.env).grant_permission('joe', 'BUILD_VIEW')
        req = Mock(method='GET', base_path='', cgi_location='',
                   path_info='/build/test', href=Href('/trac'), args={},
                   chrome={}, authname='joe',
                   perm=PermissionCache(self.env, 'joe'))

        root = Mock(get_entries=lambda: ['foo'],
                    get_history=lambda: [('trunk', rev, 'edit') for rev in
                                          range(123, 111, -1)])
        self.repos.get_node=lambda path, rev=None: root
        self.repos.youngest_rev=123
        self.repos.get_changeset=lambda rev: Mock(author='joe', date=99)

        module = BuildConfigController(self.env)
        assert module.match_request(req)
        _, data, _ = module.process_request(req)

        self.assertEqual('view_config', data['page_mode'])
        assert not 'next' in req.chrome['links']

        self.assertEquals(Resource('build', 'test'), data['context'].resource)

        self.assertEquals([], data['config']['attachments']['attachments'])
        self.assertEquals('/trac/attachment/build/test/',
                                data['config']['attachments']['attach_href'])
Example #3
0
    def test_bitten_keeps_order_of_revisions_from_versioncontrol(self):
        # Trac's API specifies that they are sorted chronological (backwards)
        # We must not assume that these revision numbers can be sorted later on,
        # for example the mercurial plugin will return the revisions as strings
        # (e.g. '880:4c19fa95fb9e')
        config = BuildConfig(self.env, name='test', path='trunk')
        config.insert()
        platform = TargetPlatform(self.env, config='test', name='any')
        platform.insert()

        PermissionSystem(self.env).grant_permission('joe', 'BUILD_VIEW')
        req = Mock(method='GET', base_path='', cgi_location='',
                   path_info='/build/'+config.name, href=Href('/trac'), args={},
                   chrome={}, authname='joe',
                   perm=PermissionCache(self.env, 'joe'))

        # revisions are intentionally not sorted in any way - bitten should just keep them!
        revision_ids = [5, 8, 2]
        revision_list = [('trunk', revision, 'edit') for revision in revision_ids]
        root = Mock(get_entries=lambda: ['foo'], get_history=lambda: revision_list)
        self.repos.get_node=lambda path, rev=None: root
        self.repos.youngest_rev=5
        self.repos.get_changeset=lambda rev: Mock(author='joe', date=99)

        module = BuildConfigController(self.env)
        assert module.match_request(req)
        _, data, _ = module.process_request(req)

        actual_revision_ids = data['config']['revisions']
        self.assertEquals(revision_ids, actual_revision_ids)
Example #4
0
    def test_view_config_paging(self):
        config = BuildConfig(self.env, name='test', path='trunk')
        config.insert()
        platform = TargetPlatform(self.env, config='test', name='any')
        platform.insert()

        PermissionSystem(self.env).grant_permission('joe', 'BUILD_VIEW')
        req = Mock(method='GET',
                   base_path='',
                   cgi_location='',
                   path_info='/build/test',
                   href=Href('/trac'),
                   args={},
                   chrome={},
                   authname='joe',
                   perm=PermissionCache(self.env, 'joe'))

        root = Mock(get_entries=lambda: ['foo'],
                    get_history=lambda: [('trunk', rev, 'edit')
                                         for rev in range(123, 110, -1)])
        self.repos = Mock(get_node=lambda path, rev=None: root,
                          sync=lambda: None,
                          normalize_path=lambda path: path,
                          normalize_rev=lambda rev: rev,
                          youngest_rev=123)
        self.repos.authz = Mock(has_permission=lambda path: True,
                                assert_permission=lambda path: None)

        module = BuildConfigController(self.env)
        assert module.match_request(req)
        _, data, _ = module.process_request(req)

        if req.chrome:
            self.assertEqual('/trac/build/test?page=2',
                             req.chrome['links']['next'][0]['href'])
Example #5
0
    def test_view_config_paging(self):
        config = BuildConfig(self.env, name='test', path='trunk')
        config.insert()
        platform = TargetPlatform(self.env, config='test', name='any')
        platform.insert()

        PermissionSystem(self.env).grant_permission('joe', 'BUILD_VIEW')
        req = Mock(method='GET', base_path='', cgi_location='',
                   path_info='/build/test', href=Href('/trac'), args={},
                   chrome={}, authname='joe',
                   perm=PermissionCache(self.env, 'joe'))

        root = Mock(get_entries=lambda: ['foo'],
                    get_history=lambda: [('trunk', rev, 'edit') for rev in
                                          range(123, 110, -1)])
        self.repos = Mock(get_node=lambda path, rev=None: root,
                          sync=lambda: None, normalize_path=lambda path: path)
        self.repos.authz = Mock(has_permission=lambda path: True, assert_permission=lambda path: None)

        module = BuildConfigController(self.env)
        assert module.match_request(req)
        _, data, _ = module.process_request(req)

        if req.chrome:
            self.assertEqual('/trac/build/test?page=2',
                             req.chrome['links']['next'][0]['href'])
Example #6
0
    def test_process_remove_platforms_no_selection(self):
        BuildConfig(self.env,
                    name='foo',
                    label='Foo',
                    path='branches/foo',
                    active=True).insert()
        platform = TargetPlatform(self.env, config='foo', name='any')
        platform.insert()

        redirected_to = []

        def redirect(url):
            redirected_to.append(url)
            raise RequestDone

        req = Mock(method='POST',
                   perm=PermissionCache(self.env, 'joe'),
                   abs_href=Href('http://example.org/'),
                   redirect=redirect,
                   authname='joe',
                   args={'remove': ''})

        provider = BuildConfigurationsAdminPageProvider(self.env)
        try:
            provider.render_admin_panel(req, 'bitten', 'configs', 'foo')
            self.fail('Expected TracError')

        except TracError, e:
            self.assertEqual('No platform selected', e.message)
Example #7
0
    def should_delete_build(self, build, repos):
        # Ignore pending builds for deactived build configs
        config = BuildConfig.fetch(self.env, build.config)
        if not config.active:
            target_platform = TargetPlatform.fetch(self.env, build.platform)
            if target_platform:
                target_platform_name = '"%s"' % (target_platform.name,)
            else:
                target_platform_name = 'unknown platform "%s"' % (build.platform,)
            log.info('Dropping build of configuration "%s" at '
                     'revision [%s] on %s because the configuration is '
                     'deactivated', config.name, build.rev,
                     target_platform_name)
            return True

        # Stay within the revision limits of the build config
        if (config.min_rev and repos.rev_older_than(build.rev,
                                                    config.min_rev)) \
        or (config.max_rev and repos.rev_older_than(config.max_rev,
                                                    build.rev)):
            # This minimum and/or maximum revision has changed since
            # this build was enqueued, so drop it
            log.info('Dropping build of configuration "%s" at revision [%s] on '
                     '"%s" because it is outside of the revision range of the '
                     'configuration', config.name, build.rev,
                     TargetPlatform.fetch(self.env, build.platform).name)
            return True

        return False
Example #8
0
    def test_process_edit_platform(self):
        BuildConfig(self.env,
                    name='foo',
                    label='Foo',
                    path='branches/foo',
                    active=True).insert()
        platform = TargetPlatform(self.env, config='foo', name='any')
        platform.insert()

        req = Mock(method='GET',
                   chrome={},
                   href=Href('/'),
                   perm=PermissionCache(self.env, 'joe'),
                   args={})

        provider = BuildConfigurationsAdminPageProvider(self.env)
        template_name, data = provider.render_admin_panel(
            req, 'bitten', 'configs', 'foo/%d' % platform.id)

        self.assertEqual('bitten_admin_configs.html', template_name)
        assert 'platform' in data
        platform = data['platform']
        self.assertEqual(
            {
                'id': 1,
                'exists': True,
                'name': 'any',
                'rules': [('', '')],
            }, platform)
Example #9
0
    def test_process_remove_platforms(self):
        BuildConfig(self.env, name='foo', label='Foo', path='branches/foo',
                    active=True).insert()
        platform = TargetPlatform(self.env, config='foo', name='any')
        platform.insert()

        redirected_to = []
        def redirect(url):
            redirected_to.append(url)
            raise RequestDone
        req = Mock(method='POST', perm=PermissionCache(self.env, 'joe'),
                   abs_href=Href('http://example.org/'), redirect=redirect,
                   authname='joe', chrome={'warnings': [], 'notices': []},
                   href=Href('/'),
                   args={'remove': '', 'sel': str(platform.id)})

        provider = BuildConfigurationsAdminPageProvider(self.env)
        try:
            provider.render_admin_panel(req, 'bitten', 'configs', 'foo')
            self.fail('Expected RequestDone')

        except RequestDone:
            self.assertEquals(['Target Platform(s) Removed.'],
                               req.chrome['notices'])
            self.assertEqual('http://example.org/admin/bitten/configs/foo',
                             redirected_to[0])
            platforms = list(TargetPlatform.select(self.env, config='foo'))
            self.assertEqual(0, len(platforms))
Example #10
0
    def test_process_update_platform_cancel(self):
        BuildConfig(self.env, name='foo', label='Foo', path='branches/foo',
                    active=True).insert()
        platform = TargetPlatform(self.env, config='foo', name='any')
        platform.insert()

        redirected_to = []
        def redirect(url):
            redirected_to.append(url)
            raise RequestDone
        req = Mock(method='POST', perm=PermissionCache(self.env, 'joe'),
                   abs_href=Href('http://example.org/'), redirect=redirect,
                   authname='joe',
                   args={'cancel': '', 'edit': '', 'name': 'Changed',
                         'property_0': 'family', 'pattern_0': 'posix'})

        provider = BuildConfigurationsAdminPageProvider(self.env)
        try:
            provider.render_admin_panel(req, 'bitten', 'configs',
                                           'foo/%d' % platform.id)
            self.fail('Expected RequestDone')

        except RequestDone:
            self.assertEqual('http://example.org/admin/bitten/configs/foo',
                             redirected_to[0])
            platforms = list(TargetPlatform.select(self.env, config='foo'))
            self.assertEqual(1, len(platforms))
            self.assertEqual('any', platforms[0].name)
            self.assertEqual([], platforms[0].rules)
Example #11
0
    def test_should_delete_build_outside_revision_range(self):
        messages = []
        self.env.log = Mock(info=lambda msg, *args: messages.append(msg))
        self.repos.rev_older_than = lambda rev1, rev2: rev1 < rev2
        config = BuildConfig(self.env,
                             'test',
                             active=True,
                             min_rev=120,
                             max_rev=123)
        config.insert()
        platform = TargetPlatform(self.env, config='test', name='stuff')
        platform.insert()
        build1 = Build(self.env,
                       config=config.name,
                       rev=42,
                       platform=platform.id,
                       rev_time=123456)
        build1.insert()
        build2 = Build(self.env,
                       config=config.name,
                       rev=10042,
                       platform=platform.id,
                       rev_time=123456)
        build2.insert()
        queue = BuildQueue(self.env, build_all=True)

        self.assertEqual(True, queue.should_delete_build(build1, self.repos))
        self.assertEqual(True, queue.should_delete_build(build2, self.repos))
        self.assert_("outside of the revision range" in messages[0])
        self.assert_("outside of the revision range" in messages[1])
Example #12
0
    def setUp(self):
        self.env = EnvironmentStub(enable=['trac.*', 'bitten.*'])
        self.env.path = tempfile.mkdtemp()

        db = self.env.get_db_cnx()
        cursor = db.cursor()
        connector, _ = DatabaseManager(self.env)._get_connector()
        for table in schema:
            for stmt in connector.to_sql(table):
                cursor.execute(stmt)

        self.config = BuildConfig(self.env, name='test', path='somepath')
        self.config.insert(db=db)
        self.platform = TargetPlatform(self.env, config='test', name='Foo')
        self.platform.insert(db=db)
        db.commit()

        # Hook up a dummy repository
        self.repos = Mock()
        self.env.get_repository = lambda authname=None: self.repos # 0.11
        try: # 0.12+
            from trac.core import Component, implements
            from trac.versioncontrol.api import IRepositoryConnector, \
                                                IRepositoryProvider
            class DummyRepos(Component):
                implements(IRepositoryConnector, IRepositoryProvider)
                def get_supported_types(self):
                    yield ('dummy', 9)
                def get_repository(this, repos_type, repos_dir, params):
                    return self.repos # Note: 'this' vs 'self' usage
                def get_repositories(self):
                    yield ('', {'dir': 'dummy_dir', 'type': 'dummy'})
            self.dummy = DummyRepos
        except ImportError:
            self.dummy = None # not supported, will use get_repository()
Example #13
0
    def test_register_slave_match_regexp_invalid(self):
        BuildConfig(self.env, 'test', active=True).insert()
        platform = TargetPlatform(self.env, config='test', name="Unix")
        platform.rules.append(('version', '8(\.\d'))
        platform.insert()

        queue = BuildQueue(self.env)
        platforms = queue.match_slave('foo', {'version': '7.8.1'})
        self.assertEqual([], platforms)
Example #14
0
    def test_register_slave_match_simple_fail(self):
        BuildConfig(self.env, 'test', active=True).insert()
        platform = TargetPlatform(self.env, config='test', name="Unix")
        platform.rules.append(('family', 'posix'))
        platform.insert()

        queue = BuildQueue(self.env)
        platforms = queue.match_slave('foo', {'family': 'nt'})
        self.assertEqual([], platforms)
Example #15
0
    def test_register_slave_match_simple_fail(self):
        BuildConfig(self.env, 'test', active=True).insert()
        platform = TargetPlatform(self.env, config='test', name="Unix")
        platform.rules.append(('family', 'posix'))
        platform.insert()

        queue = BuildQueue(self.env)
        platforms = queue.match_slave('foo', {'family': 'nt'})
        self.assertEqual([], platforms)
Example #16
0
    def test_register_slave_match_regexp_invalid(self):
        BuildConfig(self.env, 'test', active=True).insert()
        platform = TargetPlatform(self.env, config='test', name="Unix")
        platform.rules.append(('version', '8(\.\d'))
        platform.insert()

        queue = BuildQueue(self.env)
        platforms = queue.match_slave('foo', {'version': '7.8.1'})
        self.assertEqual([], platforms)
Example #17
0
    def _create_platform(self, req, config_name):
        req.perm.assert_permission('BUILD_MODIFY')

        name = req.args.get('platform_name')
        if not name:
            raise TracError('Missing required field "name"', 'Missing field')

        platform = TargetPlatform(self.env, config=config_name, name=name)
        platform.insert()
        return platform
Example #18
0
    def _create_platform(self, req, config_name):
        req.perm.assert_permission('BUILD_MODIFY')

        name = req.args.get('platform_name')
        if not name:
            raise TracError('Missing required field "name"', 'Missing field')

        platform = TargetPlatform(self.env, config=config_name, name=name)
        platform.insert()
        return platform
Example #19
0
    def test_initiate_build(self):
        config = BuildConfig(self.env,
                             'test',
                             path='somepath',
                             active=True,
                             recipe='<build><step id="s1"></step></build>')
        config.insert()
        platform = TargetPlatform(self.env, config='test', name="Unix")
        platform.rules.append(('family', 'posix'))
        platform.insert()
        build = Build(self.env,
                      'test',
                      '123',
                      platform.id,
                      slave='hal',
                      rev_time=42)
        build.insert()

        outheaders = {}
        outbody = StringIO()

        req = Mock(method='GET',
                   base_path='',
                   path_info='/builds/%d' % build.id,
                   href=Href('/trac'),
                   remote_addr='127.0.0.1',
                   args={},
                   authname='hal',
                   perm=PermissionCache(self.env, 'hal'),
                   send_response=lambda x: outheaders.setdefault('Status', x),
                   send_header=lambda x, y: outheaders.setdefault(x, y),
                   write=outbody.write,
                   form_token="12345",
                   incookie=Cookie('trac_auth='))

        module = BuildMaster(self.env)
        assert module.match_request(req)

        self.assertRaises(RequestDone, module.process_request, req)
        self.assertEqual(200, outheaders['Status'])
        self.assertEqual('163', outheaders['Content-Length'])
        self.assertEqual('application/x-bitten+xml',
                         outheaders['Content-Type'])
        self.assertEqual('attachment; filename=recipe_test_r123.xml',
                         outheaders['Content-Disposition'])
        self.assertEqual(
            '<build build="1" config="test" form_token="12345" '
            'name="hal" path="somepath" platform="Unix" '
            'reponame="" repopath="somepath" '
            'revision="123"><step id="s1"/></build>', outbody.getvalue())

        # Make sure the started timestamp has been set
        build = Build.fetch(self.env, build.id)
        assert build.started
Example #20
0
    def test_register_slave_match_regexp(self):
        BuildConfig(self.env, 'test', active=True).insert()
        platform = TargetPlatform(self.env, config='test', name="Unix")
        platform.rules.append(('version', '8\.\d\.\d'))
        platform.insert()
        platform_id = platform.id

        queue = BuildQueue(self.env)
        platforms = queue.match_slave('foo', {'version': '8.2.0'})
        self.assertEqual(1, len(platforms))
        self.assertEqual(platform_id, platforms[0].id)
Example #21
0
    def test_register_slave_match_regexp(self):
        BuildConfig(self.env, 'test', active=True).insert()
        platform = TargetPlatform(self.env, config='test', name="Unix")
        platform.rules.append(('version', '8\.\d\.\d'))
        platform.insert()
        platform_id = platform.id

        queue = BuildQueue(self.env)
        platforms = queue.match_slave('foo', {'version': '8.2.0'})
        self.assertEqual(1, len(platforms))
        self.assertEqual(platform_id, platforms[0].id)
Example #22
0
    def test_match_slave_match(self):
        BuildConfig(self.env, 'test', active=True).insert()
        platform = TargetPlatform(self.env, config='test', name="Unix")
        platform.rules.append(('family', 'posix'))
        platform.insert()
        platform_id = platform.id

        queue = BuildQueue(self.env)
        platforms = queue.match_slave('foo', {'family': 'posix'})
        self.assertEqual(1, len(platforms))
        self.assertEqual(platform_id, platforms[0].id)
Example #23
0
    def test_delete_platform_with_pending_builds(self):
        """Check that deleting a platform with pending builds removes those pending builds"""
        db = self.env.get_db_cnx()
        platform = TargetPlatform(self.env, config='test', name='Linux')
        platform.insert()
        build = Build(self.env, config='test', platform=platform.id, rev='42', rev_time=12039)
        build.insert()

        platform.delete()
        pending = list(build.select(self.env, config='test', status=Build.PENDING))
        self.assertEqual(0, len(pending))
Example #24
0
    def test_register_slave_match_case_insensitive(self):
        BuildConfig(self.env, 'test', active=True).insert()
        platform = TargetPlatform(self.env, config='test', name="Unix")
        platform.rules.append(('os', 'LiNUX'))
        platform.insert()
        platform_id = platform.id

        queue = BuildQueue(self.env)
        platforms = queue.match_slave('foo', {'os': 'linux'})
        self.assertEqual(1, len(platforms))
        self.assertEqual(platform_id, platforms[0].id)
Example #25
0
    def test_register_slave_match_case_insensitive(self):
        BuildConfig(self.env, 'test', active=True).insert()
        platform = TargetPlatform(self.env, config='test', name="Unix")
        platform.rules.append(('os', 'LiNUX'))
        platform.insert()
        platform_id = platform.id

        queue = BuildQueue(self.env)
        platforms = queue.match_slave('foo', {'os': 'linux'})
        self.assertEqual(1, len(platforms))
        self.assertEqual(platform_id, platforms[0].id)
Example #26
0
    def test_match_slave_match(self):
        BuildConfig(self.env, 'test', active=True).insert()
        platform = TargetPlatform(self.env, config='test', name="Unix")
        platform.rules.append(('family', 'posix'))
        platform.insert()
        platform_id = platform.id

        queue = BuildQueue(self.env)
        platforms = queue.match_slave('foo', {'family': 'posix'})
        self.assertEqual(1, len(platforms))
        self.assertEqual(platform_id, platforms[0].id)
Example #27
0
    def test_register_slave_match_regexp_multi(self):
        BuildConfig(self.env, 'test', active=True).insert()
        platform = TargetPlatform(self.env, config='test', name="Unix")
        platform.rules.append(('os', '^Linux'))
        platform.rules.append(('processor', '^[xi]\d?86$'))
        platform.insert()
        platform_id = platform.id

        queue = BuildQueue(self.env)
        platforms = queue.match_slave('foo', {'os': 'Linux', 'processor': 'i686'})
        self.assertEqual(1, len(platforms))
        self.assertEqual(platform_id, platforms[0].id)
Example #28
0
    def test_register_slave_match_regexp_multi(self):
        BuildConfig(self.env, 'test', active=True).insert()
        platform = TargetPlatform(self.env, config='test', name="Unix")
        platform.rules.append(('os', '^Linux'))
        platform.rules.append(('processor', '^[xi]\d?86$'))
        platform.insert()
        platform_id = platform.id

        queue = BuildQueue(self.env)
        platforms = queue.match_slave('foo', {'os': 'Linux', 'processor': 'i686'})
        self.assertEqual(1, len(platforms))
        self.assertEqual(platform_id, platforms[0].id)
Example #29
0
    def test_create_build(self):
        BuildConfig(self.env, 'test', path='somepath', active=True).insert()
        platform = TargetPlatform(self.env, config='test', name="Unix")
        platform.rules.append(('family', 'posix'))
        platform.insert()

        self.repos = Mock(
            get_node=lambda path, rev=None: Mock(
                get_entries=lambda: [Mock(), Mock()],
                get_history=lambda: [('somepath', 123, 'edit'),
                                     ('somepath', 121, 'edit'),
                                     ('somepath', 120, 'edit')]),
            get_changeset=lambda rev: Mock(date=to_datetime(42, utc)),
            normalize_path=lambda path: path,
            rev_older_than=lambda rev1, rev2: rev1 < rev2)

        inheaders = {'Content-Type': 'application/x-bitten+xml'}
        inbody = StringIO("""<slave name="hal" version="%d">
  <platform>Power Macintosh</platform>
  <os family="posix" version="8.1.0">Darwin</os>
  <package name="java" version="2.4.3"/>
</slave>""" % PROTOCOL_VERSION)
        outheaders = {}
        outbody = StringIO()
        req = Mock(method='POST',
                   base_path='',
                   path_info='/builds',
                   href=Href('/trac'),
                   abs_href=Href('http://example.org/trac'),
                   remote_addr='127.0.0.1',
                   args={},
                   perm=PermissionCache(self.env, 'hal'),
                   get_header=lambda x: inheaders.get(x),
                   read=inbody.read,
                   send_response=lambda x: outheaders.setdefault('Status', x),
                   send_header=lambda x, y: outheaders.setdefault(x, y),
                   write=outbody.write,
                   incookie=Cookie('trac_auth='))

        module = BuildMaster(self.env)
        assert module.match_request(req)

        self.assertRaises(RequestDone, module.process_request, req)

        self.assertEqual(201, outheaders['Status'])
        self.assertEqual('text/plain', outheaders['Content-Type'])
        location = outheaders['Location']
        mo = re.match('http://example.org/trac/builds/(\d+)', location)
        assert mo, 'Location was %r' % location
        self.assertEqual('Build pending', outbody.getvalue())
        build = Build.fetch(self.env, int(mo.group(1)))
        self.assertEqual(Build.IN_PROGRESS, build.status)
        self.assertEqual('hal', build.slave)
Example #30
0
    def test_should_delete_build_config_deactivated(self):
        messages = []
        self.env.log = Mock(info=lambda msg, *args: messages.append(msg))
        config = BuildConfig(self.env, 'test', active=False)
        config.insert()
        platform = TargetPlatform(self.env, config='test', name='stuff')
        platform.insert()
        build = Build(self.env, config=config.name, rev=42,
                        platform=platform.id, rev_time=123456)
        build.insert()
        queue = BuildQueue(self.env, build_all=True)

        self.assertEqual(True, queue.should_delete_build(build, self.repos))
        self.assert_("configuration is deactivated" in messages[0])
Example #31
0
    def test_next_pending_build_inactive_config(self):
        """
        Make sure that builds for a deactived build config are not scheduled.
        """
        BuildConfig(self.env, 'test').insert()
        platform = TargetPlatform(self.env, config='test', name='Foo')
        platform.insert()
        build = Build(self.env, config='test', platform=platform.id, rev=123,
                      rev_time=42, status=Build.PENDING)
        build.insert()

        queue = BuildQueue(self.env)
        build = queue.get_build_for_slave('foobar', {})
        self.assertEqual(None, build)
Example #32
0
    def test_should_delete_build_config_none(self):
        out = []
        self.env.log = Mock(
                        info=lambda msg, *args: out.extend([msg] + list(args)))
        platform = TargetPlatform(self.env, config='test', name='stuff')
        platform.insert()
        build = Build(self.env, config='does_not_exist', rev=42,
                        platform=platform.id, rev_time=123456)
        build.insert()
        queue = BuildQueue(self.env, build_all=True)

        self.assertEqual(True, queue.should_delete_build(build, self.repos))
        self.assertTrue("configuration is deactivated" in out[0])
        self.assertEquals('unknown config "does_not_exist"', out[1])
Example #33
0
    def test_should_delete_build_config_none(self):
        out = []
        self.env.log = Mock(
                        info=lambda msg, *args: out.extend([msg] + list(args)))
        platform = TargetPlatform(self.env, config='test', name='stuff')
        platform.insert()
        build = Build(self.env, config='does_not_exist', rev=42,
                        platform=platform.id, rev_time=123456)
        build.insert()
        queue = BuildQueue(self.env, build_all=True)

        self.assertEqual(True, queue.should_delete_build(build, self.repos))
        self.assertTrue("configuration is deactivated" in out[0])
        self.assertEquals('unknown config "does_not_exist"', out[1])
Example #34
0
    def test_next_pending_build_inactive_config(self):
        """
        Make sure that builds for a deactived build config are not scheduled.
        """
        BuildConfig(self.env, 'test').insert()
        platform = TargetPlatform(self.env, config='test', name='Foo')
        platform.insert()
        build = Build(self.env, config='test', platform=platform.id, rev=123,
                      rev_time=42, status=Build.PENDING)
        build.insert()

        queue = BuildQueue(self.env)
        build = queue.get_build_for_slave('foobar', {})
        self.assertEqual(None, build)
Example #35
0
    def test_should_delete_build_config_deactivated(self):
        messages = []
        self.env.log = Mock(info=lambda msg, *args: messages.append(msg))
        config = BuildConfig(self.env, 'test', active=False)
        config.insert()
        platform = TargetPlatform(self.env, config='test', name='stuff')
        platform.insert()
        build = Build(self.env, config=config.name, rev=42,
                        platform=platform.id, rev_time=123456)
        build.insert()
        queue = BuildQueue(self.env, build_all=True)

        self.assertEqual(True, queue.should_delete_build(build, self.repos))
        self.assert_("configuration is deactivated" in messages[0])
Example #36
0
    def test_populate_not_build_all(self):
        self.env.get_repository = lambda authname=None: Mock(
            get_changeset=lambda rev: Mock(date=to_datetime(rev * 1000, utc)),
            get_node=lambda path, rev=None: Mock(
                get_entries=lambda: [Mock(), Mock()],
                get_history=lambda: [('somepath', 123, 'edit'),
                                     ('somepath', 121, 'edit'),
                                     ('somepath', 120, 'edit')]
            ),
            normalize_path=lambda path: path,
            rev_older_than=lambda rev1, rev2: rev1 < rev2
        )
        BuildConfig(self.env, 'test', path='somepath', active=True).insert()
        platform1 = TargetPlatform(self.env, config='test', name='P1')
        platform1.insert()
        platform2 = TargetPlatform(self.env, config='test', name='P2')
        platform2.insert()

        queue = BuildQueue(self.env)
        queue.populate()
        queue.populate()
        queue.populate()

        builds = list(Build.select(self.env, config='test'))
        builds.sort(lambda a, b: cmp(a.platform, b.platform))
        self.assertEqual(2, len(builds))
        self.assertEqual(platform1.id, builds[0].platform)
        self.assertEqual('123', builds[0].rev)
        self.assertEqual(platform2.id, builds[1].platform)
        self.assertEqual('123', builds[1].rev)
Example #37
0
    def test_create_build(self):
        BuildConfig(self.env, 'test', path='somepath', active=True).insert()
        platform = TargetPlatform(self.env, config='test', name="Unix")
        platform.rules.append(('family', 'posix'))
        platform.insert()

        self.repos = Mock(
            get_node=lambda path, rev=None: Mock(
                get_entries=lambda: [Mock(), Mock()],
                get_history=lambda: [('somepath', 123, 'edit'),
                                     ('somepath', 121, 'edit'),
                                     ('somepath', 120, 'edit')]
            ),
            get_changeset=lambda rev: Mock(date=to_datetime(42, utc)),
            normalize_path=lambda path: path,
            rev_older_than=lambda rev1, rev2: rev1 < rev2
        )

        inheaders = {'Content-Type': 'application/x-bitten+xml'}
        inbody = StringIO("""<slave name="hal" version="%d">
  <platform>Power Macintosh</platform>
  <os family="posix" version="8.1.0">Darwin</os>
  <package name="java" version="2.4.3"/>
</slave>""" % PROTOCOL_VERSION)
        outheaders = {}
        outbody = StringIO()
        req = Mock(method='POST', base_path='', path_info='/builds',
                   href=Href('/trac'), abs_href=Href('http://example.org/trac'),
                   remote_addr='127.0.0.1', args={},
                   perm=PermissionCache(self.env, 'hal'),
                   get_header=lambda x: inheaders.get(x), read=inbody.read,
                   send_response=lambda x: outheaders.setdefault('Status', x),
                   send_header=lambda x, y: outheaders.setdefault(x, y),
                   write=outbody.write,
                   incookie=Cookie('trac_auth='))

        module = BuildMaster(self.env)
        assert module.match_request(req)

        self.assertRaises(RequestDone, module.process_request, req)

        self.assertEqual(201, outheaders['Status'])
        self.assertEqual('text/plain', outheaders['Content-Type'])
        location = outheaders['Location']
        mo = re.match('http://example.org/trac/builds/(\d+)', location)
        assert mo, 'Location was %r' % location
        self.assertEqual('Build pending', outbody.getvalue())
        build = Build.fetch(self.env, int(mo.group(1)))
        self.assertEqual(Build.IN_PROGRESS, build.status)
        self.assertEqual('hal', build.slave)
Example #38
0
    def test_view_build(self):
        config = BuildConfig(self.env, name='test', path='trunk')
        config.insert()
        platform = TargetPlatform(self.env, config='test', name='any')
        platform.insert()
        build = Build(self.env,
                      config='test',
                      platform=1,
                      rev=123,
                      rev_time=42,
                      status=Build.SUCCESS,
                      slave='hal')
        build.insert()

        PermissionSystem(self.env).grant_permission('joe', 'BUILD_VIEW')
        req = Mock(method='GET',
                   base_path='',
                   cgi_location='',
                   path_info='/build/test/1',
                   href=Href('/trac'),
                   args={},
                   chrome={},
                   authname='joe',
                   perm=PermissionCache(self.env, 'joe'))

        root = Mock(get_entries=lambda: ['foo'],
                    get_history=lambda: [('trunk', rev, 'edit')
                                         for rev in range(123, 111, -1)])
        self.repos = Mock(get_node=lambda path, rev=None: root,
                          sync=lambda: None,
                          normalize_path=lambda path: path,
                          normalize_rev=lambda rev: rev,
                          get_changeset=lambda rev: Mock(author='joe'))
        self.repos.authz = Mock(has_permission=lambda path: True,
                                assert_permission=lambda path: None)

        module = BuildController(self.env)
        assert module.match_request(req)
        _, data, _ = module.process_request(req)

        self.assertEqual('view_build', data['page_mode'])

        from trac.resource import Resource
        self.assertEquals(Resource('build', 'test/1'),
                          data['context'].resource)

        self.assertEquals([], data['build']['attachments']['attachments'])
        self.assertEquals('/trac/attachment/build/test/1/',
                          data['build']['attachments']['attach_href'])
Example #39
0
    def _process_build_initiation(self, req, config, build):
        self.log.info('Build slave %r initiated build %d', build.slave,
                      build.id)
        build.started = int(time.time())
        build.update()

        for listener in BuildSystem(self.env).listeners:
            listener.build_started(build)

        xml = xmlio.parse(config.recipe)
        xml.attr['branch'] = config.branch
        xml.attr['revision'] = build.rev
        xml.attr['config'] = config.name
        xml.attr['build'] = str(build.id)
        target_platform = TargetPlatform.fetch(self.env, build.platform)
        xml.attr['platform'] = target_platform.name
        xml.attr['name'] = build.slave
        body = str(xml)

        self.log.info('Build slave %r initiated build %d', build.slave,
                      build.id)

        self._send_response(req,
                            200,
                            body,
                            headers={
                                'Content-Type':
                                'application/x-bitten+xml',
                                'Content-Length':
                                str(len(body)),
                                'Content-Disposition':
                                'attachment; filename=recipe_%s_r%s.xml' %
                                (config.name, build.rev)
                            })
Example #40
0
    def setUp(self):
        self.env = EnvironmentStub()
        self.env.path = tempfile.mkdtemp()

        db = self.env.get_db_cnx()
        cursor = db.cursor()
        connector, _ = DatabaseManager(self.env)._get_connector()
        for table in schema:
            for stmt in connector.to_sql(table):
                cursor.execute(stmt)

        self.config = BuildConfig(self.env, name='test', path='somepath')
        self.config.insert(db=db)
        self.platform = TargetPlatform(self.env, config='test', name='Foo')
        self.platform.insert(db=db)
        db.commit()
Example #41
0
    def test_get_build_for_slave(self):
        """
        Make sure that a pending build of an activated configuration is
        scheduled for a slave that matches the target platform.
        """
        BuildConfig(self.env, 'test', active=True).insert()
        platform = TargetPlatform(self.env, config='test', name='Foo')
        platform.insert()
        build = Build(self.env, config='test', platform=platform.id, rev=123,
                      rev_time=42, status=Build.PENDING)
        build.insert()
        build_id = build.id

        queue = BuildQueue(self.env)
        build = queue.get_build_for_slave('foobar', {})
        self.assertEqual(build_id, build.id)
Example #42
0
    def test_get_build_for_slave(self):
        """
        Make sure that a pending build of an activated configuration is
        scheduled for a slave that matches the target platform.
        """
        BuildConfig(self.env, 'test', active=True).insert()
        platform = TargetPlatform(self.env, config='test', name='Foo')
        platform.insert()
        build = Build(self.env, config='test', platform=platform.id, rev=123,
                      rev_time=42, status=Build.PENDING)
        build.insert()
        build_id = build.id

        queue = BuildQueue(self.env)
        build = queue.get_build_for_slave('foobar', {})
        self.assertEqual(build_id, build.id)
Example #43
0
def _get_build_data(env, req, build):
    platform = TargetPlatform.fetch(env, build.platform)
    data = {
        'id': build.id,
        'name': build.slave,
        'rev': build.rev,
        'status': _status_label[build.status],
        'platform': getattr(platform, 'name', 'unknown'),
        'cls': _status_label[build.status].replace(' ', '-'),
        'href': req.href.build(build.config, build.id),
        'chgset_href': req.href.changeset(build.rev)
    }
    if build.started:
        data['started'] = format_datetime(build.started)
        data['started_delta'] = pretty_timedelta(build.started)
        data['duration'] = pretty_timedelta(build.started)
    if build.stopped:
        data['stopped'] = format_datetime(build.stopped)
        data['stopped_delta'] = pretty_timedelta(build.stopped)
        data['duration'] = pretty_timedelta(build.stopped, build.started)
    data['slave'] = {
        'name': build.slave,
        'ipnr': build.slave_info.get(Build.IP_ADDRESS),
        'os_name': build.slave_info.get(Build.OS_NAME),
        'os_family': build.slave_info.get(Build.OS_FAMILY),
        'os_version': build.slave_info.get(Build.OS_VERSION),
        'machine': build.slave_info.get(Build.MACHINE),
        'processor': build.slave_info.get(Build.PROCESSOR)
    }
    return data
Example #44
0
 def template_data(self):
     failed_steps = BuildStep.select(self.env, build=self.build.id,
                                     status=BuildStep.FAILURE)
     platform = TargetPlatform.fetch(self.env, id=self.build.platform)
     reposname, repos, change = self.get_change()
     return {
         'build': {
             'id': self.build.id,
             'status': self.readable_states[self.build.status],
             'link': self.build_link(),
             'config': self.build.config,
             'platform': getattr(platform, 'name', 'unknown'),
             'slave': self.build.slave,
             'failed_steps': [{
                 'name': step.name,
                 'description': step.description,
                 'errors': step.errors,
                 'log_messages': self.get_all_log_messages_for_step(step),
             } for step in failed_steps],
         },
         'change': {
             'rev': display_rev(repos, change.rev),
             'link': self.env.abs_href.changeset(change.rev,
                         reposname != '(default)' and reposname or None),
             'author': change.author,
         },
     }
Example #45
0
    def _process_build_initiation(self, req, config, build):
        self.log.info('Build slave %r initiated build %d', build.slave,
                      build.id)
        build.started = int(time.time())
        build.update()

        for listener in BuildSystem(self.env).listeners:
            listener.build_started(build)

        xml = xmlio.parse(config.recipe)
        xml.attr['path'] = config.path
        xml.attr['revision'] = build.rev
        xml.attr['config'] = config.name
        xml.attr['build'] = str(build.id)
        target_platform = TargetPlatform.fetch(self.env, build.platform)
        xml.attr['platform'] = target_platform.name
        body = str(xml)

        self.log.info('Build slave %r initiated build %d', build.slave,
                      build.id)

        req.send_response(200)
        req.send_header('Content-Type', 'application/x-bitten+xml')
        req.send_header('Content-Length', str(len(body)))
        req.send_header('Content-Disposition',
                        'attachment; filename=recipe_%s_r%s.xml' %
                        (config.name, build.rev))
        req.write(body)
        raise RequestDone
Example #46
0
    def test_insert(self):
        platform = TargetPlatform(self.env, config='test', name='Windows XP')
        platform.rules += [(Build.OS_NAME, 'Windows'), (Build.OS_VERSION, 'XP')]
        platform.insert()

        assert platform.exists
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        cursor.execute("SELECT config,name FROM bitten_platform "
                       "WHERE id=%s", (platform.id,))
        self.assertEqual(('test', 'Windows XP'), cursor.fetchone())

        cursor.execute("SELECT propname,pattern,orderno FROM bitten_rule "
                       "WHERE id=%s", (platform.id,))
        self.assertEqual((Build.OS_NAME, 'Windows', 0), cursor.fetchone())
        self.assertEqual((Build.OS_VERSION, 'XP', 1), cursor.fetchone())
Example #47
0
    def _process_build_initiation(self, req, config, build):
        self.log.info('Build slave %r initiated build %d', build.slave,
                      build.id)
        build.started = int(time.time())
        build.update()

        for listener in BuildSystem(self.env).listeners:
            listener.build_started(build)

        xml = xmlio.parse(config.recipe)
        xml.attr['branch'] = config.branch
        xml.attr['revision'] = build.rev
        xml.attr['config'] = config.name
        xml.attr['build'] = str(build.id)
        target_platform = TargetPlatform.fetch(self.env, build.platform)
        xml.attr['platform'] = target_platform.name
        xml.attr['name'] = build.slave
        body = str(xml)

        self.log.info('Build slave %r initiated build %d', build.slave,
                      build.id)

        self._send_response(req, 200, body, headers={
                    'Content-Type': 'application/x-bitten+xml',
                    'Content-Length': str(len(body)),
                    'Content-Disposition':
                        'attachment; filename=recipe_%s_r%s.xml' %
                        (config.name, build.rev)})
Example #48
0
def _get_build_data(env, req, build):
    platform = TargetPlatform.fetch(env, build.platform)
    data = {'id': build.id, 'name': build.slave, 'rev': build.rev,
            'status': _status_label[build.status],
            'platform': getattr(platform, 'name', 'unknown'),
            'cls': _status_label[build.status].replace(' ', '-'),
            'href': req.href.build(build.config, build.id),
            'chgset_href': req.href.changeset(build.rev)}
    if build.started:
        data['started'] = format_datetime(build.started)
        data['started_delta'] = pretty_timedelta(build.started)
        data['duration'] = pretty_timedelta(build.started)
    if build.stopped:
        data['stopped'] = format_datetime(build.stopped)
        data['stopped_delta'] = pretty_timedelta(build.stopped)
        data['duration'] = pretty_timedelta(build.stopped, build.started)
    data['slave'] = {
        'name': build.slave,
        'ipnr': build.slave_info.get(Build.IP_ADDRESS),
        'os_name': build.slave_info.get(Build.OS_NAME),
        'os_family': build.slave_info.get(Build.OS_FAMILY),
        'os_version': build.slave_info.get(Build.OS_VERSION),
        'machine': build.slave_info.get(Build.MACHINE),
        'processor': build.slave_info.get(Build.PROCESSOR)
    }
    return data
Example #49
0
    def should_delete_build(self, build, repos):
        config = BuildConfig.fetch(self.env, build.config)

        platform = TargetPlatform.fetch(self.env, build.platform)
        # Platform may or may not exist anymore - get safe name for logging
        platform_name = platform and platform.name \
                        or 'unknown platform "%s"' % build.platform

        # Drop build if platform no longer exists
        if not platform:
            self.log.info(
                'Dropping build of configuration "%s" at '
                'revision [%s] on %s because the platform no longer '
                'exists', config.name, build.rev, platform_name)
            return True

        # Ignore pending builds for deactived build configs
        if not config.active:
            self.log.info(
                'Dropping build of configuration "%s" at '
                'revision [%s] on %s because the configuration is '
                'deactivated', config.name, build.rev, platform_name)
            return True

        # If not 'build_all', drop if a more recent revision is available
        if not self.build_all and \
                len(list(Build.select(self.env, config=build.config,
                min_rev_time=build.rev_time, platform=build.platform))) > 1:
            self.log.info(
                'Dropping build of configuration "%s" at revision [%s] '
                'on "%s" because a more recent build exists', config.name,
                build.rev, platform_name)
            return True

        return False
Example #50
0
    def should_delete_build(self, build, repos):
        config = BuildConfig.fetch(self.env, build.config)

        platform = TargetPlatform.fetch(self.env, build.platform)
        # Platform may or may not exist anymore - get safe name for logging
        platform_name = platform and platform.name \
                        or 'unknown platform "%s"' % build.platform

        # Drop build if platform no longer exists
        if not platform:
            self.log.info('Dropping build of configuration "%s" at '
                     'revision [%s] on %s because the platform no longer '
                     'exists', config.name, build.rev, platform_name)
            return True

        # Ignore pending builds for deactived build configs
        if not config.active:
            self.log.info('Dropping build of configuration "%s" at '
                     'revision [%s] on %s because the configuration is '
                     'deactivated', config.name, build.rev, platform_name)
            return True

        # If not 'build_all', drop if a more recent revision is available
        if not self.build_all and \
                len(list(Build.select(self.env, config=build.config,
                min_rev_time=build.rev_time, platform=build.platform))) > 1:
            self.log.info('Dropping build of configuration "%s" at revision [%s] '
                     'on "%s" because a more recent build exists',
                         config.name, build.rev, platform_name)
            return True

        return False
Example #51
0
 def test_select(self):
     db = self.env.get_db_cnx()
     cursor = db.cursor()
     cursor.executemany("INSERT INTO bitten_platform (config,name) "
                        "VALUES (%s,%s)", [('test', 'Windows'),
                        ('test', 'Mac OS X')])
     platforms = list(TargetPlatform.select(self.env, config='test'))
     self.assertEqual(2, len(platforms))
Example #52
0
    def test_populate_thread_race_condition(self):
        messages = []
        self.env.log = Mock(info=lambda msg, *args: messages.append(msg))

        def get_history():
            yield ('somepath', 123, 'edit')
            yield ('somepath', 121, 'edit')
            yield ('somepath', 120, 'edit')
            time.sleep(1)  # sleep to make sure both threads collect

        self.env.get_repository = lambda authname=None: Mock(
            get_changeset=lambda rev: Mock(date=to_datetime(rev * 1000, utc)),
            get_node=lambda path, rev=None: Mock(
                get_entries=lambda: [Mock(), Mock()], get_history=get_history),
            normalize_path=lambda path: path,
            rev_older_than=lambda rev1, rev2: rev1 < rev2)
        BuildConfig(self.env, 'test', path='somepath', active=True).insert()
        platform1 = TargetPlatform(self.env, config='test', name='P1')
        platform1.insert()
        platform2 = TargetPlatform(self.env, config='test', name='P2')
        platform2.insert()

        def build_populator():
            queue = BuildQueue(self.env, build_all=True)
            queue.populate()

        thread1 = threading.Thread(target=build_populator)
        thread2 = threading.Thread(target=build_populator)
        thread1.start()
        thread2.start()
        thread1.join()
        thread2.join()

        # check builds got added
        builds = list(Build.select(self.env, config='test'))
        builds.sort(lambda a, b: cmp(a.platform, b.platform))
        self.assertEqual(6, len(builds))
        self.assertEqual(platform1.id, builds[0].platform)
        self.assertEqual('123', builds[0].rev)
        self.assertEqual(platform1.id, builds[1].platform)
        self.assertEqual('121', builds[1].rev)
        self.assertEqual(platform1.id, builds[2].platform)
        self.assertEqual('120', builds[2].rev)
        self.assertEqual(platform2.id, builds[3].platform)
        self.assertEqual('123', builds[3].rev)
        self.assertEqual(platform2.id, builds[4].platform)
        self.assertEqual('121', builds[4].rev)
        self.assertEqual(platform2.id, builds[5].platform)
        self.assertEqual('120', builds[5].rev)

        # check attempts at duplicate inserts were logged.
        failure_messages = [
            x for x in messages if x.startswith('Failed to insert build')
        ]
        self.assertEqual(6, len(failure_messages))
Example #53
0
    def test_should_delete_build_old_with_not_buildall(self):
        messages = []
        self.env.log = Mock(info=lambda msg, *args: messages.append(msg))
        config = BuildConfig(self.env, 'test', active=True)
        config.insert()
        platform = TargetPlatform(self.env, config='test', name='stuff')
        platform.insert()
        build1 = Build(self.env, config=config.name, rev=42,
                        platform=platform.id, rev_time=123456)
        build1.insert()
        build2 = Build(self.env, config=config.name, rev=43,
                        platform=platform.id, rev_time=123457,
                        slave='slave')
        build2.insert()
        queue = BuildQueue(self.env, build_all=False)

        self.assertEqual(True, queue.should_delete_build(build1, self.repos))
        self.assert_("more recent build exists" in messages[0])
Example #54
0
    def test_initiate_build(self):
        config = BuildConfig(self.env, 'test', path='somepath', active=True,
                             recipe='<build><step id="s1"></step></build>')
        config.insert()
        platform = TargetPlatform(self.env, config='test', name="Unix")
        platform.rules.append(('family', 'posix'))
        platform.insert()
        build = Build(self.env, 'test', '123', platform.id, slave='hal',
                      rev_time=42)
        build.insert()

        outheaders = {}
        outbody = StringIO()

        req = Mock(method='GET', base_path='',
                   path_info='/builds/%d' % build.id,
                   href=Href('/trac'), remote_addr='127.0.0.1', args={},
                   authname='hal',
                   perm=PermissionCache(self.env, 'hal'),
                   send_response=lambda x: outheaders.setdefault('Status', x),
                   send_header=lambda x, y: outheaders.setdefault(x, y),
                   write=outbody.write,
                   form_token="12345",
                   incookie=Cookie('trac_auth='))

        module = BuildMaster(self.env)
        assert module.match_request(req)

        self.assertRaises(RequestDone, module.process_request, req)
        self.assertEqual(200, outheaders['Status'])
        self.assertEqual('163', outheaders['Content-Length'])
        self.assertEqual('application/x-bitten+xml',
                         outheaders['Content-Type'])
        self.assertEqual('attachment; filename=recipe_test_r123.xml',
                         outheaders['Content-Disposition'])
        self.assertEqual('<build build="1" config="test" form_token="12345" '
                         'name="hal" path="somepath" platform="Unix" '
                         'reponame="" repopath="somepath" '
                         'revision="123"><step id="s1"/></build>',
                         outbody.getvalue())

        # Make sure the started timestamp has been set
        build = Build.fetch(self.env, build.id)
        assert build.started
Example #55
0
 def test_fetch(self):
     db = self.env.get_db_cnx()
     cursor = db.cursor()
     cursor.execute("INSERT INTO bitten_platform (config,name) "
                    "VALUES (%s,%s)", ('test', 'Windows'))
     id = db.get_last_id(cursor, 'bitten_platform')
     platform = TargetPlatform.fetch(self.env, id)
     assert platform.exists
     self.assertEqual('test', platform.config)
     self.assertEqual('Windows', platform.name)