Expire local static assets after 24 hours

This commit is contained in:
2026-06-07 19:29:04 +08:00
parent f47132a653
commit 4d1a01ec71
5 changed files with 395 additions and 30 deletions
+99
View File
@@ -93,6 +93,43 @@ func TestGeneratedAssetDecisionUploadsDataURL(t *testing.T) {
}
}
func TestGeneratedAssetDecisionUploadsAudioContentDataURL(t *testing.T) {
item := map[string]any{
"type": "audio",
"content": "data:audio/mpeg;base64," + base64.StdEncoding.EncodeToString([]byte("inline audio")),
"mime_type": "audio/mpeg",
}
decision, err := generatedAssetDecisionForItem("speech.generations", item, defaultGeneratedAssetUploadPolicy())
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if decision.Inline == nil {
t.Fatalf("expected inline audio content to be uploaded")
}
if decision.Inline.Kind != "audio" || decision.Inline.ContentType != "audio/mpeg" || decision.Inline.SourceKey != "content" {
t.Fatalf("unexpected inline audio metadata: %+v", decision.Inline)
}
if !containsString(decision.StripKeys, "content") {
t.Fatalf("uploaded audio content should be stripped: %+v", decision.StripKeys)
}
}
func TestGeneratedAssetDecisionDoesNotUploadPlainTextContent(t *testing.T) {
item := map[string]any{
"type": "text",
"content": base64.StdEncoding.EncodeToString([]byte(strings.Repeat("plain text ", 20))),
}
decision, err := generatedAssetDecisionForItem("speech.generations", item, defaultGeneratedAssetUploadPolicy())
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if decision.Inline != nil || len(decision.StripKeys) > 0 {
t.Fatalf("plain text content should not be treated as generated media: %+v", decision)
}
}
func TestGeneratedAssetDecisionUploadsURLWhenPolicyUploadAll(t *testing.T) {
item := map[string]any{
"type": "video",
@@ -216,6 +253,9 @@ func TestUploadGeneratedAssetStoresLocalWhenNoChannels(t *testing.T) {
if !strings.HasPrefix(urlValue, "/static/generated/gateway-result-task-123-01-") || !strings.HasSuffix(urlValue, ".png") {
t.Fatalf("unexpected local static URL: %s", urlValue)
}
if stringFromAny(upload["expiresAt"]) == "" {
t.Fatalf("local static upload should expose expiresAt: %+v", upload)
}
entries, err := os.ReadDir(storageDir)
if err != nil {
t.Fatalf("failed to read local static dir: %v", err)
@@ -232,6 +272,39 @@ func TestUploadGeneratedAssetStoresLocalWhenNoChannels(t *testing.T) {
}
}
func TestUploadGeneratedAssetStoresAudioLocalWhenNoChannels(t *testing.T) {
storageDir := t.TempDir()
service := &Service{cfg: config.Config{LocalGeneratedStorageDir: storageDir}}
asset := &generatedInlineAsset{
Bytes: []byte("inline audio payload"),
ContentType: "audio/mpeg",
Kind: "audio",
SourceKey: "content",
}
upload, contentType, kind, strategy, err := service.uploadGeneratedAsset(context.Background(), "task-tts", asset, 0, nil, false)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if contentType != "audio/mpeg" || kind != "audio" || strategy != "local_static_inline_media" {
t.Fatalf("unexpected local audio metadata: contentType=%s kind=%s strategy=%s", contentType, kind, strategy)
}
urlValue := stringFromAny(upload["url"])
if !strings.HasPrefix(urlValue, "/static/generated/gateway-result-task-tts-01-") || !strings.HasSuffix(urlValue, ".mp3") {
t.Fatalf("unexpected local audio URL: %s", urlValue)
}
if stringFromAny(upload["expiresAt"]) == "" {
t.Fatalf("local audio static upload should expose expiresAt: %+v", upload)
}
entries, err := os.ReadDir(storageDir)
if err != nil {
t.Fatalf("failed to read local static dir: %v", err)
}
if len(entries) != 1 || !strings.HasSuffix(entries[0].Name(), ".mp3") {
t.Fatalf("expected one MP3 file in local static dir, got %+v", entries)
}
}
func TestUploadFileStoresLocalWhenNoChannels(t *testing.T) {
storageDir := t.TempDir()
service := &Service{cfg: config.Config{
@@ -254,6 +327,9 @@ func TestUploadFileStoresLocalWhenNoChannels(t *testing.T) {
if !strings.HasPrefix(urlValue, "/static/uploaded/") || !strings.HasSuffix(urlValue, ".pdf") {
t.Fatalf("unexpected uploaded local static URL: %s", urlValue)
}
if stringFromAny(upload["expiresAt"]) == "" {
t.Fatalf("local uploaded static file should expose expiresAt: %+v", upload)
}
storageChannel, _ := upload["storageChannel"].(map[string]any)
if stringFromAny(storageChannel["provider"]) != "local_static" {
t.Fatalf("expected local static provider metadata, got %+v", upload["storageChannel"])
@@ -277,3 +353,26 @@ func TestUploadFileStoresLocalWhenNoChannels(t *testing.T) {
t.Fatalf("stored uploaded payload does not match source payload")
}
}
func TestRedactGeneratedResultRawDataAudioPayload(t *testing.T) {
audioHex := strings.Repeat("49443304", 40)
result := map[string]any{
"raw_data": map[string]any{
"base_resp": map[string]any{"status_code": float64(0)},
"data": map[string]any{"audio": audioHex},
},
}
if !redactGeneratedResultRawData(result) {
t.Fatalf("expected raw audio payload to be redacted")
}
rawData, _ := result["raw_data"].(map[string]any)
data, _ := rawData["data"].(map[string]any)
audio, _ := data["audio"].(map[string]any)
if audio["redacted"] != true || audio["encoding"] != "hex" || audio["contentType"] != "audio/mpeg" {
t.Fatalf("unexpected redacted audio payload: %+v", audio)
}
if _, ok := audio["sha256"].(string); !ok {
t.Fatalf("expected redacted audio payload to include sha256: %+v", audio)
}
}