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 testGetSourceVersion(self): v = VersionFromString( '/conary.rpath.com@rpl:linux/4.3-1-0/autconf213/1') assert (not v.isBranchedBinary()) source = v.getSourceVersion() assert (not source.isBranchedBinary()) assert (source.asString() == '/conary.rpath.com@rpl:linux/4.3-1/autconf213/1') # binary branched v = VersionFromString( '/conary.rpath.com@rpl:linux/4.3-1-1/autconf213/1') assert (v.isBranchedBinary()) source = v.getSourceVersion() assert (not source.isBranchedBinary()) assert (source.asString() == '/conary.rpath.com@rpl:linux/4.3-1') # make sure timestamps are removed v = ThawVersion('/conary.rpath.com@rpl:linux/1:4.3-1-0/autconf213/2:1') source = v.getSourceVersion() assert (source.timeStamps() == [0, 0]) v = ThawVersion('/conary.rpath.com@rpl:linux/1:4.3-1-1/autconf213/2:1') source = v.getSourceVersion() assert (source.timeStamps() == [0])
def testFindTrove(self): db = database.Database(':memory:', ':memory:') self.assertEqual(db.getTransactionCounter(), 0) flavor = deps.parseFlavor('~readline,!foo') v10 = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10-1") f1 = files.FileFromFilesystem("/etc/passwd", self.id1) trv = trove.Trove("testcomp", v10, flavor, None) trv.addFile(self.id1, "/bin/1", v10, f1.fileId()) trvInfo = db.addTrove(trv) db.addTroveDone(trvInfo) f2 = files.FileFromFilesystem("/etc/group", self.id2) v20 = ThawVersion("/conary.rpath.com@local:blah/20:1.3-2-1") trv = trove.Trove("testcomp", v20, flavor, None) trv.addFile(self.id2, "/bin/2", v20, f2.fileId()) trvInfo = db.addTrove(trv) db.addTroveDone(trvInfo) tup = [('testcomp', v10, flavor)] tup2 = [('testcomp', v10, flavor), ('testcomp', v20, flavor)] assert (db.findTrove(None, ('testcomp', '1.2-10-1', None)) == tup) assert (db.findTrove(None, ('testcomp', '1.2', None)) == tup) assert (set(db.findTrove( None, ('testcomp', None, parseFlavor('!foo')))) == set(tup2)) assert (db.findTrove(None, ('testcomp', ':trunk', None)) == tup) assert (db.findTrove([Label('conary.rpath.com@test:foo')], ('testcomp', ':trunk', None)) == tup) assert (db.findTrove(None, ('testcomp', ':trunk', None)) == tup) assert (db.findTrove(None, ('testcomp', '@test:trunk', None)) == tup) assert (db.findTrove([Label('conary.rpath.com@blah:foo')], ('testcomp', '@test:trunk', None)) == tup) # Transaction counter changes upon commit self.assertEqual(db.getTransactionCounter(), 0) db.commit() self.assertEqual(db.getTransactionCounter(), 1)
def testVersionCache(self): versions.thawedVersionCache.clear() assert (not versions.thawedVersionCache) # test the thawed version cache verStr = "/foo.com@spc:bar/1:1.2-3/bang.com@spc:branch/2:2.4-5" v1 = ThawVersion(verStr) v2 = ThawVersion(verStr) assert (id(v1) == id(v2)) assert (len(versions.thawedVersionCache) == 1) del v1 assert (len(versions.thawedVersionCache) == 1) del v2 assert (not versions.thawedVersionCache) versions.stringVersionCache.clear() v1 = VersionFromString("/foo.com@spc:bar/1.2-3") v2 = VersionFromString("/foo.com@spc:bar/1.2-3", timeStamps=[1.000]) v3 = VersionFromString("/foo.com@spc:bar/1.2-3") v4 = VersionFromString("/foo.com@spc:bar/1.2-3") assert (v1.timeStamps() == [0]) assert (v2.timeStamps() == [1]) assert (id(v1) != id(v2)) assert (id(v2) != id(v3)) assert (id(v1) == id(v3)) assert (id(v3) == id(v4))
def testHidden(self): store = self._connect() cu = store.db.cursor() flavor = deps.Flavor() version = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10") f = files.FileFromFilesystem("/etc/passwd", self.id) trv = trove.Trove("junk:data", version, flavor, None) trv.computeDigests() store.addTroveSetStart([], set(['/etc']), set(['passwd'])) ti = store.addTrove(trv, trv.diff(None)[0], hidden=True) store.addTroveDone(ti) store.addTroveSetDone() assert (cu.execute("select count(*) from latestcache").fetchall()[0][0] == 0) assert (cu.execute("select isPresent from instances").fetchall()[0][0] == instances.INSTANCE_PRESENT_HIDDEN) store.presentHiddenTroves() assert (cu.execute("select count(*) from latestcache").fetchall()[0][0] == 3) assert (cu.execute("select isPresent from instances").fetchall()[0][0] == instances.INSTANCE_PRESENT_NORMAL)
def testFindTrovesNotAcrossLabels(self): # Even when acrossLabels is false, if the trove source is not # ordered, don't discriminate by label path. # This may result in odd results but it is really the only sane # thing to do. v = ThawVersion('/localhost@rpl:linux/1:1.0-1-1') v2 = ThawVersion('/localhost@rpl:branch/2:1.0-1-1') ts = SimpleTroveSource([('a:run', v, deps.parseFlavor('')), ('a:run', v2, deps.parseFlavor(''))]) queries = [('a:run', None, None), ('a:run', '1.0', None), ('a:run', '1.0-1-1', None), ('a:run', 'localhost@', None)] for q in queries: results = ts.findTroves(None, [q], deps.parseFlavor(''), acrossLabels=False) assert (len(results[q]) == 2)
def testMassiveIterTroves(self): store = self._connect() infoList = [] expected = [] f = deps.parseFlavor('is:x86') v = ThawVersion('/conary.rpath.com@test:trunk/10:1-1') # add 2000 test components store.addTroveSetStart([], [], []) for x in xrange(500): n = 'test%d:runtime' % x t = trove.Trove(n, v, f, None) t.computeDigests() troveInfo = store.addTrove(t, t.diff(None)[0]) store.addTroveDone(troveInfo) # we want to iterTroves for each of our components (which # ends up being a no-op) infoList.append((n, v, f)) expected.append(t) store.addTroveSetDone() start = time.time() result = [x for x in store.iterTroves(infoList)] end = time.time() # make sure we got the expected results assert (result == expected) # we should be able to iter through all of these troves in # well under one seconds if end - start > 5: sys.stderr.write("\nWarning: testMassiveIterTroves: test ran in " "%.3f seconds, expected < 5\n\n" % (end - start))
def testCommonFiles(self): # this test simulates a trove having the ame file in different # path locations with only changed mtimes. store = self._connect() flavor = deps.Flavor() version = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10") baseNames = set(['file']) dirNames = set(['/junk1', '/junk2']) f = files.FileFromFilesystem("/etc/passwd", self.id) trv = trove.Trove("junk:data", version, flavor, None) trv.addFile(self.id1, "/junk1/file", version, f.fileId()) trv.addFile(self.id2, "/junk2/file", version, f.fileId()) trv.computeDigests() store.db.transaction() store.addTroveSetStart([], dirNames, baseNames) ti = store.addTrove(trv, trv.diff(None)[0]) f.inode.mtime.set(1) ti.addFile(self.id1, "/junk1/file", f.fileId(), version, fileStream=f.freeze()) f.inode.mtime.set(2) ti.addFile(self.id2, "/junk2/file", f.fileId(), version, fileStream=f.freeze()) store.addTroveDone(ti) store.commit()
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 testSort(self): lst = [] for i in range(1, 10): lst.append( ThawVersion("/foo.com@spc:bar/%d:1.0-%d" % ((10 - i), i))) # as time goes forward, source count #s go down # sorting is by timestamp only, so version with lowest timestamp # should be first in resulting list lst.sort() for i in range(1, 10): assert (lst[i - 1].freeze() == "/foo.com@spc:bar/%d.000:1.0-%d" % (i, (10 - i)))
def testTroveMultiFlavor(self): # create a package with 3 components, each use a different use # flag. add the package before the components. the goal is # to make the trovestore create more than one flavor flags = ('foo', 'bar', 'baz') flavors = [] for flag in flags: flavor = deps.Flavor() flavor.addDep( deps.UseDependency, deps.Dependency('use', [(flag, deps.FLAG_SENSE_REQUIRED)])) flavor.addDep(deps.InstructionSetDependency, deps.Dependency('x86', [])) flavors.append(flavor) v10 = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10") store = self._connect() # create components to add to the package troves = [] for flag, flavor in zip(flags, flavors): trv = trove.Trove('test:%s' % flag, v10, flavor, None) trv.computeDigests() troves.append(trv) # add the package union = deps.Flavor() for flavor in flavors: union.union(flavor) trv2 = trove.Trove("test", v10, union, None) for trv in troves: trv2.addTrove(trv.getName(), v10, trv2.getFlavor()) trv2.computeDigests() store.addTroveSetStart([], [], []) troveInfo = store.addTrove(trv2, trv2.diff(None)[0]) store.addTroveDone(troveInfo) store.addTroveSetDone() # add the troves store.addTroveSetStart([], [], []) for trv in troves: troveInfo = store.addTrove(trv, trv.diff(None)[0]) store.addTroveDone(troveInfo) store.addTroveSetDone() for trv in troves: self.assertEqual( trv, store.getTrove(trv.getName(), trv.getVersion(), trv.getFlavor())) troveFlavors = store.getTroveFlavors({'test': [v10]}) self.assertEqual(troveFlavors['test'][v10], [union.freeze()])
def testVersionCache(self): versions.thawedVersionCache.clear() assert not versions.thawedVersionCache # test the thawed version cache verStr = "/foo.com@spc:bar/1:1.2-3/bang.com@spc:branch/2:2.4-5" v1 = ThawVersion(verStr) v2 = ThawVersion(verStr) assert id(v1) == id(v2) assert len(versions.thawedVersionCache) == 1 del v1 assert len(versions.thawedVersionCache) == 1 del v2 assert not versions.thawedVersionCache versions.stringVersionCache.clear() v1 = VersionFromString("/foo.com@spc:bar/1.2-3") v2 = VersionFromString("/foo.com@spc:bar/1.2-3", timeStamps=[1.000]) v3 = VersionFromString("/foo.com@spc:bar/1.2-3") v4 = VersionFromString("/foo.com@spc:bar/1.2-3") assert v1.timeStamps() == [0] assert v2.timeStamps() == [1] assert id(v1) != id(v2) assert id(v2) != id(v3) assert id(v1) == id(v3) assert id(v3) == id(v4)
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 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 testBrokenPackage(self): store = self._connect() v10 = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10") v20 = ThawVersion("/conary.rpath.com@test:trunk/20:1.2-20") flavor = deps.Flavor() flavor2 = deps.parseFlavor('is:x86') trv = trove.Trove("testpkg", v10, flavor, None) trv.addTrove("testpkg:runtime", v20, flavor) trv.computeDigests() store.addTroveSetStart([], [], []) troveInfo = store.addTrove(trv, trv.diff(None)[0]) self.assertRaises(AssertionError, store.addTroveDone, troveInfo) store.rollback() trv = trove.Trove("testpkg", v10, flavor, None) trv.addTrove("testpkg:runtime", v10, flavor2) trv.computeDigests() troveInfo = store.addTrove(trv, trv.diff(None)[0]) self.assertRaises(AssertionError, store.addTroveDone, troveInfo)
def testDuplicateStreams(self): store = self._connect() flavor = deps.Flavor() v10 = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10") v20 = ThawVersion("/conary.rpath.com@test:trunk/20:1.2-20") dirNames = set(['/bin', '/etc']) baseNames = set(['1', '2']) f1 = files.FileFromFilesystem("/etc/passwd", self.id1) trv = trove.Trove("testpkg:runtime", v10, flavor, None) trv.addFile(f1.pathId(), "/bin/1", v10, f1.fileId()) trv.computeDigests() store.db.transaction() store.addTroveSetStart([], dirNames, baseNames) troveInfo = store.addTrove(trv, trv.diff(None)[0]) troveInfo.addFile(f1.pathId(), "/bin/1", f1.fileId(), v10) store.addTroveDone(troveInfo) store.addTroveSetDone() store.db.commit() trv = trove.Trove("testpkg:runtime", v20, flavor, None) trv.addFile(f1.pathId(), "/bin/1", v20, f1.fileId()) trv.addFile(f1.pathId(), "/bin/2", v20, f1.fileId()) trv.computeDigests() store.db.transaction() store.addTroveSetStart([], dirNames, baseNames) troveInfo = store.addTrove(trv, trv.diff(None)[0]) troveInfo.addFile(f1.pathId(), "/bin/1", f1.fileId(), v10) troveInfo.addFile(f1.pathId(), "/bin/2", f1.fileId(), v10) store.addTroveDone(troveInfo) store.db.commit()
def testParenthood(self): v = ThawVersion("/foo.com@spc:bar/123.0:1.2-3/branch/456:1.1-2") assert (v.hasParentVersion()) parentVersion = v.parentVersion() assert (parentVersion.asString() == "/foo.com@spc:bar/1.2-3") assert (parentVersion.trailingRevision().timeStamp == 123) v = ThawVersion( '/conary.rpath.com@rpl:devel//1//rpl-live.rb.rpath.com@rpl:1//local@local:COOK/123:1.0.1-0.6' ) assert (v.hasParentVersion()) parentVersion = v.parentVersion() assert ( parentVersion.asString() == '/conary.rpath.com@rpl:devel//1//rpl-live.rb.rpath.com@rpl:1/1.0.1-0.6' ) assert (parentVersion.trailingRevision().timeStamp == 0)
def testParenthood(self): v = ThawVersion("/foo.com@spc:bar/123.0:1.2-3/branch/456:1.1-2") assert v.hasParentVersion() parentVersion = v.parentVersion() assert parentVersion.asString() == "/foo.com@spc:bar/1.2-3" assert parentVersion.trailingRevision().timeStamp == 123 v = ThawVersion("/conary.rpath.com@rpl:devel//1//rpl-live.rb.rpath.com@rpl:1//local@local:COOK/123:1.0.1-0.6") assert v.hasParentVersion() parentVersion = v.parentVersion() assert parentVersion.asString() == "/conary.rpath.com@rpl:devel//1//rpl-live.rb.rpath.com@rpl:1/1.0.1-0.6" assert parentVersion.trailingRevision().timeStamp == 0
def testNodesTable(self): db = self.getDB() schema.createSchema(db) b = versionops.BranchTable(db) v = versiontable.VersionTable(db) i = items.Items(db) sv = versionops.SqlVersioning(db, v, b) ver = ThawVersion("/a.b.c@d:e/1:1-1-1") itemId = i.getOrAddId("foo") nodeId, versionId = sv.createVersion(itemId, ver, 0, None) cu = db.cursor() cu.execute("select sourceItemId from Nodes where nodeId = ?", nodeId) self.assertEqual(cu.fetchall()[0][0], None) srcId = i.getOrAddId("foo:source") sv.nodes.updateSourceItemId(nodeId, srcId) cu.execute("select sourceItemId from Nodes where nodeId = ?", nodeId) self.assertEqual(cu.fetchall()[0][0], srcId)
def testRemoved(self): store = self._connect() old = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-3") x86 = deps.parseFlavor("is:x86") removed = trove.Trove("trvname", old, x86, None, type=trove.TROVE_TYPE_REMOVED) removed.computeDigests() store.addTroveSetStart([], [], []) troveInfo = store.addTrove(removed, removed.diff(None)[0]) store.addTroveDone(troveInfo) store.addTroveSetDone() assert (store.getTrove("trvname", old, x86) == removed)
def testDuplicatePaths(self): store = self._connect() v10 = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10") flavor1 = deps.Flavor() flavor2 = deps.parseFlavor('is:x86') cl = changelog.ChangeLog("test", "*****@*****.**", "Changes\n") f1 = files.FileFromFilesystem("/etc/passwd", self.id1) trv1 = trove.Trove('testcomp', v10, flavor1, cl) trv1.addFile(f1.pathId(), "/bin/1", v10, f1.fileId()) trv2 = trove.Trove('testcomp', v10, flavor2, cl) trv2.addFile(f1.pathId(), "/bin/1", v10, f1.fileId()) store.db.transaction() store.addTroveSetStart([], set(['/bin']), set(['1'])) troveInfo = store.addTrove(trv1, trv1.diff(None)[0]) troveInfo.addFile(f1.pathId(), "/bin/1", f1.fileId(), v10, fileStream=f1.freeze()) store.addTroveDone(troveInfo) troveInfo = store.addTrove(trv2, trv2.diff(None)[0]) troveInfo.addFile(f1.pathId(), "/bin/1", f1.fileId(), v10, fileStream=f1.freeze()) store.addTroveDone(troveInfo) store.addTroveSetDone() store.db.commit() # make sure the path was inserted into FilePaths and friends once cu = store.db.cursor() for tbl in ['FilePaths', 'Dirnames', 'Basenames']: cu.execute("select count(*) from %s" % tbl) self.assertEquals(cu.next()[0], 1)
def testServerErrors(self): # try to get the repository to raise the errors from this class # by doing Bad Things. repos = self.openRepository() # add a pkg diff t = trove.Trove('foo', ThawVersion('/localhost@rpl:1/1.0:1.0-1-1'), deps.parseFlavor('~!foo'), None) # create an absolute changeset cs = changeset.ChangeSet() cs.newTrove(t.diff(None)[0]) try: repos.commitChangeSet(cs) except errors.TroveChecksumMissing, err: assert ( str(err) == 'Checksum Missing Error: Trove foo=/localhost@rpl:1/1.0-1-1[~!foo] has no sha1 checksum calculated, so it was rejected. Please upgrade conary.' )
def testTroveSourceStack(self): # Test the behaviour of TroveSourceStack instances s1 = SimplestFindTroveSource() s2 = SimplestFindTroveSource() s3 = SimplestFindTroveSource() nodeps = deps.parseFlavor('') count = 3 names = [] versions = [] for v in range(count): sv = str(v + 1) versions.append(ThawVersion('/localhost@rpl:devel/%s:1.0-1-1' % sv)) names.append("test%s" % sv) # Generate troves t = [] for i in range(count): l = [] t.append(l) name = names[i] for j in range(count): l.append((name, versions[j], nodeps)) s1.addTroves(t[0][1]) s2.addTroves(t[0][0], t[1][1]) s3.addTroves(t[0][2], t[1][0], t[2][2]) # Catch an early bug with a bad index try: ts1 = stack(s1) except Exception, e: # No exception expected self.fail("Caught exception: %s" % e)
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()
class SqlDB(rephelp.RepositoryHelper): id1 = md5FromString("00010001000100010001000100010001") id2 = md5FromString("00010001000100010001000100010002") id3 = md5FromString("00010001000100010001000100010003") id4 = md5FromString("00010001000100010001000100010004") id7 = md5FromString("00010001000100010001000100010007") fid1 = sha1FromString("0001000100010001000100010001000100010001") fid2 = sha1FromString("0001000100010001000100010001000100010002") fid3 = sha1FromString("0001000100010001000100010001000100010003") fid4 = sha1FromString("0001000100010001000100010001000100010004") fid7 = sha1FromString("0001000100010001000100010001000100010007") v10 = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10") v20 = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-20") emptyFlavor = deps.Flavor() noneTup = (None, None, None) def testPins(self): def _checkPins(*args): assert (db.trovesArePinned(troves) == list(args)) x86Flavor = deps.parseFlavor('is:x86(cmov)') troves = [("first", self.v10, self.emptyFlavor), ("second", self.v20, self.emptyFlavor), ("third", self.v10, x86Flavor)] db = sqldb.Database(':memory:') for name, ver, flavor in troves: ti = db.addTrove(trove.Trove(name, ver, flavor, None)) db.addTroveDone(ti) _checkPins(False, False, False) checks = [False] * 3 for i in range(len(troves)): checks[i] = True db.pinTroves(*troves[i]) _checkPins(*checks) for i in reversed(range(len(troves))): checks[i] = False db.pinTroves(*troves[i] + (False, )) _checkPins(*checks) def testIterAllTroves(self): trv1 = self.addComponent('foo:lib', '1') trv2 = self.addComponent('foo:debuginfo', '1') trv3 = self.addCollection('foo', '1', [':lib', (':debuginfo', False)]) trv4 = self.addComponent('bar:run', '1', 'bam', filePrimer=1) self.updatePkg(['foo', 'bar:run[bam]']) db = self.openDatabase() assert (set(db.iterAllTroves()) == set(x.getNameVersionFlavor() for x in [trv1, trv3, trv4])) def testDBInstances(self): cx = dbstore.connect(":memory:", driver="sqlite") cx.loadSchema() idb = sqldb.DBInstanceTable(cx) idb.addId('fred', 1, 2, [1, 2]) assert (idb[('fred', 1, 2)] == 1) assert (idb.getId(1) == ('fred', 1, 2, 1)) assert (idb.get(('fred', 1, 2), None) == 1) idb.addId('wilma', 5, 6, [1, 2]) assert (idb[('wilma', 5, 6)] == 2) idb.delId(2) self.assertRaises(KeyError, idb.__getitem__, ('wilma', 5, 6)) idb.delId(1) assert (idb.get(('fred', 1, 2), None) == None) def testDBTroveFiles(self): cx = dbstore.connect(":memory:", driver="sqlite") cx.loadSchema() fs = sqldb.DBTroveFiles(cx) cu = cx.cursor() fs.addItem(cu, self.id1, 1, "/bin/ls", self.fid1, 11, "abc", ["tag1", "tag2"]) fs.addItem(cu, self.id2, 2, "/bin/cat", self.fid2, 11, "def", ["tag1"]) fs.addItem(cu, self.id3, 1, "/bin/dd", self.fid3, 12, "tuv", []) fs.addItem(cu, self.id4, 2, "/bin/bc", self.fid4, 12, "xyz", []) assert ([x for x in fs[11]] == [("/bin/ls", "abc"), ("/bin/cat", "def")]) assert ([x for x in fs[12]] == [("/bin/dd", "tuv"), ("/bin/bc", "xyz")]) assert ([x for x in fs.iterFilesWithTag('tag1') ] == ['/bin/cat', '/bin/ls']) assert ([x for x in fs.iterFilesWithTag('tag2')] == ['/bin/ls']) fs.delInstance(11) assert ([x for x in fs[11]] == []) # make sure the tags are gone assert ([x for x in fs.iterFilesWithTag('tag1')] == []) cu = cx.cursor() cu.execute('select * from DBFileTags') assert ([x for x in cu] == []) assert (fs.getFileByFileId(self.fid3, 0) == ("/bin/dd", "tuv")) self.assertRaises(KeyError, fs.getFileByFileId, self.fid7, 0) assert ([x for x in fs[12]] == [("/bin/dd", "tuv"), ("/bin/bc", "xyz")]) fs.removePath(12, "/bin/dd") assert ([x for x in fs.getByInstanceId(12)] == [("/bin/bc", "xyz")]) assert (fs.getFileByFileId(self.fid4, justPresent=False) == ('/bin/bc', 'xyz')) assert ([x for x in fs.getByInstanceId(12, justPresent=False) ] == [("/bin/dd", "tuv"), ("/bin/bc", "xyz")]) fs.delInstance(12) fs.addItem(cu, self.id1, 1, "/bin/ls", self.fid1, 11, "abc", []) fs.addItem(cu, self.id2, 2, "/bin/cat", self.fid2, 11, "def", []) fs.addItem(cu, self.id3, 1, "/bin/dd", self.fid3, 11, "tuv", []) fs.addItem(cu, self.id4, 2, "/bin/bc", self.fid4, 11, "xyz", []) assert ([x for x in fs[11]] == [("/bin/ls", "abc"), ("/bin/cat", "def"), ("/bin/dd", "tuv"), ("/bin/bc", "xyz")]) def testDatabase1(self): db = sqldb.Database(':memory:') f1 = files.FileFromFilesystem("/etc/passwd", self.id1) f2 = files.FileFromFilesystem("/etc/services", self.id2) f3 = files.FileFromFilesystem("/etc/group", self.id3) trv = trove.Trove("testcomp", self.v10, self.emptyFlavor, None) trv.addFile(self.id1, "/bin/1", self.v10, f1.fileId()) trv.addFile(self.id2, "/bin/2", self.v10, f2.fileId()) trv.addFile(self.id3, "/bin/3", self.v10, f3.fileId()) trv.troveInfo.size.set(1234) trv.troveInfo.sourceName.set('thesource') 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) trvInfo = db.addTrove(trv) db.addFile(trvInfo, f1.pathId(), "/bin/1", f1.fileId(), self.v10, fileStream=f1.freeze()) db.addFile(trvInfo, f2.pathId(), "/bin/2", f2.fileId(), self.v10, fileStream=f2.freeze()) db.addFile(trvInfo, f3.pathId(), "/bin/3", f3.fileId(), self.v10, fileStream=f3.freeze()) db.addTroveDone(trvInfo) dbTrv = db.getTroves([("testcomp", self.v10, self.emptyFlavor)])[0] assert (dbTrv == trv) assert (dbTrv.__class__ == trove.Trove) assert (db.trovesArePinned([("testcomp", self.v10, self.emptyFlavor) ]) == [False]) dbTrv = db.getTroves([("testcomp", self.v10, self.emptyFlavor)], withFileObjects=True)[0] assert (dbTrv == trv) assert (dbTrv.__class__ == trove.TroveWithFileObjects) for f in (f1, f2, f3): assert (dbTrv.getFileObject(f.fileId()) == f) trv2 = trove.Trove("testpkg", self.v10, self.emptyFlavor, None) ti = trv2.addTrove(trv.getName(), self.v10, trv.getFlavor()) trv2.addTrove("weakref", self.v10, trv.getFlavor(), weakRef=True) ti = db.addTrove(trv2, pin=True) db.addTroveDone(ti) assert (db.trovesArePinned([("testpkg", self.v10, self.emptyFlavor) ]) == [True]) assert (db.getTroves([("testpkg", self.v10, self.emptyFlavor) ])[0] == trv2) assert (db.getTroves([ ("testpkg", self.v10, self.emptyFlavor) ])[0].getVersion().timeStamps() == trv2.getVersion().timeStamps()) assert (db.getTroves([("testpkg", self.v10, self.emptyFlavor), ("testcomp", self.v10, self.emptyFlavor), ("testitem", self.v10, self.emptyFlavor)], True) == [trv2, trv, None]) assert (db.getTroves([("testpkg", self.v10, self.emptyFlavor), ("testcomp", self.v10, req)], True) == [trv2, None]) assert (db.findTroveContainers(["testpkg", "testcomp"]) == [[], [("testpkg", self.v10, self.emptyFlavor)]]) assert (db.getTroveContainers([ ("testpkg", self.v10, self.emptyFlavor), ("testcomp", self.v10, self.emptyFlavor) ]) == [[], [("testpkg", self.v10, self.emptyFlavor)]]) res = db.findTroveReferences(["testpkg", "testcomp"]) assert (db.findTroveReferences(["testpkg", "testcomp" ]) == [[], [("testcomp", self.v10, self.emptyFlavor)]]) v10new = VersionFromString("/conary.rpath.com@test:trunk/1.2-10") assert (db.getTroves([("testpkg", v10new, self.emptyFlavor) ])[0] == trv2) assert (db.getTroves([ ("testpkg", v10new, self.emptyFlavor) ])[0].getVersion().timeStamps() == trv2.getVersion().timeStamps()) assert (set(db.findByNames(['testpkg', 'testcomp'])) == set([ ("testpkg", self.v10, self.emptyFlavor), ("testcomp", self.v10, self.emptyFlavor) ])) db.eraseTrove("testcomp", self.v10, None) assert (db.getTroves([("testpkg", self.v10, self.emptyFlavor) ])[0] == trv2) trv.computePathHashes() trvInfo = db.addTrove(trv) db.addFile(trvInfo, f1.pathId(), "/bin/1", f1.fileId(), self.v10, fileStream=f1.freeze()) db.addFile(trvInfo, f2.pathId(), "/bin/2", f2.fileId(), self.v10, fileStream=f1.freeze()) db.addFile(trvInfo, f3.pathId(), "/bin/3", f3.fileId(), self.v10, fileStream=f1.freeze()) db.addTroveDone(trvInfo) assert (db.getTroves([("testcomp", self.v10, self.emptyFlavor) ])[0] == trv) db.removeFileFromTrove(trv, "/bin/1") changedTrv = db.getTroves([trv.getNameVersionFlavor()], pristine=False)[0] otherChangedTrv = db.getTroves([trv.getNameVersionFlavor()], withFiles=False, pristine=False)[0] assert (len(changedTrv.idMap) + 1 == len(trv.idMap)) assert (len(changedTrv.troveInfo.pathHashes) + 1 == len( trv.troveInfo.pathHashes)) assert (changedTrv.troveInfo.pathHashes == otherChangedTrv.troveInfo.pathHashes) assert (len(otherChangedTrv.idMap) == 0) changedTrv.addFile(self.id1, "/bin/1", self.v10, f1.fileId()) assert (changedTrv.idMap == trv.idMap) changedTrv.computePathHashes() assert (changedTrv.troveInfo.pathHashes == trv.troveInfo.pathHashes) assert (db.getTroves([("testcomp", self.v10, self.emptyFlavor)], pristine=True)[0] == trv) db.eraseTrove("testpkg", self.v10, None) assert (db.getTroves([("testpkg", self.v10, self.emptyFlavor) ]) == [None]) self.assertRaises(KeyError, db.instances.getVersion, 100) db.eraseTrove("testcomp", self.v10, None) db.commit() cu = db.db.cursor() # make sure the versions got removed; the None entry is still there cu.execute("SELECT count(*) FROM Versions") assert (cu.next()[0] == 1) # make sure the dependency table got cleaned up cu.execute("SELECT count(*) FROM Dependencies") assert (cu.next()[0] == 0) # make sure the instances table got cleaned up cu.execute("SELECT count(*) FROM Instances") assert (cu.next()[0] == 0) # make sure the troveInfo table got cleaned up cu.execute("SELECT count(*) FROM TroveInfo") assert (cu.next()[0] == 0) def testDatabase2(self): db = sqldb.Database(':memory:') f1 = files.FileFromFilesystem("/etc/passwd", self.id1) f2 = files.FileFromFilesystem("/etc/services", self.id2) f3 = files.FileFromFilesystem("/etc/group", self.id3) trv = trove.Trove("testcomp", self.v10, self.emptyFlavor, None) trv.addFile(self.id1, "/bin/1", self.v10, f1.fileId()) trv.addFile(self.id2, "/bin/2", self.v10, f2.fileId()) trv.addFile(self.id3, "/bin/3", self.v10, f3.fileId()) trvInfo = db.addTrove(trv) db.addFile(trvInfo, f1.pathId(), "/bin/1", f1.fileId(), self.v10, fileStream=f1.freeze()) db.addFile(trvInfo, f2.pathId(), "/bin/2", f2.fileId(), self.v10, fileStream=f2.freeze()) db.addFile(trvInfo, f3.pathId(), "/bin/3", f3.fileId(), self.v10, fileStream=f3.freeze()) db.addTroveDone(trvInfo) assert (db.getTroves([("testcomp", self.v10, self.emptyFlavor), ("testcomp", self.v20, self.emptyFlavor)], True) == [trv, None]) assert (db.hasTroves([("testcomp", self.v10, self.emptyFlavor), ("testcomp", self.v20, self.emptyFlavor) ]) == [True, False]) f2 = files.FileFromFilesystem("/etc/hosts", self.id2) trv2 = trove.Trove("testcomp", self.v20, self.emptyFlavor, None) trv2.addFile(self.id1, "/bin/1", self.v10, self.fid1) trv2.addFile(self.id2, "/bin/2", self.v20, self.fid2) #trvInfo = db.addTrove(trv2) #db.addFile(trvInfo, f2.pathId(), f2, "/bin/2", self.v20) #assert(db.getTrove("testcomp", self.v20, None) == trv2) def testDatabaseTransactionCounter(self): db = sqldb.Database(':memory:') field = 'transaction counter' # We should have a row cu = db.db.cursor() cu.execute("SELECT value FROM DatabaseAttributes WHERE name = ?", field) row = cu.next() self.assertEqual(row[0], '0') updateq = "UPDATE DatabaseAttributes SET value = ? WHERE name = ?" # Update it manually cu.execute(updateq, '10', field) db.db.commit() self.assertEqual(db.getTransactionCounter(), 10) # Increment it self.assertEqual(db.incrementTransactionCounter(), 11) self.assertEqual(db.getTransactionCounter(), 11) # Delete entry, should reset the counter cu.execute("DELETE from DatabaseAttributes WHERE name = ?", field) db.db.commit() self.assertEqual(db.getTransactionCounter(), 0) self.assertEqual(db.incrementTransactionCounter(), 1) self.assertEqual(db.getTransactionCounter(), 1) self.assertEqual(db.incrementTransactionCounter(), 2) self.assertEqual(db.getTransactionCounter(), 2) # Mess it up cu.execute(updateq, 'not an integer', field) self.assertEqual(db.getTransactionCounter(), 0) self.assertEqual(db.incrementTransactionCounter(), 1) self.assertEqual(db.getTransactionCounter(), 1) def testDatabaseTroveInfoCleanup(self): # remove a trove but leave a reference - its troveInfo data # should be removed flavor1 = deps.parseFlavor('is:x86(cmov)') db = sqldb.Database(':memory:') trv1 = trove.Trove("testcomp:runtime", self.v10, flavor1, None) trvInfo = db.addTrove(trv1) db.addTroveDone(trvInfo) trv2 = trove.Trove("testcomp", self.v10, flavor1, None) trv2.addTrove(*trv1.getNameVersionFlavor()) trvInfo = db.addTrove(trv2) db.addTroveDone(trvInfo) db.commit() db.eraseTrove("testcomp:runtime", self.v10, flavor1) db.commit() cu = db.db.cursor() cu.execute('select count(*) from instances join troveInfo ' 'using(instanceId) where troveName="testcomp:runtime"') assert (not cu.fetchall()[0][0]) def testDatabaseVersionCleanup(self): flavor1 = deps.parseFlavor('is:x86(cmov)') db = sqldb.Database(':memory:') cu = db.db.cursor() v10 = ThawVersion('/conary.rpath.com@test:trunk/10:1.2-10') v20 = ThawVersion('/conary.rpath.com@test:trunk/10:1.2-20') v30 = ThawVersion('/conary.rpath.com@test:trunk/10:1.2-30') # test file version cleanup trv = trove.Trove('testcomp:runtime', v10, flavor1, None) f1 = files.FileFromFilesystem('/etc/passwd', self.id1) f2 = files.FileFromFilesystem('/etc/services', self.id2) f3 = files.FileFromFilesystem('/etc/group', self.id3) trv.addFile(self.id1, '/bin/1', v10, f1.fileId()) trv.addFile(self.id2, '/bin/2', v20, f2.fileId()) trv.addFile(self.id3, '/bin/3', v30, f3.fileId()) trvInfo = db.addTrove(trv) db.addFile(trvInfo, f1.pathId(), '/bin/1', f1.fileId(), v10, fileStream=f1.freeze()) db.addFile(trvInfo, f2.pathId(), '/bin/2', f2.fileId(), v20, fileStream=f2.freeze()) db.addFile(trvInfo, f3.pathId(), '/bin/3', f3.fileId(), v30, fileStream=f3.freeze()) db.addTroveDone(trvInfo) # check to see how many versions we have cu.execute('select count(*) from Versions') count = cu.fetchall()[0][0] # should have only 0|NULL self.assertEqual(count, 4) # now erase db.eraseTrove('testcomp:runtime', v10, flavor1) db.commit() cu.execute('select count(*) from Versions') count = cu.fetchall()[0][0] # should have only 0|NULL self.assertEqual(count, 1) # test trove version cleanup trv1 = trove.Trove('testcomp:runtime', v10, flavor1, None) trv2 = trove.Trove('group-test', v20, flavor1, None) trv2.addTrove(trv1.getName(), trv1.getVersion(), trv1.getFlavor(), weakRef=True) trvInfo = db.addTrove(trv2) db.addTroveDone(trvInfo) db.commit() cu.execute('select count(*) from Versions') count = cu.fetchall()[0][0] self.assertEqual(count, 3) db.eraseTrove('group-test', v20, flavor1) db.commit() cu.execute('select count(*) from Versions') count = cu.fetchall()[0][0] # should have only 0|NULL self.assertEqual(count, 1) def testMultipleFlavorsInstalled(self): """ verify that only one (unique) flavor is returned from db.iterVersionByName if multiple troves with the same version but different flavors are installed at the same time """ db = sqldb.Database(':memory:') flavor1 = deps.parseFlavor('is:x86(cmov)') flavor2 = deps.parseFlavor('is:x86(sse)') trv1 = trove.Trove("testcomp", self.v10, flavor1, None) trv2 = trove.Trove("testcomp", self.v10, flavor2, None) ti = db.addTrove(trv1) db.addTroveDone(ti) ti = db.addTrove(trv2) db.addTroveDone(ti) assert ([x for x in db.iterVersionByName('testcomp', False) ] == [self.v10]) assert ([x for x in db.iterVersionByName('testcomp', True) ] == [(self.v10, flavor1), (self.v10, flavor2)]) def testGroupMissingComponent(self): flavor1 = deps.parseFlavor('is:x86(cmov)') db = sqldb.Database(':memory:') trv1 = trove.Trove("group1", self.v10, flavor1, None) ti = trv1.addTrove("subcomp", self.v10, flavor1) ti = trv1.addTrove("subcomp2", self.v10, flavor1) ti = trv1.addTrove("subcomp3", self.v10, flavor1, weakRef=True) ti = db.addTrove(trv1) db.addTroveDone(ti) trv2 = trove.Trove("group2", self.v10, flavor1, None) trv2.addTrove("subcomp", self.v10, flavor1, weakRef=True) ti = db.addTrove(trv2) db.addTroveDone(ti) trv3 = trove.Trove("subcomp2", self.v10, flavor1, None) ti = db.addTrove(trv3) db.addTroveDone(ti) inst, instRefed, strongMissing, weakMissing = db.getCompleteTroveSet( ["group1", "subcomp", "subcomp2", "subcomp3"]) assert (inst == set([("group1", self.v10, flavor1)])) # this ensures the version returns has timestamps on it assert ([x for x in inst][0][1].freeze()) assert (strongMissing == set([("subcomp", self.v10, flavor1)])) assert (weakMissing == set([("subcomp3", self.v10, flavor1)])) assert (instRefed == set([("subcomp2", self.v10, flavor1)])) def testVersion2Migration(self): dbfile = os.path.join(resources.get_archive(), 'conarydbs', 'conarydb-version-2') fd, fn = tempfile.mkstemp() os.close(fd) shutil.copyfile(dbfile, fn) db, str = self.captureOutput(sqldb.Database, fn) cu = db.db.cursor() # make sure that the -*none*- entry has been added cu.execute( 'select count(*) from provides join dependencies on provides.depid=dependencies.depid and name="sqlite:lib" and flag="-*none*-"' ) assert (cu.next() == (1, )) db.close() os.unlink(fn) def testVersion3Migration(self): dbfile = os.path.join(resources.get_archive(), 'conarydbs', 'conarydb-version-3') fd, fn = tempfile.mkstemp() os.close(fd) shutil.copyfile(dbfile, fn) db, str = self.captureOutput(sqldb.Database, fn) cu = db.db.cursor() db.close() os.unlink(fn) def testVersion11Migration(self): dbfile = os.path.join(resources.get_archive(), 'conarydbs', 'conarydb-version-11') fd, fn = tempfile.mkstemp() os.close(fd) shutil.copyfile(dbfile, fn) db, str = self.captureOutput(sqldb.Database, fn) cu = db.db.cursor() # make sure there aren't any install buckets left cu.execute("select count(*) from troveinfo where infoType=?", trove._TROVEINFO_TAG_INSTALLBUCKET) assert (cu.next()[0] == 0) # make sure the path hashs look right for libpng:lib cu.execute( "select data from troveinfo, instances where " "trovename='libpng:lib' and " "troveinfo.instanceid=instances.instanceid " "and infoType=?", trove._TROVEINFO_TAG_PATH_HASHES) ph = trove.PathHashes(cu.next()[0]) cu.execute("select path from instances, dbtrovefiles where " "instances.instanceid=dbtrovefiles.instanceid " "and troveName='libpng:lib'") for path, in cu: hash = md5String(path)[:8] assert (hash in ph) ph.remove(hash) assert (not ph) db.close() os.unlink(fn) def testVersion20Migration(self): dbfile = os.path.join(resources.get_archive(), 'conarydbs', 'conarydb-version-19') fd, fn = tempfile.mkstemp() os.close(fd) shutil.copyfile(dbfile, fn) # get a list of tables db = dbstore.connect(fn, driver='sqlite') db.loadSchema() cu = db.cursor() tableCounts = dict.fromkeys(db.tables.keys()) for table in tableCounts.keys(): tableCounts[table] = cu.execute('select count(*) from %s' % table).fetchall()[0][0] # DBInstances is gone... tableCounts.pop('DBInstances') # we have a VersionId 0 entry now tableCounts['Versions'] += 1 # new table added tableCounts['DatabaseAttributes'] = 1 # do the migration db, str = self.captureOutput(sqldb.Database, fn) cu = db.db.cursor() # make sure we have all the tables db2 = dbstore.connect(fn, driver='sqlite') db2.loadSchema() cu = db2.cursor() tableCounts2 = dict.fromkeys(db2.tables.keys()) for table in tableCounts2.keys(): tableCounts2[table] = cu.execute('select count(*) from %s' % table).fetchall()[0][0] self.assertEqual(tableCounts, tableCounts2) # check to make sure that we fixed our broken deps and troveinfo cu.execute("select count(*) from troveinfo where infoType=3 " "and hex(data) == '31'") assert (cu.next()[0] == 0) cu.execute("select count(*) from dependencies where " "name like 'conary:%' and flag='1'") assert (cu.next()[0] == 0) # verify the conary:runtime trove v = VersionFromString('/conary.rpath.com@rpl:devel//1/1.0-2-0.1') f = deps.parseFlavor('~!bootstrap is: x86') t = db.getTroves([('conary:runtime', v, f)])[0] t.verifyDigitalSignatures() # verify that we can insert a '1.0' into deps and troveinfo cu.execute("insert into Dependencies values (NULL, 4, 'test', '1.0')") cu.execute("select flag from Dependencies where name='test'") assert (cu.next()[0] == '1.0') cu.execute("insert into TroveInfo values (300, 3, '1.0')") cu.execute("select data from TroveInfo where instanceId=300 and " "infotype=3") assert (cu.next()[0] == '1.0') db.close() db2.close() # make sure the addition of DatabaseAttributes happens correctly db = dbstore.connect(fn, driver='sqlite') db.loadSchema() self.assertTrue('DatabaseAttributes' in db.tables) cu = db.cursor() cu.execute("DROP TABLE DatabaseAttributes") db.commit() db.close() sdb = sqldb.Database(fn) self.assertTrue('DatabaseAttributes' in sdb.db.tables) del sdb os.unlink(fn) def testVersion20DeAnalyze(self): dbfile = os.path.join(resources.get_archive(), 'conarydbs', 'conarydb-version-20-with-analyze') fd, fn = tempfile.mkstemp() os.close(fd) shutil.copyfile(dbfile, fn) db = sqldb.Database(fn) cu = db.db.cursor() cu.execute('select count(*) from sqlite_stat1') count = cu.fetchall()[0][0] self.assertEqual(count, 0) db.close() os.unlink(fn) def testMigrationReadOnly(self): dbfile = os.path.join(resources.get_archive(), 'conarydbs', 'conarydb-version-2') fd, fn = tempfile.mkstemp() os.close(fd) shutil.copyfile(dbfile, fn) os.chmod(fn, 0444) try: db = sqldb.Database(fn) except sqldb.OldDatabaseSchema: pass else: raise os.unlink(fn) def testSubtroveUpdates(self): db = sqldb.Database(':memory:') pkg = trove.Trove("testpkg", self.v10, self.emptyFlavor, None) pkg.addTrove("testpkg:comp", self.v10, self.emptyFlavor) ti = db.addTrove(pkg) db.addTroveDone(ti) comp1 = trove.Trove("testpkg:comp", self.v10, self.emptyFlavor, None) ti = db.addTrove(comp1) db.addTroveDone(ti) comp2 = trove.Trove("testpkg:comp", self.v20, self.emptyFlavor, None) ti = db.addTrove(comp1) db.addTroveDone(ti) # ti = db.addTrove( #("testpkg:comp", self.v10, self.emptyFlavor), comp2) db.addTroveDone(ti) db.eraseTrove("testpkg:comp", self.v10, self.emptyFlavor) pristinePkg = db.getTroves([("testpkg", self.v10, self.emptyFlavor)], pristine=True)[0] instPkg = db.getTroves([("testpkg", self.v10, self.emptyFlavor)], pristine=False)[0] assert (pristinePkg == pkg) assert (instPkg != pkg) ti = db.addTrove( #("testpkg:comp", self.v20, self.emptyFlavor), comp1) db.addTroveDone(ti) db.eraseTrove("testpkg:comp", self.v20, self.emptyFlavor) pristinePkg = db.getTroves([("testpkg", self.v10, self.emptyFlavor)], pristine=True)[0] instPkg = db.getTroves([("testpkg", self.v10, self.emptyFlavor)], pristine=False)[0] assert (pristinePkg == pkg) assert (instPkg == pkg) # make sure there aren't broken bits in TroveTroves assert (db.db.cursor().execute( "select count(*) from trovetroves").next()[0] == 1) def testMapPinned(self): # test to ensure that a if you update a pinned trove twice, # a duplicate entry does not show up in TroveTroves. db = sqldb.Database(':memory:') pkg = trove.Trove("testpkg", self.v20, self.emptyFlavor, None) pkg.addTrove("testpkg:comp", self.v20, self.emptyFlavor) ti = db.addTrove(pkg) db.addTroveDone(ti) comp1 = trove.Trove("testpkg:comp", self.v10, self.emptyFlavor, None) ti = db.addTrove(comp1) db.addTroveDone(ti) # we've got a trove with a link from trove to component. # we assume the component was pinned at v10...now we need to update # the link to point to the v10 ver. db.mapPinnedTroves([('testpkg:comp', (self.v10, self.emptyFlavor), (self.v20, self.emptyFlavor))]) cu = db.db.cursor() assert ( cu.execute('SELECT COUNT(*) FROM TroveTroves WHERE inPristine=0' ).next()[0] == 1) db.mapPinnedTroves([('testpkg:comp', (self.v10, self.emptyFlavor), (self.v20, self.emptyFlavor))]) assert ( cu.execute('SELECT COUNT(*) FROM TroveTroves WHERE inPristine=0' ).next()[0] == 1) pkg = db.getTroves([('testpkg', self.v20, self.emptyFlavor)], pristine=False)[0] assert (pkg.strongTroves.keys()[0][1] == self.v10) assert (pkg.weakTroves.keys() == [])
def testDatabaseVersionCleanup(self): flavor1 = deps.parseFlavor('is:x86(cmov)') db = sqldb.Database(':memory:') cu = db.db.cursor() v10 = ThawVersion('/conary.rpath.com@test:trunk/10:1.2-10') v20 = ThawVersion('/conary.rpath.com@test:trunk/10:1.2-20') v30 = ThawVersion('/conary.rpath.com@test:trunk/10:1.2-30') # test file version cleanup trv = trove.Trove('testcomp:runtime', v10, flavor1, None) f1 = files.FileFromFilesystem('/etc/passwd', self.id1) f2 = files.FileFromFilesystem('/etc/services', self.id2) f3 = files.FileFromFilesystem('/etc/group', self.id3) trv.addFile(self.id1, '/bin/1', v10, f1.fileId()) trv.addFile(self.id2, '/bin/2', v20, f2.fileId()) trv.addFile(self.id3, '/bin/3', v30, f3.fileId()) trvInfo = db.addTrove(trv) db.addFile(trvInfo, f1.pathId(), '/bin/1', f1.fileId(), v10, fileStream=f1.freeze()) db.addFile(trvInfo, f2.pathId(), '/bin/2', f2.fileId(), v20, fileStream=f2.freeze()) db.addFile(trvInfo, f3.pathId(), '/bin/3', f3.fileId(), v30, fileStream=f3.freeze()) db.addTroveDone(trvInfo) # check to see how many versions we have cu.execute('select count(*) from Versions') count = cu.fetchall()[0][0] # should have only 0|NULL self.assertEqual(count, 4) # now erase db.eraseTrove('testcomp:runtime', v10, flavor1) db.commit() cu.execute('select count(*) from Versions') count = cu.fetchall()[0][0] # should have only 0|NULL self.assertEqual(count, 1) # test trove version cleanup trv1 = trove.Trove('testcomp:runtime', v10, flavor1, None) trv2 = trove.Trove('group-test', v20, flavor1, None) trv2.addTrove(trv1.getName(), trv1.getVersion(), trv1.getFlavor(), weakRef=True) trvInfo = db.addTrove(trv2) db.addTroveDone(trvInfo) db.commit() cu.execute('select count(*) from Versions') count = cu.fetchall()[0][0] self.assertEqual(count, 3) db.eraseTrove('group-test', v20, flavor1) db.commit() cu.execute('select count(*) from Versions') count = cu.fetchall()[0][0] # should have only 0|NULL self.assertEqual(count, 1)
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 testShadows(self): self.doTestVersion('/foo@spc:linux//shadow/1-1.2') self.doTestVersion('/foo@spc:linux//shadow/1-1-1.2') self.doTestVersion('/foo@spc:linux//shadow/1-1-1/branch//shadow2/1.1') self.doTestVersion('/foo@spc:linux//shadow/1-1-1/branch//shadow2/' '/shadow3/1.1.1') self.assertRaises(ParseError, VersionFromString, '/foo@spc:linux//shadow/1-1.2.3') self.assertRaises(ParseError, VersionFromString, '/foo@spc:linux//shadow/1-1-1.2.3') self.assertRaises(ParseError, VersionFromString, '/foo@spc:linux//shadow/1-1-1/branch/1.1') self.assertRaises( ParseError, VersionFromString, '/foo@spc:linux//shadow/1-1-1/branch//shadow2/1.1.1') self.assertRaises( ParseError, VersionFromString, '/foo@spc:linux//shadow/1-1-1/branch//shadow2/' '/shadow3/1.1.1.1') trunk = VersionFromString('/foo@spc:linux') assert (not trunk.isShadow()) assert (not trunk.hasParentBranch()) shadow = trunk.createShadow(Label('foo@spc:shadow')) assert (shadow.isShadow()) assert (shadow.asString() == '/foo@spc:linux//shadow') assert (shadow.hasParentBranch()) assert (shadow.parentBranch() == trunk) version = shadow.createVersion(Revision('1.1-1')) assert (version.isShadow()) assert (not version.isModifiedShadow()) assert (version.asString() == '/foo@spc:linux//shadow/1.1-1') assert ( version.canonicalVersion().asString() == '/foo@spc:linux/1.1-1') assert (version.shadowLength() == 1) newVer = version.createShadow(Label("foo@spc:shadow2")) assert (newVer.asString() == '/foo@spc:linux//shadow//shadow2/1.1-1') assert (newVer.shadowLength() == 2) assert (newVer.parentVersion().asString() == '/foo@spc:linux//shadow/1.1-1') assert (newVer.parentVersion().parentVersion().asString() == '/foo@spc:linux/1.1-1') assert (newVer.canonicalVersion().asString() == '/foo@spc:linux/1.1-1') assert (newVer.isShadow()) assert (not newVer.canonicalVersion().isShadow()) assert (not newVer.canonicalVersion().isModifiedShadow()) self.assertRaises(AssertionError, newVer.createBranch, Label("foo@spc:shadow2")) self.assertRaises(VersionStringError, newVer.createShadow, Label("foo@spc:shadow2")) branch = newVer.createBranch(Label("foo@spc:branch")) assert (branch.asString() == '/foo@spc:linux//shadow//shadow2/1.1-1/branch') branchVer = newVer.createBranch(Label("foo@spc:branch"), withVerRel=True) assert (branchVer.asString() == '/foo@spc:linux//shadow//shadow2/1.1-1/branch/1') assert (branchVer.shadowLength() == 0) assert (not branchVer.isShadow()) newVer.incrementSourceCount() assert ( newVer.asString() == '/foo@spc:linux//shadow//shadow2/1.1-1.0.1') assert (newVer.isModifiedShadow()) branchVer.incrementSourceCount() assert (branchVer.asString() == '/foo@spc:linux//shadow//shadow2/1.1-1/branch/2') assert (ThawVersion(branchVer.freeze()) == branchVer) newShadow = branchVer.createShadow(Label('foo@spc:shadow3')) assert (newShadow.asString() == '/foo@spc:linux//shadow//shadow2/1.1-1/branch//shadow3/2') assert (newShadow.parentVersion().asString() == '/foo@spc:linux//shadow//shadow2/1.1-1/branch/2') assert (newShadow.parentVersion().parentVersion().asString() == '/foo@spc:linux//shadow//shadow2/1.1-1') assert (newShadow.parentVersion().parentVersion().parentVersion(). asString() == '/foo@spc:linux//shadow/1.1-1') assert (newShadow.parentVersion().parentVersion().parentVersion(). parentVersion().asString() == '/foo@spc:linux/1.1-1') assert (newShadow.canonicalVersion().asString() == '/foo@spc:linux//shadow//shadow2/1.1-1/branch/2') # shadowed binary has a parent version v = VersionFromString("/foo@spc:linux//shadow/1.2-1-1") assert (v.hasParentVersion()) # shadowed source has a parent version v = VersionFromString("/foo@spc:linux//shadow/1.2-1") assert (v.hasParentVersion()) # cooked shadowed binary doesn't has a parent version v = VersionFromString("/foo@spc:linux//shadow/1.2-1-0.1") assert (not v.hasParentVersion()) v = VersionFromString("/foo@spc:linux//shadow/1.2-1").copy() assert (v.hasParentVersion()) v.incrementBuildCount() assert (v.asString() == "/foo@spc:linux//shadow/1.2-1-0.1") assert (not v.hasParentVersion()) v2 = v.createBranch(LocalLabel(), withVerRel=True) assert (v2.asString() == "/foo@spc:linux//shadow/1.2-1-0.1/local@local:LOCAL/1") v = VersionFromString("/foo@spc:linux//shadow/1.2-1.1").copy() v.incrementBuildCount() assert (v.asString() == "/foo@spc:linux//shadow/1.2-1.1-1") assert (not v.hasParentVersion()) # test to make sure versions don't count -0 having a build count v = VersionFromString('/a@b:c/4.1.25-18-0/d//e/22.3-1') assert (not v.hasParentVersion()) # If you create a pristine shadow of a modified shadow, # that version should NOT be a modifiedShadow v = VersionFromString("/foo@spc:linux//shadow//shadow2/1.2-1.1") assert (v.isShadow() and not v.isModifiedShadow()) v = v.parentVersion() assert (v.isShadow() and v.isModifiedShadow()) v = VersionFromString("/foo@spc:linux//shadow//shadow2/1.2-1.0.1") assert (v.isShadow() and v.isModifiedShadow())
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 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 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 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 getJobs(self, jobIdList, withTroves=False, withConfigs=False): if not jobIdList: return [] cu = self.db.cursor() jobIds = ','.join('%d' % x for x in jobIdList) results = cu.execute(""" SELECT jobId, uuid, owner, state, status, start, finish, failureReason, failureData, pid FROM Jobs WHERE jobId IN (%s) """ % (jobIds, )) jobsById = {} for (jobId, uuid, owner, state, status, start, finish, failureReason, failureData, pid) in results: if state is None: # quick catch check for missing jobs raise KeyError, jobId failureReason = thaw('FailureReason', (failureReason, cu.frombinary(failureData))) job = buildjob.BuildJob(jobId, status=status, state=state, start=float(start), finish=float(finish), failureReason=failureReason, uuid=uuid, pid=pid, owner=owner) jobsById[jobId] = job if withTroves: results = cu.execute(""" SELECT jobId, BuildTroves.troveId, troveName, version, flavor, context, state, status, failureReason, failureData, start, finish, logPath, pid, recipeType, buildType, troveType, Chroots.path, Chroots.nodeName FROM BuildTroves LEFT JOIN Chroots USING(chrootId) WHERE jobId IN (%s) """ % (jobIds, )) trovesById = {} for (jobId, troveId, name, version, flavor, context, state, status, failureReason, failureData, start, finish, logPath, pid, recipeType, buildType, troveType, chrootPath, chrootHost) in results: if chrootPath is None: chrootPath = '' chrootHost = '' version = versions.ThawVersion(version) flavor = ThawFlavor(flavor) failureReason = thaw( 'FailureReason', (failureReason, cu.frombinary(failureData))) troveClass = buildtrove.getClassForTroveType(troveType) buildTrove = troveClass(jobId, name, version, flavor, state=state, start=float(start), finish=float(finish), logPath=logPath, status=status, failureReason=failureReason, pid=pid, recipeType=recipeType, chrootPath=chrootPath, chrootHost=chrootHost, buildType=buildType, context=context) trovesById[troveId] = buildTrove jobsById[jobId].addTrove(name, version, flavor, context, buildTrove) results = cu.execute(""" SELECT BuildTroves.troveId, BinaryTroves.troveName, BinaryTroves.version, BinaryTroves.flavor FROM BuildTroves JOIN BinaryTroves USING(troveId) WHERE jobId IN (%s) """ % (jobIds, )) builtTroves = {} for troveId, name, version, flavor in results: builtTroves.setdefault(troveId, []).append( (name, ThawVersion(version), ThawFlavor(flavor))) for troveId, binTroves in builtTroves.iteritems(): trv = trovesById.get(troveId) if trv is not None: trv.setBuiltTroves(binTroves) cu.execute(""" SELECT troveId, key, value FROM TroveSettings WHERE jobId IN (%s) ORDER BY key, ord """ % (jobIds, )) troveSettings = {} for troveId, key, value in cu: d = troveSettings.setdefault(troveId, {}) d.setdefault(key, []).append(value) for troveId, settings in troveSettings.items(): settingsClass = settings.pop('_class')[0] trv = trovesById.get(troveId) if trv is not None: trv.settings = thaw('TroveSettings', (settingsClass, settings)) else: results = cu.execute(""" SELECT jobId, troveName, version, flavor, context FROM BuildTroves WHERE jobId IN (%s) """ % (jobIds, )) for (jobId, n, v, f, context) in results: jobsById[jobId].addTrove(n, versions.ThawVersion(v), ThawFlavor(f), context) if withConfigs: cu.execute(""" SELECT jobId, context, key, value FROM JobConfig WHERE jobId IN (%s) ORDER BY key, ord """ % (jobIds, )) jobConfigD = {} for jobId, context, key, value in cu: configD = jobConfigD.setdefault(jobId, {}) d = configD.setdefault(context, {}) d.setdefault(key, []).append(value) for jobId, configD in jobConfigD.items(): configD = dict((x[0], thaw('BuildConfiguration', x[1])) for x in configD.iteritems()) jobsById[jobId].setConfigs(configD) return [jobsById[jobId] for jobId in jobIdList]
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 getTroves(self, troveList): if not troveList: return [] cu = self.db.cursor() trovesById = {} trovesByNVF = {} for jobId, troveName, version, flavor, context in troveList: cu.execute( """ SELECT BuildTroves.troveId, pid, state, status, failureReason, failureData, start, finish, logPath, recipeType, Chroots.nodeName, Chroots.path, troveType FROM BuildTroves LEFT JOIN Chroots USING(chrootId) WHERE jobId = ? AND troveName = ? AND version = ? AND flavor = ? AND context = ? """, jobId, troveName, version.freeze(), flavor.freeze(), context) row = cu.fetchone() if not row: continue (troveId, pid, state, status, failureReason, failureData, start, finish, logPath, recipeType, chrootHost, chrootPath, troveType) = row if chrootPath is None: chrootPath = chrootHost = '' failureReason = thaw('FailureReason', (failureReason, cu.frombinary(failureData))) troveClass = buildtrove.getClassForTroveType(troveType) buildTrove = troveClass(jobId, troveName, version, flavor, context=context, pid=pid, state=state, start=float(start), finish=float(finish), logPath=logPath, status=status, failureReason=failureReason, recipeType=recipeType, chrootPath=chrootPath, chrootHost=chrootHost) trovesById[troveId] = buildTrove trovesByNVF[(jobId, troveName, version, flavor, context)] = buildTrove if not trovesByNVF: raise KeyError(troveList[0]) troveIds = ','.join('%d' % x for x in trovesById) cu.execute(""" SELECT troveId, troveName, version, flavor FROM BinaryTroves WHERE troveId IN (%s) """ % (troveIds, )) builtTroves = {} for troveId, troveName, version, flavor in cu: builtTroves.setdefault(troveId, []).append( (troveName, ThawVersion(version), ThawFlavor(flavor))) for troveId, binTroves in builtTroves.iteritems(): trovesById[troveId].setBuiltTroves(binTroves) cu.execute(""" SELECT troveId, key, value FROM TroveSettings WHERE troveId IN (%s) ORDER BY key, ord """ % (troveIds, )) troveSettings = {} for troveId, key, value in cu: d = troveSettings.setdefault(troveId, {}) d.setdefault(key, []).append(value) for troveId, settings in troveSettings.items(): settingsClass = settings.pop('_class')[0] trovesById[troveId].settings = thaw('TroveSettings', (settingsClass, settings)) out = [] for tup in troveList: if tup in trovesByNVF: out.append(trovesByNVF[tup]) else: raise KeyError(tup) return out
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 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 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 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 _mangleGroups(self, group): """ Map all packages in the group to packages on the prod label using the clonedFrom information """ log.info('mangling the group model') grpPkgs = {} toProd = {} toRemove = set() parent = False clonedFromMap = dict(self._updater._conaryhelper.getClonedFromForLabel(self._cfg.targetLabel)) for pkg in group.iterpackages(): if not pkg.version: continue name = str(pkg.name) version = ThawVersion(str(pkg.version)) flavor = ThawFlavor(str(pkg.flavor)) grpPkgs.setdefault((name, version), set()).add(flavor) for (name, version), flavors in grpPkgs.iteritems(): for flavor in flavors: # Get the nevra for this name, version, and flavor nevra = clonedFromMap.get((name, version, flavor)) # If the package is already in the toAdd map, skip over it. if [ x for x in toProd if x[0] == name and flavor in toProd[(x[0], x[1])] ]: log.warn('%s %s is already in the toProd map' % (name,flavor)) continue # Package didn't change not sure this should happen if not nevra and (name,version,flavor) in clonedFromMap.values(): continue # Another hack for rhel 5 client workstation if self._cfg.topParentSourceGroup: parent = True if 'rhel-5-client-workstation' in str(self._cfg.topSourceGroup): parent = True if not nevra and parent: log.warn('Child platform') for original, clone in clonedFromMap.iteritems(): if (name == original[0] and version.trailingRevision() == original[1].trailingRevision() and flavor == original[2]): log.warn('adding %s' % str(clone)) n2, v2, f2 = clone toProd.setdefault((n2, v2), set()).add(f2) toRemove.add((name, version, flavor)) break continue # Feels like a hack for RHEL4AS... might revisit this later #if not flavor.thaw(): # log.warn('No flavor for %s %s %s' % (name, version, flavor)) # for original, clone in clonedFromMap.iteritems(): # if original[0] == name and original[1] == version: # n2, v2, f2 = clone # toProd.setdefault((n2, v2), set()).add(f2) # toRemove.add((name, version, flavor)) # continue toRemove.add((name, version, flavor)) n2, v2, f2 = nevra toProd.setdefault((n2, v2), set()).add(f2) ## # Remove any packages that were flagged for removal. ## for n, v, f in toRemove: log.info('removing %s[%s]' % (n, f)) group.removePackage(n, flavor=f) ## # Actually add the packages to the group model. ## for (name, version), flavors in toProd.iteritems(): for f in flavors: log.info('adding %s=%s[%s]' % (name, version, f)) group.addPackage(name, version, flavors) return group
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 ])