...

Source file src/net/http/header_test.go

Documentation: net/http

		 1  // Copyright 2011 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 http
		 6  
		 7  import (
		 8  	"bytes"
		 9  	"internal/race"
		10  	"reflect"
		11  	"runtime"
		12  	"testing"
		13  	"time"
		14  )
		15  
		16  var headerWriteTests = []struct {
		17  	h				Header
		18  	exclude	map[string]bool
		19  	expected string
		20  }{
		21  	{Header{}, nil, ""},
		22  	{
		23  		Header{
		24  			"Content-Type":	 {"text/html; charset=UTF-8"},
		25  			"Content-Length": {"0"},
		26  		},
		27  		nil,
		28  		"Content-Length: 0\r\nContent-Type: text/html; charset=UTF-8\r\n",
		29  	},
		30  	{
		31  		Header{
		32  			"Content-Length": {"0", "1", "2"},
		33  		},
		34  		nil,
		35  		"Content-Length: 0\r\nContent-Length: 1\r\nContent-Length: 2\r\n",
		36  	},
		37  	{
		38  		Header{
		39  			"Expires":					{"-1"},
		40  			"Content-Length":	 {"0"},
		41  			"Content-Encoding": {"gzip"},
		42  		},
		43  		map[string]bool{"Content-Length": true},
		44  		"Content-Encoding: gzip\r\nExpires: -1\r\n",
		45  	},
		46  	{
		47  		Header{
		48  			"Expires":					{"-1"},
		49  			"Content-Length":	 {"0", "1", "2"},
		50  			"Content-Encoding": {"gzip"},
		51  		},
		52  		map[string]bool{"Content-Length": true},
		53  		"Content-Encoding: gzip\r\nExpires: -1\r\n",
		54  	},
		55  	{
		56  		Header{
		57  			"Expires":					{"-1"},
		58  			"Content-Length":	 {"0"},
		59  			"Content-Encoding": {"gzip"},
		60  		},
		61  		map[string]bool{"Content-Length": true, "Expires": true, "Content-Encoding": true},
		62  		"",
		63  	},
		64  	{
		65  		Header{
		66  			"Nil":					nil,
		67  			"Empty":				{},
		68  			"Blank":				{""},
		69  			"Double-Blank": {"", ""},
		70  		},
		71  		nil,
		72  		"Blank: \r\nDouble-Blank: \r\nDouble-Blank: \r\n",
		73  	},
		74  	// Tests header sorting when over the insertion sort threshold side:
		75  	{
		76  		Header{
		77  			"k1": {"1a", "1b"},
		78  			"k2": {"2a", "2b"},
		79  			"k3": {"3a", "3b"},
		80  			"k4": {"4a", "4b"},
		81  			"k5": {"5a", "5b"},
		82  			"k6": {"6a", "6b"},
		83  			"k7": {"7a", "7b"},
		84  			"k8": {"8a", "8b"},
		85  			"k9": {"9a", "9b"},
		86  		},
		87  		map[string]bool{"k5": true},
		88  		"k1: 1a\r\nk1: 1b\r\nk2: 2a\r\nk2: 2b\r\nk3: 3a\r\nk3: 3b\r\n" +
		89  			"k4: 4a\r\nk4: 4b\r\nk6: 6a\r\nk6: 6b\r\n" +
		90  			"k7: 7a\r\nk7: 7b\r\nk8: 8a\r\nk8: 8b\r\nk9: 9a\r\nk9: 9b\r\n",
		91  	},
		92  }
		93  
		94  func TestHeaderWrite(t *testing.T) {
		95  	var buf bytes.Buffer
		96  	for i, test := range headerWriteTests {
		97  		test.h.WriteSubset(&buf, test.exclude)
		98  		if buf.String() != test.expected {
		99  			t.Errorf("#%d:\n got: %q\nwant: %q", i, buf.String(), test.expected)
	 100  		}
	 101  		buf.Reset()
	 102  	}
	 103  }
	 104  
	 105  var parseTimeTests = []struct {
	 106  	h	 Header
	 107  	err bool
	 108  }{
	 109  	{Header{"Date": {""}}, true},
	 110  	{Header{"Date": {"invalid"}}, true},
	 111  	{Header{"Date": {"1994-11-06T08:49:37Z00:00"}}, true},
	 112  	{Header{"Date": {"Sun, 06 Nov 1994 08:49:37 GMT"}}, false},
	 113  	{Header{"Date": {"Sunday, 06-Nov-94 08:49:37 GMT"}}, false},
	 114  	{Header{"Date": {"Sun Nov	6 08:49:37 1994"}}, false},
	 115  }
	 116  
	 117  func TestParseTime(t *testing.T) {
	 118  	expect := time.Date(1994, 11, 6, 8, 49, 37, 0, time.UTC)
	 119  	for i, test := range parseTimeTests {
	 120  		d, err := ParseTime(test.h.Get("Date"))
	 121  		if err != nil {
	 122  			if !test.err {
	 123  				t.Errorf("#%d:\n got err: %v", i, err)
	 124  			}
	 125  			continue
	 126  		}
	 127  		if test.err {
	 128  			t.Errorf("#%d:\n	should err", i)
	 129  			continue
	 130  		}
	 131  		if !expect.Equal(d) {
	 132  			t.Errorf("#%d:\n got: %v\nwant: %v", i, d, expect)
	 133  		}
	 134  	}
	 135  }
	 136  
	 137  type hasTokenTest struct {
	 138  	header string
	 139  	token	string
	 140  	want	 bool
	 141  }
	 142  
	 143  var hasTokenTests = []hasTokenTest{
	 144  	{"", "", false},
	 145  	{"", "foo", false},
	 146  	{"foo", "foo", true},
	 147  	{"foo ", "foo", true},
	 148  	{" foo", "foo", true},
	 149  	{" foo ", "foo", true},
	 150  	{"foo,bar", "foo", true},
	 151  	{"bar,foo", "foo", true},
	 152  	{"bar, foo", "foo", true},
	 153  	{"bar,foo, baz", "foo", true},
	 154  	{"bar, foo,baz", "foo", true},
	 155  	{"bar,foo, baz", "foo", true},
	 156  	{"bar, foo, baz", "foo", true},
	 157  	{"FOO", "foo", true},
	 158  	{"FOO ", "foo", true},
	 159  	{" FOO", "foo", true},
	 160  	{" FOO ", "foo", true},
	 161  	{"FOO,BAR", "foo", true},
	 162  	{"BAR,FOO", "foo", true},
	 163  	{"BAR, FOO", "foo", true},
	 164  	{"BAR,FOO, baz", "foo", true},
	 165  	{"BAR, FOO,BAZ", "foo", true},
	 166  	{"BAR,FOO, BAZ", "foo", true},
	 167  	{"BAR, FOO, BAZ", "foo", true},
	 168  	{"foobar", "foo", false},
	 169  	{"barfoo ", "foo", false},
	 170  }
	 171  
	 172  func TestHasToken(t *testing.T) {
	 173  	for _, tt := range hasTokenTests {
	 174  		if hasToken(tt.header, tt.token) != tt.want {
	 175  			t.Errorf("hasToken(%q, %q) = %v; want %v", tt.header, tt.token, !tt.want, tt.want)
	 176  		}
	 177  	}
	 178  }
	 179  
	 180  func TestNilHeaderClone(t *testing.T) {
	 181  	t1 := Header(nil)
	 182  	t2 := t1.Clone()
	 183  	if t2 != nil {
	 184  		t.Errorf("cloned header does not match original: got: %+v; want: %+v", t2, nil)
	 185  	}
	 186  }
	 187  
	 188  var testHeader = Header{
	 189  	"Content-Length": {"123"},
	 190  	"Content-Type":	 {"text/plain"},
	 191  	"Date":					 {"some date at some time Z"},
	 192  	"Server":				 {DefaultUserAgent},
	 193  }
	 194  
	 195  var buf bytes.Buffer
	 196  
	 197  func BenchmarkHeaderWriteSubset(b *testing.B) {
	 198  	b.ReportAllocs()
	 199  	for i := 0; i < b.N; i++ {
	 200  		buf.Reset()
	 201  		testHeader.WriteSubset(&buf, nil)
	 202  	}
	 203  }
	 204  
	 205  func TestHeaderWriteSubsetAllocs(t *testing.T) {
	 206  	if testing.Short() {
	 207  		t.Skip("skipping alloc test in short mode")
	 208  	}
	 209  	if race.Enabled {
	 210  		t.Skip("skipping test under race detector")
	 211  	}
	 212  	if runtime.GOMAXPROCS(0) > 1 {
	 213  		t.Skip("skipping; GOMAXPROCS>1")
	 214  	}
	 215  	n := testing.AllocsPerRun(100, func() {
	 216  		buf.Reset()
	 217  		testHeader.WriteSubset(&buf, nil)
	 218  	})
	 219  	if n > 0 {
	 220  		t.Errorf("allocs = %g; want 0", n)
	 221  	}
	 222  }
	 223  
	 224  // Issue 34878: test that every call to
	 225  // cloneOrMakeHeader never returns a nil Header.
	 226  func TestCloneOrMakeHeader(t *testing.T) {
	 227  	tests := []struct {
	 228  		name		 string
	 229  		in, want Header
	 230  	}{
	 231  		{"nil", nil, Header{}},
	 232  		{"empty", Header{}, Header{}},
	 233  		{
	 234  			name: "non-empty",
	 235  			in:	 Header{"foo": {"bar"}},
	 236  			want: Header{"foo": {"bar"}},
	 237  		},
	 238  		{
	 239  			name: "nil value",
	 240  			in:	 Header{"foo": nil},
	 241  			want: Header{"foo": nil},
	 242  		},
	 243  	}
	 244  
	 245  	for _, tt := range tests {
	 246  		t.Run(tt.name, func(t *testing.T) {
	 247  			got := cloneOrMakeHeader(tt.in)
	 248  			if got == nil {
	 249  				t.Fatal("unexpected nil Header")
	 250  			}
	 251  			if !reflect.DeepEqual(got, tt.want) {
	 252  				t.Fatalf("Got:	%#v\nWant: %#v", got, tt.want)
	 253  			}
	 254  			got.Add("A", "B")
	 255  			got.Get("A")
	 256  		})
	 257  	}
	 258  }
	 259  

View as plain text