...

Source file src/mime/type_test.go

Documentation: mime

		 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  }
	 191  
	 192  func TestExtensionsByType2(t *testing.T) {
	 193  	cleanup := setMimeInit(func() {
	 194  		clearMimeTypes()
	 195  		// Initialize built-in types like in type.go before osInitMime.
	 196  		setMimeTypes(builtinTypesLower, builtinTypesLower)
	 197  	})
	 198  	defer cleanup()
	 199  
	 200  	tests := []struct {
	 201  		typ	string
	 202  		want []string
	 203  	}{
	 204  		{typ: "image/jpeg", want: []string{".jpeg", ".jpg"}},
	 205  	}
	 206  
	 207  	for _, tt := range tests {
	 208  		got, err := ExtensionsByType(tt.typ)
	 209  		if err != nil {
	 210  			t.Errorf("ExtensionsByType(%q): %v", tt.typ, err)
	 211  			continue
	 212  		}
	 213  		if !reflect.DeepEqual(got, tt.want) {
	 214  			t.Errorf("ExtensionsByType(%q) = %q; want %q", tt.typ, got, tt.want)
	 215  		}
	 216  	}
	 217  }
	 218  

View as plain text