feat: image variants engine
This commit is contained in:
1 parent
f0845de643
commit
f1d56ef50e
80 files changed
+7312
-84
No files matched your search
@@ -0,0 +1,116 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
domain "RenewCMS/internal/domain/image"
|
||||
"RenewCMS/internal/infrastructure/useCases"
|
||||
"errors"
|
||||
"io"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type understatedSizeVariantStorage struct {
|
||||
*mockVariantStorage
|
||||
}
|
||||
|
||||
func (s understatedSizeVariantStorage) Open(storedName string) (domain.Blob, error) {
|
||||
blob, err := s.mockVariantStorage.Open(storedName)
|
||||
blob.Size = 1
|
||||
return blob, err
|
||||
}
|
||||
|
||||
type sizingVariantRenderer struct {
|
||||
received int
|
||||
calls int
|
||||
}
|
||||
|
||||
func (r *sizingVariantRenderer) Render(source io.Reader, settings domain.VariantSettings) (domain.RenderedVariant, error) {
|
||||
data, err := io.ReadAll(source)
|
||||
r.received = len(data)
|
||||
r.calls++
|
||||
return domain.RenderedVariant{Content: []byte("rendered"), ContentType: "image/png"}, err
|
||||
}
|
||||
|
||||
func (r *sizingVariantRenderer) DeclaredSize(source io.Reader) (int, int, error) {
|
||||
return 1, 1, nil
|
||||
}
|
||||
|
||||
func (r *sizingVariantRenderer) EncodableFormats() []domain.VariantFormat {
|
||||
return []domain.VariantFormat{domain.FormatOriginal, domain.FormatJPEG, domain.FormatPNG}
|
||||
}
|
||||
|
||||
type lateStaleVariantFileRepo struct {
|
||||
*mockVariantFileRepo
|
||||
finds int
|
||||
stale domain.VariantFile
|
||||
}
|
||||
|
||||
func (r *lateStaleVariantFileRepo) Find(variantName string, sourceName string) (domain.VariantFile, bool, error) {
|
||||
r.finds++
|
||||
if r.finds == 1 {
|
||||
return domain.VariantFile{}, false, nil
|
||||
}
|
||||
return r.stale, true, nil
|
||||
}
|
||||
|
||||
func TestImageVariantsServeInternals(t *testing.T) {
|
||||
const cap = 1000
|
||||
|
||||
serve := func(storage domain.Storage, files domain.VariantFileRepository, renderer domain.VariantRenderer, variants *mockVariantRepo) (useCases.ServedVariant, error) {
|
||||
name := "thumb"
|
||||
images := newMockImageRepo()
|
||||
images.images[1] = domain.Image{ID: 1, Path: domain.PublicPath("a.png")}
|
||||
return useCases.NewServeVariantUseCase(variants, files, images, storage, renderer, defaultServeLimits(cap)).Serve(useCases.ServeVariantRequest{StoredName: "a.png", Variant: &name})
|
||||
}
|
||||
|
||||
t.Run("A streamed source of exactly the cap is rendered whole", func(t *testing.T) {
|
||||
variants := newMockVariantRepo()
|
||||
seedVariant(variants, "thumb", 400, 300, domain.FitCover, domain.FormatJPEG, 80)
|
||||
storage := newMockVariantStorage()
|
||||
storage.seed("a.png", make([]byte, cap))
|
||||
renderer := &sizingVariantRenderer{}
|
||||
|
||||
_, err := serve(understatedSizeVariantStorage{storage}, newMockVariantFileRepo(), renderer, variants)
|
||||
|
||||
if err != nil || renderer.calls != 1 || renderer.received != cap {
|
||||
t.Errorf("err = %v, calls = %d, received = %d", err, renderer.calls, renderer.received)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("A streamed source beyond the cap is rejected even when its reported size is small", func(t *testing.T) {
|
||||
variants := newMockVariantRepo()
|
||||
seedVariant(variants, "thumb", 400, 300, domain.FitCover, domain.FormatJPEG, 80)
|
||||
storage := newMockVariantStorage()
|
||||
storage.seed("a.png", make([]byte, cap+1))
|
||||
renderer := &sizingVariantRenderer{}
|
||||
|
||||
_, err := serve(understatedSizeVariantStorage{storage}, newMockVariantFileRepo(), renderer, variants)
|
||||
|
||||
if !errors.Is(err, domain.ErrSourceTooLarge) || renderer.calls != 0 {
|
||||
t.Errorf("err = %v, calls = %d", err, renderer.calls)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("A stale row that appears during generation is regenerated, not served", func(t *testing.T) {
|
||||
variants := newMockVariantRepo()
|
||||
seedVariant(variants, "thumb", 400, 300, domain.FitCover, domain.FormatJPEG, 80)
|
||||
storage := newMockVariantStorage()
|
||||
storage.seed("a.png", []byte("source"))
|
||||
storage.seed("old.png", []byte("old"))
|
||||
files := &lateStaleVariantFileRepo{
|
||||
mockVariantFileRepo: newMockVariantFileRepo(),
|
||||
stale: domain.VariantFile{VariantName: "thumb", SourceName: "a.png", CachedName: "old.png", ContentType: "image/png", Size: 3, Fingerprint: "stale"},
|
||||
}
|
||||
renderer := &sizingVariantRenderer{}
|
||||
|
||||
served, err := serve(storage, files, renderer, variants)
|
||||
|
||||
if err != nil || renderer.calls != 1 {
|
||||
t.Fatalf("err = %v, calls = %d", err, renderer.calls)
|
||||
}
|
||||
defer served.Content.Close()
|
||||
body, _ := io.ReadAll(served.Content)
|
||||
if string(body) != "rendered" {
|
||||
t.Errorf("body = %q", body)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user