Files
NianAIGC/backend/internal/layercompositions/compositions_test.go

97 lines
3.5 KiB
Go

package layercompositions
import (
"context"
"errors"
"testing"
"time"
"git.nianxx.cn/wangxuming/NianAIGC/backend/internal/assets"
)
type compositionRepositoryStub struct {
value Composition
found bool
}
func (repository *compositionRepositoryStub) FindLayerComposition(_ context.Context, ownerID, jobID string) (Composition, bool, error) {
if !repository.found || repository.value.OwnerID != ownerID || repository.value.JobID != jobID {
return Composition{}, false, nil
}
return repository.value, true, nil
}
func (repository *compositionRepositoryStub) SaveLayerComposition(_ context.Context, value Composition, expectedVersion int64) (Composition, error) {
if repository.found && repository.value.Version != expectedVersion {
return Composition{}, ErrConflict
}
if !repository.found && expectedVersion != 0 {
return Composition{}, ErrConflict
}
now := time.Date(2026, 9, 2, 8, 0, 0, 0, time.UTC)
value.Version = expectedVersion + 1
value.CreatedAt = now
value.UpdatedAt = now
repository.value = value
repository.found = true
return value, nil
}
type assetCatalogStub map[string]assets.Asset
func (catalog assetCatalogStub) GetOwner(_ context.Context, ownerID, assetID string) (assets.Asset, bool, error) {
asset, found := catalog[assetID]
return asset, found && asset.OwnerID == ownerID, nil
}
func TestServiceSavesOwnedCompositionAndNormalizesRotation(t *testing.T) {
repository := &compositionRepositoryStub{}
catalog := assetCatalogStub{
"base": {ID: "base", OwnerID: "owner", Kind: assets.KindImage},
"layer": {ID: "layer", OwnerID: "owner", Kind: assets.KindImage},
}
service := NewService(repository, catalog)
saved, err := service.Save(context.Background(), "owner", "job-1", 0, Composition{
BaseAssetID: "base", BaseVisible: true,
Layers: []Layer{{ID: "layer-1", AssetID: "layer", Name: "主体", Visible: true, Box: Box{100, 100, 900, 900}, Rotation: 450, Source: "upload"}},
})
if err != nil {
t.Fatal(err)
}
if saved.Version != 1 || saved.OwnerID != "owner" || saved.JobID != "job-1" || saved.Layers[0].Rotation != 90 {
t.Fatalf("saved=%#v", saved)
}
}
func TestServiceRejectsForeignOrMalformedLayerAssets(t *testing.T) {
service := NewService(&compositionRepositoryStub{}, assetCatalogStub{
"base": {ID: "base", OwnerID: "owner", Kind: assets.KindImage},
"foreign": {ID: "foreign", OwnerID: "another-owner", Kind: assets.KindImage},
})
_, err := service.Save(context.Background(), "owner", "job-1", 0, Composition{
BaseAssetID: "base", BaseVisible: true,
Layers: []Layer{{ID: "layer-1", AssetID: "foreign", Name: "主体", Visible: true, Box: Box{100, 100, 900, 900}, Source: "library"}},
})
if !errors.Is(err, ErrAssetNotFound) {
t.Fatalf("foreign asset err=%v", err)
}
_, err = service.Save(context.Background(), "owner", "job-1", 0, Composition{
BaseAssetID: "base", BaseVisible: true,
Layers: []Layer{{ID: "layer-1", AssetID: "base", Name: "主体", Visible: true, Box: Box{900, 100, 100, 900}, Source: "provider"}},
})
if !errors.Is(err, ErrInvalid) {
t.Fatalf("invalid box err=%v", err)
}
}
func TestServiceUsesOptimisticVersion(t *testing.T) {
repository := &compositionRepositoryStub{found: true, value: Composition{JobID: "job-1", OwnerID: "owner", Version: 3}}
service := NewService(repository, assetCatalogStub{"base": {ID: "base", OwnerID: "owner", Kind: assets.KindImage}})
_, err := service.Save(context.Background(), "owner", "job-1", 2, Composition{BaseAssetID: "base", BaseVisible: true})
if !errors.Is(err, ErrConflict) {
t.Fatalf("err=%v", err)
}
}