Source file
src/mime/type_test.go
1
2
3
4
5 package mime
6
7 import (
8 "internal/asan"
9 "slices"
10 "strings"
11 "sync"
12 "testing"
13 )
14
15 func setMimeInit(fn func()) (cleanup func()) {
16 once = sync.Once{}
17 testInitMime = fn
18 return func() {
19 testInitMime = nil
20 once = sync.Once{}
21 }
22 }
23
24 func clearMimeTypes() {
25 setMimeTypes(map[string]string{}, map[string]string{})
26 }
27
28 func setType(ext, typ string) {
29 if !strings.HasPrefix(ext, ".") {
30 panic("missing leading dot")
31 }
32 if err := setExtensionType(ext, typ); err != nil {
33 panic("bad test data: " + err.Error())
34 }
35 }
36
37 func TestTypeByExtension(t *testing.T) {
38 once = sync.Once{}
39
40
41
42
43
44
45 typeTests := initMimeForTests()
46
47 for ext, want := range typeTests {
48 val := TypeByExtension(ext)
49 if val != want {
50 t.Errorf("TypeByExtension(%q) = %q, want %q", ext, val, want)
51 }
52 }
53 }
54
55 func TestTypeByExtension_LocalData(t *testing.T) {
56 cleanup := setMimeInit(func() {
57 clearMimeTypes()
58 setType(".foo", "x/foo")
59 setType(".bar", "x/bar")
60 setType(".Bar", "x/bar; capital=1")
61 })
62 defer cleanup()
63
64 tests := map[string]string{
65 ".foo": "x/foo",
66 ".bar": "x/bar",
67 ".Bar": "x/bar; capital=1",
68 ".sdlkfjskdlfj": "",
69 ".t1": "",
70 }
71
72 for ext, want := range tests {
73 val := TypeByExtension(ext)
74 if val != want {
75 t.Errorf("TypeByExtension(%q) = %q, want %q", ext, val, want)
76 }
77 }
78 }
79
80 func TestTypeByExtensionCase(t *testing.T) {
81 const custom = "test/test; charset=iso-8859-1"
82 const caps = "test/test; WAS=ALLCAPS"
83
84 cleanup := setMimeInit(func() {
85 clearMimeTypes()
86 setType(".TEST", caps)
87 setType(".tesT", custom)
88 })
89 defer cleanup()
90
91
92 if got := TypeByExtension(".tesT"); got != custom {
93 t.Fatalf("for .tesT, got %q; want %q", got, custom)
94 }
95 if got := TypeByExtension(".TEST"); got != caps {
96 t.Fatalf("for .TEST, got %q; want %s", got, caps)
97 }
98
99
100 if got := TypeByExtension(".TesT"); got != custom {
101 t.Fatalf("for .TesT, got %q; want %q", got, custom)
102 }
103 }
104
105 func TestExtensionsByType(t *testing.T) {
106 cleanup := setMimeInit(func() {
107 clearMimeTypes()
108 setType(".gif", "image/gif")
109 setType(".a", "foo/letter")
110 setType(".b", "foo/letter")
111 setType(".B", "foo/letter")
112 setType(".PNG", "image/png")
113 })
114 defer cleanup()
115
116 tests := []struct {
117 typ string
118 want []string
119 wantErr string
120 }{
121 {typ: "image/gif", want: []string{".gif"}},
122 {typ: "image/png", want: []string{".png"}},
123 {typ: "foo/letter", want: []string{".a", ".b"}},
124 {typ: "x/unknown", want: nil},
125 }
126
127 for _, tt := range tests {
128 got, err := ExtensionsByType(tt.typ)
129 if err != nil && tt.wantErr != "" && strings.Contains(err.Error(), tt.wantErr) {
130 continue
131 }
132 if err != nil {
133 t.Errorf("ExtensionsByType(%q) error: %v", tt.typ, err)
134 continue
135 }
136 if tt.wantErr != "" {
137 t.Errorf("ExtensionsByType(%q) = %q, %v; want error substring %q", tt.typ, got, err, tt.wantErr)
138 continue
139 }
140 if !slices.Equal(got, tt.want) {
141 t.Errorf("ExtensionsByType(%q) = %q; want %q", tt.typ, got, tt.want)
142 }
143 }
144 }
145
146 func TestLookupMallocs(t *testing.T) {
147 if asan.Enabled {
148 t.Skip("test allocates more with -asan; see #70079")
149 }
150 n := testing.AllocsPerRun(10000, func() {
151 TypeByExtension(".html")
152 TypeByExtension(".HtML")
153 })
154 if n > 0 {
155 t.Errorf("allocs = %v; want 0", n)
156 }
157 }
158
159 func BenchmarkTypeByExtension(b *testing.B) {
160 initMime()
161 b.ResetTimer()
162
163 for _, ext := range []string{
164 ".html",
165 ".HTML",
166 ".unused",
167 } {
168 b.Run(ext, func(b *testing.B) {
169 b.RunParallel(func(pb *testing.PB) {
170 for pb.Next() {
171 TypeByExtension(ext)
172 }
173 })
174 })
175 }
176 }
177
178 func BenchmarkExtensionsByType(b *testing.B) {
179 initMime()
180 b.ResetTimer()
181
182 for _, typ := range []string{
183 "text/html",
184 "text/html; charset=utf-8",
185 "application/octet-stream",
186 } {
187 b.Run(typ, func(b *testing.B) {
188 b.RunParallel(func(pb *testing.PB) {
189 for pb.Next() {
190 if _, err := ExtensionsByType(typ); err != nil {
191 b.Fatal(err)
192 }
193 }
194 })
195 })
196 }
197 }
198
199 func TestExtensionsByType2(t *testing.T) {
200 cleanup := setMimeInit(func() {
201 clearMimeTypes()
202
203 setMimeTypes(builtinTypesLower, builtinTypesLower)
204 })
205 defer cleanup()
206
207 tests := []struct {
208 typ string
209 want []string
210 }{
211 {typ: "image/jpeg", want: []string{".jpeg", ".jpg"}},
212 }
213
214 for _, tt := range tests {
215 got, err := ExtensionsByType(tt.typ)
216 if err != nil {
217 t.Errorf("ExtensionsByType(%q): %v", tt.typ, err)
218 continue
219 }
220 if !slices.Equal(got, tt.want) {
221 t.Errorf("ExtensionsByType(%q) = %q; want %q", tt.typ, got, tt.want)
222 }
223 }
224 }
225
View as plain text