proptest_http_message/request_line/
mod.rs

1//! HTTP request line strategies.
2
3use std::{num::NonZero, ops::RangeInclusive};
4
5use proptest::prelude::Strategy;
6
7use crate::request_line::{target::RequestTarget, version::HttpVersion};
8
9pub mod target;
10pub mod verb;
11pub mod version;
12
13/// Http request line components.
14#[derive(Debug)]
15pub struct HttpRequestLine {
16  pub verb: String,
17  pub target: RequestTarget,
18  pub version: HttpVersion,
19}
20
21/// strategy for generating HTTP request line.
22///
23/// # Arguments
24/// * `max_label_count`: maximum label count to use for domain hosts in case of authority form,
25///   origin form and absolute form.
26/// * `max_segments`: maximum number of segments that compose the path in case of absolute form
27///   and origin form.
28/// * `query_count_range`: range of the number of queries to include in case of  absolute form
29///   and origin form.
30///
31/// # Returns
32/// [`HttpRequestLine`] and it representation.
33pub fn request_line(
34  max_label_count: usize,
35  max_segments: NonZero<usize>,
36  query_count_range: RangeInclusive<usize>,
37) -> impl Strategy<Value = (HttpRequestLine, String)> {
38  (
39    verb::request_verb(),
40    target::target(max_label_count, max_segments, query_count_range),
41    version::version(),
42  )
43    .prop_map(|(verb, (target, target_repr), (version, version_repr))| {
44      let repr = format!("{verb} {target_repr} {version_repr}");
45      (HttpRequestLine { verb, target, version }, repr)
46    })
47}
48
49#[cfg(test)]
50mod tests {
51  use proptest::proptest;
52
53  use super::*;
54
55  proptest! {
56    #[test]
57    fn request_line_works((request_line, repr) in request_line(20, 50.try_into().unwrap(), 0..=20)) {
58      let mut request_line_components = repr.split_ascii_whitespace();
59
60      let verb = request_line_components.next().unwrap();
61      assert_eq!(verb, request_line.verb, "expected to get verb {:?} but parsed {:?}", request_line.verb, verb);
62      verb::tests::request_verb_asserts(verb);
63
64      let target = request_line_components.next().unwrap();
65      target::tests::target_asserts(&request_line.target, target);
66
67      let version = request_line_components.next().unwrap();
68      version::tests::version_asserts(&request_line.version, version);
69    }
70  }
71}