From 177aac2d84472a4e48bf056067e2971ab86479df Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Wed, 22 Jun 2016 18:57:53 -0700 Subject: [PATCH] test upgrader, badly This adds a test for database upgrades, which I developed on a branch that added a new DB schema (v3) and an upgrader to match, but then I changed my mind about the schema and removed that part. The test will be useful some time in the future when I change the schema in a small enough way that I bother to write an upgrader for the change. For now, the test is disabled. In addition, the upgrader test is kind of lame. I'd really prefer to assert that the upgraded schema is identical to the schema of a brand-new (latest-version) database, but ALTER TABLE doesn't quite work that way (comments are omitted, and the order of the columns is slightly different). This also adds database.dump_db() for the tests. --- src/wormhole/server/database.py | 9 +++++ src/wormhole/test/test_database.py | 53 ++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 src/wormhole/test/test_database.py diff --git a/src/wormhole/server/database.py b/src/wormhole/server/database.py index 7cd09f9..d2589ad 100644 --- a/src/wormhole/server/database.py +++ b/src/wormhole/server/database.py @@ -64,3 +64,12 @@ def get_db(dbfile, target_version=TARGET_VERSION, stderr=sys.stderr): raise DBError("Unable to handle db version %s" % version) return db + +def dump_db(db): + # to let _iterdump work, we need to restore the original row factory + orig = db.row_factory + try: + db.row_factory = sqlite3.Row + return "".join(db.iterdump()) + finally: + db.row_factory = orig diff --git a/src/wormhole/test/test_database.py b/src/wormhole/test/test_database.py new file mode 100644 index 0000000..460508e --- /dev/null +++ b/src/wormhole/test/test_database.py @@ -0,0 +1,53 @@ +from __future__ import print_function, unicode_literals +import os +from twisted.trial import unittest +from ..server.database import get_db, TARGET_VERSION, dump_db + +class DB(unittest.TestCase): + def test_create_default(self): + db_url = ":memory:" + db = get_db(db_url) + rows = db.execute("SELECT * FROM version").fetchall() + self.assertEqual(len(rows), 1) + self.assertEqual(rows[0]["version"], TARGET_VERSION) + + def test_upgrade(self): + basedir = self.mktemp() + os.mkdir(basedir) + fn = os.path.join(basedir, "upgrade.db") + self.assertNotEqual(TARGET_VERSION, 2) + + # create an old-version DB in a file + db = get_db(fn, 2) + rows = db.execute("SELECT * FROM version").fetchall() + self.assertEqual(len(rows), 1) + self.assertEqual(rows[0]["version"], 2) + del db + + # then upgrade the file to the latest version + dbA = get_db(fn, TARGET_VERSION) + rows = dbA.execute("SELECT * FROM version").fetchall() + self.assertEqual(len(rows), 1) + self.assertEqual(rows[0]["version"], TARGET_VERSION) + dbA_text = dump_db(dbA) + del dbA + + # make sure the upgrades got committed to disk + dbB = get_db(fn, TARGET_VERSION) + dbB_text = dump_db(dbB) + del dbB + self.assertEqual(dbA_text, dbB_text) + + # The upgraded schema should be equivalent to that of a new DB. + # However a text dump will differ because ALTER TABLE always appends + # the new column to the end of a table, whereas our schema puts it + # somewhere in the middle (wherever it fits naturally). Also ALTER + # TABLE doesn't include comments. + if False: + latest_db = get_db(":memory:", TARGET_VERSION) + latest_text = dump_db(latest_db) + with open("up.sql","w") as f: f.write(dbA_text) + with open("new.sql","w") as f: f.write(latest_text) + # check with "diff -u _trial_temp/up.sql _trial_temp/new.sql" + self.assertEqual(dbA_text, latest_text) + test_upgrade.skip = "disabled until at least one upgrader is written"