github.com/c12o16h1/go/src@v0.0.0-20200114212001-5a151c0f00ed/mime/type_test.go (about) 1 // Copyright 2010 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package mime 6 7 import ( 8 "reflect" 9 "strings" 10 "sync" 11 "testing" 12 ) 13 14 func setMimeInit(fn func()) (cleanup func()) { 15 once = sync.Once{} 16 testInitMime = fn 17 return func() { testInitMime = nil } 18 } 19 20 func clearMimeTypes() { 21 setMimeTypes(map[string]string{}, map[string]string{}) 22 } 23 24 func setType(ext, typ string) { 25 if !strings.HasPrefix(ext, ".") { 26 panic("missing leading dot") 27 } 28 if err := setExtensionType(ext, typ); err != nil { 29 panic("bad test data: " + err.Error()) 30 } 31 } 32 33 func TestTypeByExtension(t *testing.T) { 34 once = sync.Once{} 35 // initMimeForTests returns the platform-specific extension => 36 // type tests. On Unix and Plan 9, this also tests the parsing 37 // of MIME text files (in testdata/*). On Windows, we test the 38 // real registry on the machine and assume that ".png" exists 39 // there, which empirically it always has, for all versions of 40 // Windows. 41 typeTests := initMimeForTests() 42 43 for ext, want := range typeTests { 44 val := TypeByExtension(ext) 45 if val != want { 46 t.Errorf("TypeByExtension(%q) = %q, want %q", ext, val, want) 47 } 48 } 49 } 50 51 func TestTypeByExtension_LocalData(t *testing.T) { 52 cleanup := setMimeInit(func() { 53 clearMimeTypes() 54 setType(".foo", "x/foo") 55 setType(".bar", "x/bar") 56 setType(".Bar", "x/bar; capital=1") 57 }) 58 defer cleanup() 59 60 tests := map[string]string{ 61 ".foo": "x/foo", 62 ".bar": "x/bar", 63 ".Bar": "x/bar; capital=1", 64 ".sdlkfjskdlfj": "", 65 ".t1": "", // testdata shouldn't be used 66 } 67 68 for ext, want := range tests { 69 val := TypeByExtension(ext) 70 if val != want { 71 t.Errorf("TypeByExtension(%q) = %q, want %q", ext, val, want) 72 } 73 } 74 } 75 76 func TestTypeByExtensionCase(t *testing.T) { 77 const custom = "test/test; charset=iso-8859-1" 78 const caps = "test/test; WAS=ALLCAPS" 79 80 cleanup := setMimeInit(func() { 81 clearMimeTypes() 82 setType(".TEST", caps) 83 setType(".tesT", custom) 84 }) 85 defer cleanup() 86 87 // case-sensitive lookup 88 if got := TypeByExtension(".tesT"); got != custom { 89 t.Fatalf("for .tesT, got %q; want %q", got, custom) 90 } 91 if got := TypeByExtension(".TEST"); got != caps { 92 t.Fatalf("for .TEST, got %q; want %s", got, caps) 93 } 94 95 // case-insensitive 96 if got := TypeByExtension(".TesT"); got != custom { 97 t.Fatalf("for .TesT, got %q; want %q", got, custom) 98 } 99 } 100 101 func TestExtensionsByType(t *testing.T) { 102 cleanup := setMimeInit(func() { 103 clearMimeTypes() 104 setType(".gif", "image/gif") 105 setType(".a", "foo/letter") 106 setType(".b", "foo/letter") 107 setType(".B", "foo/letter") 108 setType(".PNG", "image/png") 109 }) 110 defer cleanup() 111 112 tests := []struct { 113 typ string 114 want []string 115 wantErr string 116 }{ 117 {typ: "image/gif", want: []string{".gif"}}, 118 {typ: "image/png", want: []string{".png"}}, // lowercase 119 {typ: "foo/letter", want: []string{".a", ".b"}}, 120 {typ: "x/unknown", want: nil}, 121 } 122 123 for _, tt := range tests { 124 got, err := ExtensionsByType(tt.typ) 125 if err != nil && tt.wantErr != "" && strings.Contains(err.Error(), tt.wantErr) { 126 continue 127 } 128 if err != nil { 129 t.Errorf("ExtensionsByType(%q) error: %v", tt.typ, err) 130 continue 131 } 132 if tt.wantErr != "" { 133 t.Errorf("ExtensionsByType(%q) = %q, %v; want error substring %q", tt.typ, got, err, tt.wantErr) 134 continue 135 } 136 if !reflect.DeepEqual(got, tt.want) { 137 t.Errorf("ExtensionsByType(%q) = %q; want %q", tt.typ, got, tt.want) 138 } 139 } 140 } 141 142 func TestLookupMallocs(t *testing.T) { 143 n := testing.AllocsPerRun(10000, func() { 144 TypeByExtension(".html") 145 TypeByExtension(".HtML") 146 }) 147 if n > 0 { 148 t.Errorf("allocs = %v; want 0", n) 149 } 150 } 151 152 func BenchmarkTypeByExtension(b *testing.B) { 153 initMime() 154 b.ResetTimer() 155 156 for _, ext := range []string{ 157 ".html", 158 ".HTML", 159 ".unused", 160 } { 161 b.Run(ext, func(b *testing.B) { 162 b.RunParallel(func(pb *testing.PB) { 163 for pb.Next() { 164 TypeByExtension(ext) 165 } 166 }) 167 }) 168 } 169 } 170 171 func BenchmarkExtensionsByType(b *testing.B) { 172 initMime() 173 b.ResetTimer() 174 175 for _, typ := range []string{ 176 "text/html", 177 "text/html; charset=utf-8", 178 "application/octet-stream", 179 } { 180 b.Run(typ, func(b *testing.B) { 181 b.RunParallel(func(pb *testing.PB) { 182 for pb.Next() { 183 if _, err := ExtensionsByType(typ); err != nil { 184 b.Fatal(err) 185 } 186 } 187 }) 188 }) 189 } 190 }