Parcourir la source

[963] Changes after review.

Stephen Morris il y a 13 ans
Parent
commit
d85eda60ea

+ 1 - 0
configure.ac

@@ -996,6 +996,7 @@ AC_CONFIG_FILES([Makefile
                  src/bin/cfgmgr/tests/Makefile
                  src/bin/cfgmgr/tests/Makefile
                  src/bin/dbutil/Makefile
                  src/bin/dbutil/Makefile
                  src/bin/dbutil/tests/Makefile
                  src/bin/dbutil/tests/Makefile
+                 src/bin/dbutil/tests/testdata/Makefile
                  src/bin/host/Makefile
                  src/bin/host/Makefile
                  src/bin/loadzone/Makefile
                  src/bin/loadzone/Makefile
                  src/bin/loadzone/tests/correct/Makefile
                  src/bin/loadzone/tests/correct/Makefile

+ 10 - 0
src/bin/dbutil/Makefile.am

@@ -1,11 +1,21 @@
 SUBDIRS = . tests
 SUBDIRS = . tests
 
 
 bin_SCRIPTS = b10-dbutil
 bin_SCRIPTS = b10-dbutil
+man_MANS = b10-dbutil.8
+
+EXTRA_DIST = $(man_MANS) b10-dbutil.xml
 
 
 noinst_SCRIPTS = run_dbutil.sh
 noinst_SCRIPTS = run_dbutil.sh
 
 
 CLEANFILES = b10-dbutil b10-dbutil.pyc
 CLEANFILES = b10-dbutil b10-dbutil.pyc
 
 
+if ENABLE_MAN
+
+b10-dbutil.8: b10-dbutil.xml
+	xsltproc --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/bindctl.xml
+
+endif
+
 b10-dbutil: dbutil.py
 b10-dbutil: dbutil.py
 	$(SED) -e "s|@@PYTHONPATH@@|@pyexecdir@|" \
 	$(SED) -e "s|@@PYTHONPATH@@|@pyexecdir@|" \
 	       -e "s|@@SYSCONFDIR@@|@sysconfdir@|" \
 	       -e "s|@@SYSCONFDIR@@|@sysconfdir@|" \

+ 174 - 0
src/bin/dbutil/b10-dbutil.xml

@@ -0,0 +1,174 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+               "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+	       [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+ -
+ - Permission to use, copy, modify, and/or distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+
+<refentry>
+
+  <refentryinfo>
+    <date>March 20, 2012</date>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>b10-dbutil</refentrytitle>
+    <manvolnum>8</manvolnum>
+    <refmiscinfo>BIND10</refmiscinfo>
+  </refmeta>
+
+  <refnamediv>
+    <refname>b10-dbutil</refname>
+    <refpurpose>Zone Database Maintenance Utility</refpurpose>
+  </refnamediv>
+
+  <docinfo>
+    <copyright>
+      <year>2012</year>
+      <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+    </copyright>
+  </docinfo>
+
+  <refsynopsisdiv>
+    <cmdsynopsis>
+      <command>b10-dbutil --check</command>
+        <arg>--verbose</arg>
+        <arg><replaceable choice='req'>dbfile</replaceable></arg>
+    </cmdsynopsis>
+    <cmdsynopsis>
+      <command>b10-dbutil --upgrade</command>
+        <arg>--noconfirm</arg>
+        <arg>--verbose</arg>
+        <arg><replaceable choice='req'>dbfile</replaceable></arg>
+    </cmdsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>DESCRIPTION</title>
+    <para>
+      The <command>b10-dbutil</command> utility is a general administration
+      utility for SQL databases. (Currently only SQLite is supported by
+      BIND 10.)  It can report the current verion of the schema, and upgrade
+      an existing database to the latest version of the schema.
+    </para>
+
+    <para>
+      <command>b10-dbutil</command> operates in one of two modes, check mode
+      or upgrade mode.
+    </para>
+
+    <para>
+      In check mode (<command>b10-dbutil --check</command>), the
+      utility reads the version of the database schema from the database
+      and prints it.  It will tell you whether the schema is at the latest
+      version supported by BIND 10.
+    </para>
+
+    <para>
+      When the upgrade function is selected
+      (<command>b10-dbutil --upgrade</command>), the
+      utility takes a copy of the database, then upgrades it to the latest
+      version of the schema.  The contents of the database remain intact.
+      (The backup file is a file in the same directory as the database
+      file.  It has the same name, with ".backup" appended to it.  If a
+      file of that name already exists, the file will have the suffix
+      ".backup-1".  If that exists, the file will be suffixed ".backup-2",
+      and so on.)
+    </para>
+
+    <para>
+    When upgrading the database, it is <emphasis>strongly</emphasis>
+    recommended that BIND 10 not be running while the upgrade is in
+    progress.
+    </para>
+
+  </refsect1>
+
+  <refsect1>
+    <title>ARGUMENTS</title>
+
+    <para>The arguments are as follows:</para>
+
+    <variablelist>
+      <varlistentry>
+        <term>
+         <option>--check</option>
+        </term>
+        <listitem>
+          <para>Selects the version check function, which reports the
+          current version of the database.  This is incompatible
+          with the --upgrade option.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>
+         <option>--noconfirm</option>
+        </term>
+        <listitem>
+          <para>Only valid with --upgrade, this disables the prompt.
+          Normally the utility will print a warning that an upgrade is
+          about to take place and request that you type "Yes" to continue.
+          If this switch is given on the command line, no prompt will
+          be issued: the utility will just perform the upgrade.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>
+         <option>--upgrade</option>
+        </term>
+        <listitem>
+          <para>Selects the upgrade function, which upgrades the database
+          to the latest version of the schema.  This is incompatible
+          with the --upgrade option.
+          </para>
+          <para>
+          The upgrade function will upgrade a BIND 10 database - no matter how
+          old the schema - preserving all data.  A backup file is created
+          before the upgrade (with the same name as the database, but with
+          ".backup" suffixed to it).  If the upgrade fails, this file can
+          be copied back to restore the original database.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>
+         <option>--verbose</option>
+        </term>
+        <listitem>
+          <para>Enable verbose mode.  Each SQL command issued by the
+          utility will be printed to before it is executed.</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>
+        <option><replaceable choice='req'>dbfile</replaceable></option>
+        </term>
+        <listitem>
+          <para>
+          Name of the database file to check of upgrade.
+          </para>
+        </listitem>
+      </varlistentry>
+
+
+    </variablelist>
+  </refsect1>
+</refentry>

+ 103 - 84
src/bin/dbutil/dbutil.py.in

@@ -15,23 +15,24 @@
 # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 
-# @file Dabase Utilities
-#
-# This file holds the "dbutil" program, a general utility program for doing
-# management of the BIND 10 database.  There are two modes of operation:
-#
-#       b10-dbutil --check [database]
-#       b10-dbutil --upgrade [--noconfirm] [database]
-#
-# The first form checks the version of the given database.  The second form
-# upgrades the database to the latest version of the schema, omitting the
-# warning prompt if --noconfirm is given.  In both cases, if the databas
-# file is not given on the command line, the default database will be accessed.
-#
-# For maximum safety, prior to the upgrade a backup database is created.
-# The is the database name with ".backup" appended to it (or ".backup-n" if
-# ".backup" already exists).  This is used to restore the database if the
-# upgrade fails.
+"""
+@file Dabase Utilities
+
+This file holds the "dbutil" program, a general utility program for doing
+management of the BIND 10 database.  There are two modes of operation:
+
+      b10-dbutil --check [--verbose] database
+      b10-dbutil --upgrade [--noconfirm] [--verbose] database
+
+The first form checks the version of the given database.  The second form
+upgrades the database to the latest version of the schema, omitting the
+warning prompt if --noconfirm is given.
+
+For maximum safety, prior to the upgrade a backup database is created.
+The is the database name with ".backup" appended to it (or ".backup-n" if
+".backup" already exists).  This is used to restore the database if the
+upgrade fails.
+"""
 
 
 import sys; sys.path.append("@@PYTHONPATH@@")
 import sys; sys.path.append("@@PYTHONPATH@@")
 import os, sqlite3, shutil
 import os, sqlite3, shutil
@@ -40,17 +41,13 @@ import isc.util.process
 
 
 isc.util.process.rename()
 isc.util.process.rename()
 
 
-# Default database to use if the database is not given on the command line.
-# (This is the same string as in "auth.spec.pre.in".)
-DEFAULT_DATABASE_FILE = "@@LOCALSTATEDIR@@/@PACKAGE@/zone.sqlite3"
-
+# @brief Version String
 # This is the version displayed to the user.  It comprises the module name,
 # This is the version displayed to the user.  It comprises the module name,
 # the module version number, and the overall BIND 10 version number (set in
 # the module version number, and the overall BIND 10 version number (set in
 # configure.ac)
 # configure.ac)
 VERSION = "b10-dbutil 20120319 (BIND 10 @PACKAGE_VERSION@)"
 VERSION = "b10-dbutil 20120319 (BIND 10 @PACKAGE_VERSION@)"
 
 
-# Statements to update the database.
-#
+# @brief Statements to Update the Database
 # These are in the form of a list of dictionaries, each of which contains the
 # These are in the form of a list of dictionaries, each of which contains the
 # information to perform an incremental upgrade from one version of the
 # information to perform an incremental upgrade from one version of the
 # database to the next.  The information is:
 # database to the next.  The information is:
@@ -70,8 +67,7 @@ VERSION = "b10-dbutil 20120319 (BIND 10 @PACKAGE_VERSION@)"
 # Note that apart from the 1.0 to 2.0 upgrade, no upgrade need alter the
 # Note that apart from the 1.0 to 2.0 upgrade, no upgrade need alter the
 # schema_version table: that is done by the upgrade process using the
 # schema_version table: that is done by the upgrade process using the
 # information in the "to" field.
 # information in the "to" field.
-
-upgrades = [
+UPGRADES = [
     {'from': (1, 0), 'to': (2, 0),
     {'from': (1, 0), 'to': (2, 0),
         'statements': [
         'statements': [
 
 
@@ -179,8 +175,10 @@ upgrades = [
 # program will be able to upgrade both a V1.0 and a V2.0 database.
 # program will be able to upgrade both a V1.0 and a V2.0 database.
 ]
 ]
 
 
-# Exception class to indicate error exit
 class DbutilException(Exception):
 class DbutilException(Exception):
+    """
+    @brief Exception class to indicate error exit
+    """
     pass
     pass
 
 
 # Functions for outputting messages in a consistent format.  As this is intended
 # Functions for outputting messages in a consistent format.  As this is intended
@@ -232,11 +230,13 @@ def info(text, ex = None):
     output(sys.stdout.write, "INFO", text, ex)
     output(sys.stdout.write, "INFO", text, ex)
 
 
 
 
-# @brief Database Encapsulation
-#
-# Encapsulates the SQL database, both the connection and the cursor.  The
-# methods will cause a program exit on any error.
 class Database:
 class Database:
+    """
+    @brief Database Encapsulation
+
+    Encapsulates the SQL database, both the connection and the cursor.  The
+    methods will cause a program exit on any error.
+    """
     def __init__(self, db_file, verbose = False):
     def __init__(self, db_file, verbose = False):
         """
         """
         @brief Constructor
         @brief Constructor
@@ -376,13 +376,37 @@ def version_string(version):
     return "V" + str(version[0]) + "." + str(version[1])
     return "V" + str(version[0]) + "." + str(version[1])
 
 
 
 
+def compare_versions(first, second):
+    """
+    @brief Compare Versions
+
+    Compares two database version numbers.
+
+    @param first First version number to check (in the form of a
+           "(major, minor)" tuple).
+    @param second Second version number to check (in the form of a
+           "(major, minor)" tuple).
+
+    @return -1, 0, +1 if "first" is <, ==, > "second"
+    """
+    if first == second:
+        return 0
+
+    elif ((first[0] < second[0]) or
+          ((first[0] == second[0]) and (first[1] < second[1]))):
+        return -1
+
+    else:
+        return 1
+
+
 def get_latest_version():
 def get_latest_version():
     """
     """
-    @brief Returns the latest version of the database
+    @brief Returns the version to which this utility can upgrade the database
 
 
     This is the 'to' version held in the last element of the upgrades list
     This is the 'to' version held in the last element of the upgrades list
     """
     """
-    return upgrades[-1]['to']
+    return UPGRADES[-1]['to']
 
 
 
 
 def get_version(db):
 def get_version(db):
@@ -392,19 +416,12 @@ def get_version(db):
     @return Version of database in form (major version, minor version)
     @return Version of database in form (major version, minor version)
     """
     """
 
 
-    # Check only one row of data in the version table.
-    db.execute("SELECT COUNT(*) FROM schema_version")
-    result = db.result()
-    if result[0] == 0:
-        raise DbutilException("unable to determine database version - " +
-                              "nothing in schema_version table")
-    elif result[0] > 1:
-        raise DbutilException("unable to determine database version - " +
-                              "too many rows in schema_version table")
-
     # Get the version information.
     # Get the version information.
     db.execute("SELECT * FROM schema_version")
     db.execute("SELECT * FROM schema_version")
     result = db.result()
     result = db.result()
+    if result is None:
+        raise DbutilException("nothing in schema_version table")
+
     major = result[0]
     major = result[0]
     if (major == 1):
     if (major == 1):
         # If the version number is 1, there will be no "minor" column, so
         # If the version number is 1, there will be no "minor" column, so
@@ -413,23 +430,41 @@ def get_version(db):
     else:
     else:
         minor = result[1]
         minor = result[1]
 
 
+    result = db.result()
+    if result is not None:
+        raise DbutilException("too many rows in schema_version table")
+
     return (major, minor)
     return (major, minor)
 
 
 
 
-def match_version(db, expected):
+def check_version(db):
     """
     """
-    @brief Check database version against that expected
-
-    Checks whether the version of the database matches that expected for
-    the upgrade.  Both the major and minor versions must match.
+    @brief Check the version
 
 
-    @param db Database
-    @param expected Expected version of the database in form (major, minor)
+    Checks the version of the database and the latest version, and advises if
+    an upgrade is needed.
 
 
-    @return True if the versions match, false if they don't.
+    @param db Database object
     """
     """
     current = get_version(db)
     current = get_version(db)
-    return expected == current
+    latest = get_latest_version()
+
+    match = compare_versions(current, latest)
+    if match == 0:
+        info("database version " + version_string(current))
+        info("this is the latest version of the database schema, " +
+             "no upgrade is required")
+
+    elif match < 0:
+        info("database version " + version_string(current) +
+             ", latest version is " + version_string(latest))
+        info("re-run this program with the --upgrade switch to upgrade")
+
+    else:
+        warn("database is at a later version (" + version_string(current) +
+             ") than this program can cope with (" +
+             version_string(get_latest_version()) + ")")
+        info("please get the latest version of b10-dbutil and re-run")
 
 
 
 
 def perform_upgrade(db, upgrade):
 def perform_upgrade(db, upgrade):
@@ -464,14 +499,18 @@ def perform_all_upgrades(db):
     For each upgrade, checks that the database is at the expected version.
     For each upgrade, checks that the database is at the expected version.
     If so, calls perform_upgrade to update the database.
     If so, calls perform_upgrade to update the database.
     """
     """
-    if match_version(db, get_latest_version()):
+    match = compare_versions(get_version(db), get_latest_version())
+    if match == 0:
         info("database already at latest version, no upgrade necessary")
         info("database already at latest version, no upgrade necessary")
 
 
+    elif match > 0:
+        warn("database at a later version than this utility can support")
+
     else:
     else:
         # Work our way through all upgrade increments
         # Work our way through all upgrade increments
         count = 0
         count = 0
-        for upgrade in upgrades:
-            if match_version(db, upgrade['from']):
+        for upgrade in UPGRADES:
+            if compare_versions(get_version(db), upgrade['from']) == 0:
                 perform_upgrade(db, upgrade)
                 perform_upgrade(db, upgrade)
                 count = count + 1
                 count = count + 1
 
 
@@ -480,33 +519,9 @@ def perform_all_upgrades(db):
         else:
         else:
             # Should not get here, as we established earlier that the database
             # Should not get here, as we established earlier that the database
             # was not at the latest version so we should have upgraded.
             # was not at the latest version so we should have upgraded.
-            # (Although it is possible that as version checks are for equality,
-            # an older version of dbutil was being run against a newer version
-            # of the database.)
-            raise DbutilException("database not at latest version but no " +
-                                  "upgrade was performed")
-
-
-def check_version(db):
-    """
-    @brief Check the version
-
-    Checks the version of the database and the latest version, and advises if
-    an upgrade is needed.
-
-    @param db Database object
-    """
-    current = get_version(db);
-    latest = get_latest_version()
-
-    if current == latest:
-        info("database version " + version_string(current))
-        info("this is the latest version of the database schema, " +
-             "no upgrade is required")
-    else:
-        info("database version " + version_string(current) +
-             ", latest version is " + version_string(latest))
-        info("re-run this program with the --upgrade switch to upgrade")
+            raise DbutilException("internal error in upgrade tool - no " +
+                                  "upgrade was performed on an old version " +
+                                  "the database")
 
 
 
 
 def parse_command():
 def parse_command():
@@ -517,8 +532,8 @@ def parse_command():
 
 
     @return Tuple of parser options and parser arguments
     @return Tuple of parser options and parser arguments
     """
     """
-    usage = ("usage: %prog --check [options] [db_file]\n" +
-             "       %prog --upgrade [--noconfirm] [options] [db_file]")
+    usage = ("usage: %prog --check [options] db_file\n" +
+             "       %prog --upgrade [--noconfirm] [options] db_file")
     parser = OptionParser(usage = usage, version = VERSION)
     parser = OptionParser(usage = usage, version = VERSION)
     parser.add_option("-c", "--check", action="store_true",
     parser.add_option("-c", "--check", action="store_true",
                       dest="check", default=False,
                       dest="check", default=False,
@@ -541,7 +556,9 @@ def parse_command():
         parser.print_usage()
         parser.print_usage()
         sys.exit(1)
         sys.exit(1)
     elif len(args) == 0:
     elif len(args) == 0:
-        args.append(DEFAULT_DATABASE_FILE)
+        error("must supply name of the database file to upgrade")
+        parser.print_usage()
+        sys.exit(1)
 
 
     # Check for conflicting options.  If some are found, output a suitable
     # Check for conflicting options.  If some are found, output a suitable
     # error message and print the usage.
     # error message and print the usage.
@@ -600,3 +617,5 @@ if __name__ == "__main__":
     else:
     else:
         error("internal error, neither --check nor --upgrade selected")
         error("internal error, neither --check nor --upgrade selected")
         sys.exit(1)
         sys.exit(1)
+
+    sys.exit(0)

+ 1 - 1
src/bin/dbutil/tests/Makefile.am

@@ -1,4 +1,4 @@
-SUBDIRS = .
+SUBDIRS = . testdata
 
 
 # Tests of the update script.
 # Tests of the update script.
 
 

+ 105 - 40
src/bin/dbutil/tests/dbutil_test.sh.in

@@ -35,7 +35,7 @@ succeed() {
 #
 #
 # @param $1 Optional additional reason to output
 # @param $1 Optional additional reason to output
 fail() {
 fail() {
-    if [ "x$1" != "x" ]
+    if [ "$1" != "" ]
     then
     then
         echo "ERROR: $1"
         echo "ERROR: $1"
     fi
     fi
@@ -68,6 +68,19 @@ failzero() {
 }
 }
 
 
 
 
+# @brief Copy File
+#
+# Executes a "cp" operation followed by a "chmod" to make the target writeable.
+#
+# @param $1 Source file
+# @param $2 Target file
+copy_file () {
+    cp $1 $2
+    chmod a+w $2
+}
+
+
+
 # @brief Check backup file
 # @brief Check backup file
 #
 #
 # Record a failure if the backup file does not exist or if it is different
 # Record a failure if the backup file does not exist or if it is different
@@ -125,7 +138,7 @@ check_no_backup() {
 # @param $1 Database for which the schema is required
 # @param $1 Database for which the schema is required
 get_schema() {
 get_schema() {
     db1=@abs_builddir@/dbutil_test_schema_$$
     db1=@abs_builddir@/dbutil_test_schema_$$
-    cp $1 $db1
+    copy_file $1 $db1
 
 
     db_schema=`sqlite3 $db1 '.schema' | \
     db_schema=`sqlite3 $db1 '.schema' | \
                awk '{line = line $0} END {print line}' | \
                awk '{line = line $0} END {print line}' | \
@@ -145,8 +158,9 @@ get_schema() {
 #       on entry, and is responsible for removing them afterwards.
 #       on entry, and is responsible for removing them afterwards.
 #
 #
 # @param $1 Database to upgrade
 # @param $1 Database to upgrade
+# @param $2 Expected backup file
 upgrade_ok_test() {
 upgrade_ok_test() {
-    cp $1 $tempfile
+    copy_file $1 $tempfile
     ../run_dbutil.sh --upgrade --noconfirm $tempfile
     ../run_dbutil.sh --upgrade --noconfirm $tempfile
     if [ $? -eq 0 ]
     if [ $? -eq 0 ]
     then
     then
@@ -155,15 +169,18 @@ upgrade_ok_test() {
         expected_schema=$db_schema
         expected_schema=$db_schema
         get_schema $tempfile
         get_schema $tempfile
         actual_schema=$db_schema
         actual_schema=$db_schema
-        if [ x$expected_schema = x$actual_schema ]
+        if [ "$expected_schema" = "$actual_schema" ]
         then
         then
             succeed
             succeed
         else
         else
             fail "upgraded schema not as expected"
             fail "upgraded schema not as expected"
         fi
         fi
 
 
-        # and check the version is set correctly
+        # Check the version is set correctly
         check_version $tempfile "V2.0"
         check_version $tempfile "V2.0"
+
+        # Check that a backup was made
+        check_backup $1 $2
     else
     else
         # Error should have been output already
         # Error should have been output already
         fail
         fail
@@ -171,6 +188,23 @@ upgrade_ok_test() {
 }
 }
 
 
 
 
+# @brief Unsuccessful Upgrade Test
+#
+# Checks that an upgrade of the specified database fails.
+#
+# Note: the caller must ensure that $tempfile and $backupfile do not exist
+#       on entry, and is responsible for removing them afterwards.
+#
+# @param $1 Database to upgrade
+# @param $2 Expected backup file
+upgrade_fail_test() {
+    copy_file $1 $tempfile
+    ../run_dbutil.sh --upgrade --noconfirm $tempfile
+    failzero $?
+    check_backup $1 $backupfile
+}
+
+
 # @brief Record Count Test
 # @brief Record Count Test
 #
 #
 # Checks that the count of records in each table is preserved in the upgrade.
 # Checks that the count of records in each table is preserved in the upgrade.
@@ -181,7 +215,7 @@ upgrade_ok_test() {
 #
 #
 # @brief $1 Database to upgrade
 # @brief $1 Database to upgrade
 record_count_test() {
 record_count_test() {
-    cp $1 $tempfile
+    copy_file $1 $tempfile
 
 
     diffs_count=`sqlite3 $tempfile 'select count(*) from diffs'`
     diffs_count=`sqlite3 $tempfile 'select count(*) from diffs'`
     nsec3_count=`sqlite3 $tempfile 'select count(*) from nsec3'`
     nsec3_count=`sqlite3 $tempfile 'select count(*) from nsec3'`
@@ -233,7 +267,7 @@ record_count_test() {
 # @param $1 Database to check
 # @param $1 Database to check
 # @param $2 Expected version string
 # @param $2 Expected version string
 check_version() {
 check_version() {
-    cp $1 $verfile
+    copy_file $1 $verfile
     ../run_dbutil.sh --check $verfile
     ../run_dbutil.sh --check $verfile
     if [ $? -ne 0 ]
     if [ $? -ne 0 ]
     then
     then
@@ -251,6 +285,20 @@ check_version() {
 }
 }
 
 
 
 
+# @brief Version Check Fail
+#
+# Does a version check but expected the check to fail
+#
+# @param $1 Database to check
+# @param $2 Backup file
+check_version_fail() {
+    copy_file $1 $verfile
+    ../run_dbutil.sh --check $verfile
+    failzero $?
+    check_no_backup $tempfile $backupfile
+}
+
+
 # Main test sequence
 # Main test sequence
 
 
 rm -f $tempfile $backupfile
 rm -f $tempfile $backupfile
@@ -271,9 +319,7 @@ rm -f $tempfile $backupfile
 # Test 2 - should fail to check an empty file and fail to upgrade it
 # Test 2 - should fail to check an empty file and fail to upgrade it
 echo "2.1. Database is an empty file - check"
 echo "2.1. Database is an empty file - check"
 touch $tempfile
 touch $tempfile
-../run_dbutil.sh --check $tempfile
-failzero $?
-check_no_backup $tempfile $backupfile
+check_version_fail $tempfile $backupfile
 rm -f $tempfile $backupfile
 rm -f $tempfile $backupfile
 
 
 echo "2.2. Database is an empty file - upgrade"
 echo "2.2. Database is an empty file - upgrade"
@@ -287,11 +333,11 @@ rm -f $tempfile $backupfile
 
 
 echo "3.1. Database is not an SQLite file - check"
 echo "3.1. Database is not an SQLite file - check"
 echo "This is not an sqlite3 database" > $tempfile
 echo "This is not an sqlite3 database" > $tempfile
-../run_dbutil.sh --check $tempfile
-failzero $?
-check_no_backup $tempfile $backupfile
+check_version_fail $tempfile $backupfile
+rm -f $tempfile $backupfile
 
 
 echo "3.2. Database is not an SQLite file - upgrade"
 echo "3.2. Database is not an SQLite file - upgrade"
+echo "This is not an sqlite3 database" > $tempfile
 ../run_dbutil.sh --upgrade --noconfirm $tempfile
 ../run_dbutil.sh --upgrade --noconfirm $tempfile
 failzero $?
 failzero $?
 # ...and as before, a backup should have been created
 # ...and as before, a backup should have been created
@@ -300,17 +346,11 @@ rm -f $tempfile $backupfile
 
 
 
 
 echo "4.1. Database is an SQLite3 file without the schema table - check"
 echo "4.1. Database is an SQLite3 file without the schema table - check"
-cp $testdata/no_schema.sqlite3 $tempfile
-../run_dbutil.sh --check $tempfile
-failzero $?
-check_no_backup $tempfile $backupfile
+check_version_fail $testdata/no_schema.sqlite3 $backupfile
 rm -f $tempfile $backupfile
 rm -f $tempfile $backupfile
 
 
 echo "4.1. Database is an SQLite3 file without the schema table - upgrade"
 echo "4.1. Database is an SQLite3 file without the schema table - upgrade"
-cp $testdata/no_schema.sqlite3 $tempfile
-../run_dbutil.sh --upgrade --noconfirm $tempfile
-failzero $?
-check_backup $testdata/no_schema.sqlite3 $backupfile
+upgrade_fail_test $testdata/no_schema.sqlite3 $backupfile
 rm -f $tempfile $backupfile
 rm -f $tempfile $backupfile
 
 
 
 
@@ -320,8 +360,7 @@ check_no_backup $tempfile $backupfile
 rm -f $tempfile $backupfile
 rm -f $tempfile $backupfile
 
 
 echo "5.2. Database is an old V1 database - upgrade"
 echo "5.2. Database is an old V1 database - upgrade"
-upgrade_ok_test $testdata/old_v1.sqlite3
-check_backup $testdata/old_v1.sqlite3 $backupfile
+upgrade_ok_test $testdata/old_v1.sqlite3 $backupfile
 rm -f $tempfile $backupfile
 rm -f $tempfile $backupfile
 
 
 
 
@@ -331,8 +370,7 @@ check_no_backup $tempfile $backupfile
 rm -f $tempfile $backupfile
 rm -f $tempfile $backupfile
 
 
 echo "6.2. Database is a new V1 database - upgrade"
 echo "6.2. Database is a new V1 database - upgrade"
-upgrade_ok_test $testdata/new_v1.sqlite3
-check_backup $testdata/new_v1.sqlite3 $backupfile
+upgrade_ok_test $testdata/new_v1.sqlite3 $backupfile
 rm -f $tempfile $backupfile
 rm -f $tempfile $backupfile
 
 
 
 
@@ -342,44 +380,71 @@ check_no_backup $tempfile $backupfile
 rm -f $tempfile $backupfile
 rm -f $tempfile $backupfile
 
 
 echo "7.2. Database is a V2.0 database - upgrade"
 echo "7.2. Database is a V2.0 database - upgrade"
-upgrade_ok_test $testdata/v2_0.sqlite3
-check_backup $testdata/v2_0.sqlite3 $backupfile
+upgrade_ok_test $testdata/v2_0.sqlite3 $backupfile
 rm -f $tempfile $backupfile
 rm -f $tempfile $backupfile
 
 
 
 
-echo "8. Record count test"
-record_count_test testdata/new_v1.sqlite3
+echo "8.1. Database is V2.0 database with empty schema table - check"
+check_version_fail $testdata/empty_version.sqlite3 $backupfile
+rm -f $tempfile $backupfile
+
+echo "8.2. Database is V2.0 database with empty schema table - upgrade"
+upgrade_fail_test $testdata/empty_version.sqlite3 $backupfile
 rm -f $tempfile $backupfile
 rm -f $tempfile $backupfile
 
 
 
 
-echo "9. Backup file already exists"
+echo "9.1. Database is V2.0 database with over-full schema table - check"
+check_version_fail $testdata/too_many_version.sqlite3 $backupfile
+rm -f $tempfile $backupfile
+
+echo "9.2. Database is V2.0 database with over-full schema table - upgrade"
+upgrade_fail_test $testdata/too_many_version.sqlite3 $backupfile
+rm -f $tempfile $backupfile
+
+
+echo "10.0. Upgrade corrupt database"
+upgrade_fail_test $testdata/corrupt.sqlite3 $backupfile
+rm -f $tempfile $backupfile
+
+
+echo "11. Record count test"
+record_count_test $testdata/new_v1.sqlite3
+rm -f $tempfile $backupfile
+
+
+echo "12. Backup file already exists"
 touch $backupfile
 touch $backupfile
 touch ${backupfile}-1
 touch ${backupfile}-1
-upgrade_ok_test $testdata/v2_0.sqlite3
-check_backup $testdata/v2_0.sqlite3 ${backupfile}-2
+upgrade_ok_test $testdata/v2_0.sqlite3 ${backupfile}-2
 rm -f $tempfile $backupfile ${backupfile}-1 ${backupfile}-2
 rm -f $tempfile $backupfile ${backupfile}-1 ${backupfile}-2
 
 
 
 
-echo "10.1 Command-line errors"
-cp $testdata/old_v1.sqlite3 $tempfile
+echo "13.1 Command-line errors"
+copy_file $testdata/old_v1.sqlite3 $tempfile
 ../run_dbutil.sh $tempfile
 ../run_dbutil.sh $tempfile
 failzero $?
 failzero $?
 ../run_dbutil.sh --upgrade --check $tempfile
 ../run_dbutil.sh --upgrade --check $tempfile
 failzero $?
 failzero $?
 ../run_dbutil.sh --noconfirm --check $tempfile
 ../run_dbutil.sh --noconfirm --check $tempfile
 failzero $?
 failzero $?
+../run_dbutil.sh --check
+failzero $?
+../run_dbutil.sh --upgrade --noconfirm
+failzero $?
 ../run_dbutil.sh --check $tempfile $backupfile
 ../run_dbutil.sh --check $tempfile $backupfile
 failzero $?
 failzero $?
+../run_dbutil.sh --upgrade --noconfirm $tempfile $backupfile
+failzero $?
 rm -f $tempfile $backupfile
 rm -f $tempfile $backupfile
 
 
-echo "10.2 verbose flag"
-cp $testdata/old_v1.sqlite3 $tempfile
+echo "13.2 verbose flag"
+copy_file $testdata/old_v1.sqlite3 $tempfile
 ../run_dbutil.sh --upgrade --noconfirm --verbose $tempfile
 ../run_dbutil.sh --upgrade --noconfirm --verbose $tempfile
 passzero $?
 passzero $?
 rm -f $tempfile $backupfile
 rm -f $tempfile $backupfile
 
 
-echo "10.3 Interactive prompt - yes"
-cp $testdata/old_v1.sqlite3 $tempfile
+echo "13.3 Interactive prompt - yes"
+copy_file $testdata/old_v1.sqlite3 $tempfile
 ../run_dbutil.sh --upgrade $tempfile << .
 ../run_dbutil.sh --upgrade $tempfile << .
 Yes
 Yes
 .
 .
@@ -387,8 +452,8 @@ passzero $?
 check_version $tempfile "V2.0"
 check_version $tempfile "V2.0"
 rm -f $tempfile $backupfile
 rm -f $tempfile $backupfile
 
 
-echo "10.4 Interactive prompt - no"
-cp $testdata/old_v1.sqlite3 $tempfile
+echo "13.4 Interactive prompt - no"
+copy_file $testdata/old_v1.sqlite3 $tempfile
 ../run_dbutil.sh --upgrade $tempfile << .
 ../run_dbutil.sh --upgrade $tempfile << .
 no
 no
 .
 .

+ 12 - 0
src/bin/dbutil/tests/testdata/Makefile.am

@@ -0,0 +1,12 @@
+EXTRA_DIST =
+EXTRA_DIST += corrupt.sqlite3
+EXTRA_DIST += empty_schema.sqlite3
+EXTRA_DIST += empty_v1.sqlite3
+EXTRA_DIST += empty_version.sqlite3
+EXTRA_DIST += invalid_v1.sqlite3
+EXTRA_DIST += new_v1.sqlite3
+EXTRA_DIST += no_schema.sqlite3
+EXTRA_DIST += old_v1.sqlite3
+EXTRA_DIST += README
+EXTRA_DIST += too_many_version.sqlite3
+EXTRA_DIST += v2_0.sqlite3

+ 6 - 0
src/bin/dbutil/tests/testdata/README

@@ -21,6 +21,9 @@ empty_v1.sqlite3: A database conforming to the new V1 schema.
 The database is empty, except for the schema_version table, where the
 The database is empty, except for the schema_version table, where the
 "version" column is set to 1.
 "version" column is set to 1.
 
 
+empty_version.sqlite3: A database conforming to the V2.0 schema but without
+anything in the schema_version table.
+
 no_schema.sqlite3: A valid SQLite3 database, but without a schema_version
 no_schema.sqlite3: A valid SQLite3 database, but without a schema_version
 table.
 table.
 
 
@@ -33,3 +36,6 @@ is marked as V1, does not have the nsec3 table.
 new_v1.sqlite3: A valid SQLite3 database with data in all the tables
 new_v1.sqlite3: A valid SQLite3 database with data in all the tables
 (although the single rows in both the nsec3 and diffs table make no
 (although the single rows in both the nsec3 and diffs table make no
 sense, but are valid).
 sense, but are valid).
+
+too_many_version.sqlite3: A database conforming to the V2.0 schema but with
+too many rows of data.

BIN
src/bin/dbutil/tests/testdata/corrupt.sqlite3


BIN
src/bin/dbutil/tests/testdata/empty_version.sqlite3


BIN
src/bin/dbutil/tests/testdata/too_many_version.sqlite3