def testDistributedRedirect(self): store = self._connect() cu = store.db.cursor() flavor = deps.Flavor() localVer1 = ThawVersion("/localhost@test:trunk/10:1.1-10") localVer2 = ThawVersion("/localhost@test:trunk/20:1.2-20") remoteVer = ThawVersion("/localhost1@test:trunk/10:1.2-10") # this places /localhost1@test:trunk into the branch table, but not # the labels table trv = trove.Trove("group-foo", localVer1, flavor, None, type = trove.TROVE_TYPE_REDIRECT) trv.addRedirect("target", remoteVer.branch(), flavor) trv.computeDigests() store.addTroveSetStart([], [], []) ti = store.addTrove(trv, trv.diff(None)[0], hidden = True) store.addTroveDone(ti) # and this needs the label to exist trv = trove.Trove("group-foo", localVer2, flavor, None) trv.addTrove("target", remoteVer, flavor) trv.computeDigests() ti = store.addTrove(trv, trv.diff(None)[0], hidden = True) store.addTroveDone(ti)
def testDistributedRedirect(self): store = self._connect() cu = store.db.cursor() flavor = deps.Flavor() localVer1 = ThawVersion("/localhost@test:trunk/10:1.1-10") localVer2 = ThawVersion("/localhost@test:trunk/20:1.2-20") remoteVer = ThawVersion("/localhost1@test:trunk/10:1.2-10") # this places /localhost1@test:trunk into the branch table, but not # the labels table trv = trove.Trove("group-foo", localVer1, flavor, None, type=trove.TROVE_TYPE_REDIRECT) trv.addRedirect("target", remoteVer.branch(), flavor) trv.computeDigests() store.addTroveSetStart([], [], []) ti = store.addTrove(trv, trv.diff(None)[0], hidden=True) store.addTroveDone(ti) # and this needs the label to exist trv = trove.Trove("group-foo", localVer2, flavor, None) trv.addTrove("target", remoteVer, flavor) trv.computeDigests() ti = store.addTrove(trv, trv.diff(None)[0], hidden=True) store.addTroveDone(ti)
def testRedirect(self): store = self._connect() old = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-3") x86 = deps.parseFlavor("is:x86") x86_64 = deps.parseFlavor("is:x86_64") redir = trove.Trove("trvname", old, x86, None, type = trove.TROVE_TYPE_REDIRECT) redir.addRedirect("trv1", old.branch(), x86) redir.addRedirect("trv2", old.branch(), x86_64) redir.computeDigests() store.addTroveSetStart([], [], []) troveInfo = store.addTrove(redir, redir.diff(None)[0]) store.addTroveDone(troveInfo) store.addTroveSetDone() assert(store.getTrove("trvname", old, x86) == redir)
def testRedirect(self): store = self._connect() old = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-3") x86 = deps.parseFlavor("is:x86") x86_64 = deps.parseFlavor("is:x86_64") redir = trove.Trove("trvname", old, x86, None, type=trove.TROVE_TYPE_REDIRECT) redir.addRedirect("trv1", old.branch(), x86) redir.addRedirect("trv2", old.branch(), x86_64) redir.computeDigests() store.addTroveSetStart([], [], []) troveInfo = store.addTrove(redir, redir.diff(None)[0]) store.addTroveDone(troveInfo) store.addTroveSetDone() assert (store.getTrove("trvname", old, x86) == redir)
def testVersionMatching(self): v1 = ThawVersion('/localhost@rpl:devel/1:1.0-1-1') v2 = ThawVersion('/localhost@rpl:devel/2:2.0-1-1') v1b = ThawVersion('/localhost@rpl:branch/3:1.0-1-1') v2b = ThawVersion('/localhost@rpl:branch/4:2.0-1-1') nodeps = deps.parseFlavor('') s = SimplestFindTroveSource() n = 'test' n2 = 'test2' t_v1 = (n, v1, nodeps) t_v2 = (n, v2, nodeps) t_v1b = (n, v1b, nodeps) t_v2b = (n, v2b, nodeps) t2_v1 = (n2, v1, nodeps) t2_v2 = (n2, v2, nodeps) t2_v1b = (n2, v1b, nodeps) t2_v2b = (n2, v2b, nodeps) lbl_a = v1.branch().label() lbl_b = v1b.branch().label() s.addTroves(t_v1, t_v2, t_v1b, t_v2b, t2_v1, t2_v2, t2_v1b, t2_v2b) d = s.getTroveLeavesByLabel({n : {lbl_a : None}, n2: {lbl_b: None}}) assert(troveDictMatches(d, [t_v2, t2_v2b])) d = s.getTroveVersionsByLabel({n : {lbl_a : None}, n2 :{lbl_b:None}}) assert(troveDictMatches(d, [t_v1, t_v2, t2_v2b, t2_v1b])) d = s.getTroveVersionsByLabel({n : {lbl_a : None, lbl_b: None}}) assert(troveDictMatches(d, [t_v1, t_v2, t_v1b, t_v2b])) d = s.getTroveLeavesByBranch({n : {v1.branch() : None}, n2: {v2b.branch() : None}}) assert(troveDictMatches(d, [t_v2, t2_v2b])) d = s.getTroveVersionsByBranch({n : {v1.branch() : None}, n2: {v2b.branch() : None}}) assert(troveDictMatches(d, [t_v1, t_v2, t2_v1b, t2_v2b])) d = s.getTroveVersionFlavors({n : {v1 : None, v2b : None}, n2 : {v2 : None, v1b : None}}) assert(troveDictMatches(d, [t_v1, t_v2b, t2_v2, t2_v1b]))
def testTroves(self, flavor=None): if flavor is None: flavor = deps.Flavor() store = self._connect() dirSet = set(['/etc', '/bin']) baseSet = set(['passwd', 'services', 'group', '1', '2', '3', 'distributed']) v10 = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10") branch = v10.branch() store.createTroveBranch("testtrove", branch) f1 = files.FileFromFilesystem("/etc/passwd", self.id1) f2 = files.FileFromFilesystem("/etc/services", self.id2) f3 = files.FileFromFilesystem("/etc/group", self.id3) # make a really huge dependency, thus a very large file stream req = deps.DependencySet() for x in xrange(10000): req.addDep(deps.SonameDependencies, deps.Dependency("libtest.so.%d" %x)) f3.requires.set(req) # make sure it's way too big for a blob in mysql assert(len(f3.freeze()) >= 50000) cl = changelog.ChangeLog("test", "*****@*****.**", """\ Some changes are good. Some changes are bad. Some changes just are. """) trv = trove.Trove('testcomp', v10, flavor, cl) trv.addFile(f1.pathId(), "/bin/1", v10, f1.fileId()) trv.addFile(f2.pathId(), "/bin/2", v10, f2.fileId()) trv.addFile(f3.pathId(), "/bin/3", v10, f3.fileId()) trv.addFile(self.id4, "/bin/distributed", v10, self.fid4) trv.troveInfo.size.set(1234) trv.troveInfo.sourceName.set('somesource') req = deps.DependencySet() req.addDep(deps.FileDependencies, deps.Dependency("/bin/bash")) req.addDep(deps.TroveDependencies, deps.Dependency("foo:runtime")) req.addDep(deps.SonameDependencies, deps.Dependency("libtest.so.1")) trv.setRequires(req) # this also lets us peek at the database to make sure libtest.so.1 # is only in the dep table once prv = deps.DependencySet() prv.addDep(deps.SonameDependencies, deps.Dependency("libtest.so.1")) trv.setProvides(prv) trv.computeDigests() store.db.transaction() store.addTroveSetStart([], dirSet, baseSet) troveInfo = store.addTrove(trv, trv.diff(None)[0]) troveInfo.addFile(f1.pathId(), "/bin/1", f1.fileId(), v10, fileStream = f1.freeze()) troveInfo.addFile(f2.pathId(), "/bin/2", f2.fileId(), v10, fileStream = f2.freeze()) troveInfo.addFile(f3.pathId(), "/bin/3", f3.fileId(), v10, fileStream = f3.freeze()) troveInfo.addFile(self.id4, "/bin/distributed", self.fid4, v10) store.addTroveDone(troveInfo) store.addTroveSetDone() store.db.commit() cu = store.db.cursor() cu.execute("SELECT count(*) FROM Dependencies WHERE " "name = 'libtest.so.1'") self.assertEqual(cu.next(), (1,)) # make sure the sha1s were stored cu.execute(""" SELECT dirname, basename, sha1 FROM TroveFiles JOIN FileStreams USING (streamId) JOIN FilePaths ON TroveFiles.filePathId = FilePaths.filePathId JOIN Dirnames ON FilePaths.dirnameId = Dirnames.dirnameId JOIN Basenames ON FilePaths.basenameId = Basenames.basenameId ORDER BY dirname,basename""") items = [(os.path.join(cu.frombinary(x[0]), cu.frombinary(x[1])), cu.frombinary(x[2])) for x in cu.fetchall()] self.assertEqual(items, [ ("/bin/1", f1.contents.sha1()), ("/bin/2", f2.contents.sha1()), ("/bin/3", f3.contents.sha1()), ("/bin/distributed", None) ]) cl = changelog.ChangeLog("test", "*****@*****.**", "another log\n") fromRepos = store.getTrove("testcomp", v10, flavor, cl) self.assertEqual(fromRepos, trv) self.assertEqual(fromRepos.getVersion().timeStamps(), trv.getVersion().timeStamps()) self.assertEqual(fromRepos.getChangeLog(), trv.getChangeLog()) self.assertEqual( [ x for x in store.getTrove("testcomp", v10, flavor, withFiles = False).iterFileList() ], [] ) l = store.iterFilesInTrove("testcomp", v10, flavor, sortByPath = True) l = [ x for x in l ] self.assertEqual(l, [ (f1.pathId(), "/bin/1", f1.fileId(), v10), (f2.pathId(), "/bin/2", f2.fileId(), v10), (f3.pathId(), "/bin/3", f3.fileId(), v10), (self.id4, "/bin/distributed", self.fid4, v10)]) cl = changelog.ChangeLog("test", "*****@*****.**", "log for testpkg\n") trv2 = trove.Trove("testpkg", v10, flavor, cl) trv2.addTrove(trv.getName(), v10, flavor) trv2.addTrove("weakref", v10, flavor, weakRef = True) trv2.computeDigests() store.addTroveSetStart([], dirSet, baseSet) troveInfo = store.addTrove(trv2, trv2.diff(None)[0]) store.addTroveDone(troveInfo) store.addTroveSetDone() self.assertEqual(store.getTrove("testpkg", v10, flavor), trv2) self.assertEqual( [ x for x in store.iterTroves([ ("testcomp", v10, flavor), ("testpkg", v10, flavor ) ]) ], [trv, trv2] ) self.assertEqual( [ x for x in store.iterTroves([ ("testpkg", v10, flavor ), ("testcomp", v10, flavor) ]) ], [trv2, trv] ) self.assertEqual( [ x for x in store.iterTroves([ ("testpkg", v10, flavor), ("testpkg", v10, flavor) ]) ], [trv2, trv2] ) self.assertEqual( [ x for x in store.iterTroves([ ("testpkg", v10, flavor ), ("blah", v10, flavor) ]) ], [trv2, None] ) self.assertEqual( [ x for x in store.iterTroves([ ("blah", v10, flavor ), ("testpkg", v10, flavor) ]) ], [None, trv2] ) self.assertEqual( [ x for x in store.iterTroves([ ("blah", v10, flavor ) ]) ], [None] ) self.assertEqual( [ x for x in store.iterTroves([ ("testcomp", v10, flavor), ("blah", v10, flavor ), ("testpkg", v10, flavor ) ]) ], [trv, None, trv2] ) # erasing doesn't work #store.eraseTrove("testcomp", v10, None) #store.commit() self.assertEqual(store.getTrove("testpkg", v10, flavor), trv2) map = { 'testpkg': [ v10 ]} flavors = store.getTroveFlavors(map) if flavor is not None: flavorStr = flavor.freeze() else: flavorStr = '' self.assertEqual(flavors, { 'testpkg': {v10: [flavorStr]}}) map = { 'testpkg3': [ v10 ]} flavors = store.getTroveFlavors(map) self.assertEqual(flavors, { 'testpkg3': {v10: []}}) # test getFiles fileObjs = store.getFiles([(f1.pathId(), f1.fileId()), (f2.pathId(), f2.fileId())]) self.assertEqual(fileObjs[(f1.pathId(), f1.fileId())], f1) self.assertEqual(fileObjs[(f2.pathId(), f2.fileId())], f2) # test that asking for an invalid fileid/pathid pair results # in no entry for the (pathid, fileid) in the returned dict invalidPathId = md5FromString('9' * 32) invalidFileId = sha1FromString('9' * 40) fileObjs = store.getFiles([(invalidPathId, invalidFileId)]) # make sure fileObjs is empty assert(not fileObjs) # test that asking for contents that have to come from # a different repository works - we should get None # back fileObjs = store.getFiles([(self.id4, self.fid4)]) self.assertEqual(fileObjs, {(self.id4, self.fid4): None})
def testRemoval(self): threshold = 60 * 5; # 5 minutes def _dbStatus(db): stat = {} cu = db.cursor() for table in db.tables: cu.execute("SELECT * FROM %s" % table) l = cu.fetchall() # throw away anything which looks a timestamp; this will # break if the test case takes more than 5 minutes to run stat[table] = set() for row in l: thisRow = [] for item in row: if not isinstance(item, (float, decimal.Decimal)) or \ abs(item - now) > threshold: thisRow.append(item) stat[table].add(tuple(thisRow)) return stat def _checkStateDiff(one, two): if one != two: assert(one.keys() == two.keys()) for key in one: if one[key] != two[key]: print "table %s has changed" % key raise AssertionError, "\n%s\n!=\n%s" % (one, two) store = self._connect() # get the current timestamp from the database cu = store.db.cursor() cu.execute('''create table timestamp( foo INTEGER, changed NUMERIC(14,0) NOT NULL DEFAULT 0)''') store.db.loadSchema() store.db.createTrigger('timestamp', 'changed', "INSERT") cu.execute('insert into timestamp values(0, 0)') cu.execute('select changed from timestamp') now = cu.fetchall()[0][0] emptyState = _dbStatus(store.db) v10 = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10") v20 = ThawVersion("/conary.rpath.com@test:trunk/20:1.2-20") vB = ThawVersion("/conary.rpath.com@test:branch/1:0-0") vOtherRepo = ThawVersion("/other.repos.com@some:label/1:0-0") branch = v10.branch() flavor = deps.parseFlavor('is:x86') flavor64 = deps.parseFlavor('is:x86_64') store.createTroveBranch("trv:comp", branch) f1 = files.FileFromFilesystem("/etc/passwd", self.id1) f2 = files.FileFromFilesystem("/etc/services", self.id2) # add a file that has no contents sha1 try: d = tempfile.mkdtemp() os.symlink('foo', d + '/foo') f5 = files.FileFromFilesystem(d + '/foo', self.id5) finally: shutil.rmtree(d) req = deps.parseDep("file: /bin/bash file: /bin/awk") dirNames = set(['/bin', '']) baseNames = set(['1', '2', 'distributed', 'foo', 'group-foo.recipe']) cl = changelog.ChangeLog("test", "*****@*****.**", "changelog\n") trv = trove.Trove('trv:comp', v10, flavor, cl) trv.addFile(f1.pathId(), "/bin/1", v10, f1.fileId()) trv.addFile(f2.pathId(), "/bin/2", v10, f2.fileId()) trv.addFile(self.id4, "/bin/distributed", v10, self.fid4) trv.addFile(f5.pathId(), "/bin/foo", v10, f5.fileId()) trv.troveInfo.size.set(1234) trv.setRequires(req) store.db.transaction() store.addTroveSetStart([], dirNames, baseNames) troveInfo = store.addTrove(trv, trv.diff(None)[0]) troveInfo.addFile(f1.pathId(), "/bin/1", f1.fileId(), v10, fileStream = f1.freeze()) troveInfo.addFile(f2.pathId(), "/bin/2", f2.fileId(), v10, fileStream = f2.freeze()) troveInfo.addFile(f5.pathId(), "/bin/foo", f5.fileId(), v10, fileStream = f5.freeze()) store.addTroveDone(troveInfo) store.addTroveSetDone() store.db.commit() oneTroveState = _dbStatus(store.db) rc = store._removeTrove("trv:comp", v10, flavor) self.assertEqual(set(rc), set([ f1.contents.sha1(), f2.contents.sha1() ])) state = _dbStatus(store.db) _checkStateDiff(state, emptyState) store.db.rollback() # the redir itself doesn't overlap with trv:comp; this makes sure # that the tables which the redir target needs are preserved redir = trove.Trove('redir:comp', vB, flavor64, cl, type = trove.TROVE_TYPE_REDIRECT) redir.addRedirect('trv:comp', v10.branch(), flavor) store.addTroveSetStart([], dirNames, baseNames) troveInfo = store.addTrove(redir, redir.diff(None)[0]) store.addTroveDone(troveInfo) store.addTroveSetDone() rc = store._removeTrove("trv:comp", v10, flavor) redir2 = store.getTrove('redir:comp', vB, flavor64) assert(redir == redir2) rc = store._removeTrove("redir:comp", vB, flavor64) state = _dbStatus(store.db) _checkStateDiff(state, emptyState) store.db.rollback() trv2 = trv.copy() trv2.changeVersion(v20) store.db.transaction() store.addTroveSetStart([], dirNames, baseNames) troveInfo = store.addTrove(trv2, trv2.diff(None)[0]) troveInfo.addFile(f1.pathId(), "/bin/1", f1.fileId(), v10, fileStream = f1.freeze()) troveInfo.addFile(f2.pathId(), "/bin/2", f2.fileId(), v10, fileStream = f2.freeze()) store.addTroveDone(troveInfo) store.addTroveSetDone() store.db.commit() twoTroveState = _dbStatus(store.db) rc = store._removeTrove("trv:comp", v20, flavor) assert(not rc) state = _dbStatus(store.db) _checkStateDiff(state, oneTroveState) rc = store._removeTrove("trv:comp", v10, flavor) assert(set(rc) == set([ f1.contents.sha1(), f2.contents.sha1() ])) state = _dbStatus(store.db) _checkStateDiff(state, emptyState) store.db.rollback() # add a trove which shares a file with trv:comp and make sure removing # it doesn't remove the sha1s (make sure the fileIds are different) anotherTrove = trove.Trove('another:comp', v10, flavor, cl) anotherF = f1.copy() anotherF.inode.owner.set('unowned') anotherTrove.addFile(f1.pathId(), "/bin/1", v10, anotherF.fileId()) store.addTroveSetStart([], dirNames, baseNames) troveInfo = store.addTrove(anotherTrove, anotherTrove.diff(None)[0]) troveInfo.addFile(f1.pathId(), "/bin/1", anotherF.fileId(), v10, fileStream = f1.freeze()) store.addTroveDone(troveInfo) rc = store._removeTrove("another:comp", v10, flavor) assert(not rc) state = _dbStatus(store.db) _checkStateDiff(state, twoTroveState) store.db.rollback() # now try just marking something as removed rc = store.markTroveRemoved("trv:comp", v20, flavor) assert(not rc) removedTrove = store.getTrove("trv:comp", v20, flavor) assert(removedTrove.type() == trove.TROVE_TYPE_REMOVED) rc = store.markTroveRemoved("trv:comp", v10, flavor) assert(set(rc) == set([ f1.contents.sha1(), f2.contents.sha1() ])) removedTrove = store.getTrove("trv:comp", v10, flavor) assert(removedTrove.type() == trove.TROVE_TYPE_REMOVED) store.db.rollback() # test removing group-*:source anotherTrove = trove.Trove('group-foo:source', v10, flavor, cl) anotherF = f1.copy() anotherF.inode.owner.set('unowned') anotherTrove.addFile(f1.pathId(), "group-foo.recipe", v10, anotherF.fileId()) troveInfo = store.addTrove(anotherTrove, anotherTrove.diff(None)[0]) troveInfo.addFile(f1.pathId(), "group-foo.recipe", anotherF.fileId(), v10, fileStream = anotherF.freeze()) store.addTroveDone(troveInfo) rc = store._removeTrove("group-foo:source", v10, flavor) assert(not rc) state = _dbStatus(store.db) _checkStateDiff(state, twoTroveState) store.db.rollback() groupTrove = trove.Trove('group-foo', v10, flavor, cl) groupTrove.addTrove('foo', vOtherRepo, flavor) troveInfo = store.addTrove(groupTrove, groupTrove.diff(None)[0]) store.addTroveDone(troveInfo) rc = store._removeTrove("group-foo", v10, flavor) state = _dbStatus(store.db) _checkStateDiff(state, twoTroveState) store.db.rollback()
def testMetadata(self): store = self._connect() emptyFlavor = deps.Flavor() v1 = ThawVersion("/conary.rpath.com@test:trunk/1:1-1") branch = v1.branch() store.createTroveBranch("testtrove", branch) md_v1_l = {"shortDesc": "Short Desc", "longDesc": "Long Desc", "url": ["url1", "url2"], "license": ["CPL", "GPL"], "category": ["cat1", "cat2"], "version": "/conary.rpath.com@test:trunk/1-1", "source": "local", "language": "C", } md_v1_fr_l = {"shortDesc": "French Short Desc", "longDesc": "French Long Desc", "url": ["url1", "url2"], "license": ["CPL", "GPL"], "category": ["cat1", "cat2"], "version": "/conary.rpath.com@test:trunk/1-1", "source": "local", "language": "fr", } md_v2_l = {"shortDesc": "Short Desc V2", "longDesc": "Long Desc V2", "url": ["url1v2"], "license": ["CPLv2", "GPLv2"], "category": ['cat1v2', 'cat2v2', 'cat3v2'], "version": "/conary.rpath.com@test:trunk/1-2", "source": "foo", "language": "C", } trv3 = trove.Trove("testpkg3", v1, emptyFlavor, None) branch = v1.branch() store.db.transaction() store.updateMetadata("testpkg3", branch, "Short Desc", "Long Desc", urls=['url1', 'url2'], categories=['cat1', 'cat2'], licenses=['GPL', 'CPL'], source="", language="C") store.updateMetadata("testpkg3", branch, "French Short Desc", "French Long Desc", [], [], [], "", "fr") store.db.commit() md_v1 = store.getMetadata("testpkg3", branch) md_v1_fr = store.getMetadata("testpkg3", branch, language="fr") self.assertEqual(md_v1.freeze(), md_v1_l) self.assertEqual(md_v1_fr.freeze(), md_v1_fr_l) v2 = ThawVersion("/conary.rpath.com@test:trunk/1:1-2") store.db.transaction() store.updateMetadata("testpkg3", branch, "Short Desc V2", "Long Desc V2", urls=['url1v2'], categories=['cat1v2', 'cat2v2', 'cat3v2'], licenses=['CPLv2', 'GPLv2'], source="foo", language="C") store.db.commit() md_v2 = store.getMetadata("testpkg3", branch) md_v1 = store.getMetadata("testpkg3", branch, version=v1) md_v1_fr = store.getMetadata("testpkg3", branch, version=v1, language="fr") self.assertEqual(md_v2.freeze(), md_v2_l) self.assertEqual(md_v1.freeze(), md_v1_l) self.assertEqual(md_v1_fr.freeze(), md_v1_fr_l)
def testVersion(self): self.assertRaises(ParseError, VersionFromString, '0.50.1') verStr = "/foo.com@spc:bar/1.000:1.2-3/bang.com@spc:branch/10.000:2.4-5" verStr2 = "/foo.com@spc:bar/1.000:1.2-3/bang.com@spc:branch/15.000:2.4-6" v = ThawVersion(verStr) assert (v.freeze() == verStr) assert (v.asString(VersionFromString("/foo.com@spc:bar")) == "1.2-3/bang.com@spc:branch/2.4-5") assert (v.timeStamps() == [1, 10]) v = v.copy() v.incrementSourceCount() assert (v.asString() == ThawVersion(verStr2).asString()) assert (v.getHost() == 'bang.com') # test that cPickle works on a Version object (the changeset cache # database pickles versions) vpickled = cPickle.dumps(v) vunpickled = cPickle.loads(vpickled) assert (vunpickled.asString() == v.asString()) v2 = VersionFromString( "/foo.com@spc:bar/1.2-3/bang.com@spc:branch/2.4-5", timeStamps=[1.000, 10.000]) assert (v2.freeze() == verStr) assert ([x.asString() for x in v2.iterLabels() ] == ['foo.com@spc:bar', 'bang.com@spc:branch']) last = v.trailingRevision() assert (last.asString() == "2.4-6") assert (not v.onLocalLabel()) assert (not v.isInLocalNamespace()) assert (not v.onEmergeLabel()) assert (not v.onLocalCookLabel()) assert (v2.getHost() == 'bang.com') assert (v.trailingLabel() == Label('bang.com@spc:branch')) branch = v.branch() assert (branch.getHost() == 'bang.com') strrep = branch.asString() assert (strrep == "/foo.com@spc:bar/1.2-3/bang.com@spc:branch") branch2 = VersionFromString(branch.asString()) assert (branch == branch2) frozen = branch.freeze() branch2 = ThawVersion(frozen) assert (branch2 == branch) newVer = branch2.createVersion(Revision("1.1-2")) assert (newVer.asString() == "/foo.com@spc:bar/1.2-3/bang.com@spc:branch/1.1-2") assert (not newVer.onLocalLabel()) assert (not newVer.isInLocalNamespace()) assert (not newVer.onEmergeLabel()) assert (not newVer.onLocalCookLabel()) assert (not newVer.isOnLocalHost()) assert (newVer.canonicalVersion() == newVer) assert (v.hasParentVersion()) parent = v.parentVersion() assert (not parent.hasParentVersion()) assert (parent.asString() == "/foo.com@spc:bar/1.2-3") # check emerge label emerge = parent.createBranch(EmergeLabel(), withVerRel=1) assert (emerge.getHost() == 'local') assert ( emerge.asString() == "/foo.com@spc:bar/1.2-3/local@local:EMERGE/3") assert (not emerge.onLocalLabel()) assert (emerge.onEmergeLabel()) assert (not emerge.onRollbackLabel()) assert (not emerge.onLocalCookLabel()) assert (emerge.isOnLocalHost()) assert (emerge.isInLocalNamespace()) # check local cook label cook = parent.createBranch(CookLabel(), withVerRel=1) assert (cook.asString() == "/foo.com@spc:bar/1.2-3/local@local:COOK/3") assert (not cook.onLocalLabel()) assert (not cook.onEmergeLabel()) assert (not cook.onRollbackLabel()) assert (cook.onLocalCookLabel()) assert (cook.isOnLocalHost()) assert (cook.isInLocalNamespace()) # check local rollback label branch2 = parent.createBranch(RollbackLabel(), withVerRel=1) assert (branch2.asString() == "/foo.com@spc:bar/1.2-3/local@local:ROLLBACK/3") assert (not branch2.onLocalLabel()) assert (not branch2.onEmergeLabel()) assert (branch2.onRollbackLabel()) assert (not branch2.onLocalCookLabel()) assert (branch2.isOnLocalHost()) assert (branch2.isInLocalNamespace()) # check local branch label branch2 = parent.createBranch(LocalLabel(), withVerRel=1) assert ( branch2.asString() == "/foo.com@spc:bar/1.2-3/local@local:LOCAL/3") assert (branch2.onLocalLabel()) assert (not branch2.onEmergeLabel()) assert (not branch2.onRollbackLabel()) assert (not branch2.onLocalCookLabel()) assert (branch2.isOnLocalHost()) assert (branch2.isInLocalNamespace()) branch3 = VersionFromString(branch2.asString()) assert (branch2 == branch3) branch2 = branch2.branch() assert ( branch2.asString() == "/foo.com@spc:bar/1.2-3/local@local:LOCAL") parent = v.parentVersion() assert (parent.asString() == "/foo.com@spc:bar/1.2-3") branch2 = parent.createBranch(LocalLabel()) assert ( branch2.asString() == "/foo.com@spc:bar/1.2-3/local@local:LOCAL") shadow = parent.branch().createShadow(Label('foo.com@spc:shadow')) assert (shadow.asString() == "/foo.com@spc:bar//shadow") assert (shadow.getHost() == 'foo.com') branch = VersionFromString("/foo.com@spc:bar") v = VersionFromString("1.2-3", branch) assert (v.asString() == "/foo.com@spc:bar/1.2-3") # test getBinaryVersion and getSourceVersion v = ThawVersion(verStr) b = v.getBinaryVersion() assert (b.asString() == "/foo.com@spc:bar/1.2-3-0/bang.com@spc:branch/2.4-5") # make sure slots are working v = ThawVersion("/foo.com@spec:bar/10:1.2-3") self.assertRaises(AttributeError, v.__setattr__, "foo", 1) v = ThawVersion(v.freeze()) self.assertRaises(AttributeError, v.__setattr__, "foo", 1) v = VersionFromString('/localhost@rpl:linux/1.0-1-0/' 'local@local:EMERGE/1/COOK/2') assert (VersionFromString(v.asString()) == v)
def testRemoval(self): threshold = 60 * 5 # 5 minutes def _dbStatus(db): stat = {} cu = db.cursor() for table in db.tables: cu.execute("SELECT * FROM %s" % table) l = cu.fetchall() # throw away anything which looks a timestamp; this will # break if the test case takes more than 5 minutes to run stat[table] = set() for row in l: thisRow = [] for item in row: if not isinstance(item, (float, decimal.Decimal)) or \ abs(item - now) > threshold: thisRow.append(item) stat[table].add(tuple(thisRow)) return stat def _checkStateDiff(one, two): if one != two: assert (one.keys() == two.keys()) for key in one: if one[key] != two[key]: print "table %s has changed" % key raise AssertionError, "\n%s\n!=\n%s" % (one, two) store = self._connect() # get the current timestamp from the database cu = store.db.cursor() cu.execute('''create table timestamp( foo INTEGER, changed NUMERIC(14,0) NOT NULL DEFAULT 0)''') store.db.loadSchema() store.db.createTrigger('timestamp', 'changed', "INSERT") cu.execute('insert into timestamp values(0, 0)') cu.execute('select changed from timestamp') now = cu.fetchall()[0][0] emptyState = _dbStatus(store.db) v10 = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10") v20 = ThawVersion("/conary.rpath.com@test:trunk/20:1.2-20") vB = ThawVersion("/conary.rpath.com@test:branch/1:0-0") vOtherRepo = ThawVersion("/other.repos.com@some:label/1:0-0") branch = v10.branch() flavor = deps.parseFlavor('is:x86') flavor64 = deps.parseFlavor('is:x86_64') store.createTroveBranch("trv:comp", branch) f1 = files.FileFromFilesystem("/etc/passwd", self.id1) f2 = files.FileFromFilesystem("/etc/services", self.id2) # add a file that has no contents sha1 try: d = tempfile.mkdtemp() os.symlink('foo', d + '/foo') f5 = files.FileFromFilesystem(d + '/foo', self.id5) finally: shutil.rmtree(d) req = deps.parseDep("file: /bin/bash file: /bin/awk") dirNames = set(['/bin', '']) baseNames = set(['1', '2', 'distributed', 'foo', 'group-foo.recipe']) cl = changelog.ChangeLog("test", "*****@*****.**", "changelog\n") trv = trove.Trove('trv:comp', v10, flavor, cl) trv.addFile(f1.pathId(), "/bin/1", v10, f1.fileId()) trv.addFile(f2.pathId(), "/bin/2", v10, f2.fileId()) trv.addFile(self.id4, "/bin/distributed", v10, self.fid4) trv.addFile(f5.pathId(), "/bin/foo", v10, f5.fileId()) trv.troveInfo.size.set(1234) trv.setRequires(req) store.db.transaction() store.addTroveSetStart([], dirNames, baseNames) troveInfo = store.addTrove(trv, trv.diff(None)[0]) troveInfo.addFile(f1.pathId(), "/bin/1", f1.fileId(), v10, fileStream=f1.freeze()) troveInfo.addFile(f2.pathId(), "/bin/2", f2.fileId(), v10, fileStream=f2.freeze()) troveInfo.addFile(f5.pathId(), "/bin/foo", f5.fileId(), v10, fileStream=f5.freeze()) store.addTroveDone(troveInfo) store.addTroveSetDone() store.db.commit() oneTroveState = _dbStatus(store.db) rc = store._removeTrove("trv:comp", v10, flavor) self.assertEqual(set(rc), set([f1.contents.sha1(), f2.contents.sha1()])) state = _dbStatus(store.db) _checkStateDiff(state, emptyState) store.db.rollback() # the redir itself doesn't overlap with trv:comp; this makes sure # that the tables which the redir target needs are preserved redir = trove.Trove('redir:comp', vB, flavor64, cl, type=trove.TROVE_TYPE_REDIRECT) redir.addRedirect('trv:comp', v10.branch(), flavor) store.addTroveSetStart([], dirNames, baseNames) troveInfo = store.addTrove(redir, redir.diff(None)[0]) store.addTroveDone(troveInfo) store.addTroveSetDone() rc = store._removeTrove("trv:comp", v10, flavor) redir2 = store.getTrove('redir:comp', vB, flavor64) assert (redir == redir2) rc = store._removeTrove("redir:comp", vB, flavor64) state = _dbStatus(store.db) _checkStateDiff(state, emptyState) store.db.rollback() trv2 = trv.copy() trv2.changeVersion(v20) store.db.transaction() store.addTroveSetStart([], dirNames, baseNames) troveInfo = store.addTrove(trv2, trv2.diff(None)[0]) troveInfo.addFile(f1.pathId(), "/bin/1", f1.fileId(), v10, fileStream=f1.freeze()) troveInfo.addFile(f2.pathId(), "/bin/2", f2.fileId(), v10, fileStream=f2.freeze()) store.addTroveDone(troveInfo) store.addTroveSetDone() store.db.commit() twoTroveState = _dbStatus(store.db) rc = store._removeTrove("trv:comp", v20, flavor) assert (not rc) state = _dbStatus(store.db) _checkStateDiff(state, oneTroveState) rc = store._removeTrove("trv:comp", v10, flavor) assert (set(rc) == set([f1.contents.sha1(), f2.contents.sha1()])) state = _dbStatus(store.db) _checkStateDiff(state, emptyState) store.db.rollback() # add a trove which shares a file with trv:comp and make sure removing # it doesn't remove the sha1s (make sure the fileIds are different) anotherTrove = trove.Trove('another:comp', v10, flavor, cl) anotherF = f1.copy() anotherF.inode.owner.set('unowned') anotherTrove.addFile(f1.pathId(), "/bin/1", v10, anotherF.fileId()) store.addTroveSetStart([], dirNames, baseNames) troveInfo = store.addTrove(anotherTrove, anotherTrove.diff(None)[0]) troveInfo.addFile(f1.pathId(), "/bin/1", anotherF.fileId(), v10, fileStream=f1.freeze()) store.addTroveDone(troveInfo) rc = store._removeTrove("another:comp", v10, flavor) assert (not rc) state = _dbStatus(store.db) _checkStateDiff(state, twoTroveState) store.db.rollback() # now try just marking something as removed rc = store.markTroveRemoved("trv:comp", v20, flavor) assert (not rc) removedTrove = store.getTrove("trv:comp", v20, flavor) assert (removedTrove.type() == trove.TROVE_TYPE_REMOVED) rc = store.markTroveRemoved("trv:comp", v10, flavor) assert (set(rc) == set([f1.contents.sha1(), f2.contents.sha1()])) removedTrove = store.getTrove("trv:comp", v10, flavor) assert (removedTrove.type() == trove.TROVE_TYPE_REMOVED) store.db.rollback() # test removing group-*:source anotherTrove = trove.Trove('group-foo:source', v10, flavor, cl) anotherF = f1.copy() anotherF.inode.owner.set('unowned') anotherTrove.addFile(f1.pathId(), "group-foo.recipe", v10, anotherF.fileId()) troveInfo = store.addTrove(anotherTrove, anotherTrove.diff(None)[0]) troveInfo.addFile(f1.pathId(), "group-foo.recipe", anotherF.fileId(), v10, fileStream=anotherF.freeze()) store.addTroveDone(troveInfo) rc = store._removeTrove("group-foo:source", v10, flavor) assert (not rc) state = _dbStatus(store.db) _checkStateDiff(state, twoTroveState) store.db.rollback() groupTrove = trove.Trove('group-foo', v10, flavor, cl) groupTrove.addTrove('foo', vOtherRepo, flavor) troveInfo = store.addTrove(groupTrove, groupTrove.diff(None)[0]) store.addTroveDone(troveInfo) rc = store._removeTrove("group-foo", v10, flavor) state = _dbStatus(store.db) _checkStateDiff(state, twoTroveState) store.db.rollback()
def testMetadata(self): store = self._connect() emptyFlavor = deps.Flavor() v1 = ThawVersion("/conary.rpath.com@test:trunk/1:1-1") branch = v1.branch() store.createTroveBranch("testtrove", branch) md_v1_l = { "shortDesc": "Short Desc", "longDesc": "Long Desc", "url": ["url1", "url2"], "license": ["CPL", "GPL"], "category": ["cat1", "cat2"], "version": "/conary.rpath.com@test:trunk/1-1", "source": "local", "language": "C", } md_v1_fr_l = { "shortDesc": "French Short Desc", "longDesc": "French Long Desc", "url": ["url1", "url2"], "license": ["CPL", "GPL"], "category": ["cat1", "cat2"], "version": "/conary.rpath.com@test:trunk/1-1", "source": "local", "language": "fr", } md_v2_l = { "shortDesc": "Short Desc V2", "longDesc": "Long Desc V2", "url": ["url1v2"], "license": ["CPLv2", "GPLv2"], "category": ['cat1v2', 'cat2v2', 'cat3v2'], "version": "/conary.rpath.com@test:trunk/1-2", "source": "foo", "language": "C", } trv3 = trove.Trove("testpkg3", v1, emptyFlavor, None) branch = v1.branch() store.db.transaction() store.updateMetadata("testpkg3", branch, "Short Desc", "Long Desc", urls=['url1', 'url2'], categories=['cat1', 'cat2'], licenses=['GPL', 'CPL'], source="", language="C") store.updateMetadata("testpkg3", branch, "French Short Desc", "French Long Desc", [], [], [], "", "fr") store.db.commit() md_v1 = store.getMetadata("testpkg3", branch) md_v1_fr = store.getMetadata("testpkg3", branch, language="fr") self.assertEqual(md_v1.freeze(), md_v1_l) self.assertEqual(md_v1_fr.freeze(), md_v1_fr_l) v2 = ThawVersion("/conary.rpath.com@test:trunk/1:1-2") store.db.transaction() store.updateMetadata("testpkg3", branch, "Short Desc V2", "Long Desc V2", urls=['url1v2'], categories=['cat1v2', 'cat2v2', 'cat3v2'], licenses=['CPLv2', 'GPLv2'], source="foo", language="C") store.db.commit() md_v2 = store.getMetadata("testpkg3", branch) md_v1 = store.getMetadata("testpkg3", branch, version=v1) md_v1_fr = store.getMetadata("testpkg3", branch, version=v1, language="fr") self.assertEqual(md_v2.freeze(), md_v2_l) self.assertEqual(md_v1.freeze(), md_v1_l) self.assertEqual(md_v1_fr.freeze(), md_v1_fr_l)
def testSqlVersioning(self): db = self.getDB() schema.createSchema(db) vTbl = versiontable.VersionTable(db) bTbl = versionops.BranchTable(db) sv = versionops.SqlVersioning(db, vTbl, bTbl) i = items.Items(db) # we need the FileStreams table for eraseVersion to work # properly. It is created as part of the createTroves() call v5 = ThawVersion("/conary.rpath.com@test:trunk/5:1.2-5") v10 = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10") v15 = ThawVersion("/conary.rpath.com@test:trunk/15:1.2-15") v20 = ThawVersion("/conary.rpath.com@test:trunk/20:1.2-20") branch = v10.branch() itemId = i.addId('foo') sv.createBranch(itemId, branch) sv.createVersion(itemId, v10, 0, "foo:source") assert(bTbl.has_key(branch)) assert(vTbl.has_key(v10)) assert(sv.hasVersion(itemId, vTbl[v10])) assert(i.has_key("foo:source")) assert(not sv.hasVersion(2, vTbl[v10])) branchId = bTbl[branch] itemId2 = i.addId('bar') sv.createBranch(itemId2, branch) sv.createVersion(itemId2, v10, 0, None) self.assertRaises(versionops.DuplicateVersionError, sv.createVersion, itemId2, v10, 0, None) assert([vTbl.getId(x) for x in sv.versionsOnBranch(1, branchId)] == [ str(v10) ]) sv.createVersion(1, v20, 0, None) assert([vTbl.getId(x) for x in sv.versionsOnBranch(1, branchId)] == [ str(v20), str(v10) ]) sv.createVersion(1, v15, 0, None) db.commit() assert([vTbl.getId(x) for x in sv.versionsOnBranch(1, branchId)] == [ str(v20), str(v15), str(v10) ]) sv.createVersion(1, v5, 0, None) assert([vTbl.getId(x) for x in sv.versionsOnBranch(1, branchId)] == [ str(v20), str(v15), str(v10), str(v5) ]) label = Label("conary.rpath.com@test:trunk") assert [bTbl.getId(x) for x in sv.branchesOfLabel(1, label) ]\ == [ branch ] brLabel = Label("conary.rpath.com@test:br1") branch1 = v10.createBranch(brLabel, withVerRel = False) branch2 = v20.createBranch(brLabel, withVerRel = False) sv.createBranch(1, branch1) sv.createBranch(1, branch2) assert([bTbl.getId(x) for x in sv.branchesOfLabel(1, brLabel)] == \ [branch1, branch2]) assert([bTbl.getId(x) for x in sv.branchesOfItem(1)] == [ branch, branch1, branch2 ])
def testVersion(self): self.assertRaises(ParseError, VersionFromString, "0.50.1") verStr = "/foo.com@spc:bar/1.000:1.2-3/bang.com@spc:branch/10.000:2.4-5" verStr2 = "/foo.com@spc:bar/1.000:1.2-3/bang.com@spc:branch/15.000:2.4-6" v = ThawVersion(verStr) assert v.freeze() == verStr assert v.asString(VersionFromString("/foo.com@spc:bar")) == "1.2-3/bang.com@spc:branch/2.4-5" assert v.timeStamps() == [1, 10] v = v.copy() v.incrementSourceCount() assert v.asString() == ThawVersion(verStr2).asString() assert v.getHost() == "bang.com" # test that cPickle works on a Version object (the changeset cache # database pickles versions) vpickled = cPickle.dumps(v) vunpickled = cPickle.loads(vpickled) assert vunpickled.asString() == v.asString() v2 = VersionFromString("/foo.com@spc:bar/1.2-3/bang.com@spc:branch/2.4-5", timeStamps=[1.000, 10.000]) assert v2.freeze() == verStr assert [x.asString() for x in v2.iterLabels()] == ["foo.com@spc:bar", "bang.com@spc:branch"] last = v.trailingRevision() assert last.asString() == "2.4-6" assert not v.onLocalLabel() assert not v.isInLocalNamespace() assert not v.onEmergeLabel() assert not v.onLocalCookLabel() assert v2.getHost() == "bang.com" assert v.trailingLabel() == Label("bang.com@spc:branch") branch = v.branch() assert branch.getHost() == "bang.com" strrep = branch.asString() assert strrep == "/foo.com@spc:bar/1.2-3/bang.com@spc:branch" branch2 = VersionFromString(branch.asString()) assert branch == branch2 frozen = branch.freeze() branch2 = ThawVersion(frozen) assert branch2 == branch newVer = branch2.createVersion(Revision("1.1-2")) assert newVer.asString() == "/foo.com@spc:bar/1.2-3/bang.com@spc:branch/1.1-2" assert not newVer.onLocalLabel() assert not newVer.isInLocalNamespace() assert not newVer.onEmergeLabel() assert not newVer.onLocalCookLabel() assert not newVer.isOnLocalHost() assert newVer.canonicalVersion() == newVer assert v.hasParentVersion() parent = v.parentVersion() assert not parent.hasParentVersion() assert parent.asString() == "/foo.com@spc:bar/1.2-3" # check emerge label emerge = parent.createBranch(EmergeLabel(), withVerRel=1) assert emerge.getHost() == "local" assert emerge.asString() == "/foo.com@spc:bar/1.2-3/local@local:EMERGE/3" assert not emerge.onLocalLabel() assert emerge.onEmergeLabel() assert not emerge.onRollbackLabel() assert not emerge.onLocalCookLabel() assert emerge.isOnLocalHost() assert emerge.isInLocalNamespace() # check local cook label cook = parent.createBranch(CookLabel(), withVerRel=1) assert cook.asString() == "/foo.com@spc:bar/1.2-3/local@local:COOK/3" assert not cook.onLocalLabel() assert not cook.onEmergeLabel() assert not cook.onRollbackLabel() assert cook.onLocalCookLabel() assert cook.isOnLocalHost() assert cook.isInLocalNamespace() # check local rollback label branch2 = parent.createBranch(RollbackLabel(), withVerRel=1) assert branch2.asString() == "/foo.com@spc:bar/1.2-3/local@local:ROLLBACK/3" assert not branch2.onLocalLabel() assert not branch2.onEmergeLabel() assert branch2.onRollbackLabel() assert not branch2.onLocalCookLabel() assert branch2.isOnLocalHost() assert branch2.isInLocalNamespace() # check local branch label branch2 = parent.createBranch(LocalLabel(), withVerRel=1) assert branch2.asString() == "/foo.com@spc:bar/1.2-3/local@local:LOCAL/3" assert branch2.onLocalLabel() assert not branch2.onEmergeLabel() assert not branch2.onRollbackLabel() assert not branch2.onLocalCookLabel() assert branch2.isOnLocalHost() assert branch2.isInLocalNamespace() branch3 = VersionFromString(branch2.asString()) assert branch2 == branch3 branch2 = branch2.branch() assert branch2.asString() == "/foo.com@spc:bar/1.2-3/local@local:LOCAL" parent = v.parentVersion() assert parent.asString() == "/foo.com@spc:bar/1.2-3" branch2 = parent.createBranch(LocalLabel()) assert branch2.asString() == "/foo.com@spc:bar/1.2-3/local@local:LOCAL" shadow = parent.branch().createShadow(Label("foo.com@spc:shadow")) assert shadow.asString() == "/foo.com@spc:bar//shadow" assert shadow.getHost() == "foo.com" branch = VersionFromString("/foo.com@spc:bar") v = VersionFromString("1.2-3", branch) assert v.asString() == "/foo.com@spc:bar/1.2-3" # test getBinaryVersion and getSourceVersion v = ThawVersion(verStr) b = v.getBinaryVersion() assert b.asString() == "/foo.com@spc:bar/1.2-3-0/bang.com@spc:branch/2.4-5" # make sure slots are working v = ThawVersion("/foo.com@spec:bar/10:1.2-3") self.assertRaises(AttributeError, v.__setattr__, "foo", 1) v = ThawVersion(v.freeze()) self.assertRaises(AttributeError, v.__setattr__, "foo", 1) v = VersionFromString("/localhost@rpl:linux/1.0-1-0/" "local@local:EMERGE/1/COOK/2") assert VersionFromString(v.asString()) == v
def testVersionMatching(self): v1 = ThawVersion('/localhost@rpl:devel/1:1.0-1-1') v2 = ThawVersion('/localhost@rpl:devel/2:2.0-1-1') v1b = ThawVersion('/localhost@rpl:branch/3:1.0-1-1') v2b = ThawVersion('/localhost@rpl:branch/4:2.0-1-1') nodeps = deps.parseFlavor('') s = SimplestFindTroveSource() n = 'test' n2 = 'test2' t_v1 = (n, v1, nodeps) t_v2 = (n, v2, nodeps) t_v1b = (n, v1b, nodeps) t_v2b = (n, v2b, nodeps) t2_v1 = (n2, v1, nodeps) t2_v2 = (n2, v2, nodeps) t2_v1b = (n2, v1b, nodeps) t2_v2b = (n2, v2b, nodeps) lbl_a = v1.branch().label() lbl_b = v1b.branch().label() s.addTroves(t_v1, t_v2, t_v1b, t_v2b, t2_v1, t2_v2, t2_v1b, t2_v2b) d = s.getTroveLeavesByLabel({n: {lbl_a: None}, n2: {lbl_b: None}}) assert (troveDictMatches(d, [t_v2, t2_v2b])) d = s.getTroveVersionsByLabel({n: {lbl_a: None}, n2: {lbl_b: None}}) assert (troveDictMatches(d, [t_v1, t_v2, t2_v2b, t2_v1b])) d = s.getTroveVersionsByLabel({n: {lbl_a: None, lbl_b: None}}) assert (troveDictMatches(d, [t_v1, t_v2, t_v1b, t_v2b])) d = s.getTroveLeavesByBranch({ n: { v1.branch(): None }, n2: { v2b.branch(): None } }) assert (troveDictMatches(d, [t_v2, t2_v2b])) d = s.getTroveVersionsByBranch({ n: { v1.branch(): None }, n2: { v2b.branch(): None } }) assert (troveDictMatches(d, [t_v1, t_v2, t2_v1b, t2_v2b])) d = s.getTroveVersionFlavors({ n: { v1: None, v2b: None }, n2: { v2: None, v1b: None } }) assert (troveDictMatches(d, [t_v1, t_v2b, t2_v2, t2_v1b]))
def testFlavorMatchingAsRepository(self): # presumes that version matches work # and just tests flavoring # uses repository style v1 = ThawVersion('/localhost@rpl:devel/1:1.0-1-1') v2 = ThawVersion('/localhost@rpl:devel/2:2.0-1-1') nodeps = deps.parseFlavor('') rl_nossl = deps.parseFlavor('readline,!ssl') rl_ssl = deps.parseFlavor('readline,ssl') norl_ssl = deps.parseFlavor('!readline,ssl') norl_nossl = deps.parseFlavor('!readline,!ssl') p_rl_nossl = deps.parseFlavor('~readline,~!ssl') p_rl_ssl = deps.parseFlavor('~readline,~ssl') p_norl_ssl = deps.parseFlavor('~!readline,~ssl') p_norl_nossl = deps.parseFlavor('~!readline,~!ssl') ssl = deps.parseFlavor('ssl') rl = deps.parseFlavor('readline') s = SimplestFindTroveSource() s.searchAsRepository() n = 'test:run' n2 = 'test2:run' t_v1_rl_nossl = (n, v1, rl_nossl) t_v1_norl_ssl = (n, v1, norl_ssl) t_v2_norl_nossl = (n, v2, norl_nossl) t_v2_rl_ssl = (n, v2, rl_ssl) lbl_a = v1.branch().label() s.addTroves(t_v1_rl_nossl, t_v1_norl_ssl, t_v2_norl_nossl, t_v2_rl_ssl) for trv in t_v1_rl_nossl, t_v1_norl_ssl, t_v2_norl_nossl, t_v2_rl_ssl: self.addComponent(*trv) repos = self.openRepository() assert (s.hasTroves([t_v1_rl_nossl])[0]) for src in s, repos: d = s.getTroveLeavesByLabel({n: {lbl_a: [rl_nossl]}}) assert (troveDictMatches(d, [t_v1_rl_nossl])) # if you specify flavors, and bestFlavor is False you all # allowed flavors back, not just the best match. In this # case ~rl, does not match !readline, so we only get the rl,ssl # trove returned d = src.getTroveLeavesByLabel({n: { lbl_a: [p_rl_nossl] }}, bestFlavor=False) assert (troveDictMatches(d, [t_v2_rl_ssl, t_v1_rl_nossl])) d = src.getTroveLeavesByLabel({n: { lbl_a: [rl_nossl, rl_ssl] }}, bestFlavor=True) assert (troveDictMatches(d, [t_v1_rl_nossl, t_v2_rl_ssl])) d = src.getTroveLeavesByLabel({n: { lbl_a: [nodeps] }}, bestFlavor=True) assert (troveDictMatches(d, [t_v2_norl_nossl])) d = src.getTroveLeavesByLabel({n: {lbl_a: [ssl]}}, bestFlavor=True) assert (troveDictMatches(d, [t_v1_norl_ssl])) d = src.getTroveLeavesByLabel({n: { lbl_a: [p_norl_ssl] }}, bestFlavor=True) assert (troveDictMatches(d, [t_v2_rl_ssl])) s.searchAsDatabase() # with database, only strong flavors are allowed, so only the # rl_nossl trove matches even with bestFlavor = False d = s.getTroveLeavesByLabel({n: { lbl_a: [p_rl_nossl] }}, bestFlavor=False) assert (troveDictMatches(d, [t_v1_rl_nossl])) # same w/ by database d = s.getTroveLeavesByLabel({n: {lbl_a: [rl_nossl, rl_ssl]}}) assert (troveDictMatches(d, [t_v1_rl_nossl, t_v2_rl_ssl])) d = s.getTroveLeavesByLabel({n: {lbl_a: [nodeps]}}) # either of these are acceptable -- both flavors score the same # against nodeps. assert (troveDictMatches(d, [t_v2_norl_nossl]) or troveDictMatches(d, [t_v2_rl_ssl])) # different w/ by database - partial match is good enough d = s.getTroveLeavesByLabel({n: {lbl_a: [ssl]}}) assert (troveDictMatches(d, [t_v2_rl_ssl])) # different w/ by database - partial match is good enough d = s.getTroveLeavesByLabel({n: {lbl_a: [rl]}}) assert (troveDictMatches(d, [t_v2_rl_ssl])) # different w/ by database - strong flavor means ~!rl must match # an entry with either !rl or ~!rl, cannot match rl d = s.getTroveLeavesByLabel({n: {lbl_a: [p_norl_ssl]}}) assert (troveDictMatches(d, [t_v1_norl_ssl]))
def testFlavorMatchingAsRepository(self): # presumes that version matches work # and just tests flavoring # uses repository style v1 = ThawVersion('/localhost@rpl:devel/1:1.0-1-1') v2 = ThawVersion('/localhost@rpl:devel/2:2.0-1-1') nodeps = deps.parseFlavor('') rl_nossl = deps.parseFlavor('readline,!ssl') rl_ssl = deps.parseFlavor('readline,ssl') norl_ssl = deps.parseFlavor('!readline,ssl') norl_nossl = deps.parseFlavor('!readline,!ssl') p_rl_nossl = deps.parseFlavor('~readline,~!ssl') p_rl_ssl = deps.parseFlavor('~readline,~ssl') p_norl_ssl = deps.parseFlavor('~!readline,~ssl') p_norl_nossl = deps.parseFlavor('~!readline,~!ssl') ssl = deps.parseFlavor('ssl') rl = deps.parseFlavor('readline') s = SimplestFindTroveSource() s.searchAsRepository() n = 'test:run' n2 = 'test2:run' t_v1_rl_nossl = (n, v1, rl_nossl) t_v1_norl_ssl = (n, v1, norl_ssl) t_v2_norl_nossl = (n, v2, norl_nossl) t_v2_rl_ssl = (n, v2, rl_ssl) lbl_a = v1.branch().label() s.addTroves(t_v1_rl_nossl, t_v1_norl_ssl, t_v2_norl_nossl, t_v2_rl_ssl) for trv in t_v1_rl_nossl, t_v1_norl_ssl, t_v2_norl_nossl, t_v2_rl_ssl: self.addComponent(*trv) repos = self.openRepository() assert(s.hasTroves([t_v1_rl_nossl])[0]) for src in s, repos: d = s.getTroveLeavesByLabel({n : {lbl_a : [rl_nossl]}}) assert(troveDictMatches(d, [t_v1_rl_nossl])) # if you specify flavors, and bestFlavor is False you all # allowed flavors back, not just the best match. In this # case ~rl, does not match !readline, so we only get the rl,ssl # trove returned d = src.getTroveLeavesByLabel({n : {lbl_a : [p_rl_nossl]}}, bestFlavor=False) assert(troveDictMatches(d, [t_v2_rl_ssl, t_v1_rl_nossl])) d = src.getTroveLeavesByLabel({n : {lbl_a : [rl_nossl, rl_ssl]}}, bestFlavor=True) assert(troveDictMatches(d, [t_v1_rl_nossl, t_v2_rl_ssl])) d = src.getTroveLeavesByLabel({n : {lbl_a : [nodeps]}}, bestFlavor=True) assert(troveDictMatches(d, [t_v2_norl_nossl])) d = src.getTroveLeavesByLabel({n : {lbl_a : [ssl]}}, bestFlavor=True) assert(troveDictMatches(d, [t_v1_norl_ssl])) d = src.getTroveLeavesByLabel({n : {lbl_a : [p_norl_ssl]}}, bestFlavor=True) assert(troveDictMatches(d, [t_v2_rl_ssl])) s.searchAsDatabase() # with database, only strong flavors are allowed, so only the # rl_nossl trove matches even with bestFlavor = False d = s.getTroveLeavesByLabel({n : {lbl_a : [p_rl_nossl]}}, bestFlavor=False) assert(troveDictMatches(d, [t_v1_rl_nossl])) # same w/ by database d = s.getTroveLeavesByLabel({n : {lbl_a : [rl_nossl, rl_ssl]}}) assert(troveDictMatches(d, [t_v1_rl_nossl, t_v2_rl_ssl])) d = s.getTroveLeavesByLabel({n : {lbl_a : [nodeps]}}) # either of these are acceptable -- both flavors score the same # against nodeps. assert(troveDictMatches(d, [t_v2_norl_nossl]) or troveDictMatches(d, [t_v2_rl_ssl])) # different w/ by database - partial match is good enough d = s.getTroveLeavesByLabel({n : {lbl_a : [ssl]}}) assert(troveDictMatches(d, [t_v2_rl_ssl])) # different w/ by database - partial match is good enough d = s.getTroveLeavesByLabel({n : {lbl_a : [rl]}}) assert(troveDictMatches(d, [t_v2_rl_ssl])) # different w/ by database - strong flavor means ~!rl must match # an entry with either !rl or ~!rl, cannot match rl d = s.getTroveLeavesByLabel({n : {lbl_a : [p_norl_ssl]}}) assert(troveDictMatches(d, [t_v1_norl_ssl]))
def testTroves(self, flavor=None): if flavor is None: flavor = deps.Flavor() store = self._connect() dirSet = set(['/etc', '/bin']) baseSet = set( ['passwd', 'services', 'group', '1', '2', '3', 'distributed']) v10 = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10") branch = v10.branch() store.createTroveBranch("testtrove", branch) f1 = files.FileFromFilesystem("/etc/passwd", self.id1) f2 = files.FileFromFilesystem("/etc/services", self.id2) f3 = files.FileFromFilesystem("/etc/group", self.id3) # make a really huge dependency, thus a very large file stream req = deps.DependencySet() for x in xrange(10000): req.addDep(deps.SonameDependencies, deps.Dependency("libtest.so.%d" % x)) f3.requires.set(req) # make sure it's way too big for a blob in mysql assert (len(f3.freeze()) >= 50000) cl = changelog.ChangeLog( "test", "*****@*****.**", """\ Some changes are good. Some changes are bad. Some changes just are. """) trv = trove.Trove('testcomp', v10, flavor, cl) trv.addFile(f1.pathId(), "/bin/1", v10, f1.fileId()) trv.addFile(f2.pathId(), "/bin/2", v10, f2.fileId()) trv.addFile(f3.pathId(), "/bin/3", v10, f3.fileId()) trv.addFile(self.id4, "/bin/distributed", v10, self.fid4) trv.troveInfo.size.set(1234) trv.troveInfo.sourceName.set('somesource') req = deps.DependencySet() req.addDep(deps.FileDependencies, deps.Dependency("/bin/bash")) req.addDep(deps.TroveDependencies, deps.Dependency("foo:runtime")) req.addDep(deps.SonameDependencies, deps.Dependency("libtest.so.1")) trv.setRequires(req) # this also lets us peek at the database to make sure libtest.so.1 # is only in the dep table once prv = deps.DependencySet() prv.addDep(deps.SonameDependencies, deps.Dependency("libtest.so.1")) trv.setProvides(prv) trv.computeDigests() store.db.transaction() store.addTroveSetStart([], dirSet, baseSet) troveInfo = store.addTrove(trv, trv.diff(None)[0]) troveInfo.addFile(f1.pathId(), "/bin/1", f1.fileId(), v10, fileStream=f1.freeze()) troveInfo.addFile(f2.pathId(), "/bin/2", f2.fileId(), v10, fileStream=f2.freeze()) troveInfo.addFile(f3.pathId(), "/bin/3", f3.fileId(), v10, fileStream=f3.freeze()) troveInfo.addFile(self.id4, "/bin/distributed", self.fid4, v10) store.addTroveDone(troveInfo) store.addTroveSetDone() store.db.commit() cu = store.db.cursor() cu.execute("SELECT count(*) FROM Dependencies WHERE " "name = 'libtest.so.1'") self.assertEqual(cu.next(), (1, )) # make sure the sha1s were stored cu.execute(""" SELECT dirname, basename, sha1 FROM TroveFiles JOIN FileStreams USING (streamId) JOIN FilePaths ON TroveFiles.filePathId = FilePaths.filePathId JOIN Dirnames ON FilePaths.dirnameId = Dirnames.dirnameId JOIN Basenames ON FilePaths.basenameId = Basenames.basenameId ORDER BY dirname,basename""") items = [(os.path.join(cu.frombinary(x[0]), cu.frombinary(x[1])), cu.frombinary(x[2])) for x in cu.fetchall()] self.assertEqual(items, [("/bin/1", f1.contents.sha1()), ("/bin/2", f2.contents.sha1()), ("/bin/3", f3.contents.sha1()), ("/bin/distributed", None)]) cl = changelog.ChangeLog("test", "*****@*****.**", "another log\n") fromRepos = store.getTrove("testcomp", v10, flavor, cl) self.assertEqual(fromRepos, trv) self.assertEqual(fromRepos.getVersion().timeStamps(), trv.getVersion().timeStamps()) self.assertEqual(fromRepos.getChangeLog(), trv.getChangeLog()) self.assertEqual([ x for x in store.getTrove("testcomp", v10, flavor, withFiles=False).iterFileList() ], []) l = store.iterFilesInTrove("testcomp", v10, flavor, sortByPath=True) l = [x for x in l] self.assertEqual(l, [(f1.pathId(), "/bin/1", f1.fileId(), v10), (f2.pathId(), "/bin/2", f2.fileId(), v10), (f3.pathId(), "/bin/3", f3.fileId(), v10), (self.id4, "/bin/distributed", self.fid4, v10)]) cl = changelog.ChangeLog("test", "*****@*****.**", "log for testpkg\n") trv2 = trove.Trove("testpkg", v10, flavor, cl) trv2.addTrove(trv.getName(), v10, flavor) trv2.addTrove("weakref", v10, flavor, weakRef=True) trv2.computeDigests() store.addTroveSetStart([], dirSet, baseSet) troveInfo = store.addTrove(trv2, trv2.diff(None)[0]) store.addTroveDone(troveInfo) store.addTroveSetDone() self.assertEqual(store.getTrove("testpkg", v10, flavor), trv2) self.assertEqual([ x for x in store.iterTroves([("testcomp", v10, flavor), ("testpkg", v10, flavor)]) ], [trv, trv2]) self.assertEqual([ x for x in store.iterTroves([("testpkg", v10, flavor), ("testcomp", v10, flavor)]) ], [trv2, trv]) self.assertEqual([ x for x in store.iterTroves([("testpkg", v10, flavor), ("testpkg", v10, flavor)]) ], [trv2, trv2]) self.assertEqual([ x for x in store.iterTroves([("testpkg", v10, flavor), ("blah", v10, flavor)]) ], [trv2, None]) self.assertEqual([ x for x in store.iterTroves([("blah", v10, flavor), ("testpkg", v10, flavor)]) ], [None, trv2]) self.assertEqual( [x for x in store.iterTroves([("blah", v10, flavor)])], [None]) self.assertEqual([ x for x in store.iterTroves([( "testcomp", v10, flavor), ("blah", v10, flavor), ("testpkg", v10, flavor)]) ], [trv, None, trv2]) # erasing doesn't work #store.eraseTrove("testcomp", v10, None) #store.commit() self.assertEqual(store.getTrove("testpkg", v10, flavor), trv2) map = {'testpkg': [v10]} flavors = store.getTroveFlavors(map) if flavor is not None: flavorStr = flavor.freeze() else: flavorStr = '' self.assertEqual(flavors, {'testpkg': {v10: [flavorStr]}}) map = {'testpkg3': [v10]} flavors = store.getTroveFlavors(map) self.assertEqual(flavors, {'testpkg3': {v10: []}}) # test getFiles fileObjs = store.getFiles([(f1.pathId(), f1.fileId()), (f2.pathId(), f2.fileId())]) self.assertEqual(fileObjs[(f1.pathId(), f1.fileId())], f1) self.assertEqual(fileObjs[(f2.pathId(), f2.fileId())], f2) # test that asking for an invalid fileid/pathid pair results # in no entry for the (pathid, fileid) in the returned dict invalidPathId = md5FromString('9' * 32) invalidFileId = sha1FromString('9' * 40) fileObjs = store.getFiles([(invalidPathId, invalidFileId)]) # make sure fileObjs is empty assert (not fileObjs) # test that asking for contents that have to come from # a different repository works - we should get None # back fileObjs = store.getFiles([(self.id4, self.fid4)]) self.assertEqual(fileObjs, {(self.id4, self.fid4): None})
def testSqlVersioning(self): db = self.getDB() schema.createSchema(db) vTbl = versiontable.VersionTable(db) bTbl = versionops.BranchTable(db) sv = versionops.SqlVersioning(db, vTbl, bTbl) i = items.Items(db) # we need the FileStreams table for eraseVersion to work # properly. It is created as part of the createTroves() call v5 = ThawVersion("/conary.rpath.com@test:trunk/5:1.2-5") v10 = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10") v15 = ThawVersion("/conary.rpath.com@test:trunk/15:1.2-15") v20 = ThawVersion("/conary.rpath.com@test:trunk/20:1.2-20") branch = v10.branch() itemId = i.addId('foo') sv.createBranch(itemId, branch) sv.createVersion(itemId, v10, 0, "foo:source") assert (bTbl.has_key(branch)) assert (vTbl.has_key(v10)) assert (sv.hasVersion(itemId, vTbl[v10])) assert (i.has_key("foo:source")) assert (not sv.hasVersion(2, vTbl[v10])) branchId = bTbl[branch] itemId2 = i.addId('bar') sv.createBranch(itemId2, branch) sv.createVersion(itemId2, v10, 0, None) self.assertRaises(versionops.DuplicateVersionError, sv.createVersion, itemId2, v10, 0, None) assert ([vTbl.getId(x) for x in sv.versionsOnBranch(1, branchId)] == [str(v10)]) sv.createVersion(1, v20, 0, None) assert ([vTbl.getId(x) for x in sv.versionsOnBranch(1, branchId) ] == [str(v20), str(v10)]) sv.createVersion(1, v15, 0, None) db.commit() assert ([vTbl.getId(x) for x in sv.versionsOnBranch(1, branchId) ] == [str(v20), str(v15), str(v10)]) sv.createVersion(1, v5, 0, None) assert ([vTbl.getId(x) for x in sv.versionsOnBranch(1, branchId) ] == [str(v20), str(v15), str(v10), str(v5)]) label = Label("conary.rpath.com@test:trunk") assert [bTbl.getId(x) for x in sv.branchesOfLabel(1, label) ]\ == [ branch ] brLabel = Label("conary.rpath.com@test:br1") branch1 = v10.createBranch(brLabel, withVerRel=False) branch2 = v20.createBranch(brLabel, withVerRel=False) sv.createBranch(1, branch1) sv.createBranch(1, branch2) assert([bTbl.getId(x) for x in sv.branchesOfLabel(1, brLabel)] == \ [branch1, branch2]) assert ([bTbl.getId(x) for x in sv.branchesOfItem(1)] == [branch, branch1, branch2])