def _testStr(self, strForm, frzForm): first = parseDep(strForm) frz = first.freeze() second = ThawDependencySet(frz) assert(frz == frzForm) assert(first == second) assert(parseDep(str(first)).freeze() == frzForm)
def testDependenciesSearchPath(self): self.addComponent('foo:lib=1.0') self.addCollection('foo=1.0', ['foo:lib']) self.addComponent('bar:lib=/localhost@foo:bar/1.0') d = deps.parseDep('trove: foo:lib') d.union(deps.parseDep('trove: bar:lib')) self.addComponent('pkg:runtime', requires=d) grp = self._build( 'pkg = world["pkg:runtime"]', 'altLabel = r.Repository("localhost@foo:bar", r.flavor)', 'sp = r.SearchPath(world, altLabel)', 'return r.Group(pkg + pkg.depsNeeded(sp))') self.checkTroves(grp, [ (('bar:lib', '/localhost@foo:bar/1.0-1-1', ''), True, True), (('foo', '/localhost@rpl:linux/1.0-1-1', ''), True, True), (('foo:lib', '/localhost@rpl:linux/1.0-1-1', ''), True, False), (('pkg:runtime', '/localhost@rpl:linux/1.0-1-1', ''), True, True) ]) grp = self._build( 'pkg = world["pkg:runtime"]', 'foo = world["foo"]', 'bar = world["bar:lib=localhost@foo:bar"]', 'altLabel = r.Repository("localhost@foo:bar", r.flavor)', 'sp = r.SearchPath(foo, bar)', 'return r.Group(pkg + pkg.depsNeeded(sp))') self.checkTroves(grp, [ (('bar:lib', '/localhost@foo:bar/1.0-1-1', ''), True, True), (('foo', '/localhost@rpl:linux/1.0-1-1', ''), True, True), (('foo:lib', '/localhost@rpl:linux/1.0-1-1', ''), True, False), (('pkg:runtime', '/localhost@rpl:linux/1.0-1-1', ''), True, True) ])
def testGroupResolutionAcrossRepos(self): self.openRepository() repos = self.openRepository(1) self.addComponent('test:runtime', '1.0', '!ssl') self.addComponent('test:runtime', '2.0', '!ssl') self.addComponent('test:runtime', '/localhost1@rpl:foobar/1.0', 'ssl') self.addComponent('test:runtime', '/localhost1@rpl:foobar/2.0', 'ssl') trv = self.addCollection( 'group-dist', '1.0', [('test:runtime', '1.0', '!ssl'), ('test:runtime', '/localhost1@rpl:foobar/1.0', 'ssl')]) sugg = repos.resolveDependenciesByGroups( [trv], [deps.parseDep('trove:test:runtime')]) troves = sugg[deps.parseDep('trove:test:runtime')][0] troveVers = set((x[1].getHost(), x[1].trailingRevision().getVersion()) for x in troves) assert (troveVers == set([('localhost', '1.0'), ('localhost1', '1.0')])) # this doesn't match anything. Make sure there's a spot in the suggestion list. sugg = repos.resolveDependenciesByGroups( [trv], [deps.parseDep('trove:foo:runtime trove:bar:runtime')]) resultList, = sugg.values() self.assertEqual(resultList, [[], []])
def __init__(self, **kwargs): assert type(self) != _File for arg in kwargs: aliasedArg = self.aliasedArgs.get(arg, arg) if aliasedArg not in self.kwargs: raise ParameterError("'%s' is not allowed for this class" % arg) for key, val in self.aliasedArgs.iteritems(): if key in kwargs and val in kwargs: raise ParameterError("'%s' and '%s' cannot be specified together" % (key, val)) elif key in kwargs: kwargs[val] = kwargs[key] for key, val in self.__class__.kwargs.iteritems(): setattr(self, key, kwargs.get(key, val)) self.mtime = int(self.mtime or time.time()) if type(self.requires) == str: self.requires = deps.parseDep(self.requires) elif self.requires is None: self.requires = deps.DependencySet() if isinstance(self.provides, str): self.provides = deps.parseDep(self.provides) elif self.provides is None: self.provides = deps.DependencySet() if type(self.flavor) == str: self.flavor = deps.parseFlavor(self.flavor) if self.flavor is None: self.flavor = deps.Flavor() if self.tags is None: self.tags = []
def testFlagSets(self): dt, db, cu = self.init() dep = parseDep( "soname: ELF32/libc.so.6(GLIBC_2.0 GLIBC_2.1 GLIBC_2.2)") jobInfo = self.createJobInfo(db, self.reqTrove("test", dep)) assert(self.check(*jobInfo)[0:2] == ([ ( ("test", self.new, self.flv), dep )], [] )) # make sure that having separate troves provide each flag doesn't # yield resolved dependencies prv1 = parseDep("soname: ELF32/libc.so.6(GLIBC_2.0)") prv2 = parseDep("soname: ELF32/libc.so.6(GLIBC_2.1)") prv3 = parseDep("soname: ELF32/libc.so.6(GLIBC_2.2)") dt.add(cu, self.prvTrove("test-prov", prv1), 1) dt.add(cu, self.prvTrove("test-prov", prv2), 2) dt.add(cu, self.prvTrove("test-prov", prv3), 3) db.commit() assert(self.check(*jobInfo)[0:2] == ([ ( ("test", self.new, self.flv), dep )], [] )) # now set up a trove that provides all of the flags; this trove # should resolve the dependency prv = parseDep( "soname: ELF32/libc.so.6(GLIBC_2.0 GLIBC_2.1 GLIBC_2.2)") dt.add(cu, self.prvTrove("test-prov", prv), 4) db.commit() assert(self.check(*jobInfo)[0:2] == ([], []))
def testProvidesQuery(self): db = self.openDatabase() self.addComponent("foo:runtime", "1.0", provides="soname: ELF32/foo.so.3(GLIBC_2.0)") self.updatePkg("foo:runtime") tups, primary = query.getTrovesToDisplay( db, [], [], [deps.parseDep("soname: ELF32/foo.so.3(GLIBC_2.0)"), deps.parseDep("trove:foo:runtime")] ) assert tups[0][0] == "foo:runtime"
def testThawRawDeps(self): for raw, expect in [ ( ('foo', []), parseDep('java: foo')), ( ('ELF64/foo.so', ['SysV']), parseDep('soname: ELF64/foo.so(SysV)')), ( ('ELF64/foo.so', ['SysV', 'GLIBC_42']), parseDep('soname: ELF64/foo.so(SysV GLIBC_42)')), ( ('use', ['~maybe', 'yes', '~!maybenot', '!no']), parseFlavor('yes,!no,~maybe,~!maybenot')), ]: actual = DependencyClass.thawRawDep(*raw) expected = expect.iterDeps().next()[1] self.assertEqual(actual, expected)
def testRegularFileDeps(self): reqStr = 'trove: bar:lib' provStr = 'python: tarfile(2.4 lib64)' flavorStr = '~sse2 is: x86_64' foo = filetypes.RegularFile(requires = reqStr, provides = provStr, flavor = flavorStr) fileObj = foo.get(pathId) self.assertEquals(fileObj.flavor(), deps.parseFlavor(flavorStr)) self.assertEquals(fileObj.requires(), deps.parseDep(reqStr)) self.assertEquals(fileObj.provides(), deps.parseDep(provStr))
def testRegularFileDeps(self): reqStr = 'trove: bar:lib' provStr = 'python: tarfile(2.4 lib64)' flavorStr = '~sse2 is: x86_64' foo = filetypes.RegularFile(requires=reqStr, provides=provStr, flavor=flavorStr) fileObj = foo.get(pathId) self.assertEquals(fileObj.flavor(), deps.parseFlavor(flavorStr)) self.assertEquals(fileObj.requires(), deps.parseDep(reqStr)) self.assertEquals(fileObj.provides(), deps.parseDep(provStr))
def testProvidesQuery(self): db = self.openDatabase() self.addComponent('foo:runtime', '1.0', provides='soname: ELF32/foo.so.3(GLIBC_2.0)') self.updatePkg('foo:runtime') tups, primary = query.getTrovesToDisplay(db, [], [], [ deps.parseDep('soname: ELF32/foo.so.3(GLIBC_2.0)'), deps.parseDep('trove:foo:runtime') ]) assert (tups[0][0] == 'foo:runtime')
def testGetTrovesWithProvides(self): v = '/localhost@rpl:linux/1.0-1-1' f = '' db = database.Database(self.rootDir, self.cfg.dbPath) prov1 = deps.parseDep('trove: test1:runtime') prov2 = deps.parseDep('trove: test2:runtime') self.addQuickDbTestPkg(db, 'test1', v,f, provides=prov1) self.addQuickDbTestPkg(db, 'test2', v,f, provides=prov2) self.addQuickDbTestPkg(db, 'test1-foo', v,f, provides=prov1) provMap = db.getTrovesWithProvides([prov1, prov2]) assert(sorted(x[0] for x in provMap[prov1]) == ['test1','test1-foo']) assert([x[0] for x in provMap[prov2]] == ['test2'])
def testGetTrovesWithProvides(self): v = '/localhost@rpl:linux/1.0-1-1' f = '' db = database.Database(self.rootDir, self.cfg.dbPath) prov1 = deps.parseDep('trove: test1:runtime') prov2 = deps.parseDep('trove: test2:runtime') self.addQuickDbTestPkg(db, 'test1', v, f, provides=prov1) self.addQuickDbTestPkg(db, 'test2', v, f, provides=prov2) self.addQuickDbTestPkg(db, 'test1-foo', v, f, provides=prov1) provMap = db.getTrovesWithProvides([prov1, prov2]) assert (sorted(x[0] for x in provMap[prov1]) == ['test1', 'test1-foo']) assert ([x[0] for x in provMap[prov2]] == ['test2'])
def addPluggableRequirements(self, path, fullpath, pkgFiles, macros): d = macros.destdir f = util.joinPaths(d, path) if not os.path.islink(f): return self._openDb() fullpath = util.joinPaths(d, path) contents = os.readlink(fullpath) if not contents.startswith(os.path.sep): # contents is normally a relative symlink thanks to # the RelativeSymlinks policy. if it's not, then we have an # absolute symlink, and we'll just use it directly contents = util.joinPaths(os.path.dirname(fullpath), contents) if contents.startswith(d): contents = contents[len(d):] if os.path.exists(util.joinPaths(d, contents)): # the file is provided by the destdir, don't search for it return troves = self.db.iterTrovesByPath(contents) if not troves: # If there's a file, conary doesn't own it. either way, # DanglingSymlinks will fire an error. return trv = troves[0] fileDep = deps.parseDep('file: %s' % contents) troveDep = deps.parseDep('trove: %s' % trv.getName()) provides = trv.getProvides() if provides.satisfies(fileDep): self._addRequirement(path, contents, [], pkgFiles, deps.FileDependencies) self.recipe.DanglingSymlinks(exceptions=re.escape(path), allowUnusedFilters=True) if trv.getName() not in self.recipe.buildRequires: self.recipe.reportMissingBuildRequires(trv.getName()) elif provides.satisfies(troveDep): self._addRequirement(path, trv.getName(), [], pkgFiles, deps.TroveDependencies) # warn that a file dep would be better, but we'll settle for a # dep on the trove that contains the file self.warn("'%s' does not provide '%s', so a requirement on the " \ "trove itself was used to satisfy dangling symlink: %s" %\ (trv.getName(), fileDep, path)) self.recipe.DanglingSymlinks(exceptions=re.escape(path), allowUnusedFilters=True) if trv.getName() not in self.recipe.buildRequires: self.recipe.reportMissingBuildRequires(trv.getName())
def addPluggableRequirements(self, path, fullpath, pkgFiles, macros): d = macros.destdir f = util.joinPaths(d, path) if not os.path.islink(f): return self._openDb() fullpath = util.joinPaths(d, path) contents = os.readlink(fullpath) if not contents.startswith(os.path.sep): # contents is normally a relative symlink thanks to # the RelativeSymlinks policy. if it's not, then we have an # absolute symlink, and we'll just use it directly contents = util.joinPaths(os.path.dirname(fullpath), contents) if contents.startswith(d): contents = contents[len(d):] if os.path.exists(util.joinPaths(d, contents)): # the file is provided by the destdir, don't search for it return troves = self.db.iterTrovesByPath(contents) if not troves: # If there's a file, conary doesn't own it. either way, # DanglingSymlinks will fire an error. return trv = troves[0] fileDep = deps.parseDep('file: %s' % contents) troveDep = deps.parseDep('trove: %s' % trv.getName()) provides = trv.getProvides() if provides.satisfies(fileDep): self._addRequirement(path, contents, [], pkgFiles, deps.FileDependencies) self.recipe.DanglingSymlinks(exceptions = re.escape(path), allowUnusedFilters = True) if trv.getName() not in self.recipe.buildRequires: self.recipe.reportMissingBuildRequires(trv.getName()) elif provides.satisfies(troveDep): self._addRequirement(path, trv.getName(), [], pkgFiles, deps.TroveDependencies) # warn that a file dep would be better, but we'll settle for a # dep on the trove that contains the file self.warn("'%s' does not provide '%s', so a requirement on the " \ "trove itself was used to satisfy dangling symlink: %s" %\ (trv.getName(), fileDep, path)) self.recipe.DanglingSymlinks(exceptions = re.escape(path), allowUnusedFilters = True) if trv.getName() not in self.recipe.buildRequires: self.recipe.reportMissingBuildRequires(trv.getName())
def testKeepRequiredWithOverlappingFiles(self): # Test that keepRequired will function when an old trove overlaps with # a new trove providing that the old trove had the overlapping files # removed previously. prov1 = deps.parseDep('file: /lib/libfoo.so.1') prov2 = deps.parseDep('file: /lib/libfoo.so.2') self.addComponent('foo:lib=1.0', provides=prov1, fileContents=[('/lib/libfoo.so.1', '1'), ('/etc/conflict', 'contents')]) self.addComponent('foo:lib=2.0', provides=prov2, fileContents=[('/lib/libfoo.so.2', '2'), ('/etc/conflict', 'contents')]) self.addComponent('bar:runtime=1.0', requires=prov1, fileContents=[('/bin/bar1', '1')]) self.addComponent('bar:runtime=2.0', requires=prov2, fileContents=[('/bin/bar2', '2')]) self.updatePkg(['foo:lib=1.0', 'bar:runtime=1.0']) (rc, str) = self.captureOutput(self.updatePkg, 'bar:runtime=2.0', resolve=True, keepExisting=True, keepRequired=True) expectedStr = """\ The following dependencies would not be met after this update: bar:runtime=1.0-1-1 (Already installed) requires: file: /lib/libfoo.so.1 which is provided by: foo:lib=1.0-1-1 (Would be updated to 2.0-1-1) """ assert (str == expectedStr) self.removeFile(self.rootDir, '/etc/conflict') (rc, str) = self.captureOutput(self.updatePkg, 'bar:runtime=2.0', resolve=True, keepExisting=True, keepRequired=True) assert ( str == 'Including extra troves to resolve dependencies:\n' ' foo:lib=2.0-1-1\n' 'warning: keeping foo:lib - required by at least bar:runtime\n')
def testDependencyChain(self): self.addComponent('a:runtime=1.0', requires=deps.parseDep('trove: a:lib')) self.addComponent('a:lib=1.0', requires=deps.parseDep('trove: b:lib')) self.addComponent('b:lib=1.0') grp = self._build("avail = world.find('a:lib', 'b:lib')", "c = world['a:runtime']", "s = c.depsNeeded(avail)", "return r.Group(c + s)") self.checkTroves(grp, [ (('a:runtime', '/localhost@rpl:linux/1.0-1-1', ''), True, True), (('a:lib', '/localhost@rpl:linux/1.0-1-1', ''), True, True), (('b:lib', '/localhost@rpl:linux/1.0-1-1', ''), True, True), ])
def testIterativeOrdering(self): """Jobs order correctly when the graph is built over several check() calls. @tests: CNY-3654 """ dt, db, cu = self.init() # Create a cycle between two troves, as that's easy to verify in the # final ordering. One of them also requires a third trove, which will # be added in a separate dep check cycle. dep1 = parseDep('python: dep1') dep2 = parseDep('python: dep2') dep3 = parseDep('python: dep3') # trv1 requires dep2 + dep3 trv1reqs = deps.DependencySet() trv1reqs.union(dep2) trv1reqs.union(dep3) trv1 = self.prvReqTrove('trv1:runtime', dep1, trv1reqs) trv2 = self.prvReqTrove('trv2:runtime', dep2, dep1) trv3 = self.prvTrove('trv3:runtime', dep3) # The first job has just the cycle in it, and is missing trv3 to # complete the graph. _, job12, src = self.createJobInfo(db, trv1, trv2) # The second job includes the needed trove _, job3, src3 = self.createJobInfo(db, trv3) # Merge the second job's changeset into the first so the trove source # is complete. src.addChangeSets(src3.csList) checker = db.db.dependencyChecker(src, findOrdering=True) # First pass: missing one dep checker.addJobs(job12) result = checker.check() self.assertEqual(result.unsatisfiedList, [(('trv1:runtime', self.new, self.flv), dep3)]) # Second pass: add provider checker.addJobs(job3) result = checker.check() self.assertEqual(result.unsatisfiedList, []) # trv1 and trv2 require each other and so constitute a single job, trv3 # is not part of the cycle so it is a separate job. The original bug # would have all three troves as separate jobs since it forgot about # the deps from the first check. checker.done() self.assertEqual(result.getChangeSetList(), [job3, job12])
def testUpdateWithCapabilityDeps(self): myDep = deps.parseDep('trove: test:python(1.0)') self.addComponent('test:python', '1.0-1-1', provides=myDep, filePrimer=1) self.addComponent('test:runtime', '1.0-1-1', requires=myDep, filePrimer=2) self.addCollection('test', '1.0-1-1', ['test:python', 'test:runtime']) self.updatePkg(self.rootDir, 'test') self.addComponent('test:python', '1.0-2-1', provides=myDep, filePrimer=1) self.addComponent('test:runtime', '1.0-2-1', requires=myDep, filePrimer=2) self.addCollection('test', '1.0-2-1', ['test:python', 'test:runtime']) self.updatePkg(self.rootDir, 'test')
def _test(s): try: depSet = parseDep(s) except ParseError: return else: assert(0)
def testFailureReasons(self): def _freeze(failureReason): rv = apiutils.freeze('FailureReason', failureReason) assert(isinstance(rv[0], int)) assert(isinstance(rv[1], str)) return rv def _thaw(frz): return apiutils.thaw('FailureReason', frz) f = failure.BuildFailed('foo') assert(str(f) == 'Failed while building: foo') assert(_thaw(_freeze(f)) == f) f = failure.MissingBuildreqs([ ('foo:runtime', '', deps.parseFlavor('cross,bar.core'))]) assert(_thaw(_freeze(f)) == f) assert(str(f) == 'Could not satisfy build requirements: foo:runtime=[bar.core,cross]') trv = self.addComponent('blah:run', '1.0') f = failure.MissingDependencies([(trv.getNameVersionFlavor(), deps.parseDep('trove: blam trove:foo'))]) assert(_thaw(_freeze(f)) == f) assert(str(f) == 'Could not satisfy dependencies:\n' ' blah:run=/localhost@rpl:linux/1.0-1-1[] requires:\n' '\ttrove: blam\n' '\ttrove: foo') f = failure.InternalError(['foo', 'bar']) assert(_thaw(_freeze(f)) == f) f = failure.Stopped('Blah') assert(_thaw(_freeze(f)) == f)
def testInstances(self): cx = self.getDB() schema.createSchema(cx) cx.commit() v = versiontable.VersionTable(cx) f = flavors.Flavors(cx) it = items.Items(cx) item = it.addId('foo') version = v.addId(versions.VersionFromString('/c@r:d/1.0-1-1')) d = deps.parseDep('') flavor = f.get(d, None) idb = instances.InstanceTable(cx) idb.addId(item, version, flavor, clonedFromId = None, troveType = 0) self.assertEqual(idb[(item, version, flavor)], 1) self.assertEqual(idb.getId(1), (item, version, flavor, 1) ) del idb idb = instances.InstanceTable(cx) self.assertEqual(idb[(item, version, flavor)], 1) cu = cx.cursor() cu.execute("select isPresent, clonedFromId from instances where instanceid = 1") row = cu.fetchall()[0] self.assertEqual(row[0], 1) self.assertEqual(row[1], None) idb.update(1, isPresent = 0, clonedFromId = 1) cu.execute("select isPresent, clonedFromId from instances where instanceid = 1") row = cu.fetchall()[0] self.assertEqual(row[0], 0) self.assertEqual(row[1], 1)
def _get(versionFilter, flavorFilter, whatProvidesList): return queryrep.getTrovesToDisplay(repos, [], [], [deps.parseDep(x) for x in whatProvidesList], versionFilter, flavorFilter, self.cfg.installLabelPath, targetFlavor, None)
def testResolveResult(self): trv = self.addComponent('foo:runtime', '1.0', 'ssl') tup = trv.getNameVersionFlavor() job = (tup[0], (None, None), (tup[1], tup[2]), False) r = resolver.ResolveResult() r.troveResolved([job], [], []) r2 = thaw('ResolveResult', freeze('ResolveResult', r)) assert(r2.getBuildReqs() == [ job ]) assert(r2.success) assert(not r2.inCycle) r = resolver.ResolveResult(inCycle=True) r.troveMissingBuildReqs(True, [('foo', None, parseFlavor('ssl'))]) r2 = thaw('ResolveResult', freeze('ResolveResult', r)) assert(not r2.hasMissingDeps()) assert(r2.hasMissingBuildReqs()) assert(r2.getMissingBuildReqs() == [(True, ('foo', '', parseFlavor('ssl')))]) assert(not r2.success) assert(r2.inCycle) r = resolver.ResolveResult(inCycle=True) r.troveMissingDependencies(True, [(trv.getNameVersionFlavor(), parseDep('trove: foo trove: bar'))]) r2 = thaw('ResolveResult', freeze('ResolveResult', r)) assert(r.getMissingDeps() == r2.getMissingDeps()) assert(r2.hasMissingDeps()) assert(not r2.success) assert(r2.inCycle)
def testGroupDoesOneThingDepsDoesAnother(self): # create foo:lib and group-a # group-a=2.0-1-1 # `- foo:lib=2.1-1-1 self.addComponent('foo:lib', '2.1-1-1') self.addCollection('group-a', '2.1-1-1', ['foo:lib']) # update to group-a self.updatePkg(self.rootDir, 'group-a') # group-a=1.0-1-1 # `- foo:lib=2.0-1-1 self.addComponent('foo:lib', '2.0-1-1') self.addCollection('group-a', '2.0-1-1', [('foo:lib', '2.0-1-1')]) # create bar:runtime which requires foo:lib from 1.0-1-1 # (which does not conflict with foo:lib 2.0-1-1) dep = deps.parseDep('soname: ELF32/libfoo.so.1(SysV x86)') self.addComponent('foo:lib', '1.0-1-1', provides=dep, filePrimer=1) self.addComponent('bar:runtime', '1.0-1-1', requires=dep) # now try to downgrade group-a and install bar:runtime with # dependency solving at the same time. We should get # a job that updates foo:lib 2.1-1-1 to 2.0-1-1, and a # new install of foo:lib=1.0-1-1 self.checkUpdate(['group-a=2.0-1-1', 'bar:runtime'], [ 'foo:lib=2.1-1-1--2.0-1-1', 'foo:lib=--1.0-1-1', 'bar:runtime=1.0-1-1', 'group-a=2.1-1-1--2.0-1-1' ], resolve=True)
def testInstances(self): cx = self.getDB() schema.createSchema(cx) cx.commit() v = versiontable.VersionTable(cx) f = flavors.Flavors(cx) it = items.Items(cx) item = it.addId('foo') version = v.addId(versions.VersionFromString('/c@r:d/1.0-1-1')) d = deps.parseDep('') flavor = f.get(d, None) idb = instances.InstanceTable(cx) idb.addId(item, version, flavor, clonedFromId=None, troveType=0) self.assertEqual(idb[(item, version, flavor)], 1) self.assertEqual(idb.getId(1), (item, version, flavor, 1)) del idb idb = instances.InstanceTable(cx) self.assertEqual(idb[(item, version, flavor)], 1) cu = cx.cursor() cu.execute( "select isPresent, clonedFromId from instances where instanceid = 1" ) row = cu.fetchall()[0] self.assertEqual(row[0], 1) self.assertEqual(row[1], None) idb.update(1, isPresent=0, clonedFromId=1) cu.execute( "select isPresent, clonedFromId from instances where instanceid = 1" ) row = cu.fetchall()[0] self.assertEqual(row[0], 0) self.assertEqual(row[1], 1)
def testGroupDoesOneThingDepsDoesAnother(self): # create foo:lib and group-a # group-a=2.0-1-1 # `- foo:lib=2.1-1-1 self.addComponent('foo:lib', '2.1-1-1') self.addCollection('group-a', '2.1-1-1', [ 'foo:lib' ]) # update to group-a self.updatePkg(self.rootDir, 'group-a') # group-a=1.0-1-1 # `- foo:lib=2.0-1-1 self.addComponent('foo:lib', '2.0-1-1') self.addCollection('group-a', '2.0-1-1', [ ('foo:lib', '2.0-1-1') ]) # create bar:runtime which requires foo:lib from 1.0-1-1 # (which does not conflict with foo:lib 2.0-1-1) dep = deps.parseDep('soname: ELF32/libfoo.so.1(SysV x86)') self.addComponent('foo:lib', '1.0-1-1', provides=dep, filePrimer=1) self.addComponent('bar:runtime', '1.0-1-1', requires=dep) # now try to downgrade group-a and install bar:runtime with # dependency solving at the same time. We should get # a job that updates foo:lib 2.1-1-1 to 2.0-1-1, and a # new install of foo:lib=1.0-1-1 self.checkUpdate(['group-a=2.0-1-1', 'bar:runtime'], ['foo:lib=2.1-1-1--2.0-1-1', 'foo:lib=--1.0-1-1', 'bar:runtime=1.0-1-1', 'group-a=2.1-1-1--2.0-1-1'], resolve=True)
def testGroupRemovesRequiredComponent(self): # in this scenario, you have a component "req:runtime" that # requires "prov:runtime". group-test installed "prov:runtime" # on the system. When moving to a new version of "group-test" # that does not include "prov:runtime", we expect prov:runtime to # be left behind since it satisfies a dependency b1 = '/localhost@rpl:branch/' b2 = '/localhost@rpl:compat/' myDep = deps.parseDep('trove: prov:runtime file:/usr/bin/prov') # create initial components # we create 2 versions of req:runtime to trigger bugs related # to sorting on untimestamped versions. self.addComponent('req:runtime', '1.0-1-1', requires=myDep, filePrimer=1) self.addComponent('req:runtime', '1.0-1-2', requires='file:/usr/bin/prov', filePrimer=2) self.addComponent('prov:runtime', '1.0-1-1', provides=myDep, filePrimer=3) self.addComponent('test:runtime', '1.0-1-1', filePrimer=4) # add prov:runtime and test:runtime to group-test (we have # test:runtime so we won't have an empty group later on) self.addCollection('group-test', '1.0-1-1', ['prov:runtime', 'test:runtime']) # install group-test and req:runtime. self.updatePkg(self.rootDir, 'group-test', '1.0-1-1') self.updatePkg(self.rootDir, 'req:runtime', '1.0-1-1') self.updatePkg(self.rootDir, 'req:runtime', '1.0-1-2', keepExisting=True) # now, add the trove that provides our dep into the :compat branch self.addComponent('prov:runtime', b2+'1.0-1-1', provides=myDep, filePrimer=2) # make a group-test which only has test:runtime in it self.addComponent('test:runtime', b1+'1.0-1-1', filePrimer=3) self.addCollection('group-test', b1+'1.0-1-1', ['test:runtime']) # update to the group-test on the new branch # set the installLabelPath to include the new branch # and the compat branch. Use resolve=True to get prov:runtime from # the :compat branch self.cfg.installLabelPath = conarycfg.CfgLabelList( [ versions.Label('localhost@rpl:branch'), versions.Label('localhost@rpl:compat') ] ) # this should leave prov installed self.logFilter.add() self.checkUpdate('group-test=%s1.0-1-1' % b1, ['group-test=:linux--:branch', 'test:runtime=:linux--:branch'], resolve=True, keepRequired = True) self.logFilter.compare('warning: keeping prov:runtime - required by at least req:runtime') self.logFilter.remove()
def testInfoOrdering(self): dt, db, cu = self.init() # info-user:foo needs info-group:foo # test needs info-user:foo jobInfo = self.createJobInfo(db, self.prvReqTrove("info-user:user", parseDep("userinfo: user"), parseDep("groupinfo: group")), self.prvTrove("info-group:group", parseDep("groupinfo: group")), self.reqTrove("test", parseDep("userinfo: user")) ) resolvedOrder = self.check(findOrdering=True, *jobInfo)[2] order = [ [ y[0] for y in x ] for x in resolvedOrder ] assert(order == [['info-group:group'], ['info-user:user'], ['test']])
def testKeepDepsDeps(self): self.addComponent("foo:runtime=1.0", requires=deps.parseDep('trove: dep:runtime')) self.addCollection("foo=1.0", [":runtime"]) self.addComponent("dep:runtime=1.0", requires=deps.parseDep('trove: dep2:runtime')) self.addCollection("dep=1.0", [":runtime"]) self.addComponent("dep2:runtime=1.0", fileContents=[('/dep2', '1')]) self.addCollection("dep2=1.0", [":runtime"]) updJob, suggMap = self._applyModel(['install foo']) self.assertEquals(len(suggMap), 2) self.verifyFile(self.rootDir + '/dep2', '1') updJob, suggMap = self._applyModel(['install foo']) self.assertEquals(len(suggMap), 0) self.verifyFile(self.rootDir + '/dep2', '1')
def testKeepDepsDeps(self): self.addComponent("foo:runtime=1.0", requires = deps.parseDep('trove: dep:runtime')) self.addCollection("foo=1.0", [ ":runtime" ]) self.addComponent("dep:runtime=1.0", requires = deps.parseDep('trove: dep2:runtime')) self.addCollection("dep=1.0", [ ":runtime" ]) self.addComponent("dep2:runtime=1.0", fileContents = [ ('/dep2', '1') ]) self.addCollection("dep2=1.0", [ ":runtime" ]) updJob, suggMap = self._applyModel(['install foo']) self.assertEquals(len(suggMap), 2) self.verifyFile(self.rootDir + '/dep2', '1') updJob, suggMap = self._applyModel(['install foo']) self.assertEquals(len(suggMap), 0) self.verifyFile(self.rootDir + '/dep2', '1')
def testDependencies(self): self.addComponent('foo:runtime=1.0', requires=deps.parseDep('trove: bar:lib')) self.addComponent('bar:lib=1.0') grp = self._build("runtime = world.find('foo:runtime')", "suggestions = runtime.depsNeeded(world)", "r.Group(runtime + suggestions)") self.checkTroves(grp, [ (('bar:lib', '/localhost@rpl:linux/1.0-1-1', ''), True, True), (('foo:runtime', '/localhost@rpl:linux/1.0-1-1', ''), True, True) ]) # resolve against a TroveSet grp = self._build("lib = world.find('bar:lib')", "runtime = world.find('foo:runtime')", "suggestions = runtime.depsNeeded(lib)", "r.Group(runtime + suggestions)") self.checkTroves(grp, [ (('bar:lib', '/localhost@rpl:linux/1.0-1-1', ''), True, True), (('foo:runtime', '/localhost@rpl:linux/1.0-1-1', ''), True, True) ]) # test failOnUnresolved grp = self._build( "emptyWorld = r.Repository('localhost@foo:bar', r.flavor)", "runtime = world.find('foo:runtime')", "suggestions = runtime.depsNeeded(emptyWorld,", " failOnUnresolved = False)", "r.Group(runtime + suggestions)") self.assertRaises( cook.CookError, self._build, "emptyWorld = r.Repository('localhost@foo:bar', r.flavor)", "runtime = world.find('foo:runtime')", "suggestions = runtime.depsNeeded(emptyWorld)", "r.Group(runtime + suggestions)") # test requires in subgroups grp = self._build("runtime = world['foo:runtime']", "sub = runtime.createGroup('group-sub')", "suggestions = sub.depsNeeded(world)", "r.Group(runtime + suggestions)") self.checkTroves(grp, [ (('bar:lib', '/localhost@rpl:linux/1.0-1-1', ''), True, True), (('foo:runtime', '/localhost@rpl:linux/1.0-1-1', ''), True, True) ]) # test provides in subgroups grp = self._build( "emptyWorld = r.Repository('localhost@foo:bar', r.flavor)", "lib = world['bar:lib']", "sub = lib.createGroup('group-sub')", "outer = world['foo:runtime']", "suggestions = outer.depsNeeded(sub)", "r.Group(outer)")
def testDependenciesSearchPath(self): self.addComponent("foo:lib=1.0") self.addCollection("foo=1.0", ["foo:lib"]) self.addComponent("bar:lib=/localhost@foo:bar/1.0") d = deps.parseDep("trove: foo:lib") d.union(deps.parseDep("trove: bar:lib")) self.addComponent("pkg:runtime", requires=d) grp = self._build( 'pkg = world["pkg:runtime"]', 'altLabel = r.Repository("localhost@foo:bar", r.flavor)', "sp = r.SearchPath(world, altLabel)", "return r.Group(pkg + pkg.depsNeeded(sp))", ) self.checkTroves( grp, [ (("bar:lib", "/localhost@foo:bar/1.0-1-1", ""), True, True), (("foo", "/localhost@rpl:linux/1.0-1-1", ""), True, True), (("foo:lib", "/localhost@rpl:linux/1.0-1-1", ""), True, False), (("pkg:runtime", "/localhost@rpl:linux/1.0-1-1", ""), True, True), ], ) grp = self._build( 'pkg = world["pkg:runtime"]', 'foo = world["foo"]', 'bar = world["bar:lib=localhost@foo:bar"]', 'altLabel = r.Repository("localhost@foo:bar", r.flavor)', "sp = r.SearchPath(foo, bar)", "return r.Group(pkg + pkg.depsNeeded(sp))", ) self.checkTroves( grp, [ (("bar:lib", "/localhost@foo:bar/1.0-1-1", ""), True, True), (("foo", "/localhost@rpl:linux/1.0-1-1", ""), True, True), (("foo:lib", "/localhost@rpl:linux/1.0-1-1", ""), True, False), (("pkg:runtime", "/localhost@rpl:linux/1.0-1-1", ""), True, True), ], )
def testResolveByGroups(self): cacheDir = self.workDir + '/cache' util.mkdirChain(cacheDir) store = repocache.RepositoryCache(cacheDir, readOnly=False) repos = self.openRepository() self.addComponent('bar:runtime', '1') self.addComponent('foo:runtime', '1') self.addComponent('bam:runtime', '1') foo = self.addCollection('foo', '1', [':runtime']) bar = self.addCollection('bar', '1', [':runtime']) bam = self.addCollection('bam', '1', [':runtime']) dep = deps.parseDep('trove: foo:runtime trove:bar:runtime') dep2 = deps.parseDep('trove: bam:runtime') xx = store.resolveDependenciesByGroups(repos, [foo, bar, bam], [dep, dep2]) yy = store.resolveDependenciesByGroups(repos, [foo, bar, bam], [dep, dep2]) assert(xx == yy)
def testResolveByGroups(self): cacheDir = self.workDir + '/cache' util.mkdirChain(cacheDir) store = repocache.RepositoryCache(cacheDir, readOnly=False) repos = self.openRepository() self.addComponent('bar:runtime', '1') self.addComponent('foo:runtime', '1') self.addComponent('bam:runtime', '1') foo = self.addCollection('foo', '1', [':runtime']) bar = self.addCollection('bar', '1', [':runtime']) bam = self.addCollection('bam', '1', [':runtime']) dep = deps.parseDep('trove: foo:runtime trove:bar:runtime') dep2 = deps.parseDep('trove: bam:runtime') xx = store.resolveDependenciesByGroups(repos, [foo, bar, bam], [dep, dep2]) yy = store.resolveDependenciesByGroups(repos, [foo, bar, bam], [dep, dep2]) assert (xx == yy)
def testGetLocalProvides(self): db = self.openDatabase() baz = self.addDbComponent(db, 'baz:run', '1', '', provides=parseDep('trove:foo:run')) foo2 = self.addDbComponent(db, 'foo:run', '2', '', provides=parseDep('trove:foo:run'), requires=parseDep('trove:baz:run')) foo1 = self.addDbComponent(db, 'foo:run', '1', '', provides=parseDep('trove:foo:run'), requires=parseDep('trove:baz:run')) bar = self.addDbComponent(db, 'bar:run', '1', '', provides=parseDep('trove:bar:run'), requires=parseDep('trove:foo:run')) bam = self.addDbComponent(db, 'bam:run', '1', '', provides=parseDep('trove:bam:run'), requires=parseDep('trove:foo:run')) depSet = parseDep('trove:bam:run trove:bar:run') sols = db.getTrovesWithProvides([depSet], True) assert(sols[depSet] == [[bam.getNameVersionFlavor()], [bar.getNameVersionFlavor()]])
def testBuildTrove(self): trv = self.addComponent('blah:source', '1.0') bt = buildtrove.BuildTrove(1, trv.getName(), trv.getVersion(), trv.getFlavor()) f = failure.MissingDependencies([(trv.getNameVersionFlavor(), deps.parseDep('trove: blam trove:foo'))]) bt.setFailureReason(f) frz = apiutils.freeze('BuildTrove', bt) bt2 = apiutils.thaw('BuildTrove', frz) assert(bt2.getFailureReason() == bt.getFailureReason()) assert(bt2.getFlavor() == bt.getFlavor())
def testDependencyChain(self): self.addComponent("a:runtime=1.0", requires=deps.parseDep("trove: a:lib")) self.addComponent("a:lib=1.0", requires=deps.parseDep("trove: b:lib")) self.addComponent("b:lib=1.0") grp = self._build( "avail = world.find('a:lib', 'b:lib')", "c = world['a:runtime']", "s = c.depsNeeded(avail)", "return r.Group(c + s)", ) self.checkTroves( grp, [ (("a:runtime", "/localhost@rpl:linux/1.0-1-1", ""), True, True), (("a:lib", "/localhost@rpl:linux/1.0-1-1", ""), True, True), (("b:lib", "/localhost@rpl:linux/1.0-1-1", ""), True, True), ], )
def testKeepRequiredWithOverlappingFiles(self): # Test that keepRequired will function when an old trove overlaps with # a new trove providing that the old trove had the overlapping files # removed previously. prov1 = deps.parseDep('file: /lib/libfoo.so.1') prov2 = deps.parseDep('file: /lib/libfoo.so.2') self.addComponent('foo:lib=1.0', provides = prov1, fileContents = [ ('/lib/libfoo.so.1', '1'), ('/etc/conflict', 'contents') ] ) self.addComponent('foo:lib=2.0', provides = prov2, fileContents = [ ('/lib/libfoo.so.2', '2'), ('/etc/conflict', 'contents') ] ) self.addComponent('bar:runtime=1.0', requires = prov1, fileContents = [ ('/bin/bar1', '1') ] ) self.addComponent('bar:runtime=2.0', requires = prov2, fileContents = [ ('/bin/bar2', '2') ] ) self.updatePkg([ 'foo:lib=1.0', 'bar:runtime=1.0']) (rc, str) = self.captureOutput(self.updatePkg, 'bar:runtime=2.0', resolve = True, keepExisting = True, keepRequired = True) expectedStr = """\ The following dependencies would not be met after this update: bar:runtime=1.0-1-1 (Already installed) requires: file: /lib/libfoo.so.1 which is provided by: foo:lib=1.0-1-1 (Would be updated to 2.0-1-1) """ assert(str == expectedStr) self.removeFile(self.rootDir, '/etc/conflict') (rc, str) = self.captureOutput(self.updatePkg, 'bar:runtime=2.0', resolve = True, keepExisting = True, keepRequired = True) assert(str == 'Including extra troves to resolve dependencies:\n' ' foo:lib=2.0-1-1\n' 'warning: keeping foo:lib - required by at least bar:runtime\n')
def testMultDepsResolvedByOneTrove(self): # test multiple dependencies resolved by the same trove - make sure # there's no duplicate information given myDep = deps.parseDep('trove: test:runtime trove: test:foo') self.addQuickTestComponent('prov:runtime', '2.0-1-1', '~!builddocs', provides=myDep) self.addQuickTestComponent('req:runtime', '2.0-1-1', '~!builddocs', requires=myDep) rc, msg = self.captureOutput(self.updatePkg, self.cfg.root, 'req:runtime') assert(msg == "1 additional trove is needed:\n" " prov:runtime=2.0-1-1 is required by:\n" " req:runtime=2.0-1-1\n")
def testBuildTrove(self): trv = self.addComponent('blah:source', '1.0') bt = buildtrove.BuildTrove(1, trv.getName(), trv.getVersion(), trv.getFlavor()) f = failure.MissingDependencies([ (trv.getNameVersionFlavor(), deps.parseDep('trove: blam trove:foo')) ]) bt.setFailureReason(f) frz = apiutils.freeze('BuildTrove', bt) bt2 = apiutils.thaw('BuildTrove', frz) assert (bt2.getFailureReason() == bt.getFailureReason()) assert (bt2.getFlavor() == bt.getFlavor())
def testOldNeedsNew(self): dt, db, cu = self.init() prv1 = parseDep("soname: ELF32/libtest.so.1(foo)") prv2 = parseDep("soname: ELF32/libtest.so.2(foo)") prvTrv1 = self.prvTrove("test-prov", prv1, version="1.0-1-1") reqTrv1 = self.reqTrove("test-req", prv1, version="1.0-1-1") troveInfo = db.addTrove(prvTrv1) db.addTroveDone(troveInfo) troveInfo = db.addTrove(reqTrv1) db.addTroveDone(troveInfo) db.commit() prvTrv2 = self.prvTrove("test-prov", prv2, version="2.0-1-1") reqTrv2 = self.reqTrove("test-req", prv2, version="2.0-1-1") jobInfo = self.createJobInfo(db, (prvTrv1, prvTrv2), (reqTrv1, reqTrv2)) order = self.check(findOrdering=True, *jobInfo)[2] assert(len(order) == 1)
def __init__(self, **kwargs): assert type(self) != _File for arg in kwargs: aliasedArg = self.aliasedArgs.get(arg, arg) if aliasedArg not in self.kwargs: raise ParameterError("'%s' is not allowed for this class" % arg) for key, val in self.aliasedArgs.iteritems(): if key in kwargs and val in kwargs: raise ParameterError( \ "'%s' and '%s' cannot be specified together" % \ (key, val)) elif key in kwargs: kwargs[val] = kwargs[key] for key, val in self.__class__.kwargs.iteritems(): setattr(self, key, kwargs.get(key, val)) self.mtime = int(self.mtime or time.time()) if type(self.requires) == str: self.requires = deps.parseDep(self.requires) elif self.requires is None: self.requires = deps.DependencySet() if isinstance(self.provides, str): self.provides = deps.parseDep(self.provides) elif self.provides is None: self.provides = deps.DependencySet() if type(self.flavor) == str: self.flavor = deps.parseFlavor(self.flavor) if self.flavor is None: self.flavor = deps.Flavor() if self.tags is None: self.tags = []
def getRpmLibProvidesSet(rpm): """ Retreieve a dependency set that represents the rpmlib provides from the loaded rpm module @param rpm: the rpm module @type rpm: module @return: A dependency containing the virtual items that rpmlib provides @rtype: conary.deps.deps.DependencySet() """ depset = deps.DependencySet() for prov in rpm.ds.Rpmlib(): dep = deps.parseDep('rpmlib: '+prov.N().split('(')[1].split(')')[0]) depset.union(dep) return depset
def testDepResolutionResultFormat2(self): #CNY-2254 self.addComponent('foo:python', '1', provides='python: foo(2.4)') self.addComponent('conary-policy:lib', '1') repos = self.openRepository() depSet = deps.parseDep('trove: conary-policy:lib python: foo') results = repos.resolveDependencies(self.cfg.buildLabel, [depSet]) for idx, (depClass, dep) in enumerate(depSet.iterDeps(sort=True)): sol, = results[depSet][idx] solName = sol[0] if dep.name == 'conary-policy:lib': self.assertEquals(solName, 'conary-policy:lib') else: self.assertEquals(solName, 'foo:python')
def testGroupResolutionAcrossRepos(self): self.openRepository() repos = self.openRepository(1) self.addComponent('test:runtime', '1.0', '!ssl') self.addComponent('test:runtime', '2.0', '!ssl') self.addComponent('test:runtime', '/localhost1@rpl:foobar/1.0', 'ssl') self.addComponent('test:runtime', '/localhost1@rpl:foobar/2.0', 'ssl') trv = self.addCollection('group-dist', '1.0', [('test:runtime', '1.0', '!ssl'), ('test:runtime', '/localhost1@rpl:foobar/1.0', 'ssl')]) sugg = repos.resolveDependenciesByGroups([trv], [deps.parseDep('trove:test:runtime')]) troves = sugg[deps.parseDep('trove:test:runtime')][0] troveVers = set((x[1].getHost(), x[1].trailingRevision().getVersion()) for x in troves) assert(troveVers == set([('localhost', '1.0'), ('localhost1', '1.0')])) # this doesn't match anything. Make sure there's a spot in the suggestion list. sugg = repos.resolveDependenciesByGroups([trv], [deps.parseDep('trove:foo:runtime trove:bar:runtime')]) resultList, = sugg.values() self.assertEqual(resultList, [[], []])
def getRpmLibProvidesSet(rpm): """ Retreieve a dependency set that represents the rpmlib provides from the loaded rpm module @param rpm: the rpm module @type rpm: module @return: A dependency containing the virtual items that rpmlib provides @rtype: conary.deps.deps.DependencySet() """ depset = deps.DependencySet() for prov in rpm.ds.Rpmlib(): dep = deps.parseDep('rpmlib: ' + prov.N().split('(')[1].split(')')[0]) depset.union(dep) return depset
def getDepsForTroveList(self, troveTupList, provides = True, requires = True): def missingNeeded(depTuple): if depTuple is None: return True if provides and depTuple[0] is None: return True if requires and depTuple[1] is None: return True return False def mergeCacheEntry(troveTup, depTuple): existing = self.depCache.get(depTuple) if existing is None: self.depCache[troveTup] = depInfo else: self.depCache[troveTup] = (depTuple[0] or existing[0], depTuple[1] or existing[1]) # look in the dep cache and trove cache result = [ None ] * len(troveTupList) for i, tup in enumerate(troveTupList): result[i] = self.getDepCacheEntry(tup) if result[i] is None and self.troveIsCached(tup): trv = self.cache[tup] result[i] = (trv.getProvides(), trv.getRequires()) elif result[i] is None and trove.troveIsPackage(tup[0]): # packages provide only themselves; querying the repository # to figure that out seems unnecessarily complicated result[i] = (deps.parseDep('trove: %s' % tup[0]), deps.DependencySet()) needed = [ (i, troveTup) for i, (troveTup, depSets) in enumerate(izip(troveTupList, result)) if missingNeeded(depSets) ] if not needed: return result # use the getDepsForTroveList call; it raises an error if it needs # to access some repositories which don't support it log.info("Getting deps for %d troves" % len(needed)) try: depList = self.troveSource.getDepsForTroveList( [ x[1] for x in needed ], provides = provides, requires = requires) except netclient.PartialResultsError, e: # we can't use this call everywhere; handle what we can and we'll # deal with the None's later depList = e.partialResults
def testRPMJobOrdering(self): """ Ensure that introducing a native conary package in the dependency chain between two encapsuled RPM packages causes Conary to split the three packages into separate jobs. foo:rpm -> bar:runtime -> baz:rpm """ self.addRPMComponent('baz:rpm=1.0', 'simple-1.0-1.i386.rpm') self.addComponent('bar:runtime=1.0', requires=deps.parseDep('trove: baz:rpm')) self.addRPMComponent('foo:rpm=1.0', 'ownerships-1.0-1.i386.rpm', requires=deps.parseDep('trove: bar:runtime')) rc, txt = self.captureOutput(self.updatePkg, [ 'foo:rpm', ], resolve=True, raiseError=True, info=True) self.assertEquals(txt, 'Job 1 of 3:\n' ' Install baz:rpm=1.0-1-1\n' 'Job 2 of 3:\n' ' Install bar:runtime=1.0-1-1\n' 'Job 3 of 3:\n' ' Install foo:rpm=1.0-1-1\n')
def testDepResolutionResultFormat(self): # test result formats in case dep resolution fails repos = self.openRepository() test1r = self.addComponent('test:runtime', '1.0') test1 = self.addCollection('test', '1.0', [':runtime']) test2r = self.addComponent('test:runtime', '2.0') test2 = self.addCollection('test', '2.0', [':runtime']) grp1 = self.addCollection('group-dist', '1.0', [('test', '1.0')]) grp2 = self.addCollection('group-dist', '2.0', [('test', '2.0')]) # test a match dep = deps.parseDep('trove:test:runtime') sugg = repos.resolveDependenciesByGroups([grp1], [dep]) self.assertEqual(sugg[dep], [[test1r.getNameVersionFlavor()]]) sugg = repos.resolveDependenciesByGroups([grp2], [dep]) self.assertEqual(sugg[dep], [[test2r.getNameVersionFlavor()]]) # test misses dep = deps.parseDep('trove:foo:runtime') sugg = repos.resolveDependenciesByGroups([grp1], [dep]) self.assertEqual(sugg[dep], [[]]) dep = deps.parseDep('trove:foo:runtime trove:bar:runtime') sugg = repos.resolveDependenciesByGroups([grp1], [dep]) self.assertEqual(sugg[dep], [[], []]) # test hits and misses dep = deps.parseDep('trove:foo:runtime trove:test:runtime') sugg = repos.resolveDependenciesByGroups([grp1], [dep]) self.assertEqual(sugg[dep], [[], [test1r.getNameVersionFlavor()]]) dep = deps.parseDep( 'trove:foo:runtime trove:test:runtime trove:bar:runtime') sugg = repos.resolveDependenciesByGroups([grp2], [dep]) self.assertEqual(sugg[dep], [[], [], [test2r.getNameVersionFlavor()]]) # test a more complex case dep1 = deps.parseDep('trove:test:runtime') dep2 = deps.parseDep('trove:foo:runtime') dep3 = deps.parseDep('trove:foo:runtime trove:test:runtime') sugg = repos.resolveDependenciesByGroups([grp1, grp2], [dep1, dep2, dep3]) # tehse should return the latest deps from grp2 self.assertEqual(sugg[dep1], [[test2r.getNameVersionFlavor()]]) self.assertEqual(sugg[dep2], [[]]) self.assertEqual(sugg[dep3], [[], [test2r.getNameVersionFlavor()]])
def testResolveUsingLatest(self): myDep = deps.parseDep('trove: test:runtime') self.addQuickTestComponent('prov:runtime', '1.0-1-1', '!builddocs', provides=myDep) self.addQuickTestComponent('prov:runtime', '2.0-1-1', '~!builddocs', provides=myDep) self.addQuickTestComponent('req:runtime', '2.0-1-1', '~!builddocs', requires=myDep) oldFlavor = self.cfg.flavor try: self.cfg.flavor = [ deps.parseFlavor('!builddocs') ] rc, msg = self.captureOutput(self.updatePkg, self.cfg.root, 'req:runtime') assert(msg == "1 additional trove is needed:\n" " prov:runtime=2.0-1-1 is required by:\n" " req:runtime=2.0-1-1\n") finally: self.cfg.flavor = oldFlavor
def testIncludeDeps(self): self.addComponent("foo:runtime=localhost@other:label/1.0", fileContents=[('/foo', '1.0')]) self.addCollection("foo=localhost@other:label/1.0", [':runtime']) self.addComponent("inctrove:cml", fileContents=[("/some/path/to.cml", "search foo=localhost@other:label\n") ]) self.addComponent('bar:runtime', '1.0', requires=deps.parseDep('trove: foo:runtime')) self.addCollection("bar", [":runtime"]) self._applyModel([ 'search %s' % self.cfg.buildLabel, 'include inctrove:cml', 'install bar' ], addSearchLabel=False) self.verifyFile(self.rootDir + '/foo', '1.0')
def testSimple(self): # install self.addComponent('foo:runtime=1.0', fileContents=[('/foo', '1.0')]) self.addCollection('foo=1.0', [':runtime']) self._applyModel(['install foo']) self.verifyFile(self.rootDir + '/foo', '1.0') # this should cause an update to 2.0 self.addComponent('foo:runtime=2.0', fileContents=[('/foo', '2.0')]) self.addCollection('foo=2.0', [':runtime']) self._applyModel(['install foo']) self.verifyFile(self.rootDir + '/foo', '2.0') # this should cause an update to 3.0, with bar dragged in by deps self.addComponent('bar:runtime=3.0', fileContents=[('/bar', '3.0')]) self.addCollection('bar=3.0', [':runtime']) self.addComponent('foo:runtime=3.0', fileContents=[('/foo', '3.0')], requires=deps.parseDep('trove: bar:runtime')) self.addCollection('foo=3.0', [':runtime']) self._applyModel(['install foo']) self.verifyFile(self.rootDir + '/foo', '3.0') self.verifyFile(self.rootDir + '/bar', '3.0')
def testExistingDepResolution(self): # something which is recursively included from the update, but # normally wouldn't be installed, is needed to resolve a dependency self.addQuickTestComponent("test:runtime", '1.0-1-1') self.addQuickTestComponent("test:lib", '1.0-1-1', filePrimer=1) self.addQuickTestCollection("test", '1.0-1-1', [("test:lib", '1.0-1-1'), ("test:runtime", '1.0-1-1')]) self.updatePkg(self.rootDir, "test") self.erasePkg(self.rootDir, "test:lib") self.addQuickTestComponent("test:runtime", '2.0-1-1', requires=deps.parseDep('trove: test:lib')) self.addQuickTestComponent("test:lib", '2.0-1-1', filePrimer=1) self.addQuickTestCollection("test", '2.0-1-1', [("test:lib", '2.0-1-1'), ("test:runtime", '2.0-1-1')]) (rc, str) = self.captureOutput(self.updatePkg, self.rootDir, "test", resolve=True) assert (str == 'Including extra troves to resolve dependencies:\n' ' test:lib=2.0-1-1\n')