chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

674
vendor/http/tests/header_map.rs vendored Normal file
View File

@@ -0,0 +1,674 @@
use http::header::*;
use http::*;
#[test]
fn smoke() {
let mut headers = HeaderMap::new();
assert!(headers.get("hello").is_none());
let name: HeaderName = "hello".parse().unwrap();
match headers.entry(&name) {
Entry::Vacant(e) => {
e.insert("world".parse().unwrap());
}
_ => panic!(),
}
assert!(headers.get("hello").is_some());
match headers.entry(&name) {
Entry::Occupied(mut e) => {
assert_eq!(e.get(), &"world");
// Push another value
e.append("zomg".parse().unwrap());
let mut i = e.iter();
assert_eq!(*i.next().unwrap(), "world");
assert_eq!(*i.next().unwrap(), "zomg");
assert!(i.next().is_none());
}
_ => panic!(),
}
}
#[test]
#[should_panic]
fn reserve_over_capacity() {
// See https://github.com/hyperium/http/issues/352
let mut headers = HeaderMap::<u32>::with_capacity(32);
headers.reserve(50_000); // over MAX_SIZE
}
#[test]
fn with_capacity_max() {
// The largest capacity such that (cap + cap / 3) < MAX_SIZE.
HeaderMap::<u32>::with_capacity(24_576);
}
#[test]
#[should_panic]
fn with_capacity_overflow() {
HeaderMap::<u32>::with_capacity(24_577);
}
#[test]
#[should_panic]
fn reserve_overflow() {
// See https://github.com/hyperium/http/issues/352
let mut headers = HeaderMap::<u32>::with_capacity(0);
headers.reserve(std::usize::MAX); // next_power_of_two overflows
}
#[test]
fn reserve() {
let mut headers = HeaderMap::<usize>::default();
assert_eq!(headers.capacity(), 0);
let requested_cap = 8;
headers.reserve(requested_cap);
let reserved_cap = headers.capacity();
assert!(
reserved_cap >= requested_cap,
"requested {} capacity, but it reserved only {} entries",
requested_cap,
reserved_cap,
);
for i in 0..requested_cap {
let name = format!("h{i}").parse::<HeaderName>().unwrap();
headers.insert(name, i);
}
assert_eq!(headers.capacity(), reserved_cap, "unexpected reallocation");
}
#[test]
fn drain() {
let mut headers = HeaderMap::new();
// Insert a single value
let name: HeaderName = "hello".parse().unwrap();
headers.insert(name, "world".parse().unwrap());
{
let mut iter = headers.drain();
let (name, value) = iter.next().unwrap();
assert_eq!(name.unwrap().as_str(), "hello");
assert_eq!(value, "world");
assert!(iter.next().is_none());
}
assert!(headers.is_empty());
// Insert two sequential values
headers.insert(
"hello".parse::<HeaderName>().unwrap(),
"world".parse().unwrap(),
);
headers.insert(
"zomg".parse::<HeaderName>().unwrap(),
"bar".parse().unwrap(),
);
headers.append(
"hello".parse::<HeaderName>().unwrap(),
"world2".parse().unwrap(),
);
// Drain...
{
let mut iter = headers.drain();
let (name, value) = iter.next().unwrap();
assert_eq!(name.unwrap().as_str(), "hello");
assert_eq!(value, "world");
let (name, value) = iter.next().unwrap();
assert_eq!(name, None);
assert_eq!(value, "world2");
let (name, value) = iter.next().unwrap();
assert_eq!(name.unwrap().as_str(), "zomg");
assert_eq!(value, "bar");
assert!(iter.next().is_none());
}
}
#[test]
fn drain_drop_immediately() {
// test mem::forgetting does not double-free
let mut headers = HeaderMap::new();
headers.insert("hello", "world".parse().unwrap());
headers.insert("zomg", "bar".parse().unwrap());
headers.append("hello", "world2".parse().unwrap());
let iter = headers.drain();
assert_eq!(iter.size_hint(), (2, Some(3)));
// not consuming `iter`
}
#[test]
fn drain_forget() {
// test mem::forgetting does not double-free
let mut headers = HeaderMap::<HeaderValue>::new();
headers.insert("hello", "world".parse().unwrap());
headers.insert("zomg", "bar".parse().unwrap());
assert_eq!(headers.len(), 2);
{
let mut iter = headers.drain();
assert_eq!(iter.size_hint(), (2, Some(2)));
let _ = iter.next().unwrap();
std::mem::forget(iter);
}
assert_eq!(headers.len(), 0);
}
#[test]
fn drain_entry() {
let mut headers = HeaderMap::new();
headers.insert(
"hello".parse::<HeaderName>().unwrap(),
"world".parse().unwrap(),
);
headers.insert(
"zomg".parse::<HeaderName>().unwrap(),
"foo".parse().unwrap(),
);
headers.append(
"hello".parse::<HeaderName>().unwrap(),
"world2".parse().unwrap(),
);
headers.insert(
"more".parse::<HeaderName>().unwrap(),
"words".parse().unwrap(),
);
headers.append(
"more".parse::<HeaderName>().unwrap(),
"insertions".parse().unwrap(),
);
assert_eq!(5, headers.len());
// Using insert_mult
{
let mut e = match headers.entry("hello") {
Entry::Occupied(e) => e,
_ => panic!(),
};
let vals: Vec<_> = e.insert_mult("wat".parse().unwrap()).collect();
assert_eq!(2, vals.len());
assert_eq!(vals[0], "world");
assert_eq!(vals[1], "world2");
}
assert_eq!(5 - 2 + 1, headers.len());
}
#[test]
fn eq() {
let mut a = HeaderMap::new();
let mut b = HeaderMap::new();
assert_eq!(a, b);
a.insert(
"hello".parse::<HeaderName>().unwrap(),
"world".parse().unwrap(),
);
assert_ne!(a, b);
b.insert(
"hello".parse::<HeaderName>().unwrap(),
"world".parse().unwrap(),
);
assert_eq!(a, b);
a.insert("foo".parse::<HeaderName>().unwrap(), "bar".parse().unwrap());
a.append("foo".parse::<HeaderName>().unwrap(), "baz".parse().unwrap());
assert_ne!(a, b);
b.insert("foo".parse::<HeaderName>().unwrap(), "bar".parse().unwrap());
assert_ne!(a, b);
b.append("foo".parse::<HeaderName>().unwrap(), "baz".parse().unwrap());
assert_eq!(a, b);
a.append("a".parse::<HeaderName>().unwrap(), "a".parse().unwrap());
a.append("a".parse::<HeaderName>().unwrap(), "b".parse().unwrap());
b.append("a".parse::<HeaderName>().unwrap(), "b".parse().unwrap());
b.append("a".parse::<HeaderName>().unwrap(), "a".parse().unwrap());
assert_ne!(a, b);
}
#[test]
fn into_header_name() {
let mut m = HeaderMap::new();
m.insert(HOST, "localhost".parse().unwrap());
m.insert(&ACCEPT, "*/*".parse().unwrap());
m.insert("connection", "keep-alive".parse().unwrap());
m.append(LOCATION, "/".parse().unwrap());
m.append(&VIA, "bob".parse().unwrap());
m.append("transfer-encoding", "chunked".parse().unwrap());
assert_eq!(m.len(), 6);
}
#[test]
fn as_header_name() {
let mut m = HeaderMap::new();
let v: HeaderValue = "localhost".parse().unwrap();
m.insert(HOST, v.clone());
let expected = Some(&v);
assert_eq!(m.get("host"), expected);
assert_eq!(m.get(&HOST), expected);
let s = String::from("host");
assert_eq!(m.get(&s), expected);
assert_eq!(m.get(s.as_str()), expected);
}
#[test]
fn insert_all_std_headers() {
let mut m = HeaderMap::new();
for (i, hdr) in STD.iter().enumerate() {
m.insert(hdr.clone(), hdr.as_str().parse().unwrap());
for j in 0..(i + 1) {
assert_eq!(m[&STD[j]], STD[j].as_str());
}
if i != 0 {
for j in (i + 1)..STD.len() {
assert!(
m.get(&STD[j]).is_none(),
"contained {}; j={}",
STD[j].as_str(),
j
);
}
}
}
}
#[test]
fn insert_79_custom_std_headers() {
let mut h = HeaderMap::new();
let hdrs = custom_std(79);
for (i, hdr) in hdrs.iter().enumerate() {
h.insert(hdr.clone(), hdr.as_str().parse().unwrap());
for j in 0..(i + 1) {
assert_eq!(h[&hdrs[j]], hdrs[j].as_str());
}
for j in (i + 1)..hdrs.len() {
assert!(h.get(&hdrs[j]).is_none());
}
}
}
#[test]
fn append_multiple_values() {
let mut map = HeaderMap::new();
map.append(header::CONTENT_TYPE, "json".parse().unwrap());
map.append(header::CONTENT_TYPE, "html".parse().unwrap());
map.append(header::CONTENT_TYPE, "xml".parse().unwrap());
let vals = map
.get_all(&header::CONTENT_TYPE)
.iter()
.collect::<Vec<_>>();
assert_eq!(&vals, &[&"json", &"html", &"xml"]);
}
fn custom_std(n: usize) -> Vec<HeaderName> {
(0..n)
.map(|i| {
let s = format!("{}-{}", STD[i % STD.len()].as_str(), i);
s.parse().unwrap()
})
.collect()
}
const STD: &'static [HeaderName] = &[
ACCEPT,
ACCEPT_CHARSET,
ACCEPT_ENCODING,
ACCEPT_LANGUAGE,
ACCEPT_RANGES,
ACCESS_CONTROL_ALLOW_CREDENTIALS,
ACCESS_CONTROL_ALLOW_HEADERS,
ACCESS_CONTROL_ALLOW_METHODS,
ACCESS_CONTROL_ALLOW_ORIGIN,
ACCESS_CONTROL_EXPOSE_HEADERS,
ACCESS_CONTROL_MAX_AGE,
ACCESS_CONTROL_REQUEST_HEADERS,
ACCESS_CONTROL_REQUEST_METHOD,
AGE,
ALLOW,
ALT_SVC,
AUTHORIZATION,
CACHE_CONTROL,
CACHE_STATUS,
CDN_CACHE_CONTROL,
CONNECTION,
CONTENT_DISPOSITION,
CONTENT_ENCODING,
CONTENT_LANGUAGE,
CONTENT_LENGTH,
CONTENT_LOCATION,
CONTENT_RANGE,
CONTENT_SECURITY_POLICY,
CONTENT_SECURITY_POLICY_REPORT_ONLY,
CONTENT_TYPE,
COOKIE,
DNT,
DATE,
ETAG,
EXPECT,
EXPIRES,
FORWARDED,
FROM,
HOST,
IF_MATCH,
IF_MODIFIED_SINCE,
IF_NONE_MATCH,
IF_RANGE,
IF_UNMODIFIED_SINCE,
LAST_MODIFIED,
LINK,
LOCATION,
MAX_FORWARDS,
ORIGIN,
PRAGMA,
PROXY_AUTHENTICATE,
PROXY_AUTHORIZATION,
PUBLIC_KEY_PINS,
PUBLIC_KEY_PINS_REPORT_ONLY,
RANGE,
REFERER,
REFERRER_POLICY,
RETRY_AFTER,
SERVER,
SET_COOKIE,
STRICT_TRANSPORT_SECURITY,
TE,
TRAILER,
TRANSFER_ENCODING,
USER_AGENT,
UPGRADE,
UPGRADE_INSECURE_REQUESTS,
VARY,
VIA,
WARNING,
WWW_AUTHENTICATE,
X_CONTENT_TYPE_OPTIONS,
X_DNS_PREFETCH_CONTROL,
X_FRAME_OPTIONS,
X_XSS_PROTECTION,
];
#[test]
fn get_invalid() {
let mut headers = HeaderMap::new();
headers.insert("foo", "bar".parse().unwrap());
assert!(headers.get("Evil\r\nKey").is_none());
}
#[test]
#[should_panic]
fn insert_invalid() {
let mut headers = HeaderMap::new();
headers.insert("evil\r\nfoo", "bar".parse().unwrap());
}
#[test]
fn value_htab() {
// RFC 7230 Section 3.2:
// > field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
HeaderValue::from_static("hello\tworld");
HeaderValue::from_str("hello\tworld").unwrap();
}
#[test]
fn remove_multiple_a() {
let mut headers = HeaderMap::new();
headers.insert(VIA, "1.1 example.com".parse().unwrap());
headers.insert(SET_COOKIE, "cookie_1=value 1".parse().unwrap());
headers.append(SET_COOKIE, "cookie_2=value 2".parse().unwrap());
headers.append(VIA, "1.1 other.com".parse().unwrap());
headers.append(SET_COOKIE, "cookie_3=value 3".parse().unwrap());
headers.insert(VARY, "*".parse().unwrap());
assert_eq!(headers.len(), 6);
let cookie = headers.remove(SET_COOKIE);
assert_eq!(cookie, Some("cookie_1=value 1".parse().unwrap()));
assert_eq!(headers.len(), 3);
let via = headers.remove(VIA);
assert_eq!(via, Some("1.1 example.com".parse().unwrap()));
assert_eq!(headers.len(), 1);
let vary = headers.remove(VARY);
assert_eq!(vary, Some("*".parse().unwrap()));
assert_eq!(headers.len(), 0);
}
#[test]
fn remove_multiple_b() {
let mut headers = HeaderMap::new();
headers.insert(VIA, "1.1 example.com".parse().unwrap());
headers.insert(SET_COOKIE, "cookie_1=value 1".parse().unwrap());
headers.append(SET_COOKIE, "cookie_2=value 2".parse().unwrap());
headers.append(VIA, "1.1 other.com".parse().unwrap());
headers.append(SET_COOKIE, "cookie_3=value 3".parse().unwrap());
headers.insert(VARY, "*".parse().unwrap());
assert_eq!(headers.len(), 6);
let vary = headers.remove(VARY);
assert_eq!(vary, Some("*".parse().unwrap()));
assert_eq!(headers.len(), 5);
let via = headers.remove(VIA);
assert_eq!(via, Some("1.1 example.com".parse().unwrap()));
assert_eq!(headers.len(), 3);
let cookie = headers.remove(SET_COOKIE);
assert_eq!(cookie, Some("cookie_1=value 1".parse().unwrap()));
assert_eq!(headers.len(), 0);
}
#[test]
fn remove_entry_multi_0() {
let mut headers = HeaderMap::new();
let cookies = remove_all_values(&mut headers, SET_COOKIE);
assert_eq!(cookies.len(), 0);
assert_eq!(headers.len(), 0);
}
#[test]
fn remove_entry_multi_0_others() {
let mut headers = HeaderMap::new();
headers.insert(VIA, "1.1 example.com".parse().unwrap());
headers.append(VIA, "1.1 other.com".parse().unwrap());
let cookies = remove_all_values(&mut headers, SET_COOKIE);
assert_eq!(cookies.len(), 0);
assert_eq!(headers.len(), 2);
}
#[test]
fn remove_entry_multi_1() {
let mut headers = HeaderMap::new();
headers.insert(SET_COOKIE, "cookie_1=value 1".parse().unwrap());
let cookies = remove_all_values(&mut headers, SET_COOKIE);
assert_eq!(cookies.len(), 1);
assert_eq!(headers.len(), 0);
}
#[test]
fn remove_entry_multi_1_other() {
let mut headers = HeaderMap::new();
headers.insert(SET_COOKIE, "cookie_1=value 1".parse().unwrap());
headers.insert(VIA, "1.1 example.com".parse().unwrap());
let cookies = remove_all_values(&mut headers, SET_COOKIE);
assert_eq!(cookies.len(), 1);
assert_eq!(headers.len(), 1);
let vias = remove_all_values(&mut headers, VIA);
assert_eq!(vias.len(), 1);
assert_eq!(headers.len(), 0);
}
// For issue hyperimum/http#446
#[test]
fn remove_entry_multi_2() {
let mut headers = HeaderMap::new();
headers.insert(SET_COOKIE, "cookie_1=value 1".parse().unwrap());
headers.append(SET_COOKIE, "cookie_2=value 2".parse().unwrap());
let cookies = remove_all_values(&mut headers, SET_COOKIE);
assert_eq!(cookies.len(), 2);
assert_eq!(headers.len(), 0);
}
#[test]
fn remove_entry_multi_3() {
let mut headers = HeaderMap::new();
headers.insert(SET_COOKIE, "cookie_1=value 1".parse().unwrap());
headers.append(SET_COOKIE, "cookie_2=value 2".parse().unwrap());
headers.append(SET_COOKIE, "cookie_3=value 3".parse().unwrap());
let cookies = remove_all_values(&mut headers, SET_COOKIE);
assert_eq!(cookies.len(), 3);
assert_eq!(headers.len(), 0);
}
#[test]
fn remove_entry_multi_3_others() {
let mut headers = HeaderMap::new();
headers.insert(VIA, "1.1 example.com".parse().unwrap());
headers.insert(SET_COOKIE, "cookie_1=value 1".parse().unwrap());
headers.append(SET_COOKIE, "cookie_2=value 2".parse().unwrap());
headers.append(VIA, "1.1 other.com".parse().unwrap());
headers.append(SET_COOKIE, "cookie_3=value 3".parse().unwrap());
headers.insert(VARY, "*".parse().unwrap());
let cookies = remove_all_values(&mut headers, SET_COOKIE);
assert_eq!(cookies.len(), 3);
assert_eq!(headers.len(), 3);
let vias = remove_all_values(&mut headers, VIA);
assert_eq!(vias.len(), 2);
assert_eq!(headers.len(), 1);
let varies = remove_all_values(&mut headers, VARY);
assert_eq!(varies.len(), 1);
assert_eq!(headers.len(), 0);
}
fn remove_all_values<K>(headers: &mut HeaderMap, key: K) -> Vec<HeaderValue>
where
K: IntoHeaderName,
{
match headers.entry(key) {
Entry::Occupied(e) => e.remove_entry_mult().1.collect(),
Entry::Vacant(_) => vec![],
}
}
#[test]
fn remove_entry_3_others_a() {
let mut headers = HeaderMap::new();
headers.insert(VIA, "1.1 example.com".parse().unwrap());
headers.insert(SET_COOKIE, "cookie_1=value 1".parse().unwrap());
headers.append(SET_COOKIE, "cookie_2=value 2".parse().unwrap());
headers.append(VIA, "1.1 other.com".parse().unwrap());
headers.append(SET_COOKIE, "cookie_3=value 3".parse().unwrap());
headers.insert(VARY, "*".parse().unwrap());
assert_eq!(headers.len(), 6);
let cookie = remove_values(&mut headers, SET_COOKIE);
assert_eq!(cookie, Some("cookie_1=value 1".parse().unwrap()));
assert_eq!(headers.len(), 3);
let via = remove_values(&mut headers, VIA);
assert_eq!(via, Some("1.1 example.com".parse().unwrap()));
assert_eq!(headers.len(), 1);
let vary = remove_values(&mut headers, VARY);
assert_eq!(vary, Some("*".parse().unwrap()));
assert_eq!(headers.len(), 0);
}
#[test]
fn remove_entry_3_others_b() {
let mut headers = HeaderMap::new();
headers.insert(VIA, "1.1 example.com".parse().unwrap());
headers.insert(SET_COOKIE, "cookie_1=value 1".parse().unwrap());
headers.append(SET_COOKIE, "cookie_2=value 2".parse().unwrap());
headers.append(VIA, "1.1 other.com".parse().unwrap());
headers.append(SET_COOKIE, "cookie_3=value 3".parse().unwrap());
headers.insert(VARY, "*".parse().unwrap());
assert_eq!(headers.len(), 6);
let vary = remove_values(&mut headers, VARY);
assert_eq!(vary, Some("*".parse().unwrap()));
assert_eq!(headers.len(), 5);
let via = remove_values(&mut headers, VIA);
assert_eq!(via, Some("1.1 example.com".parse().unwrap()));
assert_eq!(headers.len(), 3);
let cookie = remove_values(&mut headers, SET_COOKIE);
assert_eq!(cookie, Some("cookie_1=value 1".parse().unwrap()));
assert_eq!(headers.len(), 0);
}
fn remove_values<K>(headers: &mut HeaderMap, key: K) -> Option<HeaderValue>
where
K: IntoHeaderName,
{
match headers.entry(key) {
Entry::Occupied(e) => Some(e.remove_entry().1),
Entry::Vacant(_) => None,
}
}
#[test]
fn ensure_miri_sharedreadonly_not_violated() {
let mut headers = HeaderMap::new();
headers.insert(
HeaderName::from_static("chunky-trailer"),
HeaderValue::from_static("header data"),
);
let _foo = &headers.iter().next();
}

