package attach import ( "strings" "testing" "gocloud.dev/blob" "gocloud.dev/blob/fileblob" "gocloud.dev/blob/memblob" ) func TestIsInlineContentType(t *testing.T) { cases := []struct { in string want bool }{ {"image/jpeg", true}, {"image/png", true}, {"image/gif", true}, {"image/webp", true}, {"image/avif", true}, {"IMAGE/WEBP; charset=binary", true}, {"text/html; charset=utf-8", false}, {"image/svg+xml", false}, {"application/pdf", false}, {"text/plain", false}, {"application/octet-stream", false}, {"application/zip", false}, {"image/bmp", false}, {"image/x-icon", false}, {"video/mp4", false}, {"audio/mpeg", false}, {"", false}, {"not a media type;;", false}, } for _, tc := range cases { if got := IsInlineContentType(tc.in); got != tc.want { t.Errorf("IsInlineContentType(%q) = %v, want %v", tc.in, got, tc.want) } } } // TestWriteBlobDisposition is the driver half of the public-bucket fix: a // public bucket serves the headers Store stores with the object, so the // attachment disposition must survive the write on the real drivers. The // metadata-skip fileblob bucket shows that a driver which does not keep // attributes still accepts the option without an error. func TestWriteBlobDisposition(t *testing.T) { cases := []struct { name, ct, disposition string }{ {"html", "text/html", "attachment"}, {"text", "text/plain", "attachment"}, {"pdf", "application/pdf", "attachment"}, {"svg", "image/svg+xml", "attachment"}, {"zip", "application/zip", "attachment"}, {"png", "image/png", ""}, {"jpeg", "image/jpeg", ""}, {"avif", "image/avif", ""}, } sidecar, err := fileblob.OpenBucket(t.TempDir(), nil) if err != nil { t.Fatal(err) } noMeta, err := fileblob.OpenBucket(t.TempDir(), &fileblob.Options{Metadata: fileblob.MetadataDontWrite}) if err != nil { t.Fatal(err) } buckets := []struct { name string bucket *blob.Bucket keepsAttrs bool }{ {"memblob", memblob.OpenBucket(nil), true}, {"fileblob sidecar", sidecar, true}, {"fileblob metadata skipped", noMeta, false}, } const body = "" for _, b := range buckets { bucket := b.bucket t.Cleanup(func() { _ = bucket.Close() }) t.Run(b.name, func(t *testing.T) { ctx := t.Context() for _, tc := range cases { key := "abc/def/012/" + tc.name + "-file.bin" n, err := writeBlob(ctx, bucket, key, strings.NewReader(body), tc.ct, 0) if err != nil { t.Fatalf("%s: writeBlob: %v", tc.name, err) } if n != int64(len(body)) { t.Fatalf("%s: wrote %d bytes, want %d", tc.name, n, len(body)) } got, err := bucket.ReadAll(ctx, key) if err != nil { t.Fatalf("%s: ReadAll: %v", tc.name, err) } if string(got) != body { t.Fatalf("%s: body = %q, want %q", tc.name, got, body) } if !b.keepsAttrs { continue } attrs, err := bucket.Attributes(ctx, key) if err != nil { t.Fatalf("%s: Attributes: %v", tc.name, err) } if attrs.ContentType != tc.ct { t.Errorf("%s: ContentType = %q, want %q", tc.name, attrs.ContentType, tc.ct) } if attrs.ContentDisposition != tc.disposition { t.Errorf("%s: ContentDisposition = %q, want %q", tc.name, attrs.ContentDisposition, tc.disposition) } } }) } }