OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / net / http2 / hpack / tables_test.go
1 // Copyright 2017 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 hpack
6
7 import (
8         "bufio"
9         "regexp"
10         "strconv"
11         "strings"
12         "testing"
13 )
14
15 func TestHeaderFieldTable(t *testing.T) {
16         table := &headerFieldTable{}
17         table.init()
18         table.addEntry(pair("key1", "value1-1"))
19         table.addEntry(pair("key2", "value2-1"))
20         table.addEntry(pair("key1", "value1-2"))
21         table.addEntry(pair("key3", "value3-1"))
22         table.addEntry(pair("key4", "value4-1"))
23         table.addEntry(pair("key2", "value2-2"))
24
25         // Tests will be run twice: once before evicting anything, and
26         // again after evicting the three oldest entries.
27         tests := []struct {
28                 f                 HeaderField
29                 beforeWantStaticI uint64
30                 beforeWantMatch   bool
31                 afterWantStaticI  uint64
32                 afterWantMatch    bool
33         }{
34                 {HeaderField{"key1", "value1-1", false}, 1, true, 0, false},
35                 {HeaderField{"key1", "value1-2", false}, 3, true, 0, false},
36                 {HeaderField{"key1", "value1-3", false}, 3, false, 0, false},
37                 {HeaderField{"key2", "value2-1", false}, 2, true, 3, false},
38                 {HeaderField{"key2", "value2-2", false}, 6, true, 3, true},
39                 {HeaderField{"key2", "value2-3", false}, 6, false, 3, false},
40                 {HeaderField{"key4", "value4-1", false}, 5, true, 2, true},
41                 // Name match only, because sensitive.
42                 {HeaderField{"key4", "value4-1", true}, 5, false, 2, false},
43                 // Key not found.
44                 {HeaderField{"key5", "value5-x", false}, 0, false, 0, false},
45         }
46
47         staticToDynamic := func(i uint64) uint64 {
48                 if i == 0 {
49                         return 0
50                 }
51                 return uint64(table.len()) - i + 1 // dynamic is the reversed table
52         }
53
54         searchStatic := func(f HeaderField) (uint64, bool) {
55                 old := staticTable
56                 staticTable = table
57                 defer func() { staticTable = old }()
58                 return staticTable.search(f)
59         }
60
61         searchDynamic := func(f HeaderField) (uint64, bool) {
62                 return table.search(f)
63         }
64
65         for _, test := range tests {
66                 gotI, gotMatch := searchStatic(test.f)
67                 if wantI, wantMatch := test.beforeWantStaticI, test.beforeWantMatch; gotI != wantI || gotMatch != wantMatch {
68                         t.Errorf("before evictions: searchStatic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch)
69                 }
70                 gotI, gotMatch = searchDynamic(test.f)
71                 wantDynamicI := staticToDynamic(test.beforeWantStaticI)
72                 if wantI, wantMatch := wantDynamicI, test.beforeWantMatch; gotI != wantI || gotMatch != wantMatch {
73                         t.Errorf("before evictions: searchDynamic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch)
74                 }
75         }
76
77         table.evictOldest(3)
78
79         for _, test := range tests {
80                 gotI, gotMatch := searchStatic(test.f)
81                 if wantI, wantMatch := test.afterWantStaticI, test.afterWantMatch; gotI != wantI || gotMatch != wantMatch {
82                         t.Errorf("after evictions: searchStatic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch)
83                 }
84                 gotI, gotMatch = searchDynamic(test.f)
85                 wantDynamicI := staticToDynamic(test.afterWantStaticI)
86                 if wantI, wantMatch := wantDynamicI, test.afterWantMatch; gotI != wantI || gotMatch != wantMatch {
87                         t.Errorf("after evictions: searchDynamic(%+v)=%v,%v want %v,%v", test.f, gotI, gotMatch, wantI, wantMatch)
88                 }
89         }
90 }
91
92 func TestHeaderFieldTable_LookupMapEviction(t *testing.T) {
93         table := &headerFieldTable{}
94         table.init()
95         table.addEntry(pair("key1", "value1-1"))
96         table.addEntry(pair("key2", "value2-1"))
97         table.addEntry(pair("key1", "value1-2"))
98         table.addEntry(pair("key3", "value3-1"))
99         table.addEntry(pair("key4", "value4-1"))
100         table.addEntry(pair("key2", "value2-2"))
101
102         // evict all pairs
103         table.evictOldest(table.len())
104
105         if l := table.len(); l > 0 {
106                 t.Errorf("table.len() = %d, want 0", l)
107         }
108
109         if l := len(table.byName); l > 0 {
110                 t.Errorf("len(table.byName) = %d, want 0", l)
111         }
112
113         if l := len(table.byNameValue); l > 0 {
114                 t.Errorf("len(table.byNameValue) = %d, want 0", l)
115         }
116 }
117
118 func TestStaticTable(t *testing.T) {
119         fromSpec := `
120           +-------+-----------------------------+---------------+
121           | 1     | :authority                  |               |
122           | 2     | :method                     | GET           |
123           | 3     | :method                     | POST          |
124           | 4     | :path                       | /             |
125           | 5     | :path                       | /index.html   |
126           | 6     | :scheme                     | http          |
127           | 7     | :scheme                     | https         |
128           | 8     | :status                     | 200           |
129           | 9     | :status                     | 204           |
130           | 10    | :status                     | 206           |
131           | 11    | :status                     | 304           |
132           | 12    | :status                     | 400           |
133           | 13    | :status                     | 404           |
134           | 14    | :status                     | 500           |
135           | 15    | accept-charset              |               |
136           | 16    | accept-encoding             | gzip, deflate |
137           | 17    | accept-language             |               |
138           | 18    | accept-ranges               |               |
139           | 19    | accept                      |               |
140           | 20    | access-control-allow-origin |               |
141           | 21    | age                         |               |
142           | 22    | allow                       |               |
143           | 23    | authorization               |               |
144           | 24    | cache-control               |               |
145           | 25    | content-disposition         |               |
146           | 26    | content-encoding            |               |
147           | 27    | content-language            |               |
148           | 28    | content-length              |               |
149           | 29    | content-location            |               |
150           | 30    | content-range               |               |
151           | 31    | content-type                |               |
152           | 32    | cookie                      |               |
153           | 33    | date                        |               |
154           | 34    | etag                        |               |
155           | 35    | expect                      |               |
156           | 36    | expires                     |               |
157           | 37    | from                        |               |
158           | 38    | host                        |               |
159           | 39    | if-match                    |               |
160           | 40    | if-modified-since           |               |
161           | 41    | if-none-match               |               |
162           | 42    | if-range                    |               |
163           | 43    | if-unmodified-since         |               |
164           | 44    | last-modified               |               |
165           | 45    | link                        |               |
166           | 46    | location                    |               |
167           | 47    | max-forwards                |               |
168           | 48    | proxy-authenticate          |               |
169           | 49    | proxy-authorization         |               |
170           | 50    | range                       |               |
171           | 51    | referer                     |               |
172           | 52    | refresh                     |               |
173           | 53    | retry-after                 |               |
174           | 54    | server                      |               |
175           | 55    | set-cookie                  |               |
176           | 56    | strict-transport-security   |               |
177           | 57    | transfer-encoding           |               |
178           | 58    | user-agent                  |               |
179           | 59    | vary                        |               |
180           | 60    | via                         |               |
181           | 61    | www-authenticate            |               |
182           +-------+-----------------------------+---------------+
183 `
184         bs := bufio.NewScanner(strings.NewReader(fromSpec))
185         re := regexp.MustCompile(`\| (\d+)\s+\| (\S+)\s*\| (\S(.*\S)?)?\s+\|`)
186         for bs.Scan() {
187                 l := bs.Text()
188                 if !strings.Contains(l, "|") {
189                         continue
190                 }
191                 m := re.FindStringSubmatch(l)
192                 if m == nil {
193                         continue
194                 }
195                 i, err := strconv.Atoi(m[1])
196                 if err != nil {
197                         t.Errorf("Bogus integer on line %q", l)
198                         continue
199                 }
200                 if i < 1 || i > staticTable.len() {
201                         t.Errorf("Bogus index %d on line %q", i, l)
202                         continue
203                 }
204                 if got, want := staticTable.ents[i-1].Name, m[2]; got != want {
205                         t.Errorf("header index %d name = %q; want %q", i, got, want)
206                 }
207                 if got, want := staticTable.ents[i-1].Value, m[3]; got != want {
208                         t.Errorf("header index %d value = %q; want %q", i, got, want)
209                 }
210         }
211         if err := bs.Err(); err != nil {
212                 t.Error(err)
213         }
214 }