docs/server/storage/database_test.go

204 lines
6.0 KiB
Go

package storage
import (
"database/sql"
"io/ioutil"
"os"
"testing"
"github.com/endophage/gotuf/data"
"github.com/jinzhu/gorm"
_ "github.com/mattn/go-sqlite3"
"github.com/stretchr/testify/assert"
)
// GormTUFFile represents a TUF file in the database
type GormTUFFile struct {
ID int `sql:"AUTO_INCREMENT" gorm:"primary_key"`
Gun string `sql:"type:varchar(255);not null"`
Role string `sql:"type:varchar(255);not null"`
Version int
Data []byte `sql:"type:longblob"`
}
// TableName sets a specific table name for GormTUFFile
func (g GormTUFFile) TableName() string {
return "tuf_files"
}
// GormTimestampKey represents a single timestamp key in the database
type GormTimestampKey struct {
Gun string `sql:"type:varchar(255)" gorm:"primary key"`
Cipher string `sql:"type:varchar(30)"`
Public []byte `sql:"type:blob;not null"`
}
// TableName sets a specific table name for our GormTimestampKey
func (g GormTimestampKey) TableName() string {
return "timestamp_keys"
}
// SetUpSQLite creates a sqlite database for testing
func SetUpSQLite(t *testing.T) (*gorm.DB, *MySQLStorage) {
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
defer os.RemoveAll(tempBaseDir)
// We are using SQLite for the tests
db, err := sql.Open("sqlite3", tempBaseDir+"test_db")
assert.NoError(t, err)
// Create the DB tables
gormDB, _ := gorm.Open("sqlite3", db)
query := gormDB.CreateTable(&GormTUFFile{})
assert.NoError(t, query.Error)
query = gormDB.Model(&GormTUFFile{}).AddUniqueIndex(
"idx_gun", "gun", "role", "version")
assert.NoError(t, query.Error)
query = gormDB.CreateTable(&GormTimestampKey{})
assert.NoError(t, query.Error)
return &gormDB, NewMySQLStorage(db)
}
func TestMySQLUpdateCurrent(t *testing.T) {
_, dbStore := SetUpSQLite(t)
update := MetaUpdate{
Role: "root",
Version: 0,
Data: []byte("1"),
}
err := dbStore.UpdateCurrent("testGUN", update)
assert.NoError(t, err, "Creating a row in an empty DB failed.")
err = dbStore.UpdateCurrent("testGUN", update)
assert.Error(t, err, "Error should not be nil")
assert.IsType(t, &ErrOldVersion{}, err,
"Expected ErrOldVersion error type, got: %v", err)
dbStore.DB.Close()
}
func TestMySQLUpdateMany(t *testing.T) {
_, dbStore := SetUpSQLite(t)
update1 := MetaUpdate{
Role: "root",
Version: 0,
Data: []byte("1"),
}
update2 := MetaUpdate{
Role: "targets",
Version: 1,
Data: []byte("2"),
}
err := dbStore.UpdateMany("testGUN", []MetaUpdate{update1, update2})
assert.NoError(t, err, "UpdateMany errored unexpectedly: %v", err)
dbStore.DB.Close()
}
func TestMySQLUpdateManyDuplicateRollback(t *testing.T) {
_, dbStore := SetUpSQLite(t)
update := MetaUpdate{
Role: "root",
Version: 0,
Data: []byte("1"),
}
err := dbStore.UpdateMany("testGUN", []MetaUpdate{update, update})
assert.Error(t, err, "There should be an error updating twice.")
// sqlite3 error and mysql error aren't compatible
// assert.IsType(t, &ErrOldVersion{}, err,
// "UpdateMany returned wrong error type")
// the whole transaction should have rolled back, so there should be
// no entries.
byt, err := dbStore.GetCurrent("testGUN", "root")
assert.Nil(t, byt)
assert.Error(t, err, "There should be an error Getting any entries")
assert.IsType(t, &ErrNotFound{}, err, "Should get a not found error")
dbStore.DB.Close()
}
func TestMySQLGetCurrent(t *testing.T) {
_, dbStore := SetUpSQLite(t)
byt, err := dbStore.GetCurrent("testGUN", "root")
assert.Nil(t, byt)
assert.Error(t, err, "There should be an error Getting an empty table")
assert.IsType(t, &ErrNotFound{}, err, "Should get a not found error")
// use UpdateCurrent to create one and test GetCurrent
update := MetaUpdate{
Role: "root",
Version: 0,
Data: []byte("1"),
}
err = dbStore.UpdateCurrent("testGUN", update)
assert.NoError(t, err, "Creating a row in an empty DB failed.")
byt, err = dbStore.GetCurrent("testGUN", "root")
assert.NoError(t, err, "There should not be any errors getting.")
assert.Equal(t, []byte("1"), byt, "Returned data was incorrect")
dbStore.DB.Close()
}
func TestMySQLDelete(t *testing.T) {
_, dbStore := SetUpSQLite(t)
// Not testing deleting from an empty table, because that's not an error
// in SQLite3
// use UpdateCurrent to create one and test GetCurrent
update := MetaUpdate{
Role: "root",
Version: 0,
Data: []byte("1"),
}
err := dbStore.UpdateCurrent("testGUN", update)
assert.NoError(t, err, "Creating a row in an empty DB failed.")
err = dbStore.Delete("testGUN")
assert.NoError(t, err, "There should not be any errors deleting.")
dbStore.DB.Close()
}
func TestMySQLGetTimestampKeyNoKey(t *testing.T) {
_, dbStore := SetUpSQLite(t)
cipher, public, err := dbStore.GetTimestampKey("testGUN")
assert.Equal(t, data.KeyAlgorithm(""), cipher)
assert.Nil(t, public)
assert.IsType(t, &ErrNoKey{}, err,
"Expected ErrNoKey from GetTimestampKey")
err = dbStore.SetTimestampKey("testGUN", "testCipher", []byte("1"))
assert.NoError(t, err, "Inserting timestamp into empty DB should succeed")
cipher, public, err = dbStore.GetTimestampKey("testGUN")
assert.Equal(t, data.KeyAlgorithm("testCipher"), cipher,
"Returned cipher was incorrect")
assert.Equal(t, []byte("1"), public, "Returned pubkey was incorrect")
}
func TestMySQLSetTimestampKeyExists(t *testing.T) {
_, dbStore := SetUpSQLite(t)
err := dbStore.SetTimestampKey("testGUN", "testCipher", []byte("1"))
assert.NoError(t, err, "Inserting timestamp into empty DB should succeed")
err = dbStore.SetTimestampKey("testGUN", "testCipher", []byte("1"))
// sqlite3 error and mysql error aren't compatible
// assert.IsType(t, &ErrTimestampKeyExists{}, err,
// "Expected ErrTimestampKeyExists from SetTimestampKey")
dbStore.DB.Close()
}