95 lines
3.6 KiB
Go
95 lines
3.6 KiB
Go
package admin
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
|
|
"telesrv/internal/domain"
|
|
)
|
|
|
|
type fakeGifCatalogService struct {
|
|
entries []domain.GifCatalogEntry
|
|
listCalls int
|
|
uploadCalls int
|
|
createCalls int
|
|
}
|
|
|
|
func (s *fakeGifCatalogService) ValidateGifUpload(_ string, data []byte) (string, bool) {
|
|
return "image/gif", strings.HasPrefix(string(data), "GIF89a")
|
|
}
|
|
func (s *fakeGifCatalogService) AdminUploadGifMaterial(context.Context, string, []byte) (domain.Document, error) {
|
|
s.uploadCalls++
|
|
return domain.Document{ID: 91}, nil
|
|
}
|
|
func (s *fakeGifCatalogService) AdminCreateGifCatalogEntry(context.Context, string, int64) (domain.GifCatalogEntry, error) {
|
|
s.createCalls++
|
|
entry := domain.GifCatalogEntry{ID: 92, DocumentID: 91, Title: "Wave", Enabled: true}
|
|
s.entries = append(s.entries, entry)
|
|
return entry, nil
|
|
}
|
|
func (s *fakeGifCatalogService) AdminListGifCatalog(context.Context) ([]domain.GifCatalogEntry, error) {
|
|
s.listCalls++
|
|
return append([]domain.GifCatalogEntry(nil), s.entries...), nil
|
|
}
|
|
func (*fakeGifCatalogService) AdminSetGifCatalogEnabled(context.Context, int64, bool) (bool, error) {
|
|
return true, nil
|
|
}
|
|
func (*fakeGifCatalogService) AdminSetGifCatalogSortOrder(context.Context, int64, int) (bool, error) {
|
|
return true, nil
|
|
}
|
|
func (*fakeGifCatalogService) AdminSetGifCatalogCategory(context.Context, int64, string) (bool, error) {
|
|
return true, nil
|
|
}
|
|
func (*fakeGifCatalogService) AdminAutoCategorizeGifCatalog(context.Context) (int, error) {
|
|
return 0, nil
|
|
}
|
|
func (*fakeGifCatalogService) AdminDeleteUncategorizedGifs(context.Context) (int, int, error) {
|
|
return 0, 0, nil
|
|
}
|
|
func (*fakeGifCatalogService) AdminDeleteGifCatalogEntry(context.Context, int64) (bool, error) {
|
|
return true, nil
|
|
}
|
|
func (*fakeGifCatalogService) GetFile(context.Context, domain.FileDownloadRequest) (domain.FileChunk, bool, error) {
|
|
return domain.FileChunk{}, false, nil
|
|
}
|
|
|
|
func TestCreateGifCatalogEntryReplayAndContentFingerprint(t *testing.T) {
|
|
ctx := context.Background()
|
|
repo := newMemoryCommandRepo()
|
|
gifs := &fakeGifCatalogService{}
|
|
svc := NewService(Dependencies{Commands: repo, GifCatalog: gifs, Now: fixedNow})
|
|
req := CreateGifCatalogEntryRequest{
|
|
CommandMeta: CommandMeta{CommandID: "gif-create-1", Actor: "ops", Reason: "catalog"},
|
|
Title: "Wave",
|
|
FileName: "wave.gif",
|
|
Data: []byte("GIF89a-one"),
|
|
}
|
|
first, err := svc.CreateGifCatalogEntry(ctx, req)
|
|
if err != nil || first.Status != string(domain.AdminCommandCompleted) {
|
|
t.Fatalf("first create = %+v err=%v", first, err)
|
|
}
|
|
if gifs.listCalls != 1 || gifs.uploadCalls != 1 || gifs.createCalls != 1 {
|
|
t.Fatalf("first calls list/upload/create=%d/%d/%d", gifs.listCalls, gifs.uploadCalls, gifs.createCalls)
|
|
}
|
|
|
|
// Even when the catalog has become full, the same completed command must be
|
|
// replayed before capacity preflight and must not upload another blob.
|
|
gifs.entries = make([]domain.GifCatalogEntry, domain.MaxGifCatalogEntries)
|
|
replay, err := svc.CreateGifCatalogEntry(ctx, req)
|
|
if err != nil || !replay.AlreadyExecuted {
|
|
t.Fatalf("replay = %+v err=%v", replay, err)
|
|
}
|
|
if gifs.listCalls != 1 || gifs.uploadCalls != 1 || gifs.createCalls != 1 {
|
|
t.Fatalf("replay calls list/upload/create=%d/%d/%d", gifs.listCalls, gifs.uploadCalls, gifs.createCalls)
|
|
}
|
|
|
|
conflict := req
|
|
conflict.Data = []byte("GIF89a-two")
|
|
if _, err := svc.CreateGifCatalogEntry(ctx, conflict); err == nil || err.Error() != "COMMAND_ID_CONFLICT" {
|
|
t.Fatalf("different content with same command id err=%v", err)
|
|
}
|
|
if gifs.listCalls != 1 || gifs.uploadCalls != 1 || gifs.createCalls != 1 {
|
|
t.Fatalf("conflict mutated list/upload/create=%d/%d/%d", gifs.listCalls, gifs.uploadCalls, gifs.createCalls)
|
|
}
|
|
}
|