fixup! fixup! fixup! Merge branch 'main' into import_export_merge

This commit is contained in:
Iraq Jaber
2025-06-06 12:31:18 +02:00
parent 5b1099c90f
commit 400fb97d6d
7 changed files with 359 additions and 116 deletions

View File

@@ -14,6 +14,11 @@ type Pool interface {
Close(ctx context.Context) error
}
type PoolTest interface {
Pool
MigrateTest(ctx context.Context) error
}
// Client is a single database connection which can be released back to the pool.
type Client interface {
Beginner

View File

@@ -80,3 +80,20 @@ func (c *pgxPool) Migrate(ctx context.Context) error {
isMigrated = err == nil
return err
}
// Migrate implements [database.PoolTest].
func (c *pgxPool) MigrateTest(ctx context.Context) error {
// allow multiple migrations
// if isMigrated {
// return nil
// }
client, err := c.Pool.Acquire(ctx)
if err != nil {
return err
}
err = migration.Migrate(ctx, client.Conn())
isMigrated = err == nil
return err
}

View File

@@ -32,12 +32,12 @@ const queryInstanceStmt = `SELECT id, name, default_org_id, iam_project_id, cons
` FROM zitadel.instances`
// Get implements [domain.InstanceRepository].
// func (i *instance) Get(ctx context.Context, opts ...database.QueryOption) (*domain.Instance, error) {
func (i *instance) Get(ctx context.Context, opts ...database.Condition) (*domain.Instance, error) {
i.builder = database.StatementBuilder{}
i.builder.WriteString(queryInstanceStmt)
// return only non deleted isntances
opts = append(opts, database.IsNull(i.DeletedAtColumn()))
andCondition := database.And(opts...)
andCondition.Write(&i.builder)
@@ -46,12 +46,12 @@ func (i *instance) Get(ctx context.Context, opts ...database.Condition) (*domain
}
// List implements [domain.InstanceRepository].
// func (i *instance) List(ctx context.Context, opts ...database.QueryOption) (*domain.Instance, error) {
func (i *instance) List(ctx context.Context, opts ...database.Condition) ([]*domain.Instance, error) {
i.builder = database.StatementBuilder{}
i.builder.WriteString(queryInstanceStmt)
// return only non deleted isntances
opts = append(opts, database.IsNull(i.DeletedAtColumn()))
andCondition := database.And(opts...)
andCondition.Write(&i.builder)

View File

@@ -296,115 +296,337 @@ func TestGetInstance(t *testing.T) {
}
func TestListInstance(t *testing.T) {
tests := []struct {
name string
testFunc func() *domain.Instance
type test struct {
name string
testFunc func() ([]*domain.Instance, database.PoolTest, func())
conditionClauses []database.Condition
noInstanceReturned bool
}{
}
tests := []test{
{
name: "happy path",
testFunc: func() *domain.Instance {
instanceRepo := repository.InstanceRepository(pool)
instanceId := gofakeit.Name()
instanceName := gofakeit.Name()
name: "happy path single instance",
testFunc: func() ([]*domain.Instance, database.PoolTest, func()) {
ctx := context.Background()
inst := domain.Instance{
ID: instanceId,
Name: instanceName,
DefaultOrgID: "defaultOrgId",
IAMProjectID: "iamProject",
ConsoleClientID: "consoleCLient",
ConsoleAppID: "consoleApp",
DefaultLanguage: "defaultLanguage",
pool, stop, err := newEmbeededDB()
assert.NoError(t, err)
instanceRepo := repository.InstanceRepository(pool)
noOfInstances := 1
instances := make([]*domain.Instance, noOfInstances)
for i := range noOfInstances {
instanceId := gofakeit.Name()
instanceName := gofakeit.Name()
inst := domain.Instance{
ID: instanceId,
Name: instanceName,
DefaultOrgID: "defaultOrgId",
IAMProjectID: "iamProject",
ConsoleClientID: "consoleCLient",
ConsoleAppID: "consoleApp",
DefaultLanguage: "defaultLanguage",
}
// create instance
err := instanceRepo.Create(ctx, &inst)
assert.NoError(t, err)
instances[i] = &inst
}
// create instance
err := instanceRepo.Create(ctx, &inst)
assert.NoError(t, err)
return &inst
return instances, pool, stop
},
},
{
name: "get non existent instance",
testFunc: func() *domain.Instance {
instanceId := gofakeit.Name()
name: "happy path multiple instance",
testFunc: func() ([]*domain.Instance, database.PoolTest, func()) {
ctx := context.Background()
pool, stop, err := newEmbeededDB()
assert.NoError(t, err)
inst := domain.Instance{
ID: instanceId,
instanceRepo := repository.InstanceRepository(pool)
noOfInstances := 5
instances := make([]*domain.Instance, noOfInstances)
for i := range noOfInstances {
instanceId := gofakeit.Name()
instanceName := gofakeit.Name()
inst := domain.Instance{
ID: instanceId,
Name: instanceName,
DefaultOrgID: "defaultOrgId",
IAMProjectID: "iamProject",
ConsoleClientID: "consoleCLient",
ConsoleAppID: "consoleApp",
DefaultLanguage: "defaultLanguage",
}
// create instance
err := instanceRepo.Create(ctx, &inst)
assert.NoError(t, err)
instances[i] = &inst
}
return &inst
return instances, pool, stop
},
noInstanceReturned: true,
},
func() test {
instanceRepo := repository.InstanceRepository(pool)
instanceId := gofakeit.Name()
return test{
name: "instance filter on id",
testFunc: func() ([]*domain.Instance, database.PoolTest, func()) {
ctx := context.Background()
noOfInstances := 1
instances := make([]*domain.Instance, noOfInstances)
for i := range noOfInstances {
instanceName := gofakeit.Name()
inst := domain.Instance{
ID: instanceId,
Name: instanceName,
DefaultOrgID: "defaultOrgId",
IAMProjectID: "iamProject",
ConsoleClientID: "consoleCLient",
ConsoleAppID: "consoleApp",
DefaultLanguage: "defaultLanguage",
}
// create instance
err := instanceRepo.Create(ctx, &inst)
assert.NoError(t, err)
instances[i] = &inst
}
return instances, nil, nil
},
conditionClauses: []database.Condition{instanceRepo.IDCondition(instanceId)},
}
}(),
func() test {
instanceRepo := repository.InstanceRepository(pool)
instanceName := gofakeit.Name()
return test{
name: "multiple instance filter on name",
testFunc: func() ([]*domain.Instance, database.PoolTest, func()) {
ctx := context.Background()
noOfInstances := 5
instances := make([]*domain.Instance, noOfInstances)
for i := range noOfInstances {
instanceId := gofakeit.Name()
inst := domain.Instance{
ID: instanceId,
Name: instanceName,
DefaultOrgID: "defaultOrgId",
IAMProjectID: "iamProject",
ConsoleClientID: "consoleCLient",
ConsoleAppID: "consoleApp",
DefaultLanguage: "defaultLanguage",
}
// create instance
err := instanceRepo.Create(ctx, &inst)
assert.NoError(t, err)
instances[i] = &inst
}
return instances, nil, nil
},
conditionClauses: []database.Condition{instanceRepo.NameCondition(database.TextOperationEqual, instanceName)},
}
}(),
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
var instances []*domain.Instance
pool := pool
if tt.testFunc != nil {
var stop func()
var pool_ database.PoolTest
instances, pool_, stop = tt.testFunc()
if pool_ != nil {
pool = pool_
defer stop()
}
}
instanceRepo := repository.InstanceRepository(pool)
// check instance values
returnedInstances, err := instanceRepo.List(ctx,
tt.conditionClauses...,
)
assert.NoError(t, err)
if tt.noInstanceReturned {
assert.Nil(t, returnedInstances)
return
}
assert.Equal(t, len(instances), len(returnedInstances))
for i, instance := range instances {
assert.Equal(t, returnedInstances[i].ID, instance.ID)
assert.Equal(t, returnedInstances[i].Name, instance.Name)
assert.Equal(t, returnedInstances[i].DefaultOrgID, instance.DefaultOrgID)
assert.Equal(t, returnedInstances[i].IAMProjectID, instance.IAMProjectID)
assert.Equal(t, returnedInstances[i].ConsoleClientID, instance.ConsoleClientID)
assert.Equal(t, returnedInstances[i].ConsoleAppID, instance.ConsoleAppID)
assert.Equal(t, returnedInstances[i].DefaultLanguage, instance.DefaultLanguage)
assert.NoError(t, err)
}
})
}
}
func TestDeleteInstance(t *testing.T) {
type test struct {
name string
testFunc func()
conditionClauses database.Condition
noInstanceReturned bool
}
tests := []test{
func() test {
instanceRepo := repository.InstanceRepository(pool)
instanceName := gofakeit.Name()
return test{
name: "happy path delete single instance",
testFunc: func() {
ctx := context.Background()
noOfInstances := 1
instances := make([]*domain.Instance, noOfInstances)
for i := range noOfInstances {
instanceId := gofakeit.Name()
inst := domain.Instance{
ID: instanceId,
Name: instanceName,
DefaultOrgID: "defaultOrgId",
IAMProjectID: "iamProject",
ConsoleClientID: "consoleCLient",
ConsoleAppID: "consoleApp",
DefaultLanguage: "defaultLanguage",
}
// create instance
err := instanceRepo.Create(ctx, &inst)
assert.NoError(t, err)
instances[i] = &inst
}
},
conditionClauses: instanceRepo.NameCondition(database.TextOperationEqual, instanceName),
}
}(),
func() test {
instanceRepo := repository.InstanceRepository(pool)
instanceName := gofakeit.Name()
return test{
name: "multiple instance filter on name",
testFunc: func() {
ctx := context.Background()
noOfInstances := 5
instances := make([]*domain.Instance, noOfInstances)
for i := range noOfInstances {
instanceId := gofakeit.Name()
inst := domain.Instance{
ID: instanceId,
Name: instanceName,
DefaultOrgID: "defaultOrgId",
IAMProjectID: "iamProject",
ConsoleClientID: "consoleCLient",
ConsoleAppID: "consoleApp",
DefaultLanguage: "defaultLanguage",
}
// create instance
err := instanceRepo.Create(ctx, &inst)
assert.NoError(t, err)
instances[i] = &inst
}
},
conditionClauses: instanceRepo.NameCondition(database.TextOperationEqual, instanceName),
}
}(),
func() test {
instanceRepo := repository.InstanceRepository(pool)
instanceName := gofakeit.Name()
return test{
name: "deleted already deleted instance",
testFunc: func() {
ctx := context.Background()
noOfInstances := 1
instances := make([]*domain.Instance, noOfInstances)
for i := range noOfInstances {
instanceId := gofakeit.Name()
inst := domain.Instance{
ID: instanceId,
Name: instanceName,
DefaultOrgID: "defaultOrgId",
IAMProjectID: "iamProject",
ConsoleClientID: "consoleCLient",
ConsoleAppID: "consoleApp",
DefaultLanguage: "defaultLanguage",
}
// create instance
err := instanceRepo.Create(ctx, &inst)
assert.NoError(t, err)
instances[i] = &inst
}
// delete instance
err := instanceRepo.Delete(ctx,
instanceRepo.NameCondition(database.TextOperationEqual, instanceName),
)
assert.NoError(t, err)
},
conditionClauses: instanceRepo.NameCondition(database.TextOperationEqual, instanceName),
}
}(),
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
instanceRepo := repository.InstanceRepository(pool)
var instance *domain.Instance
if tt.testFunc != nil {
instance = tt.testFunc()
tt.testFunc()
}
// check instance values
returnedInstance, err := instanceRepo.List(ctx,
instanceRepo.IDCondition(instance.ID),
// delete instance
err := instanceRepo.Delete(ctx,
tt.conditionClauses,
)
assert.NoError(t, err)
if tt.noInstanceReturned {
assert.Nil(t, returnedInstance)
return
}
assert.Equal(t, returnedInstance.ID, instance.ID)
assert.Equal(t, returnedInstance.Name, instance.Name)
assert.Equal(t, returnedInstance.DefaultOrgID, instance.DefaultOrgID)
assert.Equal(t, returnedInstance.IAMProjectID, instance.IAMProjectID)
assert.Equal(t, returnedInstance.ConsoleClientID, instance.ConsoleClientID)
assert.Equal(t, returnedInstance.ConsoleAppID, instance.ConsoleAppID)
assert.Equal(t, returnedInstance.DefaultLanguage, instance.DefaultLanguage)
// check instance was deleted
instance, err := instanceRepo.Get(ctx,
tt.conditionClauses,
)
assert.NoError(t, err)
assert.Nil(t, instance)
})
}
}
func TestUpdateDeleteInstance(t *testing.T) {
instanceRepo := repository.InstanceRepository(pool)
instanceId := gofakeit.Name()
instanceName := gofakeit.Name()
ctx := context.Background()
inst := domain.Instance{
ID: instanceId,
Name: instanceName,
DefaultOrgID: "defaultOrgId",
IAMProjectID: "iamProject",
ConsoleClientID: "consoleCLient",
ConsoleAppID: "consoleApp",
DefaultLanguage: "defaultLanguage",
}
err := instanceRepo.Create(ctx, &inst)
assert.NoError(t, err)
instance, err := instanceRepo.Get(ctx,
instanceRepo.NameCondition(database.TextOperationEqual, instanceName),
)
assert.NotNil(t, instance)
assert.NoError(t, err)
// delete instance
err = instanceRepo.Delete(ctx,
instanceRepo.IDCondition(instanceId),
)
assert.NoError(t, err)
instance, err = instanceRepo.Get(ctx,
instanceRepo.NameCondition(database.TextOperationEqual, instanceName),
)
assert.NoError(t, err)
assert.Nil(t, instance)
}

View File

@@ -2,6 +2,7 @@ package repository_test
import (
"context"
"fmt"
"log"
"os"
"testing"
@@ -14,28 +15,39 @@ func TestMain(m *testing.M) {
os.Exit(runTests(m))
}
var pool database.Pool
var pool database.PoolTest
func runTests(m *testing.M) int {
connector, stop, err := embedded.StartEmbedded()
var stop func()
var err error
pool, stop, err = newEmbeededDB()
if err != nil {
log.Fatalf("unable to start embedded postgres: %v", err)
log.Print(err)
return 1
}
defer stop()
ctx := context.Background()
pool, err = connector.Connect(ctx)
if err != nil {
log.Printf("unable to connect to embedded postgres: %v", err)
return 1
}
err = pool.Migrate(ctx)
if err != nil {
log.Printf("unable to migrate database: %v", err)
return 1
}
return m.Run()
}
func newEmbeededDB() (pool database.PoolTest, stop func(), err error) {
var connector database.Connector
connector, stop, err = embedded.StartEmbedded()
if err != nil {
return nil, nil, fmt.Errorf("unable to start embedded postgres: %v", err)
}
ctx := context.Background()
pool_, err := connector.Connect(ctx)
if err != nil {
return nil, nil, fmt.Errorf("unable to connect to embedded postgres: %v", err)
}
pool = pool_.(database.PoolTest)
err = pool.MigrateTest(ctx)
if err != nil {
return nil, nil, fmt.Errorf("unable to migrate database: %v", err)
}
return pool, stop, err
}