365
vendor/http/tests/header_map_fuzz.rs vendored Normal file
View File

@@ -0,0 +1,365 @@
use http::header::*;
use http::*;
use quickcheck::{Arbitrary, Gen, QuickCheck, TestResult};
use rand::rngs::StdRng;
use rand::seq::SliceRandom;
use rand::{Rng, SeedableRng};
use std::collections::HashMap;
#[cfg(not(miri))]
#[test]
fn header_map_fuzz() {
fn prop(fuzz: Fuzz) -> TestResult {
fuzz.run();
TestResult::from_bool(true)
}
QuickCheck::new().quickcheck(prop as fn(Fuzz) -> TestResult)
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
struct Fuzz {
// The magic seed that makes the test case reproducible
seed: [u8; 32],
// Actions to perform
steps: Vec<Step>,
// Number of steps to drop
reduce: usize,
}
#[derive(Debug)]
struct Weight {
insert: usize,
remove: usize,
append: usize,
}
#[derive(Debug, Clone)]
struct Step {
action: Action,
expect: AltMap,
}
#[derive(Debug, Clone)]
enum Action {
Insert {
name: HeaderName, // Name to insert
val: HeaderValue, // Value to insert
old: Option<HeaderValue>, // Old value
},
Append {
name: HeaderName,
val: HeaderValue,
ret: bool,
},
Remove {
name: HeaderName, // Name to remove
val: Option<HeaderValue>, // Value to get
},
}
// An alternate implementation of HeaderMap backed by HashMap
#[derive(Debug, Clone, Default)]
struct AltMap {
map: HashMap<HeaderName, Vec<HeaderValue>>,
}
impl Fuzz {
fn new(seed: [u8; 32]) -> Fuzz {
// Seed the RNG
let mut rng = StdRng::from_seed(seed);
let mut steps = vec![];
let mut expect = AltMap::default();
let num = rng.gen_range(5..500);
let weight = Weight {
insert: rng.gen_range(1..10),
remove: rng.gen_range(1..10),
append: rng.gen_range(1..10),
};
while steps.len() < num {
steps.push(expect.gen_step(&weight, &mut rng));
}
Fuzz {
seed,
steps,
reduce: 0,
}
}
fn run(self) {
// Create a new header map
let mut map = HeaderMap::new();
// Number of steps to perform
let take = self.steps.len() - self.reduce;
for step in self.steps.into_iter().take(take) {
step.action.apply(&mut map);
step.expect.assert_identical(&map);
}
}
}
impl Arbitrary for Fuzz {
fn arbitrary(_: &mut Gen) -> Self {
Self::new(rand::thread_rng().gen())
}
}
impl AltMap {
fn gen_step(&mut self, weight: &Weight, rng: &mut StdRng) -> Step {
let action = self.gen_action(weight, rng);
Step {
action,
expect: self.clone(),
}
}
/// This will also apply the action against `self`
fn gen_action(&mut self, weight: &Weight, rng: &mut StdRng) -> Action {
let sum = weight.insert + weight.remove + weight.append;
let mut num = rng.gen_range(0..sum);
if num < weight.insert {
return self.gen_insert(rng);
}
num -= weight.insert;
if num < weight.remove {
return self.gen_remove(rng);
}
num -= weight.remove;
if num < weight.append {
return self.gen_append(rng);
}
unreachable!();
}
fn gen_insert(&mut self, rng: &mut StdRng) -> Action {
let name = self.gen_name(4, rng);
let val = gen_header_value(rng);
let old = self.insert(name.clone(), val.clone());
Action::Insert { name, val, old }
}
fn gen_remove(&mut self, rng: &mut StdRng) -> Action {
let name = self.gen_name(-4, rng);
let val = self.remove(&name);
Action::Remove { name, val }
}
fn gen_append(&mut self, rng: &mut StdRng) -> Action {
let name = self.gen_name(-5, rng);
let val = gen_header_value(rng);
let vals = self.map.entry(name.clone()).or_insert(vec![]);
let ret = !vals.is_empty();
vals.push(val.clone());
Action::Append { name, val, ret }
}
/// Negative numbers weigh finding an existing header higher
fn gen_name(&self, weight: i32, rng: &mut StdRng) -> HeaderName {
let mut existing = rng.gen_ratio(1, weight.abs() as u32);
if weight < 0 {
existing = !existing;
}
if existing {
// Existing header
if let Some(name) = self.find_random_name(rng) {
name
} else {
gen_header_name(rng)
}
} else {
gen_header_name(rng)
}
}
fn find_random_name(&self, rng: &mut StdRng) -> Option<HeaderName> {
if self.map.is_empty() {
None
} else {
let n = rng.gen_range(0..self.map.len());
self.map.keys().nth(n).map(Clone::clone)
}
}
fn insert(&mut self, name: HeaderName, val: HeaderValue) -> Option<HeaderValue> {
let old = self.map.insert(name, vec![val]);
old.and_then(|v| v.into_iter().next())
}
fn remove(&mut self, name: &HeaderName) -> Option<HeaderValue> {
self.map.remove(name).and_then(|v| v.into_iter().next())
}
fn assert_identical(&self, other: &HeaderMap<HeaderValue>) {
assert_eq!(self.map.len(), other.keys_len());
for (key, val) in &self.map {
// Test get
assert_eq!(other.get(key), val.get(0));
// Test get_all
let vals = other.get_all(key);
let actual: Vec<_> = vals.iter().collect();
assert_eq!(&actual[..], &val[..]);
}
}
}
impl Action {
fn apply(self, map: &mut HeaderMap<HeaderValue>) {
match self {
Action::Insert { name, val, old } => {
let actual = map.insert(name, val);
assert_eq!(actual, old);
}
Action::Remove { name, val } => {
// Just to help track the state, load all associated values.
let _ = map.get_all(&name).iter().collect::<Vec<_>>();
let actual = map.remove(&name);
assert_eq!(actual, val);
}
Action::Append { name, val, ret } => {
assert_eq!(ret, map.append(name, val));
}
}
}
}
fn gen_header_name(g: &mut StdRng) -> HeaderName {
const STANDARD_HEADERS: &'static [HeaderName] = &[
header::ACCEPT,
header::ACCEPT_CHARSET,
header::ACCEPT_ENCODING,
header::ACCEPT_LANGUAGE,
header::ACCEPT_RANGES,
header::ACCESS_CONTROL_ALLOW_CREDENTIALS,
header::ACCESS_CONTROL_ALLOW_HEADERS,
header::ACCESS_CONTROL_ALLOW_METHODS,
header::ACCESS_CONTROL_ALLOW_ORIGIN,
header::ACCESS_CONTROL_EXPOSE_HEADERS,
header::ACCESS_CONTROL_MAX_AGE,
header::ACCESS_CONTROL_REQUEST_HEADERS,
header::ACCESS_CONTROL_REQUEST_METHOD,
header::AGE,
header::ALLOW,
header::ALT_SVC,
header::AUTHORIZATION,
header::CACHE_CONTROL,
header::CACHE_STATUS,
header::CDN_CACHE_CONTROL,
header::CONNECTION,
header::CONTENT_DISPOSITION,
header::CONTENT_ENCODING,
header::CONTENT_LANGUAGE,
header::CONTENT_LENGTH,
header::CONTENT_LOCATION,
header::CONTENT_RANGE,
header::CONTENT_SECURITY_POLICY,
header::CONTENT_SECURITY_POLICY_REPORT_ONLY,
header::CONTENT_TYPE,
header::COOKIE,
header::DNT,
header::DATE,
header::ETAG,
header::EXPECT,
header::EXPIRES,
header::FORWARDED,
header::FROM,
header::HOST,
header::IF_MATCH,
header::IF_MODIFIED_SINCE,
header::IF_NONE_MATCH,
header::IF_RANGE,
header::IF_UNMODIFIED_SINCE,
header::LAST_MODIFIED,
header::LINK,
header::LOCATION,
header::MAX_FORWARDS,
header::ORIGIN,
header::PRAGMA,
header::PROXY_AUTHENTICATE,
header::PROXY_AUTHORIZATION,
header::PUBLIC_KEY_PINS,
header::PUBLIC_KEY_PINS_REPORT_ONLY,
header::RANGE,
header::REFERER,
header::REFERRER_POLICY,
header::REFRESH,
header::RETRY_AFTER,
header::SEC_WEBSOCKET_ACCEPT,
header::SEC_WEBSOCKET_EXTENSIONS,
header::SEC_WEBSOCKET_KEY,
header::SEC_WEBSOCKET_PROTOCOL,
header::SEC_WEBSOCKET_VERSION,
header::SERVER,
header::SET_COOKIE,
header::STRICT_TRANSPORT_SECURITY,
header::TE,
header::TRAILER,
header::TRANSFER_ENCODING,
header::UPGRADE,
header::UPGRADE_INSECURE_REQUESTS,
header::USER_AGENT,
header::VARY,
header::VIA,
header::WARNING,
header::WWW_AUTHENTICATE,
header::X_CONTENT_TYPE_OPTIONS,
header::X_DNS_PREFETCH_CONTROL,
header::X_FRAME_OPTIONS,
header::X_XSS_PROTECTION,
];
if g.gen_ratio(1, 2) {
STANDARD_HEADERS.choose(g).unwrap().clone()
} else {
let value = gen_string(g, 1, 25);
HeaderName::from_bytes(value.as_bytes()).unwrap()
}
}
fn gen_header_value(g: &mut StdRng) -> HeaderValue {
let value = gen_string(g, 0, 70);
HeaderValue::from_bytes(value.as_bytes()).unwrap()
}
fn gen_string(g: &mut StdRng, min: usize, max: usize) -> String {
let bytes: Vec<_> = (min..max)
.map(|_| {
// Chars to pick from
b"ABCDEFGHIJKLMNOPQRSTUVabcdefghilpqrstuvwxyz----"
.choose(g)
.unwrap()
.clone()
})
.collect();
String::from_utf8(bytes).unwrap()
}

