#!/bin/sh # 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. # Checks that the logger will limit the output of messages less severe than # the severity/debug setting. testname="Database Upgrade Test" echo $testname failcount=0 tempfile=@abs_builddir@/dbutil_test_tempfile_$$ backupfile=${tempfile}.backup testdata=@abs_srcdir@/testdata verfile=@abs_builddir@/dbutil_test_verfile_$$ # @brief Record a success succeed() { echo "--- PASS" } # @brief Record a fail # # @param $1 Optional additional reason to output fail() { if [ "$1" != "" ] then echo "ERROR: $1" fi echo "*** FAIL" failcount=`expr $failcount + 1` } # @brief Record a pass if the argument is zero # # @param $1 Value to test passzero() { if [ $1 -eq 0 ]; then succeed else fail fi } # @brief Record a fail if the argument is non-zero # # @param $1 Value to test failzero() { if [ $1 -ne 0 ]; then succeed else fail fi } # @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 # # Record a failure if the backup file does not exist or if it is different # to the data file. (N.B. No success is recorded if they are the same.) # # @param $1 Source database file # @param $2 Backup file check_backup() { if [ ! -e $1 ] then fail "database file $1 not found" elif [ ! -e $2 ] then fail "backup file $2 not found" else diff $1 $2 > /dev/null if [ $? -ne 0 ] then fail "database file $1 different to backup file $2" fi fi } # @brief Check No Backup File # # Record a failure if the backup file exists. (N.B. No success is recorded if # it does not.) # # @param $1 Source database file (unused, present for symmetry) # @param $2 Backup file check_no_backup() { if [ -e $2 ] then fail "backup of database $2 exists when it should not" fi } # @brief Get Database Schema # # As the schema stored in the database is format-dependent - how it is printed # depends on how the commands were entered (on one line, split across two # lines etc.) - comparing schema is awkward. # # The function sets the local variable db_schema to the output of the # .schema command, with spaces removed and upper converted to lowercase. # # The database is copied before the schema is taken (and removed after) # as SQLite3 assumes a writeable database, which may not be the case if # getting the schema from a reference copy. # # @param $1 Database for which the schema is required get_schema() { db1=@abs_builddir@/dbutil_test_schema_$$ copy_file $1 $db1 db_schema=`sqlite3 $db1 '.schema' | \ sed -e ':a' -e 'N' -e '$!ba' -e 's/,[\ ]*\n/, /g' | \ sort | \ awk '{line = line $0} END {print line}' | \ sed -e 's/ //g' | \ tr [:upper:] [:lower:]` rm -f $db1 } # @brief Successful Schema Upgrade Test # # This test is done where the upgrade is expected to be successful - when # the end result of the test is that the test database is upgraded to a # database of the expected schema. # # 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_ok_test() { copy_file $1 $tempfile @SHELL@ ../run_dbutil.sh --upgrade --noconfirm $tempfile if [ $? -eq 0 ] then # Compare schema with the reference get_schema $testdata/v2_2.sqlite3 expected_schema=$db_schema get_schema $tempfile actual_schema=$db_schema if [ "$expected_schema" = "$actual_schema" ] then succeed else fail "upgraded schema not as expected" fi # Check the version is set correctly check_version $tempfile "V2.2" # Check that a backup was made check_backup $1 $2 else # Error should have been output already fail fi } # @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 @SHELL@ ../run_dbutil.sh --upgrade --noconfirm $tempfile failzero $? check_backup $1 $backupfile } # @brief Record Count Test # # Checks that the count of records in each table is preserved in the upgrade. # # Note 1: This test assumes that the "diffs" table is present. # Note 2: The caller must ensure that $tempfile and $backupfile do not exist # on entry, and is responsible for removing them afterwards. # # @brief $1 Database to upgrade record_count_test() { copy_file $1 $tempfile diffs_count=`sqlite3 $tempfile 'select count(*) from diffs'` nsec3_count=`sqlite3 $tempfile 'select count(*) from nsec3'` records_count=`sqlite3 $tempfile 'select count(*) from records'` zones_count=`sqlite3 $tempfile 'select count(*) from zones'` @SHELL@ ../run_dbutil.sh --upgrade --noconfirm $tempfile if [ $? -ne 0 ] then # Reason for failure should already have been output fail else new_diffs_count=`sqlite3 $tempfile 'select count(*) from diffs'` new_nsec3_count=`sqlite3 $tempfile 'select count(*) from nsec3'` new_records_count=`sqlite3 $tempfile 'select count(*) from records'` new_zones_count=`sqlite3 $tempfile 'select count(*) from zones'` if [ $diffs_count -ne $new_diffs_count ] then fail "diffs table was not completely copied" fi if [ $nsec3_count -ne $new_nsec3_count ] then fail "nsec3 table was not completely copied" fi if [ $records_count -ne $new_records_count ] then fail "records table was not completely copied" fi if [ $zones_count -ne $new_zones_count ] then fail "zones table was not completely copied" fi # As an extra check, test that the backup was successful check_backup $1 $backupfile fi } # @brief Version Check # # Checks that the database is at the specified version (and so checks the # --check function). On success, a pass is recorded. # # @param $1 Database to check # @param $2 Expected version string check_version() { copy_file $1 $verfile @SHELL@ ../run_dbutil.sh --check $verfile if [ $? -gt 2 ] then fail "version check failed on database $1; return code $?" else @SHELL@ ../run_dbutil.sh --check $verfile 2>&1 | grep "$2" > /dev/null if [ $? -ne 0 ] then fail "database $1 not at expected version $2 (output: $?)" else succeed fi fi rm -f $verfile } # @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 @SHELL@ ../run_dbutil.sh --check $verfile failzero $? check_no_backup $tempfile $backupfile } # Main test sequence rm -f $tempfile $backupfile # This is the section number that is echoed during tests. It is # incremented when each section is run. sec=0 # Test: check that the utility fails if the database does not exist sec=`expr $sec + 1` echo $sec".1. Non-existent database - check" @SHELL@ ../run_dbutil.sh --check $tempfile failzero $? check_no_backup $tempfile $backupfile echo $sec".2. Non-existent database - upgrade" @SHELL@ ../run_dbutil.sh --upgrade --noconfirm $tempfile failzero $? check_no_backup $tempfile $backupfile rm -f $tempfile $backupfile # Test: should fail to check an empty file and fail to upgrade it sec=`expr $sec + 1` echo $sec".1. Database is an empty file - check" touch $tempfile check_version_fail $tempfile $backupfile rm -f $tempfile $backupfile echo $sec".2. Database is an empty file - upgrade" touch $tempfile @SHELL@ ../run_dbutil.sh --upgrade --noconfirm $tempfile failzero $? # A backup is performed before anything else, so the backup should exist. check_backup $tempfile $backupfile rm -f $tempfile $backupfile sec=`expr $sec + 1` echo $sec".1. Database is not an SQLite file - check" echo "This is not an sqlite3 database" > $tempfile check_version_fail $tempfile $backupfile rm -f $tempfile $backupfile echo $sec".2. Database is not an SQLite file - upgrade" echo "This is not an sqlite3 database" > $tempfile @SHELL@ ../run_dbutil.sh --upgrade --noconfirm $tempfile failzero $? # ...and as before, a backup should have been created check_backup $tempfile $backupfile rm -f $tempfile $backupfile sec=`expr $sec + 1` echo $sec".1. Database is an SQLite3 file without the schema table - check" check_version_fail $testdata/no_schema.sqlite3 $backupfile rm -f $tempfile $backupfile echo $sec".1. Database is an SQLite3 file without the schema table - upgrade" upgrade_fail_test $testdata/no_schema.sqlite3 $backupfile rm -f $tempfile $backupfile sec=`expr $sec + 1` echo $sec".1. Database is an old V1 database - check" check_version $testdata/old_v1.sqlite3 "V1.0" check_no_backup $tempfile $backupfile rm -f $tempfile $backupfile echo $sec".2. Database is an old V1 database - upgrade" upgrade_ok_test $testdata/old_v1.sqlite3 $backupfile rm -f $tempfile $backupfile sec=`expr $sec + 1` echo $sec".1. Database is new V1 database - check" check_version $testdata/new_v1.sqlite3 "V1.0" check_no_backup $tempfile $backupfile rm -f $tempfile $backupfile echo $sec".2. Database is a new V1 database - upgrade" upgrade_ok_test $testdata/new_v1.sqlite3 $backupfile rm -f $tempfile $backupfile sec=`expr $sec + 1` echo $sec".1. Database is V2.0 database - check" check_version $testdata/v2_0.sqlite3 "V2.0" check_no_backup $tempfile $backupfile rm -f $tempfile $backupfile echo $sec".2. Database is a V2.0 database - upgrade" upgrade_ok_test $testdata/v2_0.sqlite3 $backupfile rm -f $tempfile $backupfile sec=`expr $sec + 1` echo $sec".1. Database is V2.1 database - check" check_version $testdata/v2_1.sqlite3 "V2.1" check_no_backup $tempfile $backupfile rm -f $tempfile $backupfile echo $sec".2. Database is a V2.1 database - upgrade" upgrade_ok_test $testdata/v2_1.sqlite3 $backupfile rm -f $tempfile $backupfile sec=`expr $sec + 1` echo $sec".1. Database is V2.2 database - check" check_version $testdata/v2_2.sqlite3 "V2.2" check_no_backup $tempfile $backupfile rm -f $tempfile $backupfile echo $sec".2. Database is a V2.2 database - upgrade" upgrade_ok_test $testdata/v2_2.sqlite3 $backupfile rm -f $tempfile $backupfile sec=`expr $sec + 1` echo $sec".1. Database is V2.0 database with empty schema table - check" check_version_fail $testdata/empty_version.sqlite3 $backupfile rm -f $tempfile $backupfile echo $sec".2. Database is V2.0 database with empty schema table - upgrade" upgrade_fail_test $testdata/empty_version.sqlite3 $backupfile rm -f $tempfile $backupfile sec=`expr $sec + 1` echo $sec".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 $sec".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 sec=`expr $sec + 1` echo $sec". Upgrade corrupt database" upgrade_fail_test $testdata/corrupt.sqlite3 $backupfile rm -f $tempfile $backupfile sec=`expr $sec + 1` echo $sec". Record count test" record_count_test $testdata/new_v1.sqlite3 rm -f $tempfile $backupfile sec=`expr $sec + 1` echo $sec". Backup file already exists" touch $backupfile touch ${backupfile}-1 upgrade_ok_test $testdata/v2_0.sqlite3 ${backupfile}-2 rm -f $tempfile $backupfile ${backupfile}-1 ${backupfile}-2 sec=`expr $sec + 1` echo $sec".1 Command-line errors" copy_file $testdata/old_v1.sqlite3 $tempfile @SHELL@ ../run_dbutil.sh $tempfile failzero $? @SHELL@ ../run_dbutil.sh --upgrade --check $tempfile failzero $? @SHELL@ ../run_dbutil.sh --noconfirm --check $tempfile failzero $? @SHELL@ ../run_dbutil.sh --check failzero $? @SHELL@ ../run_dbutil.sh --upgrade --noconfirm failzero $? @SHELL@ ../run_dbutil.sh --check $tempfile $backupfile failzero $? @SHELL@ ../run_dbutil.sh --upgrade --noconfirm $tempfile $backupfile failzero $? rm -f $tempfile $backupfile echo $sec".2 verbose flag" copy_file $testdata/old_v1.sqlite3 $tempfile @SHELL@ ../run_dbutil.sh --upgrade --noconfirm --verbose $tempfile passzero $? rm -f $tempfile $backupfile echo $sec".3 Interactive prompt - yes" copy_file $testdata/old_v1.sqlite3 $tempfile @SHELL@ ../run_dbutil.sh --upgrade $tempfile << . Yes . passzero $? check_version $tempfile "V2.2" rm -f $tempfile $backupfile echo $sec".4 Interactive prompt - no" copy_file $testdata/old_v1.sqlite3 $tempfile @SHELL@ ../run_dbutil.sh --upgrade $tempfile << . no . passzero $? diff $testdata/old_v1.sqlite3 $tempfile > /dev/null passzero $? rm -f $tempfile $backupfile echo $sec".5 quiet flag" copy_file $testdata/old_v1.sqlite3 $tempfile @SHELL@ ../run_dbutil.sh --check --quiet $tempfile 2>&1 | grep . failzero $? rm -f $tempfile $backupfile # Report the result if [ $failcount -eq 0 ]; then echo "PASS: $testname" elif [ $failcount -eq 1 ]; then echo "FAIL: $testname - 1 test failed" else echo "FAIL: $testname - $failcount tests failed" fi # Exit with appropriate error status exit $failcount