def test_process_build(self): old_build = self.prepare_old_build() build = self.prepare_foo_build(repo_id=123, version='4') with self.mocks(): self.build_resolver.main() self.db.rollback() self.assertIs(True, build.deps_resolved) expected_changes = [ (build.id, 'C', 2, RpmEVR(1, '2', '1.fc22'), RpmEVR(1, '3', '1.fc22')), (build.id, 'E', 2, None, RpmEVR(0, '0.1', '1.fc22.1')), ] actual_changes = [(c.build_id, c.dep_name, c.distance, c.prev_evr, c.curr_evr) for c in build.dependency_changes] self.assertCountEqual(expected_changes, actual_changes) actual_deps = (self.db.query( Dependency.name, Dependency.epoch, Dependency.version, Dependency.release, Dependency.arch, ).filter(Dependency.id.in_(build.dependency_keys)).all()) self.assertCountEqual(FOO_DEPS, actual_deps) self.assertIsNone(old_build.dependency_keys)
def test_repo_generation(self): self.prepare_old_build() self.collection.latest_repo_resolved = None self.collection.latest_repo_id = None self.db.commit() with self.mocks(requires=[['F', 'A'], ['nonexistent']]) as fedmsg_mock: self.repo_resolver.main() self.assertTrue(self.collection.latest_repo_resolved) self.assert_collection_fedmsg_emitted(fedmsg_mock, 'unknown', 'ok') self.db.expire_all() foo = self.db.query(Package).filter_by(name='foo').first() self.assertTrue(foo.resolved) self.assertEqual(20, foo.dependency_priority) expected_changes = [ ('C', 2, RpmEVR(1, '2', '1.fc22'), RpmEVR(1, '3', '1.fc22')), ('E', 2, None, RpmEVR(0, '0.1', '1.fc22.1')), ] actual_changes = [(c.dep_name, c.distance, c.prev_evr, c.curr_evr) for c in foo.unapplied_changes] self.assertCountEqual(expected_changes, actual_changes) resolution_change = self.db.query(ResolutionChange)\ .filter_by(package_id=foo.id)\ .one() self.assertFalse( self.db.query(ResolutionProblem).filter_by( resolution_id=resolution_change.id).count()) self.assertTrue(self.collection.latest_repo_resolved) self.assertEqual(123, self.collection.latest_repo_id)
def test_rpmevr_db_comparison(self): dep = Dependency(name='foo', version='1.1', release='8.fc26', arch='x86_64') self.db.add(dep) evr = RpmEVR(0, '1.1', '11.fc26') res = (self.db.query(Dependency).filter(Dependency.evr > evr).first()) self.assertIsNone(res) res = (self.db.query(Dependency).filter(Dependency.evr < evr).first()) self.assertIs(dep, res)
def test_rpmevr_db_comparison(self): build = self.prepare_build('rnv') change = UnappliedChange( package_id=build.package.id, dep_name='foo', prev_epoch=None, prev_version='1.1', prev_release='8.fc26', curr_epoch=None, curr_version='1.1', curr_release='8.fc26', ) self.db.add(change) evr = RpmEVR(0, '1.1', '11.fc26') res = self.db.query(UnappliedChange)\ .filter(UnappliedChange.prev_evr > evr).first() self.assertIsNone(res) res = self.db.query(UnappliedChange)\ .filter(UnappliedChange.prev_evr < evr).first() self.assertEqual(change, res)
def test_rpmevr_comparison(self): evr1 = RpmEVR(0, '1.1', '11.fc26') evr2 = RpmEVR(None, '1.1', '8.fc26') self.assertGreater(evr1, evr2)
def affected_by(dep_name): """ Display which packages are possibly affected by given dependency change. """ if len(g.current_collections) != 1: abort(400) collection = g.current_collections[0] try: evr1 = RpmEVR(int(request.args['epoch1']), request.args['version1'], request.args['release1']) evr2 = RpmEVR(int(request.args['epoch2']), request.args['version2'], request.args['release2']) except (KeyError, ValueError): abort(400) # Dependencies in the evr1 to evr2 interval # Note that evr comparisons are overloaded custom comparators that invoke RPM-correct # comparisons implemented in rpmvercmp.sql deps_in = (db.query(Dependency.id).filter( Dependency.name == dep_name).filter(Dependency.evr > evr1).filter( Dependency.evr < evr2).cte('deps_in')) # Dependencies with greater evr than evr2 deps_higher = (db.query( Dependency.id).filter(Dependency.name == dep_name).filter( Dependency.evr >= evr2).cte('deps_higher')) # Dependencies with lesser evr than evr1 deps_lower = (db.query( Dependency.id).filter(Dependency.name == dep_name).filter( Dependency.evr <= evr1).cte('deps_lower')) # Get only changes where the prev_evr to curr_evr interval overlaps with evr1 to evr2 filtered_changes = union( # Changes with previous evr in the evr1 to evr2 interval db.query(AppliedChange).filter( AppliedChange.prev_dep_id.in_(db.query(deps_in))), # Changes with current evr in the evr1 to evr2 interval db.query(AppliedChange).filter( AppliedChange.curr_dep_id.in_(db.query(deps_in))), # Changes with both evrs "around" the evr1 to evr2 interval db.query(AppliedChange).filter( (AppliedChange.prev_dep_id.in_(db.query(deps_lower))) & (AppliedChange.curr_dep_id.in_(db.query(deps_higher)))), ).alias('filtered_changes') prev_build = aliased(Build) # Get a subquery for previous build state subq = db.query(prev_build.state.label('prev_state'))\ .order_by(prev_build.started.desc())\ .filter(prev_build.started < Build.started)\ .filter(prev_build.package_id == Build.package_id)\ .limit(1)\ .correlate().as_scalar() prev_dep = aliased(Dependency) curr_dep = aliased(Dependency) failed = ( db.query( prev_dep.name.label('dep_name'), prev_dep.evr.label('prev_evr'), curr_dep.evr.label('curr_evr'), AppliedChange.distance, Build.id.label('build_id'), Build.state.label('build_state'), Build.started.label('build_started'), Package.name.label('package_name'), Package.resolved.label('package_resolved'), Package.last_complete_build_state.label('package_lb_state'), subq.label('prev_build_state'), ).select_entity_from(filtered_changes).join( prev_dep, AppliedChange.prev_dep).join( curr_dep, AppliedChange.curr_dep).join(AppliedChange.build).join( Build.package).filter_by(blocked=False, tracked=True, collection_id=collection.id) # Show only packages where the build after failed, but the previous one was ok .filter(Build.state == Build.FAILED).filter( subq != Build.FAILED).order_by(AppliedChange.distance, Build.started.desc()).all()) # Auxiliary function to compute state string for the query row def package_state(row): return Package( tracked=True, blocked=False, resolved=row.package_resolved, last_complete_build_state=row.package_lb_state, ).state_string return render_template("affected-by.html", package_state=package_state, dep_name=dep_name, evr1=evr1, evr2=evr2, collection=collection, failed=failed)