82
vendor/http/tests/status_code.rs vendored Normal file
View File

@@ -0,0 +1,82 @@
use http::*;
#[test]
fn from_bytes() {
for ok in &[
"100", "101", "199", "200", "250", "299", "321", "399", "499", "599", "600", "999",
] {
assert!(StatusCode::from_bytes(ok.as_bytes()).is_ok());
}
for not_ok in &[
"0", "00", "10", "40", "99", "000", "010", "099", "1000", "1999",
] {
assert!(StatusCode::from_bytes(not_ok.as_bytes()).is_err());
}
}
#[test]
fn equates_with_u16() {
let status = StatusCode::from_u16(200u16).unwrap();
assert_eq!(200u16, status);
assert_eq!(status, 200u16);
}
#[test]
fn roundtrip() {
for s in 100..1000 {
let sstr = s.to_string();
let status = StatusCode::from_bytes(sstr.as_bytes()).unwrap();
assert_eq!(s, u16::from(status));
assert_eq!(sstr, status.as_str());
}
}
#[test]
fn is_informational() {
assert!(status_code(100).is_informational());
assert!(status_code(199).is_informational());
assert!(!status_code(200).is_informational());
}
#[test]
fn is_success() {
assert!(status_code(200).is_success());
assert!(status_code(299).is_success());
assert!(!status_code(199).is_success());
assert!(!status_code(300).is_success());
}
#[test]
fn is_redirection() {
assert!(status_code(300).is_redirection());
assert!(status_code(399).is_redirection());
assert!(!status_code(299).is_redirection());
assert!(!status_code(400).is_redirection());
}
#[test]
fn is_client_error() {
assert!(status_code(400).is_client_error());
assert!(status_code(499).is_client_error());
assert!(!status_code(399).is_client_error());
assert!(!status_code(500).is_client_error());
}
#[test]
fn is_server_error() {
assert!(status_code(500).is_server_error());
assert!(status_code(599).is_server_error());
assert!(!status_code(499).is_server_error());
assert!(!status_code(600).is_server_error());
}
/// Helper method for readability
fn status_code(status_code: u16) -> StatusCode {
StatusCode::from_u16(status_code).unwrap()
}