Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More server DB tests #854

Merged
merged 4 commits into from
Jul 27, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion buildscripts/dbtests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function cleanup {
fi
}

clientCmd="make test"
clientCmd="make TESTOPTS='-p 1' test"
if [[ -z "${CIRCLECI}" ]]; then
BUILDOPTS="--force-rm"
else
Expand Down
15 changes: 12 additions & 3 deletions server/storage/memory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,19 @@ func TestMemoryUpdateCurrentEmpty(t *testing.T) {
}

// UpdateCurrent will successfully add a new (higher) version of an existing TUF file,
// but will return an error if there is an older version of a TUF file.
func TestMemoryUpdateCurrentVersionCheck(t *testing.T) {
// but will return an error if the to-be-added version already exists in the DB.
func TestMemoryUpdateCurrentVersionCheckOldVersionExists(t *testing.T) {
s := NewMemStorage()
expected := testUpdateCurrentVersionCheck(t, s)
expected := testUpdateCurrentVersionCheck(t, s, true)
assertExpectedMemoryTUFMeta(t, expected, s)
}

// UpdateCurrent will successfully add a new (higher) version of an existing TUF file,
// but will return an error if the to-be-added version does not exist in the DB, but
// is older than an existing version in the DB.
func TestMemoryUpdateCurrentVersionCheckOldVersionNotExist(t *testing.T) {
s := NewMemStorage()
expected := testUpdateCurrentVersionCheck(t, s, false)
assertExpectedMemoryTUFMeta(t, expected, s)
}

Expand Down
2 changes: 1 addition & 1 deletion server/storage/mysql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func init() {
if i == 29 {
logrus.Fatalf("Unable to connect to %s after 60 seconds", dburl)
}
time.Sleep(2)
time.Sleep(2 * time.Second)
}

sqldbSetup = func(t *testing.T) (*SQLStorage, func()) {
Expand Down
56 changes: 51 additions & 5 deletions server/storage/rethink_realdb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,14 @@ func TestRethinkBootstrapSetsUsernamePassword(t *testing.T) {
_, err := rethinkdb.UserConnection(tlsOpts, source, username, "wrongpass")
require.Error(t, err)

// the other user cannot access rethink
// the other user cannot access rethink, causing health checks to fail
userSession, err := rethinkdb.UserConnection(tlsOpts, source, otherUser, otherPass)
require.NoError(t, err)
s = NewRethinkDBStorage(dbname, otherUser, otherPass, userSession)
_, _, err = s.GetCurrent("gun", data.CanonicalRootRole)
require.Error(t, err)
require.IsType(t, gorethink.RQLRuntimeError{}, err)
require.Error(t, s.CheckHealth())

// our user can access the DB though
userSession, err = rethinkdb.UserConnection(tlsOpts, source, username, password)
Expand All @@ -75,6 +76,35 @@ func TestRethinkBootstrapSetsUsernamePassword(t *testing.T) {
_, _, err = s.GetCurrent("gun", data.CanonicalRootRole)
require.Error(t, err)
require.IsType(t, ErrNotFound{}, err)
require.NoError(t, s.CheckHealth())
}

func TestRethinkCheckHealth(t *testing.T) {
dbStore, cleanup := rethinkDBSetup(t)
defer cleanup()

// sanity check - all tables present - health check passes
require.NoError(t, dbStore.CheckHealth())

// if the DB is unreachable, health check fails
require.NoError(t, dbStore.sess.Close())
require.Error(t, dbStore.CheckHealth())

// if the connection is reopened, health check succeeds
require.NoError(t, dbStore.sess.Reconnect())
require.NoError(t, dbStore.CheckHealth())

// only one table existing causes health check to fail
require.NoError(t, gorethink.DB(dbStore.dbName).TableDrop(TUFFilesRethinkTable.Name).Exec(dbStore.sess))
require.Error(t, dbStore.CheckHealth())

// No tables, health check fails
require.NoError(t, gorethink.DB(dbStore.dbName).TableDrop(PubKeysRethinkTable.Name).Exec(dbStore.sess))
require.Error(t, dbStore.CheckHealth())

// No DB, health check fails
cleanup()
require.Error(t, dbStore.CheckHealth())
}

// UpdateCurrent will add a new TUF file if no previous version of that gun and role existed.
Expand All @@ -86,14 +116,23 @@ func TestRethinkUpdateCurrentEmpty(t *testing.T) {
}

// UpdateCurrent will add a new TUF file if the version is higher than previous, but fail
// if the version is equal to or less than the current, whether or not that previous
// version exists
func TestRethinkUpdateCurrentVersionCheck(t *testing.T) {
// if the version already exists in the DB
func TestRethinkUpdateCurrentVersionCheckOldVersionExists(t *testing.T) {
dbStore, cleanup := rethinkDBSetup(t)
defer cleanup()

testUpdateCurrentVersionCheck(t, dbStore, true)
}

// UpdateCurrent will successfully add a new (higher) version of an existing TUF file,
// but will return an error if the to-be-added version does not exist in the DB, but
// is older than an existing version in the DB.
func TestRethinkUpdateCurrentVersionCheckOldVersionNotExist(t *testing.T) {
t.Skip("Currently rethink only errors if the previous version exists - it doesn't check for strictly increasing")
dbStore, cleanup := rethinkDBSetup(t)
defer cleanup()

testUpdateCurrentVersionCheck(t, dbStore)
testUpdateCurrentVersionCheck(t, dbStore, false)
}

// UpdateMany succeeds if the updates do not conflict with each other or with what's
Expand Down Expand Up @@ -121,3 +160,10 @@ func TestRethinkDeleteSuccess(t *testing.T) {

testDeleteSuccess(t, dbStore)
}

func TestRethinkTUFMetaStoreGetCurrent(t *testing.T) {
dbStore, cleanup := rethinkDBSetup(t)
defer cleanup()

testTUFMetaStoreGetCurrent(t, dbStore)
}
16 changes: 6 additions & 10 deletions server/storage/rethinkdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/Sirupsen/logrus"
"github.com/docker/notary/storage/rethinkdb"
"github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/utils"
"gopkg.in/dancannon/gorethink.v2"
)

Expand Down Expand Up @@ -327,15 +326,12 @@ func (rdb RethinkDB) Bootstrap() error {

// CheckHealth checks that all tables and databases exist and are query-able
func (rdb RethinkDB) CheckHealth() error {
var tables []string
res, err := gorethink.DB(rdb.dbName).TableList().Run(rdb.sess)
if err != nil {
return err
}
defer res.Close()
err = res.All(&tables)
if err != nil || !utils.StrSliceContains(tables, RDBTUFFile{}.TableName()) || !utils.StrSliceContains(tables, RDBKey{}.TableName()) {
return fmt.Errorf("%s is unavailable and missing one or more tables", rdb.dbName)
for _, table := range []string{TUFFilesRethinkTable.Name, PubKeysRethinkTable.Name} {
res, err := gorethink.DB(rdb.dbName).Table(table).Info().Run(rdb.sess)
if err != nil {
return fmt.Errorf("%s is unavailable, or missing one or more tables, or permissions are incorrectly set", rdb.dbName)
}
defer res.Close()
}
return nil
}
5 changes: 3 additions & 2 deletions server/storage/sqldb.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,10 @@ func isReadErr(q *gorm.DB, row TUFFile) error {
return nil
}

// Delete deletes all the records for a specific GUN
// Delete deletes all the records for a specific GUN - we have to do a hard delete using Unscoped
// otherwise we can't insert for that GUN again
func (db *SQLStorage) Delete(gun string) error {
return db.Where(&TUFFile{Gun: gun}).Delete(TUFFile{}).Error
return db.Unscoped().Where(&TUFFile{Gun: gun}).Delete(TUFFile{}).Error
}

// GetKey returns the Public Key data for a gun+role
Expand Down
97 changes: 34 additions & 63 deletions server/storage/sqldb_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// +build !rethinkdb

package storage

import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"testing"
"time"

Expand Down Expand Up @@ -38,32 +39,6 @@ type sqldbSetupFunc func(*testing.T) (*SQLStorage, func())

var sqldbSetup sqldbSetupFunc

// SampleTUF returns a sample TUFFile with the given Version (ID will have
// to be set independently)
func SampleTUF(version int) TUFFile {
return SampleCustomTUF(data.CanonicalRootRole, "testGUN", []byte("1"), version)
}

func SampleCustomTUF(role, gun string, data []byte, version int) TUFFile {
checksum := sha256.Sum256(data)
hexChecksum := hex.EncodeToString(checksum[:])
return TUFFile{
Gun: gun,
Role: role,
Version: version,
Sha256: hexChecksum,
Data: data,
}
}

func SampleUpdate(version int) MetaUpdate {
return MetaUpdate{
Role: "root",
Version: version,
Data: []byte("1"),
}
}

func assertExpectedGormTUFMeta(t *testing.T, expected []StoredTUFMeta, gormDB gorm.DB) {
expectedGorm := make([]TUFFile, len(expected))
for i, tufObj := range expected {
Expand Down Expand Up @@ -101,14 +76,27 @@ func TestSQLUpdateCurrentEmpty(t *testing.T) {
dbStore.DB.Close()
}

// TestSQLUpdateCurrentNewVersion asserts that UpdateCurrent will add a
// TestSQLUpdateCurrentVersionCheckOldVersionExists asserts that UpdateCurrent will add a
// new (higher) version of an existing TUF file, and that an error is raised if
// trying to update to an older version of a TUF file that already exists.
func TestSQLUpdateCurrentVersionCheckOldVersionExists(t *testing.T) {
dbStore, cleanup := sqldbSetup(t)
defer cleanup()

expected := testUpdateCurrentVersionCheck(t, dbStore, true)
assertExpectedGormTUFMeta(t, expected, dbStore.DB)

dbStore.DB.Close()
}

// TestSQLUpdateCurrentVersionCheckOldVersionNotExist asserts that UpdateCurrent will add a
// new (higher) version of an existing TUF file, and that an error is raised if
// trying to update to an older version of a TUF file.
func TestSQLUpdateCurrentNewVersion(t *testing.T) {
// trying to update to an older version of a TUF file that doesn't exist in the DB.
func TestSQLUpdateCurrentVersionCheckOldVersionNotExist(t *testing.T) {
dbStore, cleanup := sqldbSetup(t)
defer cleanup()

expected := testUpdateCurrentVersionCheck(t, dbStore)
expected := testUpdateCurrentVersionCheck(t, dbStore, false)
assertExpectedGormTUFMeta(t, expected, dbStore.DB)

dbStore.DB.Close()
Expand Down Expand Up @@ -151,30 +139,6 @@ func TestSQLDelete(t *testing.T) {
dbStore.DB.Close()
}

func TestSQLGetCurrent(t *testing.T) {
dbStore, cleanup := sqldbSetup(t)
defer cleanup()

_, byt, err := dbStore.GetCurrent("testGUN", "root")
require.Nil(t, byt)
require.Error(t, err, "There should be an error Getting an empty table")
require.IsType(t, ErrNotFound{}, err, "Should get a not found error")

tuf := SampleTUF(0)
query := dbStore.DB.Create(&tuf)
require.NoError(t, query.Error, "Creating a row in an empty DB failed.")

cDate, byt, err := dbStore.GetCurrent("testGUN", "root")
require.NoError(t, err, "There should not be any errors getting.")
require.Equal(t, []byte("1"), byt, "Returned data was incorrect")
// the update date was sometime wthin the last minute
fmt.Println(cDate)
require.True(t, cDate.After(time.Now().Add(-1*time.Minute)))
require.True(t, cDate.Before(time.Now().Add(5*time.Second)))

dbStore.DB.Close()
}

func TestSQLGetKeyNoKey(t *testing.T) {
dbStore, cleanup := sqldbSetup(t)
defer cleanup()
Expand Down Expand Up @@ -295,9 +259,9 @@ func TestSQLSetKeySameRoleGun(t *testing.T) {
dbStore.DB.Close()
}

// TestDBCheckHealthTableMissing asserts that the health check fails if one or
// TestSQLDBCheckHealthTableMissing asserts that the health check fails if one or
// both the tables are missing.
func TestDBCheckHealthTableMissing(t *testing.T) {
func TestSQLDBCheckHealthTableMissing(t *testing.T) {
dbStore, cleanup := sqldbSetup(t)
defer cleanup()

Expand All @@ -319,9 +283,9 @@ func TestDBCheckHealthTableMissing(t *testing.T) {
require.Error(t, err, "Cannot access table:")
}

// TestDBCheckHealthDBCOnnection asserts that if the DB is not connectable, the
// TestSQLDBCheckHealthDBConnection asserts that if the DB is not connectable, the
// health check fails.
func TestDBCheckHealthDBConnectionFail(t *testing.T) {
func TestSQLDBCheckHealthDBConnectionFail(t *testing.T) {
dbStore, cleanup := sqldbSetup(t)
defer cleanup()

Expand All @@ -332,17 +296,17 @@ func TestDBCheckHealthDBConnectionFail(t *testing.T) {
require.Error(t, err, "Cannot access table:")
}

// TestDBCheckHealthSuceeds asserts that if the DB is connectable and both
// TestSQLDBCheckHealthSuceeds asserts that if the DB is connectable and both
// tables exist, the health check succeeds.
func TestDBCheckHealthSucceeds(t *testing.T) {
func TestSQLDBCheckHealthSucceeds(t *testing.T) {
dbStore, cleanup := sqldbSetup(t)
defer cleanup()

err := dbStore.CheckHealth()
require.NoError(t, err)
}

func TestDBGetChecksum(t *testing.T) {
func TestSQLDBGetChecksum(t *testing.T) {
dbStore, cleanup := sqldbSetup(t)
defer cleanup()

Expand Down Expand Up @@ -398,11 +362,18 @@ func TestDBGetChecksum(t *testing.T) {
require.True(t, cDate.Before(time.Now().Add(5*time.Second)))
}

func TestDBGetChecksumNotFound(t *testing.T) {
func TestSQLDBGetChecksumNotFound(t *testing.T) {
dbStore, cleanup := sqldbSetup(t)
defer cleanup()

_, _, err := dbStore.GetChecksum("gun", data.CanonicalTimestampRole, "12345")
require.Error(t, err)
require.IsType(t, ErrNotFound{}, err)
}

func TestSQLTUFMetaStoreGetCurrent(t *testing.T) {
dbStore, cleanup := sqldbSetup(t)
defer cleanup()

testTUFMetaStoreGetCurrent(t, dbStore)
}
2 changes: 1 addition & 1 deletion server/storage/sqlite_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build !mysqldb
// +build !mysqldb,!rethinkdb

// Initializes an SQLlite DBs for testing purposes

Expand Down
Loading