Example #1
0
    def testUnknownTroveInfo(self):
        class ExtraTroveInfo(trove.TroveInfo):

            streamDict = dict(trove.TroveInfo.streamDict)
            streamDict[254] = (streams.DYNAMIC, streams.IntStream, 'unknown')

        class MockTrove:
            def getName(self):
                return 'sometrove'

            def __init__(self, troveInfo=None):
                self.troveInfo = troveInfo

        full = ExtraTroveInfo()
        full.sourceName.set('foo')
        full.unknown.set(10)

        db = sqldb.Database(':memory:')
        cu = db.db.cursor()

        tiTable = db.troveInfoTable

        f = full.freeze()
        trove.TroveInfo(f)

        tiTable.addInfo(cu, MockTrove(trove.TroveInfo(full.freeze())), 1)

        returned = trove.TroveInfo()
        tiTable.getInfo(cu, MockTrove(returned), 1)
        assert (full.freeze() == returned.freeze())

        # make sure that if there is no unknown troveinfo, that nothing
        # gets stored
        ti = trove.TroveInfo()
        ti.size.set(10)
        tiTable.addInfo(cu, MockTrove(ti), 2)
        cu.execute('select count(*) from troveinfo where length(data)=0')
        count = cu.fetchall()[0][0]
        self.assertTrue(count == 0)

        # now store all of the trove info in a database (with nothing
        # unknown) and make sure it can be read using old objects
        db = sqldb.Database(':memory:')
        cu = db.db.cursor()

        tiTable = db.troveInfoTable
        tiTable.addInfo(cu, MockTrove(full), 1)
        returned = trove.TroveInfo()
        tiTable.getInfo(cu, MockTrove(returned), 1)

        assert (full.freeze() == returned.freeze())
Example #2
0
    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() == [])
Example #3
0
    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)
Example #4
0
    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)]))
Example #5
0
 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)
Example #6
0
 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)
Example #7
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)
Example #8
0
    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)
Example #9
0
 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)])
Example #10
0
    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])
Example #11
0
    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)
Example #12
0
    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)
Example #13
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)
Example #14
0
    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)