Add unit tests for SQLite metadata package (#3277)

Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
This commit is contained in:
Alessandro (Ale) Segala 2023-12-18 13:58:49 -08:00 committed by GitHub
parent 106b42fa5c
commit 9dba9c8f9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 323 additions and 38 deletions

View File

@ -14,34 +14,28 @@ limitations under the License.
package sqlite
import (
"io"
"net/url"
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/dapr/components-contrib/metadata"
"github.com/dapr/components-contrib/state"
"github.com/dapr/kit/logger"
kitmd "github.com/dapr/kit/metadata"
)
func TestSqliteMetadata(t *testing.T) {
stateMetadata := func(props map[string]string) state.Metadata {
return state.Metadata{Base: metadata.Base{Properties: props}}
}
func TestValidate(t *testing.T) {
t.Run("default options", func(t *testing.T) {
md := &SqliteAuthMetadata{}
md.Reset()
err := kitmd.DecodeMetadata(stateMetadata(map[string]string{
md := initTestMetadata(t, map[string]string{
"connectionString": "file:data.db",
}), &md)
})
err := md.Validate()
require.NoError(t, err)
err = md.Validate()
require.NoError(t, err)
assert.Equal(t, "file:data.db", md.ConnectionString)
assert.Equal(t, DefaultTimeout, md.Timeout)
assert.Equal(t, DefaultBusyTimeout, md.BusyTimeout)
@ -49,48 +43,339 @@ func TestSqliteMetadata(t *testing.T) {
})
t.Run("empty connection string", func(t *testing.T) {
md := &SqliteAuthMetadata{}
md.Reset()
err := kitmd.DecodeMetadata(stateMetadata(map[string]string{}), &md)
require.NoError(t, err)
err = md.Validate()
md := initTestMetadata(t, map[string]string{})
err := md.Validate()
require.Error(t, err)
require.ErrorContains(t, err, "missing connection string")
})
t.Run("invalid timeout", func(t *testing.T) {
md := &SqliteAuthMetadata{}
md.Reset()
err := kitmd.DecodeMetadata(stateMetadata(map[string]string{
md := initTestMetadata(t, map[string]string{
"connectionString": "file:data.db",
"timeout": "500ms",
}), &md)
require.NoError(t, err)
err = md.Validate()
})
err := md.Validate()
require.Error(t, err)
require.ErrorContains(t, err, "timeout")
})
t.Run("aliases", func(t *testing.T) {
md := &SqliteAuthMetadata{}
md.Reset()
err := kitmd.DecodeMetadata(stateMetadata(map[string]string{
md := initTestMetadata(t, map[string]string{
"url": "file:data.db",
"timeoutinseconds": "1200",
}), &md)
})
err := md.Validate()
require.NoError(t, err)
err = md.Validate()
require.NoError(t, err)
assert.Equal(t, "file:data.db", md.ConnectionString)
assert.Equal(t, 20*time.Minute, md.Timeout)
})
}
func TestGetConnectionStringe(t *testing.T) {
log := logger.NewLogger("test")
log.SetOutput(io.Discard)
t.Run("file name without prefix", func(t *testing.T) {
md := initTestMetadata(t, map[string]string{
"connectionString": "data.db",
})
err := md.Validate()
require.NoError(t, err)
connString, err := md.GetConnectionString(log, GetConnectionStringOpts{})
require.NoError(t, err)
u, err := url.Parse(connString)
require.NoError(t, err)
assert.True(t, strings.HasPrefix(connString, "file:data.db?"))
assert.EqualValues(t, url.Values{
"_pragma": {
"busy_timeout(2000)",
"journal_mode(WAL)",
},
"_txlock": {"immediate"},
}, u.Query())
})
t.Run("file name with prefix", func(t *testing.T) {
md := initTestMetadata(t, map[string]string{
"connectionString": "file:data.db",
})
err := md.Validate()
require.NoError(t, err)
connString, err := md.GetConnectionString(log, GetConnectionStringOpts{})
require.NoError(t, err)
u, err := url.Parse(connString)
require.NoError(t, err)
assert.True(t, strings.HasPrefix(connString, "file:data.db?"))
assert.EqualValues(t, url.Values{
"_pragma": {
"busy_timeout(2000)",
"journal_mode(WAL)",
},
"_txlock": {"immediate"},
}, u.Query())
})
t.Run("in-memory without prefix", func(t *testing.T) {
md := initTestMetadata(t, map[string]string{
"connectionString": ":memory:",
})
err := md.Validate()
require.NoError(t, err)
connString, err := md.GetConnectionString(log, GetConnectionStringOpts{})
require.NoError(t, err)
u, err := url.Parse(connString)
require.NoError(t, err)
assert.True(t, strings.HasPrefix(connString, "file::memory:?"))
assert.EqualValues(t, url.Values{
"_pragma": {
"busy_timeout(2000)",
"journal_mode(MEMORY)",
},
"_txlock": {"immediate"},
"cache": {"shared"},
}, u.Query())
})
t.Run("in-memory with prefix", func(t *testing.T) {
md := initTestMetadata(t, map[string]string{
"connectionString": "file::memory:",
})
err := md.Validate()
require.NoError(t, err)
connString, err := md.GetConnectionString(log, GetConnectionStringOpts{})
require.NoError(t, err)
u, err := url.Parse(connString)
require.NoError(t, err)
assert.True(t, strings.HasPrefix(connString, "file::memory:?"))
assert.EqualValues(t, url.Values{
"_pragma": {
"busy_timeout(2000)",
"journal_mode(MEMORY)",
},
"_txlock": {"immediate"},
"cache": {"shared"},
}, u.Query())
})
t.Run("enable foreign keys", func(t *testing.T) {
md := initTestMetadata(t, map[string]string{
"connectionString": "data.db",
})
err := md.Validate()
require.NoError(t, err)
connString, err := md.GetConnectionString(log, GetConnectionStringOpts{
EnableForeignKeys: true,
})
require.NoError(t, err)
u, err := url.Parse(connString)
require.NoError(t, err)
assert.True(t, strings.HasPrefix(connString, "file:data.db?"))
assert.EqualValues(t, url.Values{
"_pragma": {
"busy_timeout(2000)",
"journal_mode(WAL)",
"foreign_keys(1)",
},
"_txlock": {"immediate"},
}, u.Query())
})
t.Run("set busy timeout", func(t *testing.T) {
md := initTestMetadata(t, map[string]string{
"connectionString": "data.db",
"busyTimeout": "1m",
})
err := md.Validate()
require.NoError(t, err)
connString, err := md.GetConnectionString(log, GetConnectionStringOpts{})
require.NoError(t, err)
u, err := url.Parse(connString)
require.NoError(t, err)
assert.True(t, strings.HasPrefix(connString, "file:data.db?"))
assert.EqualValues(t, url.Values{
"_pragma": {
"busy_timeout(60000)",
"journal_mode(WAL)",
},
"_txlock": {"immediate"},
}, u.Query())
})
t.Run("disable WAL", func(t *testing.T) {
md := initTestMetadata(t, map[string]string{
"connectionString": "data.db",
"disableWAL": "true",
})
err := md.Validate()
require.NoError(t, err)
connString, err := md.GetConnectionString(log, GetConnectionStringOpts{})
require.NoError(t, err)
u, err := url.Parse(connString)
require.NoError(t, err)
assert.True(t, strings.HasPrefix(connString, "file:data.db?"))
assert.EqualValues(t, url.Values{
"_pragma": {
"busy_timeout(2000)",
"journal_mode(DELETE)",
},
"_txlock": {"immediate"},
}, u.Query())
})
t.Run("read-only", func(t *testing.T) {
md := initTestMetadata(t, map[string]string{
"connectionString": "file:data.db?mode=ro",
})
err := md.Validate()
require.NoError(t, err)
connString, err := md.GetConnectionString(log, GetConnectionStringOpts{})
require.NoError(t, err)
u, err := url.Parse(connString)
require.NoError(t, err)
assert.True(t, strings.HasPrefix(connString, "file:data.db?"))
assert.EqualValues(t, url.Values{
"_pragma": {
"busy_timeout(2000)",
"journal_mode(DELETE)",
},
"_txlock": {"immediate"},
"mode": {"ro"},
}, u.Query())
})
t.Run("immutable", func(t *testing.T) {
md := initTestMetadata(t, map[string]string{
"connectionString": "file:data.db?immutable=1",
})
err := md.Validate()
require.NoError(t, err)
connString, err := md.GetConnectionString(log, GetConnectionStringOpts{})
require.NoError(t, err)
u, err := url.Parse(connString)
require.NoError(t, err)
assert.True(t, strings.HasPrefix(connString, "file:data.db?"))
assert.EqualValues(t, url.Values{
"_pragma": {
"busy_timeout(2000)",
"journal_mode(DELETE)",
},
"_txlock": {"immediate"},
"immutable": {"1"},
}, u.Query())
})
t.Run("do not override txlock", func(t *testing.T) {
md := initTestMetadata(t, map[string]string{
"connectionString": "file:data.db?_txlock=deferred",
})
err := md.Validate()
require.NoError(t, err)
connString, err := md.GetConnectionString(log, GetConnectionStringOpts{})
require.NoError(t, err)
u, err := url.Parse(connString)
require.NoError(t, err)
assert.True(t, strings.HasPrefix(connString, "file:data.db?"))
assert.EqualValues(t, url.Values{
"_pragma": {
"busy_timeout(2000)",
"journal_mode(WAL)",
},
"_txlock": {"deferred"},
}, u.Query())
})
t.Run("error if busy_timeout is set", func(t *testing.T) {
md := initTestMetadata(t, map[string]string{
"connectionString": "file:data.db?_pragma=busy_timeout(1000)",
})
err := md.Validate()
require.NoError(t, err)
_, err = md.GetConnectionString(log, GetConnectionStringOpts{})
require.Error(t, err)
require.ErrorContains(t, err, "_pragma=busy_timeout")
})
t.Run("error if journal_mode is set", func(t *testing.T) {
md := initTestMetadata(t, map[string]string{
"connectionString": "file:data.db?_pragma=journal_mode(DELETE)",
})
err := md.Validate()
require.NoError(t, err)
_, err = md.GetConnectionString(log, GetConnectionStringOpts{})
require.Error(t, err)
require.ErrorContains(t, err, "_pragma=journal_mode")
})
t.Run("error if foreign_keys is set", func(t *testing.T) {
md := initTestMetadata(t, map[string]string{
"connectionString": "file:data.db?_pragma=foreign_keys(1)",
})
err := md.Validate()
require.NoError(t, err)
_, err = md.GetConnectionString(log, GetConnectionStringOpts{})
require.Error(t, err)
require.ErrorContains(t, err, "_pragma=foreign_keys")
})
}
func initTestMetadata(t *testing.T, props map[string]string) *SqliteAuthMetadata {
t.Helper()
md := &SqliteAuthMetadata{}
md.Reset()
err := kitmd.DecodeMetadata(props, &md)
require.NoError(t, err)
return md
}