package storage import ( "bytes" "context" "errors" "io" "os" "testing" "time" ) // requireS3TestEnv liefert die S3-Testkonfiguration oder ueberspringt den // Test — dasselbe Muster wie TEST_ADMIN_DSN im Core-Modul: kein S3- // kompatibler Speicher in dieser Umgebung verfuegbar/geprueft (siehe // FDN-03-Pruefprotokoll), daher hier bewusst als optional markiert statt // den Treiber ungetestet zu lassen. func requireS3TestEnv(t *testing.T) *S3Driver { t.Helper() bucket := os.Getenv("TEST_S3_BUCKET") if bucket == "" { t.Skip("TEST_S3_BUCKET nicht gesetzt, S3-Integrationstest uebersprungen") } endpoint := os.Getenv("TEST_S3_ENDPOINT") region := os.Getenv("TEST_S3_REGION") if region == "" { region = "us-east-1" } accessKey := os.Getenv("TEST_S3_ACCESS_KEY_ID") secretKey := os.Getenv("TEST_S3_SECRET_ACCESS_KEY") d, err := NewS3Driver(context.Background(), bucket, region, endpoint, accessKey, secretKey, true) if err != nil { t.Fatalf("s3-treiber aufbauen: %v", err) } return d } // TestS3Driver_RoundTrip ist Pruefung 1 fuer den S3-Treiber. func TestS3Driver_RoundTrip(t *testing.T) { d := requireS3TestEnv(t) ctx := context.Background() key := "fdn03-test/roundtrip" content := []byte("s3 roundtrip inhalt") t.Cleanup(func() { _ = d.Delete(ctx, key) }) if _, err := d.Put(ctx, key, bytes.NewReader(content), int64(len(content)), "text/plain"); err != nil { t.Fatalf("put: %v", err) } rc, err := d.Get(ctx, key) if err != nil { t.Fatalf("get: %v", err) } defer func() { _ = rc.Close() }() got, err := io.ReadAll(rc) if err != nil { t.Fatalf("lesen: %v", err) } if !bytes.Equal(got, content) { t.Fatalf("gelesener inhalt = %q, want %q", got, content) } } // TestS3Driver_MissingObject ist Pruefung 3 fuer den S3-Treiber. func TestS3Driver_MissingObject(t *testing.T) { d := requireS3TestEnv(t) ctx := context.Background() if _, err := d.Get(ctx, "fdn03-test/nie-angelegt"); !errors.Is(err, ErrNotFound) { t.Fatalf("get eines fehlenden objekts: erwartet ErrNotFound, habe %v", err) } if err := d.Delete(ctx, "fdn03-test/nie-angelegt"); !errors.Is(err, ErrNotFound) { t.Fatalf("delete eines fehlenden objekts: erwartet ErrNotFound, habe %v", err) } } // TestS3Driver_SignedURL ist Pruefung 2 fuer den S3-Treiber: eine // presigned URL wird erzeugt und ist innerhalb der Gueltigkeit abrufbar. func TestS3Driver_SignedURL(t *testing.T) { d := requireS3TestEnv(t) ctx := context.Background() key := "fdn03-test/signed-url" content := []byte("presigned") t.Cleanup(func() { _ = d.Delete(ctx, key) }) if _, err := d.Put(ctx, key, bytes.NewReader(content), int64(len(content)), "text/plain"); err != nil { t.Fatalf("put: %v", err) } url, err := d.SignedURL(ctx, key, time.Minute) if err != nil { t.Fatalf("signedurl: %v", err) } if url == "" { t.Fatal("erwartet nicht-leere presigned url") } }