2023-04-24 20:52:12 +02:00
|
|
|
package testsuite
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-07-07 20:22:31 +02:00
|
|
|
"reflect"
|
2024-06-27 17:03:50 +02:00
|
|
|
"sync"
|
2023-04-24 20:52:12 +02:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"forge.cadoles.com/cadoles/bouncer/internal/store"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
)
|
|
|
|
|
|
|
|
type layerRepositoryTestCase struct {
|
|
|
|
Name string
|
|
|
|
Do func(repo store.LayerRepository) error
|
|
|
|
}
|
|
|
|
|
|
|
|
const layerType store.LayerType = "test"
|
|
|
|
|
|
|
|
var layerRepositoryTestCases = []layerRepositoryTestCase{
|
|
|
|
{
|
|
|
|
Name: "Create layer",
|
|
|
|
Do: func(repo store.LayerRepository) error {
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
options := map[string]any{}
|
|
|
|
|
|
|
|
layer, err := repo.CreateLayer(ctx, "create_layer_proxy", "create_layer", layerType, options)
|
|
|
|
if err != nil {
|
|
|
|
return errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if layer == nil {
|
|
|
|
return errors.Errorf("layer should not be nil")
|
|
|
|
}
|
|
|
|
|
|
|
|
if layer.Name == "" {
|
|
|
|
return errors.Errorf("layer.Name should not be empty")
|
|
|
|
}
|
|
|
|
|
|
|
|
if layer.Proxy == "" {
|
|
|
|
return errors.Errorf("layer.Proxy should not be empty")
|
|
|
|
}
|
|
|
|
|
|
|
|
if layer.CreatedAt.IsZero() {
|
|
|
|
return errors.Errorf("layer.CreatedAt should not be zero value")
|
|
|
|
}
|
|
|
|
|
|
|
|
if layer.UpdatedAt.IsZero() {
|
|
|
|
return errors.Errorf("layer.UpdatedAt should not be zero value")
|
|
|
|
}
|
|
|
|
|
2024-06-27 17:03:50 +02:00
|
|
|
if layer.Revision != 0 {
|
|
|
|
return errors.Errorf("layer.Revision should be zero")
|
|
|
|
}
|
|
|
|
|
2023-07-07 20:22:31 +02:00
|
|
|
return nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "Create then get layer",
|
|
|
|
Do: func(repo store.LayerRepository) error {
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
var proxyName store.ProxyName = "create_then_get_layer_proxy"
|
|
|
|
var layerName store.LayerName = "create_then_get_layer"
|
|
|
|
var layerType store.LayerType = "dummy"
|
|
|
|
var layerOptions store.LayerOptions = store.LayerOptions{
|
|
|
|
"foo": "bar",
|
|
|
|
"test": struct {
|
|
|
|
Items []int `json:"items"`
|
|
|
|
}{
|
|
|
|
Items: []int{1, 2, 3},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
createdLayer, err := repo.CreateLayer(ctx, proxyName, layerName, layerType, layerOptions)
|
|
|
|
if err != nil {
|
|
|
|
return errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
foundLayer, err := repo.GetLayer(ctx, proxyName, layerName)
|
|
|
|
if err != nil {
|
|
|
|
return errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if e, g := createdLayer.Name, foundLayer.Name; e != g {
|
|
|
|
return errors.Errorf("foundLayer.Name: expected '%v', got '%v'", createdLayer.Name, foundLayer.Name)
|
|
|
|
}
|
|
|
|
|
|
|
|
if e, g := createdLayer.CreatedAt, foundLayer.CreatedAt; !reflect.DeepEqual(e, g) {
|
|
|
|
return errors.Errorf("foundLayer.CreatedAt: expected '%v', got '%v'", createdLayer.CreatedAt, foundLayer.CreatedAt)
|
|
|
|
}
|
|
|
|
|
|
|
|
if e, g := createdLayer.UpdatedAt, foundLayer.UpdatedAt; !reflect.DeepEqual(e, g) {
|
|
|
|
return errors.Errorf("foundLayer.UpdatedAt: expected '%v', got '%v'", createdLayer.UpdatedAt, foundLayer.UpdatedAt)
|
|
|
|
}
|
|
|
|
|
|
|
|
if e, g := createdLayer.Enabled, foundLayer.Enabled; !reflect.DeepEqual(e, g) {
|
|
|
|
return errors.Errorf("foundLayer.Enabled: expected '%v', got '%v'", createdLayer.Enabled, foundLayer.Enabled)
|
|
|
|
}
|
|
|
|
|
|
|
|
if e, g := createdLayer.Weight, foundLayer.Weight; !reflect.DeepEqual(e, g) {
|
|
|
|
return errors.Errorf("foundLayer.Weight: expected '%v', got '%v'", createdLayer.Weight, foundLayer.Weight)
|
|
|
|
}
|
|
|
|
|
|
|
|
if e, g := createdLayer.Proxy, foundLayer.Proxy; !reflect.DeepEqual(e, g) {
|
|
|
|
return errors.Errorf("foundLayer.Proxy: expected '%v', got '%v'", createdLayer.Proxy, foundLayer.Proxy)
|
|
|
|
}
|
|
|
|
|
|
|
|
if e, g := createdLayer.Options, foundLayer.Options; !reflect.DeepEqual(e, g) {
|
|
|
|
return errors.Errorf("foundLayer.Options: expected '%v', got '%v'", createdLayer.Options, foundLayer.Options)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "Create then delete layer",
|
|
|
|
Do: func(repo store.LayerRepository) error {
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
var layerName store.LayerName = "create_then_delete_layer"
|
|
|
|
var proxyName store.ProxyName = store.ProxyName(string(layerName) + "_proxy")
|
|
|
|
var layerType store.LayerType = "dummy"
|
|
|
|
var layerOptions store.LayerOptions = store.LayerOptions{
|
|
|
|
"foo": "bar",
|
|
|
|
"test": struct {
|
|
|
|
Items []int `json:"items"`
|
|
|
|
}{
|
|
|
|
Items: []int{1, 2, 3},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
createdLayer, err := repo.CreateLayer(ctx, proxyName, layerName, layerType, layerOptions)
|
|
|
|
if err != nil {
|
|
|
|
return errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := repo.DeleteLayer(ctx, createdLayer.Proxy, createdLayer.Name); err != nil {
|
|
|
|
return errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
foundLayer, err := repo.GetLayer(ctx, createdLayer.Proxy, createdLayer.Name)
|
|
|
|
if err == nil {
|
|
|
|
return errors.New("err should not be nil")
|
|
|
|
}
|
|
|
|
|
|
|
|
if !errors.Is(err, store.ErrNotFound) {
|
|
|
|
return errors.Errorf("err should be store.ErrNotFound, got '%+v'", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if foundLayer != nil {
|
|
|
|
return errors.Errorf("foundLayer should be nil, got '%v'", foundLayer)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "Create already existing layer",
|
|
|
|
Do: func(repo store.LayerRepository) error {
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
var layerName store.LayerName = "create_already_existing_layer"
|
|
|
|
var proxyName store.ProxyName = store.ProxyName(string(layerName) + "_proxy")
|
|
|
|
var layerType store.LayerType = "dummy"
|
|
|
|
var layerOptions store.LayerOptions = store.LayerOptions{
|
|
|
|
"foo": "bar",
|
|
|
|
"test": struct {
|
|
|
|
Items []int `json:"items"`
|
|
|
|
}{
|
|
|
|
Items: []int{1, 2, 3},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err := repo.CreateLayer(ctx, proxyName, layerName, layerType, layerOptions)
|
|
|
|
if err != nil {
|
|
|
|
return errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = repo.CreateLayer(ctx, proxyName, layerName, layerType, layerOptions)
|
|
|
|
if err == nil {
|
|
|
|
return errors.New("err should not be nil")
|
|
|
|
}
|
|
|
|
|
|
|
|
if !errors.Is(err, store.ErrAlreadyExist) {
|
|
|
|
return errors.Errorf("err: expected store.ErrAlreadyExists, got '%+v'", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "Create then query layer",
|
|
|
|
Do: func(repo store.LayerRepository) error {
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
var layerName store.LayerName = "create_then_query_layer"
|
|
|
|
var proxyName store.ProxyName = store.ProxyName(string(layerName) + "_proxy")
|
|
|
|
var layerType store.LayerType = "dummy"
|
|
|
|
var layerOptions store.LayerOptions = store.LayerOptions{
|
|
|
|
"foo": "bar",
|
|
|
|
"test": struct {
|
|
|
|
Items []int `json:"items"`
|
|
|
|
}{
|
|
|
|
Items: []int{1, 2, 3},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
createdLayer, err := repo.CreateLayer(ctx, proxyName, layerName, layerType, layerOptions)
|
|
|
|
if err != nil {
|
|
|
|
return errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
headers, err := repo.QueryLayers(ctx, createdLayer.Proxy)
|
|
|
|
if err != nil {
|
|
|
|
return errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(headers) < 1 {
|
|
|
|
return errors.Errorf("len(headers): expected value > 1, got '%v'", len(headers))
|
|
|
|
}
|
|
|
|
|
|
|
|
found := false
|
|
|
|
|
|
|
|
for _, h := range headers {
|
|
|
|
if h.Name == createdLayer.Name {
|
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !found {
|
|
|
|
return errors.New("could not find created layer in query results")
|
|
|
|
}
|
|
|
|
|
2024-06-27 17:03:50 +02:00
|
|
|
return nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "Create then update layer",
|
|
|
|
Do: func(repo store.LayerRepository) error {
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
var layerName store.LayerName = "create_then_update_layer"
|
|
|
|
var proxyName store.ProxyName = store.ProxyName(string(layerName) + "_proxy")
|
|
|
|
var layerType store.LayerType = "dummy"
|
|
|
|
var layerOptions store.LayerOptions = store.LayerOptions{}
|
|
|
|
|
|
|
|
createdLayer, err := repo.CreateLayer(ctx, proxyName, layerName, layerType, layerOptions)
|
|
|
|
if err != nil {
|
|
|
|
return errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if e, g := 0, createdLayer.Revision; e != g {
|
|
|
|
return errors.Errorf("createdLayer.Revision: expected '%v', got '%v'", e, g)
|
|
|
|
}
|
|
|
|
|
|
|
|
updatedLayer, err := repo.UpdateLayer(ctx, proxyName, layerName)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "err should be nil")
|
|
|
|
}
|
|
|
|
|
|
|
|
if e, g := 1, updatedLayer.Revision; e != g {
|
|
|
|
return errors.Errorf("updatedLayer.Revision: expected '%v', got '%v'", e, g)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "Update layer concurrently",
|
|
|
|
Do: func(repo store.LayerRepository) error {
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
var layerName store.LayerName = "update_layer_concurrently"
|
|
|
|
var proxyName store.ProxyName = store.ProxyName(string(layerName) + "_proxy")
|
|
|
|
var layerType store.LayerType = "dummy"
|
|
|
|
var layerOptions store.LayerOptions = store.LayerOptions{}
|
|
|
|
|
|
|
|
createdLayer, err := repo.CreateLayer(ctx, proxyName, layerName, layerType, layerOptions)
|
|
|
|
if err != nil {
|
|
|
|
return errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if createdLayer.Revision != 0 {
|
|
|
|
return errors.Errorf("createdLayer.Revision should be zero")
|
|
|
|
}
|
|
|
|
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
|
|
|
|
total := 100
|
|
|
|
|
|
|
|
wg.Add(total)
|
|
|
|
|
|
|
|
for i := 0; i < total; i++ {
|
|
|
|
go func(i int) {
|
|
|
|
defer wg.Done()
|
|
|
|
|
|
|
|
if _, err := repo.UpdateLayer(ctx, createdLayer.Proxy, createdLayer.Name); err != nil {
|
|
|
|
panic(errors.Wrap(err, "err should be nil"))
|
|
|
|
}
|
|
|
|
}(i)
|
|
|
|
}
|
|
|
|
|
|
|
|
wg.Wait()
|
|
|
|
|
|
|
|
layer, err := repo.GetLayer(ctx, createdLayer.Proxy, createdLayer.Name)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "err should be nil")
|
|
|
|
}
|
|
|
|
|
|
|
|
if e, g := total, layer.Revision; e != g {
|
|
|
|
return errors.Errorf("layer.Revision: expected '%v', got '%v'", e, g)
|
|
|
|
}
|
|
|
|
|
2023-04-24 20:52:12 +02:00
|
|
|
return nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestLayerRepository(t *testing.T, repo store.LayerRepository) {
|
|
|
|
for _, tc := range layerRepositoryTestCases {
|
|
|
|
func(tc layerRepositoryTestCase) {
|
|
|
|
t.Run(tc.Name, func(t *testing.T) {
|
|
|
|
if err := tc.Do(repo); err != nil {
|
|
|
|
t.Fatalf("%+v", errors.WithStack(err))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}(tc)
|
|
|
|
}
|
|
|
|
}
|