ntfy-server/attachment/store_s3_test.go

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

121 lines
2.9 KiB
Go
Raw Normal View History

2026-03-14 21:10:46 -04:00
package attachment
import (
2026-03-22 08:15:23 -04:00
"context"
2026-03-16 09:48:26 -04:00
"io"
2026-03-22 08:15:23 -04:00
"os"
2026-03-16 09:48:26 -04:00
"strings"
"sync"
2026-03-14 21:10:46 -04:00
"testing"
2026-03-17 20:53:41 -04:00
"time"
2026-03-14 21:10:46 -04:00
"github.com/stretchr/testify/require"
2026-03-16 09:48:26 -04:00
"heckel.io/ntfy/v2/s3"
2026-03-14 21:10:46 -04:00
)
2026-03-22 08:15:23 -04:00
func TestS3Store_WriteWithPrefix(t *testing.T) {
s3URL := os.Getenv("NTFY_TEST_S3_URL")
2026-03-22 08:15:23 -04:00
if s3URL == "" {
t.Skip("NTFY_TEST_S3_URL not set")
2026-03-22 08:15:23 -04:00
}
cfg, err := s3.ParseURL(s3URL)
require.Nil(t, err)
cfg.Prefix = "test-prefix"
client := s3.New(cfg)
deleteAllObjects(t, client)
2026-03-22 08:15:23 -04:00
backend := newS3Backend(client)
2026-03-25 15:28:23 -04:00
cache, err := newStore(backend, 10*1024, time.Hour, nil)
2026-03-22 08:15:23 -04:00
require.Nil(t, err)
t.Cleanup(func() {
deleteAllObjects(t, client)
2026-03-22 08:15:23 -04:00
cache.Close()
})
2026-03-16 09:48:26 -04:00
2026-03-21 21:14:49 -04:00
size, err := cache.Write("abcdefghijkl", strings.NewReader("test"), 0)
2026-03-16 09:48:26 -04:00
require.Nil(t, err)
require.Equal(t, int64(4), size)
2026-03-17 20:53:41 -04:00
reader, _, err := cache.Read("abcdefghijkl")
2026-03-16 09:48:26 -04:00
require.Nil(t, err)
data, err := io.ReadAll(reader)
reader.Close()
2026-03-14 21:10:46 -04:00
require.Nil(t, err)
2026-03-16 09:48:26 -04:00
require.Equal(t, "test", string(data))
2026-03-14 21:10:46 -04:00
}
2026-03-16 09:48:26 -04:00
// --- Helpers ---
2026-03-22 08:15:23 -04:00
func newTestRealS3Store(t *testing.T, totalSizeLimit int64) (*Store, *modTimeOverrideBackend) {
2026-03-16 09:48:26 -04:00
t.Helper()
s3URL := os.Getenv("NTFY_TEST_S3_URL")
2026-03-22 08:15:23 -04:00
if s3URL == "" {
t.Skip("NTFY_TEST_S3_URL not set")
2026-03-16 20:00:19 -04:00
}
2026-03-22 08:15:23 -04:00
cfg, err := s3.ParseURL(s3URL)
require.Nil(t, err)
if cfg.Prefix != "" {
cfg.Prefix = cfg.Prefix + "/testpkg-attachment"
} else {
cfg.Prefix = "testpkg-attachment"
}
2026-03-22 08:15:23 -04:00
client := s3.New(cfg)
inner := newS3Backend(client)
wrapper := &modTimeOverrideBackend{backend: inner, modTimes: make(map[string]time.Time)}
deleteAllObjects(t, client)
2026-03-25 15:28:23 -04:00
store, err := newStore(wrapper, totalSizeLimit, time.Hour, nil)
2026-03-22 08:15:23 -04:00
require.Nil(t, err)
t.Cleanup(func() {
deleteAllObjects(t, client)
2026-03-22 08:15:23 -04:00
store.Close()
})
return store, wrapper
}
func deleteAllObjects(t *testing.T, client *s3.Client) {
t.Helper()
for i := 0; i < 20; i++ {
objects, err := client.ListObjectsV2(context.Background())
require.Nil(t, err)
if len(objects) == 0 {
return
}
keys := make([]string, len(objects))
for j, obj := range objects {
keys[j] = obj.Key
}
require.Nil(t, client.DeleteObjects(context.Background(), keys))
time.Sleep(200 * time.Millisecond)
2026-03-16 20:00:19 -04:00
}
t.Fatal("timed out waiting for bucket to be empty")
2026-03-16 20:00:19 -04:00
}
2026-03-22 08:15:23 -04:00
// modTimeOverrideBackend wraps a backend and allows overriding LastModified times returned by List().
// This is used in tests to simulate old objects on backends (like real S3) where
// LastModified cannot be set directly.
type modTimeOverrideBackend struct {
backend
mu sync.Mutex
modTimes map[string]time.Time // object ID -> override time
2026-03-16 20:00:19 -04:00
}
2026-03-22 08:15:23 -04:00
func (b *modTimeOverrideBackend) List() ([]object, error) {
objects, err := b.backend.List()
2026-03-16 09:48:26 -04:00
if err != nil {
2026-03-22 08:15:23 -04:00
return nil, err
2026-03-16 09:48:26 -04:00
}
2026-03-22 08:15:23 -04:00
b.mu.Lock()
defer b.mu.Unlock()
for i, obj := range objects {
if t, ok := b.modTimes[obj.ID]; ok {
objects[i].LastModified = t
2026-03-16 09:48:26 -04:00
}
}
2026-03-22 08:15:23 -04:00
return objects, nil
2026-03-16 09:48:26 -04:00
}
2026-03-14 21:10:46 -04:00
2026-03-22 08:15:23 -04:00
func (b *modTimeOverrideBackend) setModTime(id string, t time.Time) {
b.mu.Lock()
b.modTimes[id] = t
b.mu.Unlock()
2026-03-14 21:10:46 -04:00
}