1 use http::header::*;
2 use http::*;
3
4 #[test]
smoke()5 fn smoke() {
6 let mut headers = HeaderMap::new();
7
8 assert!(headers.get("hello").is_none());
9
10 let name: HeaderName = "hello".parse().unwrap();
11
12 match headers.entry(&name) {
13 Entry::Vacant(e) => {
14 e.insert("world".parse().unwrap());
15 }
16 _ => panic!(),
17 }
18
19 assert!(headers.get("hello").is_some());
20
21 match headers.entry(&name) {
22 Entry::Occupied(mut e) => {
23 assert_eq!(e.get(), &"world");
24
25 // Push another value
26 e.append("zomg".parse().unwrap());
27
28 let mut i = e.iter();
29
30 assert_eq!(*i.next().unwrap(), "world");
31 assert_eq!(*i.next().unwrap(), "zomg");
32 assert!(i.next().is_none());
33 }
34 _ => panic!(),
35 }
36 }
37
38 #[test]
39 #[should_panic]
reserve_over_capacity()40 fn reserve_over_capacity() {
41 // See https://github.com/hyperium/http/issues/352
42 let mut headers = HeaderMap::<u32>::with_capacity(32);
43 headers.reserve(50_000); // over MAX_SIZE
44 }
45
46 #[test]
with_capacity_max()47 fn with_capacity_max() {
48 // The largest capacity such that (cap + cap / 3) < MAX_SIZE.
49 HeaderMap::<u32>::with_capacity(24_576);
50 }
51
52 #[test]
53 #[should_panic]
with_capacity_overflow()54 fn with_capacity_overflow() {
55 HeaderMap::<u32>::with_capacity(24_577);
56 }
57
58 #[test]
59 #[should_panic]
reserve_overflow()60 fn reserve_overflow() {
61 // See https://github.com/hyperium/http/issues/352
62 let mut headers = HeaderMap::<u32>::with_capacity(0);
63 headers.reserve(std::usize::MAX); // next_power_of_two overflows
64 }
65
66 #[test]
drain()67 fn drain() {
68 let mut headers = HeaderMap::new();
69
70 // Insert a single value
71 let name: HeaderName = "hello".parse().unwrap();
72 headers.insert(name, "world".parse().unwrap());
73
74 {
75 let mut iter = headers.drain();
76 let (name, value) = iter.next().unwrap();
77 assert_eq!(name.unwrap().as_str(), "hello");
78
79 assert_eq!(value, "world");
80
81 assert!(iter.next().is_none());
82 }
83
84 assert!(headers.is_empty());
85
86 // Insert two sequential values
87 headers.insert(
88 "hello".parse::<HeaderName>().unwrap(),
89 "world".parse().unwrap(),
90 );
91 headers.insert(
92 "zomg".parse::<HeaderName>().unwrap(),
93 "bar".parse().unwrap(),
94 );
95 headers.append(
96 "hello".parse::<HeaderName>().unwrap(),
97 "world2".parse().unwrap(),
98 );
99
100 // Drain...
101 {
102 let mut iter = headers.drain();
103
104 let (name, value) = iter.next().unwrap();
105 assert_eq!(name.unwrap().as_str(), "hello");
106 assert_eq!(value, "world");
107
108 let (name, value) = iter.next().unwrap();
109 assert_eq!(name, None);
110 assert_eq!(value, "world2");
111
112 let (name, value) = iter.next().unwrap();
113 assert_eq!(name.unwrap().as_str(), "zomg");
114 assert_eq!(value, "bar");
115
116 assert!(iter.next().is_none());
117 }
118 }
119
120 #[test]
drain_drop_immediately()121 fn drain_drop_immediately() {
122 // test mem::forgetting does not double-free
123
124 let mut headers = HeaderMap::new();
125 headers.insert("hello", "world".parse().unwrap());
126 headers.insert("zomg", "bar".parse().unwrap());
127 headers.append("hello", "world2".parse().unwrap());
128
129 let iter = headers.drain();
130 assert_eq!(iter.size_hint(), (2, Some(3)));
131 // not consuming `iter`
132 }
133
134 #[test]
drain_forget()135 fn drain_forget() {
136 // test mem::forgetting does not double-free
137
138 let mut headers = HeaderMap::<HeaderValue>::new();
139 headers.insert("hello", "world".parse().unwrap());
140 headers.insert("zomg", "bar".parse().unwrap());
141
142 assert_eq!(headers.len(), 2);
143
144 {
145 let mut iter = headers.drain();
146 assert_eq!(iter.size_hint(), (2, Some(2)));
147 let _ = iter.next().unwrap();
148 std::mem::forget(iter);
149 }
150
151 assert_eq!(headers.len(), 0);
152 }
153
154 #[test]
drain_entry()155 fn drain_entry() {
156 let mut headers = HeaderMap::new();
157
158 headers.insert(
159 "hello".parse::<HeaderName>().unwrap(),
160 "world".parse().unwrap(),
161 );
162 headers.insert(
163 "zomg".parse::<HeaderName>().unwrap(),
164 "foo".parse().unwrap(),
165 );
166 headers.append(
167 "hello".parse::<HeaderName>().unwrap(),
168 "world2".parse().unwrap(),
169 );
170 headers.insert(
171 "more".parse::<HeaderName>().unwrap(),
172 "words".parse().unwrap(),
173 );
174 headers.append(
175 "more".parse::<HeaderName>().unwrap(),
176 "insertions".parse().unwrap(),
177 );
178
179 // Using insert
180 {
181 let mut e = match headers.entry("hello") {
182 Entry::Occupied(e) => e,
183 _ => panic!(),
184 };
185
186 let vals: Vec<_> = e.insert_mult("wat".parse().unwrap()).collect();
187 assert_eq!(2, vals.len());
188 assert_eq!(vals[0], "world");
189 assert_eq!(vals[1], "world2");
190 }
191 }
192
193 #[test]
eq()194 fn eq() {
195 let mut a = HeaderMap::new();
196 let mut b = HeaderMap::new();
197
198 assert_eq!(a, b);
199
200 a.insert(
201 "hello".parse::<HeaderName>().unwrap(),
202 "world".parse().unwrap(),
203 );
204 assert_ne!(a, b);
205
206 b.insert(
207 "hello".parse::<HeaderName>().unwrap(),
208 "world".parse().unwrap(),
209 );
210 assert_eq!(a, b);
211
212 a.insert("foo".parse::<HeaderName>().unwrap(), "bar".parse().unwrap());
213 a.append("foo".parse::<HeaderName>().unwrap(), "baz".parse().unwrap());
214 assert_ne!(a, b);
215
216 b.insert("foo".parse::<HeaderName>().unwrap(), "bar".parse().unwrap());
217 assert_ne!(a, b);
218
219 b.append("foo".parse::<HeaderName>().unwrap(), "baz".parse().unwrap());
220 assert_eq!(a, b);
221
222 a.append("a".parse::<HeaderName>().unwrap(), "a".parse().unwrap());
223 a.append("a".parse::<HeaderName>().unwrap(), "b".parse().unwrap());
224 b.append("a".parse::<HeaderName>().unwrap(), "b".parse().unwrap());
225 b.append("a".parse::<HeaderName>().unwrap(), "a".parse().unwrap());
226
227 assert_ne!(a, b);
228 }
229
230 #[test]
into_header_name()231 fn into_header_name() {
232 let mut m = HeaderMap::new();
233 m.insert(HOST, "localhost".parse().unwrap());
234 m.insert(&ACCEPT, "*/*".parse().unwrap());
235 m.insert("connection", "keep-alive".parse().unwrap());
236
237 m.append(LOCATION, "/".parse().unwrap());
238 m.append(&VIA, "bob".parse().unwrap());
239 m.append("transfer-encoding", "chunked".parse().unwrap());
240
241 assert_eq!(m.len(), 6);
242 }
243
244 #[test]
as_header_name()245 fn as_header_name() {
246 let mut m = HeaderMap::new();
247 let v: HeaderValue = "localhost".parse().unwrap();
248 m.insert(HOST, v.clone());
249
250 let expected = Some(&v);
251
252 assert_eq!(m.get("host"), expected);
253 assert_eq!(m.get(&HOST), expected);
254
255 let s = String::from("host");
256 assert_eq!(m.get(&s), expected);
257 assert_eq!(m.get(s.as_str()), expected);
258 }
259
260 #[test]
insert_all_std_headers()261 fn insert_all_std_headers() {
262 let mut m = HeaderMap::new();
263
264 for (i, hdr) in STD.iter().enumerate() {
265 m.insert(hdr.clone(), hdr.as_str().parse().unwrap());
266
267 for j in 0..(i + 1) {
268 assert_eq!(m[&STD[j]], STD[j].as_str());
269 }
270
271 if i != 0 {
272 for j in (i + 1)..STD.len() {
273 assert!(
274 m.get(&STD[j]).is_none(),
275 "contained {}; j={}",
276 STD[j].as_str(),
277 j
278 );
279 }
280 }
281 }
282 }
283
284 #[test]
insert_79_custom_std_headers()285 fn insert_79_custom_std_headers() {
286 let mut h = HeaderMap::new();
287 let hdrs = custom_std(79);
288
289 for (i, hdr) in hdrs.iter().enumerate() {
290 h.insert(hdr.clone(), hdr.as_str().parse().unwrap());
291
292 for j in 0..(i + 1) {
293 assert_eq!(h[&hdrs[j]], hdrs[j].as_str());
294 }
295
296 for j in (i + 1)..hdrs.len() {
297 assert!(h.get(&hdrs[j]).is_none());
298 }
299 }
300 }
301
302 #[test]
append_multiple_values()303 fn append_multiple_values() {
304 let mut map = HeaderMap::new();
305
306 map.append(header::CONTENT_TYPE, "json".parse().unwrap());
307 map.append(header::CONTENT_TYPE, "html".parse().unwrap());
308 map.append(header::CONTENT_TYPE, "xml".parse().unwrap());
309
310 let vals = map
311 .get_all(&header::CONTENT_TYPE)
312 .iter()
313 .collect::<Vec<_>>();
314
315 assert_eq!(&vals, &[&"json", &"html", &"xml"]);
316 }
317
custom_std(n: usize) -> Vec<HeaderName>318 fn custom_std(n: usize) -> Vec<HeaderName> {
319 (0..n)
320 .map(|i| {
321 let s = format!("{}-{}", STD[i % STD.len()].as_str(), i);
322 s.parse().unwrap()
323 })
324 .collect()
325 }
326
327 const STD: &'static [HeaderName] = &[
328 ACCEPT,
329 ACCEPT_CHARSET,
330 ACCEPT_ENCODING,
331 ACCEPT_LANGUAGE,
332 ACCEPT_RANGES,
333 ACCESS_CONTROL_ALLOW_CREDENTIALS,
334 ACCESS_CONTROL_ALLOW_HEADERS,
335 ACCESS_CONTROL_ALLOW_METHODS,
336 ACCESS_CONTROL_ALLOW_ORIGIN,
337 ACCESS_CONTROL_EXPOSE_HEADERS,
338 ACCESS_CONTROL_MAX_AGE,
339 ACCESS_CONTROL_REQUEST_HEADERS,
340 ACCESS_CONTROL_REQUEST_METHOD,
341 AGE,
342 ALLOW,
343 ALT_SVC,
344 AUTHORIZATION,
345 CACHE_CONTROL,
346 CONNECTION,
347 CONTENT_DISPOSITION,
348 CONTENT_ENCODING,
349 CONTENT_LANGUAGE,
350 CONTENT_LENGTH,
351 CONTENT_LOCATION,
352 CONTENT_RANGE,
353 CONTENT_SECURITY_POLICY,
354 CONTENT_SECURITY_POLICY_REPORT_ONLY,
355 CONTENT_TYPE,
356 COOKIE,
357 DNT,
358 DATE,
359 ETAG,
360 EXPECT,
361 EXPIRES,
362 FORWARDED,
363 FROM,
364 HOST,
365 IF_MATCH,
366 IF_MODIFIED_SINCE,
367 IF_NONE_MATCH,
368 IF_RANGE,
369 IF_UNMODIFIED_SINCE,
370 LAST_MODIFIED,
371 LINK,
372 LOCATION,
373 MAX_FORWARDS,
374 ORIGIN,
375 PRAGMA,
376 PROXY_AUTHENTICATE,
377 PROXY_AUTHORIZATION,
378 PUBLIC_KEY_PINS,
379 PUBLIC_KEY_PINS_REPORT_ONLY,
380 RANGE,
381 REFERER,
382 REFERRER_POLICY,
383 RETRY_AFTER,
384 SERVER,
385 SET_COOKIE,
386 STRICT_TRANSPORT_SECURITY,
387 TE,
388 TRAILER,
389 TRANSFER_ENCODING,
390 USER_AGENT,
391 UPGRADE,
392 UPGRADE_INSECURE_REQUESTS,
393 VARY,
394 VIA,
395 WARNING,
396 WWW_AUTHENTICATE,
397 X_CONTENT_TYPE_OPTIONS,
398 X_DNS_PREFETCH_CONTROL,
399 X_FRAME_OPTIONS,
400 X_XSS_PROTECTION,
401 ];
402
403 #[test]
get_invalid()404 fn get_invalid() {
405 let mut headers = HeaderMap::new();
406 headers.insert("foo", "bar".parse().unwrap());
407 assert!(headers.get("Evil\r\nKey").is_none());
408 }
409
410 #[test]
411 #[should_panic]
insert_invalid()412 fn insert_invalid() {
413 let mut headers = HeaderMap::new();
414 headers.insert("evil\r\nfoo", "bar".parse().unwrap());
415 }
416
417 #[test]
value_htab()418 fn value_htab() {
419 // RFC 7230 Section 3.2:
420 // > field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
421 HeaderValue::from_static("hello\tworld");
422 HeaderValue::from_str("hello\tworld").unwrap();
423 }
424