2024-07-18 23:03:18 +08:00
|
|
|
package sql
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2024-07-23 01:08:30 +08:00
|
|
|
"database/sql/driver"
|
|
|
|
"errors"
|
2024-07-18 23:03:18 +08:00
|
|
|
"testing"
|
|
|
|
|
2024-07-23 01:08:30 +08:00
|
|
|
sqlmock "github.com/DATA-DOG/go-sqlmock"
|
|
|
|
"github.com/stretchr/testify/require"
|
2024-11-12 19:52:04 +08:00
|
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
2024-07-23 01:08:30 +08:00
|
|
|
|
2024-11-12 19:52:04 +08:00
|
|
|
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
2024-07-18 23:03:18 +08:00
|
|
|
"github.com/grafana/grafana/pkg/storage/unified/resource"
|
|
|
|
"github.com/grafana/grafana/pkg/storage/unified/sql/db/dbimpl"
|
2024-07-23 01:08:30 +08:00
|
|
|
"github.com/grafana/grafana/pkg/storage/unified/sql/test"
|
|
|
|
"github.com/grafana/grafana/pkg/util/testutil"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
errTest = errors.New("things happened")
|
|
|
|
resKey = &resource.ResourceKey{
|
|
|
|
Namespace: "ns",
|
|
|
|
Group: "gr",
|
|
|
|
Resource: "rs",
|
|
|
|
Name: "nm",
|
|
|
|
}
|
2024-07-18 23:03:18 +08:00
|
|
|
)
|
|
|
|
|
2024-07-23 01:08:30 +08:00
|
|
|
type (
|
|
|
|
Cols = []string // column names
|
|
|
|
Rows = [][]driver.Value // row values returned
|
|
|
|
)
|
|
|
|
|
|
|
|
type testBackend struct {
|
|
|
|
*backend
|
|
|
|
test.TestDBProvider
|
2024-07-18 23:03:18 +08:00
|
|
|
}
|
|
|
|
|
2024-10-11 17:11:33 +08:00
|
|
|
func (b testBackend) ExecWithResult(expectedSQL string, lastInsertID int64, rowsAffected int64) {
|
|
|
|
b.SQLMock.ExpectExec(expectedSQL).WillReturnResult(sqlmock.NewResult(lastInsertID, rowsAffected))
|
2024-07-23 01:08:30 +08:00
|
|
|
}
|
2024-07-18 23:03:18 +08:00
|
|
|
|
2024-07-23 01:08:30 +08:00
|
|
|
func (b testBackend) ExecWithErr(expectedSQL string, err error) {
|
|
|
|
b.SQLMock.ExpectExec(expectedSQL).WillReturnError(err)
|
|
|
|
}
|
2024-07-18 23:03:18 +08:00
|
|
|
|
2024-07-23 01:08:30 +08:00
|
|
|
func (b testBackend) QueryWithResult(expectedSQL string, numCols int, rs Rows) {
|
|
|
|
rows := b.SQLMock.NewRows(make([]string, numCols))
|
|
|
|
if len(rs) > 0 {
|
|
|
|
rows = rows.AddRows(rs...)
|
|
|
|
}
|
|
|
|
b.SQLMock.ExpectQuery(expectedSQL).WillReturnRows(rows)
|
|
|
|
}
|
2024-07-18 23:03:18 +08:00
|
|
|
|
2024-07-23 01:08:30 +08:00
|
|
|
func (b testBackend) QueryWithErr(expectedSQL string, err error) {
|
|
|
|
b.SQLMock.ExpectQuery(expectedSQL).WillReturnError(err)
|
|
|
|
}
|
2024-07-18 23:03:18 +08:00
|
|
|
|
2024-07-23 01:08:30 +08:00
|
|
|
func setupBackendTest(t *testing.T) (testBackend, context.Context) {
|
|
|
|
t.Helper()
|
2024-07-18 23:03:18 +08:00
|
|
|
|
2024-07-23 01:08:30 +08:00
|
|
|
ctx := testutil.NewDefaultTestContext(t)
|
|
|
|
dbp := test.NewDBProviderMatchWords(t)
|
2025-01-23 18:34:48 +08:00
|
|
|
b, err := NewBackend(BackendOptions{DBProvider: dbp})
|
2024-07-23 01:08:30 +08:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, b)
|
2024-07-18 23:03:18 +08:00
|
|
|
|
2024-07-23 01:08:30 +08:00
|
|
|
err = b.Init(ctx)
|
|
|
|
require.NoError(t, err)
|
2024-07-18 23:03:18 +08:00
|
|
|
|
2024-07-23 01:08:30 +08:00
|
|
|
bb, ok := b.(*backend)
|
|
|
|
require.True(t, ok)
|
|
|
|
require.NotNil(t, bb)
|
|
|
|
|
|
|
|
return testBackend{
|
|
|
|
backend: bb,
|
|
|
|
TestDBProvider: dbp,
|
|
|
|
}, ctx
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNewBackend(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
t.Run("happy path", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
dbp := test.NewDBProviderNopSQL(t)
|
|
|
|
b, err := NewBackend(BackendOptions{DBProvider: dbp})
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, b)
|
2024-07-18 23:03:18 +08:00
|
|
|
})
|
|
|
|
|
2024-07-23 01:08:30 +08:00
|
|
|
t.Run("no db provider", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
b, err := NewBackend(BackendOptions{})
|
|
|
|
require.Nil(t, b)
|
|
|
|
require.Error(t, err)
|
|
|
|
require.ErrorContains(t, err, "no db provider")
|
2024-07-18 23:03:18 +08:00
|
|
|
})
|
2024-07-23 01:08:30 +08:00
|
|
|
}
|
2024-07-18 23:03:18 +08:00
|
|
|
|
2024-07-23 01:08:30 +08:00
|
|
|
func TestBackend_Init(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
t.Run("happy path", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
ctx := testutil.NewDefaultTestContext(t)
|
|
|
|
dbp := test.NewDBProviderWithPing(t)
|
2025-01-23 18:34:48 +08:00
|
|
|
b, err := NewBackend(BackendOptions{DBProvider: dbp})
|
2024-07-23 01:08:30 +08:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, b)
|
|
|
|
|
|
|
|
dbp.SQLMock.ExpectPing().WillReturnError(nil)
|
|
|
|
err = b.Init(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// if it isn't idempotent, then it will make a second ping and the
|
|
|
|
// expectation will fail
|
|
|
|
err = b.Init(ctx)
|
|
|
|
require.NoError(t, err, "should be idempotent")
|
|
|
|
|
|
|
|
err = b.Stop(ctx)
|
|
|
|
require.NoError(t, err)
|
2024-07-18 23:03:18 +08:00
|
|
|
})
|
|
|
|
|
2024-07-23 01:08:30 +08:00
|
|
|
t.Run("no db provider", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
ctx := testutil.NewDefaultTestContext(t)
|
|
|
|
dbp := test.TestDBProvider{
|
|
|
|
Err: errTest,
|
|
|
|
}
|
|
|
|
b, err := NewBackend(BackendOptions{DBProvider: dbp})
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, b)
|
|
|
|
|
|
|
|
err = b.Init(ctx)
|
|
|
|
require.Error(t, err)
|
|
|
|
require.ErrorContains(t, err, "initialize resource DB")
|
2024-07-18 23:03:18 +08:00
|
|
|
})
|
|
|
|
|
2024-07-23 01:08:30 +08:00
|
|
|
t.Run("no dialect for driver", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
ctx := testutil.NewDefaultTestContext(t)
|
|
|
|
mockDB, _, err := sqlmock.New()
|
|
|
|
require.NoError(t, err)
|
|
|
|
dbp := test.TestDBProvider{
|
|
|
|
DB: dbimpl.NewDB(mockDB, "juancarlo"),
|
|
|
|
}
|
|
|
|
|
|
|
|
b, err := NewBackend(BackendOptions{DBProvider: dbp})
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, b)
|
|
|
|
|
|
|
|
err = b.Init(ctx)
|
|
|
|
require.Error(t, err)
|
|
|
|
require.ErrorContains(t, err, "no dialect for driver")
|
2024-07-18 23:03:18 +08:00
|
|
|
})
|
|
|
|
|
2024-07-23 01:08:30 +08:00
|
|
|
t.Run("database unreachable", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
ctx := testutil.NewDefaultTestContext(t)
|
|
|
|
dbp := test.NewDBProviderWithPing(t)
|
2025-01-23 18:34:48 +08:00
|
|
|
b, err := NewBackend(BackendOptions{DBProvider: dbp})
|
2024-07-23 01:08:30 +08:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, dbp.DB)
|
|
|
|
|
|
|
|
dbp.SQLMock.ExpectPing().WillReturnError(errTest)
|
|
|
|
err = b.Init(ctx)
|
|
|
|
require.Error(t, err)
|
|
|
|
require.ErrorIs(t, err, errTest)
|
2024-07-18 23:03:18 +08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-07-23 01:08:30 +08:00
|
|
|
func TestBackend_IsHealthy(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
ctx := testutil.NewDefaultTestContext(t)
|
|
|
|
dbp := test.NewDBProviderWithPing(t)
|
2025-01-23 18:34:48 +08:00
|
|
|
b, err := NewBackend(BackendOptions{DBProvider: dbp})
|
2024-07-23 01:08:30 +08:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, dbp.DB)
|
|
|
|
|
|
|
|
dbp.SQLMock.ExpectPing().WillReturnError(nil)
|
|
|
|
err = b.Init(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
dbp.SQLMock.ExpectPing().WillReturnError(nil)
|
|
|
|
res, err := b.IsHealthy(ctx, nil)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, res)
|
|
|
|
|
|
|
|
dbp.SQLMock.ExpectPing().WillReturnError(errTest)
|
|
|
|
res, err = b.IsHealthy(ctx, nil)
|
|
|
|
require.Nil(t, res)
|
|
|
|
require.Error(t, err)
|
|
|
|
require.ErrorIs(t, err, errTest)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestBackend_create(t *testing.T) {
|
|
|
|
t.Parallel()
|
2024-11-12 19:52:04 +08:00
|
|
|
meta, err := utils.MetaAccessor(&unstructured.Unstructured{
|
|
|
|
Object: map[string]any{},
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
2024-07-23 01:08:30 +08:00
|
|
|
event := resource.WriteEvent{
|
2024-11-12 19:52:04 +08:00
|
|
|
Type: resource.WatchEvent_ADDED,
|
|
|
|
Key: resKey,
|
|
|
|
Object: meta,
|
2024-07-23 01:08:30 +08:00
|
|
|
}
|
2024-07-18 23:03:18 +08:00
|
|
|
|
2024-07-23 01:08:30 +08:00
|
|
|
t.Run("happy path", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
b, ctx := setupBackendTest(t)
|
|
|
|
b.SQLMock.ExpectBegin()
|
2025-03-13 16:24:12 +08:00
|
|
|
expectSuccessfulResourceVersionExec(t, b.TestDBProvider,
|
|
|
|
func() { b.ExecWithResult("insert resource", 0, 1) },
|
|
|
|
func() { b.ExecWithResult("insert resource_history", 0, 1) },
|
|
|
|
)
|
2024-07-23 01:08:30 +08:00
|
|
|
b.SQLMock.ExpectCommit()
|
|
|
|
v, err := b.create(ctx, event)
|
|
|
|
require.NoError(t, err)
|
2025-03-13 16:24:12 +08:00
|
|
|
require.Equal(t, int64(200), v)
|
2024-07-18 23:03:18 +08:00
|
|
|
})
|
|
|
|
|
2024-07-23 01:08:30 +08:00
|
|
|
t.Run("error inserting into resource", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
b, ctx := setupBackendTest(t)
|
|
|
|
|
|
|
|
b.SQLMock.ExpectBegin()
|
|
|
|
b.ExecWithErr("insert resource", errTest)
|
|
|
|
b.SQLMock.ExpectRollback()
|
|
|
|
|
|
|
|
v, err := b.create(ctx, event)
|
|
|
|
require.Zero(t, v)
|
|
|
|
require.Error(t, err)
|
2025-03-13 16:24:12 +08:00
|
|
|
require.ErrorContains(t, err, "insert into resource")
|
2024-07-18 23:03:18 +08:00
|
|
|
})
|
|
|
|
|
2024-07-23 01:08:30 +08:00
|
|
|
t.Run("error inserting into resource_history", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
b, ctx := setupBackendTest(t)
|
|
|
|
|
|
|
|
b.SQLMock.ExpectBegin()
|
2024-10-11 17:11:33 +08:00
|
|
|
b.ExecWithResult("insert resource", 0, 1)
|
2024-07-23 01:08:30 +08:00
|
|
|
b.ExecWithErr("insert resource_history", errTest)
|
|
|
|
b.SQLMock.ExpectRollback()
|
|
|
|
|
|
|
|
v, err := b.create(ctx, event)
|
|
|
|
require.Zero(t, v)
|
|
|
|
require.Error(t, err)
|
2025-03-13 16:24:12 +08:00
|
|
|
require.ErrorContains(t, err, "insert into resource history")
|
2024-07-18 23:03:18 +08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-07-23 01:08:30 +08:00
|
|
|
func TestBackend_update(t *testing.T) {
|
|
|
|
t.Parallel()
|
2024-11-12 19:52:04 +08:00
|
|
|
meta, err := utils.MetaAccessor(&unstructured.Unstructured{
|
|
|
|
Object: map[string]any{},
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
meta.SetFolder("folderuid")
|
2024-07-23 01:08:30 +08:00
|
|
|
event := resource.WriteEvent{
|
2024-11-12 19:52:04 +08:00
|
|
|
Type: resource.WatchEvent_MODIFIED,
|
|
|
|
Key: resKey,
|
|
|
|
Object: meta,
|
2024-07-23 01:08:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
t.Run("happy path", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
b, ctx := setupBackendTest(t)
|
|
|
|
|
|
|
|
b.SQLMock.ExpectBegin()
|
2025-03-13 16:24:12 +08:00
|
|
|
expectSuccessfulResourceVersionExec(t, b.TestDBProvider,
|
|
|
|
func() { b.ExecWithResult("update resource", 0, 1) },
|
|
|
|
func() { b.ExecWithResult("insert resource_history", 0, 1) },
|
|
|
|
)
|
2024-07-23 01:08:30 +08:00
|
|
|
b.SQLMock.ExpectCommit()
|
|
|
|
|
|
|
|
v, err := b.update(ctx, event)
|
|
|
|
require.NoError(t, err)
|
2025-03-13 16:24:12 +08:00
|
|
|
require.Equal(t, int64(200), v)
|
2024-07-23 01:08:30 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("error in first update to resource", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
b, ctx := setupBackendTest(t)
|
|
|
|
|
|
|
|
b.SQLMock.ExpectBegin()
|
|
|
|
b.ExecWithErr("update resource", errTest)
|
|
|
|
b.SQLMock.ExpectRollback()
|
|
|
|
|
|
|
|
v, err := b.update(ctx, event)
|
|
|
|
require.Zero(t, v)
|
|
|
|
require.Error(t, err)
|
2025-03-13 16:24:12 +08:00
|
|
|
require.ErrorContains(t, err, "resource update")
|
2024-07-23 01:08:30 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("error inserting into resource history", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
b, ctx := setupBackendTest(t)
|
|
|
|
|
|
|
|
b.SQLMock.ExpectBegin()
|
2024-10-11 17:11:33 +08:00
|
|
|
b.ExecWithResult("update resource", 0, 1)
|
2024-07-23 01:08:30 +08:00
|
|
|
b.ExecWithErr("insert resource_history", errTest)
|
|
|
|
b.SQLMock.ExpectRollback()
|
|
|
|
|
|
|
|
v, err := b.update(ctx, event)
|
|
|
|
require.Zero(t, v)
|
|
|
|
require.Error(t, err)
|
|
|
|
require.ErrorContains(t, err, "insert into resource history")
|
|
|
|
})
|
2024-07-18 23:03:18 +08:00
|
|
|
}
|
|
|
|
|
2024-07-23 01:08:30 +08:00
|
|
|
func TestBackend_delete(t *testing.T) {
|
|
|
|
t.Parallel()
|
2024-11-12 19:52:04 +08:00
|
|
|
meta, err := utils.MetaAccessor(&unstructured.Unstructured{
|
|
|
|
Object: map[string]any{},
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
2024-07-23 01:08:30 +08:00
|
|
|
event := resource.WriteEvent{
|
2024-11-12 19:52:04 +08:00
|
|
|
Type: resource.WatchEvent_DELETED,
|
|
|
|
Key: resKey,
|
|
|
|
Object: meta,
|
2024-07-18 23:03:18 +08:00
|
|
|
}
|
2024-07-23 01:08:30 +08:00
|
|
|
|
|
|
|
t.Run("happy path", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
b, ctx := setupBackendTest(t)
|
|
|
|
|
|
|
|
b.SQLMock.ExpectBegin()
|
2025-03-13 16:24:12 +08:00
|
|
|
expectSuccessfulResourceVersionExec(t, b.TestDBProvider,
|
|
|
|
func() { b.ExecWithResult("delete resource", 0, 1) },
|
|
|
|
func() { b.ExecWithResult("insert resource_history", 0, 1) },
|
|
|
|
)
|
2024-07-23 01:08:30 +08:00
|
|
|
b.SQLMock.ExpectCommit()
|
|
|
|
|
|
|
|
v, err := b.delete(ctx, event)
|
|
|
|
require.NoError(t, err)
|
2025-03-13 16:24:12 +08:00
|
|
|
require.Equal(t, int64(200), v)
|
2024-07-23 01:08:30 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("error deleting resource", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
b, ctx := setupBackendTest(t)
|
|
|
|
|
|
|
|
b.SQLMock.ExpectBegin()
|
|
|
|
b.ExecWithErr("delete resource", errTest)
|
|
|
|
b.SQLMock.ExpectCommit()
|
|
|
|
|
|
|
|
v, err := b.delete(ctx, event)
|
|
|
|
require.Zero(t, v)
|
|
|
|
require.Error(t, err)
|
|
|
|
require.ErrorContains(t, err, "delete resource")
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("error inserting into resource history", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
b, ctx := setupBackendTest(t)
|
|
|
|
|
|
|
|
b.SQLMock.ExpectBegin()
|
2024-10-11 17:11:33 +08:00
|
|
|
b.ExecWithResult("delete resource", 0, 1)
|
2024-07-23 01:08:30 +08:00
|
|
|
b.ExecWithErr("insert resource_history", errTest)
|
|
|
|
b.SQLMock.ExpectCommit()
|
|
|
|
|
|
|
|
v, err := b.delete(ctx, event)
|
|
|
|
require.Zero(t, v)
|
|
|
|
require.Error(t, err)
|
|
|
|
require.ErrorContains(t, err, "insert into resource history")
|
|
|
|
})
|
2024-07-18 23:03:18 +08:00
|
|
|
}
|
2024-12-14 06:55:43 +08:00
|
|
|
|
|
|
|
func TestBackend_restore(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
meta, err := utils.MetaAccessor(&unstructured.Unstructured{
|
|
|
|
Object: map[string]any{},
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
meta.SetUID("new-uid")
|
|
|
|
oldMeta, err := utils.MetaAccessor(&unstructured.Unstructured{
|
|
|
|
Object: map[string]any{},
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
oldMeta.SetUID("old-uid")
|
|
|
|
event := resource.WriteEvent{
|
|
|
|
Type: resource.WatchEvent_ADDED,
|
|
|
|
Key: resKey,
|
|
|
|
Object: meta,
|
|
|
|
ObjectOld: oldMeta,
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Run("happy path", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
b, ctx := setupBackendTest(t)
|
|
|
|
|
|
|
|
b.SQLMock.ExpectBegin()
|
2025-03-13 16:24:12 +08:00
|
|
|
expectSuccessfulResourceVersionExec(t, b.TestDBProvider,
|
|
|
|
func() { b.ExecWithResult("insert resource", 0, 1) },
|
|
|
|
func() { b.ExecWithResult("insert resource_history", 0, 1) },
|
|
|
|
func() { b.ExecWithResult("update resource_history", 0, 1) },
|
|
|
|
)
|
2024-12-14 06:55:43 +08:00
|
|
|
b.SQLMock.ExpectCommit()
|
|
|
|
|
|
|
|
v, err := b.restore(ctx, event)
|
|
|
|
require.NoError(t, err)
|
2025-03-13 16:24:12 +08:00
|
|
|
require.Equal(t, int64(200), v)
|
2024-12-14 06:55:43 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("error restoring resource", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
b, ctx := setupBackendTest(t)
|
|
|
|
|
|
|
|
b.SQLMock.ExpectBegin()
|
|
|
|
b.ExecWithErr("insert resource", errTest)
|
|
|
|
b.SQLMock.ExpectRollback()
|
|
|
|
|
|
|
|
v, err := b.restore(ctx, event)
|
|
|
|
require.Zero(t, v)
|
|
|
|
require.Error(t, err)
|
2025-03-13 16:24:12 +08:00
|
|
|
require.ErrorContains(t, err, "insert into resource")
|
2024-12-14 06:55:43 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("error inserting into resource history", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
b, ctx := setupBackendTest(t)
|
|
|
|
|
|
|
|
b.SQLMock.ExpectBegin()
|
|
|
|
b.ExecWithResult("insert resource", 0, 1)
|
|
|
|
b.ExecWithErr("insert resource_history", errTest)
|
|
|
|
b.SQLMock.ExpectRollback()
|
|
|
|
|
|
|
|
v, err := b.restore(ctx, event)
|
|
|
|
require.Zero(t, v)
|
|
|
|
require.Error(t, err)
|
|
|
|
require.ErrorContains(t, err, "insert into resource history")
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("error updating resource history uid", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
b, ctx := setupBackendTest(t)
|
|
|
|
|
|
|
|
b.SQLMock.ExpectBegin()
|
|
|
|
b.ExecWithResult("insert resource", 0, 1)
|
|
|
|
b.ExecWithResult("insert resource_history", 0, 1)
|
|
|
|
b.ExecWithErr("update resource_history", errTest)
|
|
|
|
b.SQLMock.ExpectRollback()
|
|
|
|
|
|
|
|
v, err := b.restore(ctx, event)
|
|
|
|
require.Zero(t, v)
|
|
|
|
require.Error(t, err)
|
|
|
|
require.ErrorContains(t, err, "update history uid")
|
|
|
|
})
|
|
|
|
}
|