Add unit tests for SQLite metadata package (#3277)
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
This commit is contained in:
parent
106b42fa5c
commit
9dba9c8f9d
|
|
@ -14,34 +14,28 @@ limitations under the License.
|
||||||
package sqlite
|
package sqlite
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/dapr/components-contrib/metadata"
|
"github.com/dapr/kit/logger"
|
||||||
"github.com/dapr/components-contrib/state"
|
|
||||||
kitmd "github.com/dapr/kit/metadata"
|
kitmd "github.com/dapr/kit/metadata"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSqliteMetadata(t *testing.T) {
|
func TestValidate(t *testing.T) {
|
||||||
stateMetadata := func(props map[string]string) state.Metadata {
|
|
||||||
return state.Metadata{Base: metadata.Base{Properties: props}}
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Run("default options", func(t *testing.T) {
|
t.Run("default options", func(t *testing.T) {
|
||||||
md := &SqliteAuthMetadata{}
|
md := initTestMetadata(t, map[string]string{
|
||||||
md.Reset()
|
|
||||||
|
|
||||||
err := kitmd.DecodeMetadata(stateMetadata(map[string]string{
|
|
||||||
"connectionString": "file:data.db",
|
"connectionString": "file:data.db",
|
||||||
}), &md)
|
})
|
||||||
|
|
||||||
|
err := md.Validate()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = md.Validate()
|
|
||||||
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Equal(t, "file:data.db", md.ConnectionString)
|
assert.Equal(t, "file:data.db", md.ConnectionString)
|
||||||
assert.Equal(t, DefaultTimeout, md.Timeout)
|
assert.Equal(t, DefaultTimeout, md.Timeout)
|
||||||
assert.Equal(t, DefaultBusyTimeout, md.BusyTimeout)
|
assert.Equal(t, DefaultBusyTimeout, md.BusyTimeout)
|
||||||
|
|
@ -49,48 +43,339 @@ func TestSqliteMetadata(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("empty connection string", func(t *testing.T) {
|
t.Run("empty connection string", func(t *testing.T) {
|
||||||
md := &SqliteAuthMetadata{}
|
md := initTestMetadata(t, map[string]string{})
|
||||||
md.Reset()
|
|
||||||
|
|
||||||
err := kitmd.DecodeMetadata(stateMetadata(map[string]string{}), &md)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
err = md.Validate()
|
|
||||||
|
|
||||||
|
err := md.Validate()
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.ErrorContains(t, err, "missing connection string")
|
require.ErrorContains(t, err, "missing connection string")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("invalid timeout", func(t *testing.T) {
|
t.Run("invalid timeout", func(t *testing.T) {
|
||||||
md := &SqliteAuthMetadata{}
|
md := initTestMetadata(t, map[string]string{
|
||||||
md.Reset()
|
|
||||||
|
|
||||||
err := kitmd.DecodeMetadata(stateMetadata(map[string]string{
|
|
||||||
"connectionString": "file:data.db",
|
"connectionString": "file:data.db",
|
||||||
"timeout": "500ms",
|
"timeout": "500ms",
|
||||||
}), &md)
|
})
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
err = md.Validate()
|
|
||||||
|
|
||||||
|
err := md.Validate()
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.ErrorContains(t, err, "timeout")
|
require.ErrorContains(t, err, "timeout")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("aliases", func(t *testing.T) {
|
t.Run("aliases", func(t *testing.T) {
|
||||||
md := &SqliteAuthMetadata{}
|
md := initTestMetadata(t, map[string]string{
|
||||||
md.Reset()
|
|
||||||
|
|
||||||
err := kitmd.DecodeMetadata(stateMetadata(map[string]string{
|
|
||||||
"url": "file:data.db",
|
"url": "file:data.db",
|
||||||
"timeoutinseconds": "1200",
|
"timeoutinseconds": "1200",
|
||||||
}), &md)
|
})
|
||||||
|
|
||||||
|
err := md.Validate()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = md.Validate()
|
|
||||||
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Equal(t, "file:data.db", md.ConnectionString)
|
assert.Equal(t, "file:data.db", md.ConnectionString)
|
||||||
assert.Equal(t, 20*time.Minute, md.Timeout)
|
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
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue