1 use anyhow::Context as _;
2 use futures::join;
3 use test_programs::p3::wasi::http::handler;
4 use test_programs::p3::wasi::http::types::{ErrorCode, Headers, Method, Request, Scheme, Trailers};
5 use test_programs::p3::{wit_future, wit_stream};
6 use wit_bindgen::{FutureReader, FutureWriter, StreamWriter};
7 
8 struct Component;
9 
10 test_programs::p3::export!(Component);
11 
12 fn make_request() -> (
13     Request,
14     StreamWriter<u8>,
15     FutureWriter<Result<Option<Trailers>, ErrorCode>>,
16     FutureReader<Result<(), ErrorCode>>,
17 ) {
18     let (contents_tx, contents_rx) = wit_stream::new();
19     let (trailers_tx, trailers_rx) = wit_future::new(|| todo!());
20     let (request, transmit) = Request::new(
21         Headers::from_list(&[("Content-Length".to_string(), b"11".to_vec())]).unwrap(),
22         Some(contents_rx),
23         trailers_rx,
24         None,
25     );
26 
27     request.set_method(&Method::Post).expect("setting method");
28     request
29         .set_scheme(Some(&Scheme::Http))
30         .expect("setting scheme");
31     let addr = test_programs::p3::wasi::cli::environment::get_environment()
32         .into_iter()
33         .find_map(|(k, v)| k.eq("HTTP_SERVER").then_some(v))
34         .unwrap();
35     request
36         .set_authority(Some(&addr))
37         .expect("setting authority");
38     request
39         .set_path_with_query(Some("/"))
40         .expect("setting path with query");
41 
42     (request, contents_tx, trailers_tx, transmit)
43 }
44 
45 impl test_programs::p3::exports::wasi::cli::run::Guest for Component {
46     async fn run() -> Result<(), ()> {
47         {
48             let (request, mut contents_tx, trailers_tx, transmit) = make_request();
49             let (transmit, handle) = join!(async { transmit.await }, async {
50                 let res = handler::handle(request)
51                     .await
52                     .context("failed to send request")?;
53                 println!("writing enough");
54                 let remaining = contents_tx.write_all(b"long enough".to_vec()).await;
55                 assert!(
56                     remaining.is_empty(),
57                     "{}",
58                     String::from_utf8_lossy(&remaining)
59                 );
60                 drop(contents_tx);
61                 trailers_tx
62                     .write(Ok(None))
63                     .await
64                     .context("failed to finish body")?;
65                 anyhow::Ok(res)
66             });
67             let res = handle.unwrap();
68             drop(res);
69             transmit.expect("failed to transmit request");
70         }
71 
72         {
73             let (request, mut contents_tx, trailers_tx, transmit) = make_request();
74             let (transmit, handle) = join!(async { transmit.await }, async {
75                 let res = handler::handle(request)
76                     .await
77                     .context("failed to send request")?;
78                 println!("writing too little");
79                 let remaining = contents_tx.write_all(b"msg".to_vec()).await;
80                 assert!(
81                     remaining.is_empty(),
82                     "{}",
83                     String::from_utf8_lossy(&remaining)
84                 );
85                 drop(contents_tx);
86                 trailers_tx
87                     .write(Ok(None))
88                     .await
89                     .context("failed to finish body")?;
90                 anyhow::Ok(res)
91             });
92             let res = handle.unwrap();
93             drop(res);
94             let err = transmit.expect_err("request transmission should have failed");
95             assert!(
96                 matches!(err, ErrorCode::HttpRequestBodySize(Some(3))),
97                 "unexpected error: {err:#?}"
98             );
99         }
100 
101         {
102             let (request, mut contents_tx, trailers_tx, transmit) = make_request();
103             let (transmit, handle) = join!(async { transmit.await }, async {
104                 let res = handler::handle(request)
105                     .await
106                     .context("failed to send request")?;
107                 println!("writing too much");
108                 let remaining = contents_tx.write_all(b"more than 11 bytes".to_vec()).await;
109                 assert!(
110                     remaining.is_empty(),
111                     "{}",
112                     String::from_utf8_lossy(&remaining)
113                 );
114                 drop(contents_tx);
115                 _ = trailers_tx.write(Ok(None)).await;
116                 anyhow::Ok(res)
117             });
118             let res = handle.unwrap();
119             drop(res);
120             let err = transmit.expect_err("request transmission should have failed");
121             assert!(
122                 matches!(err, ErrorCode::HttpRequestBodySize(Some(18))),
123                 "unexpected error: {err:#?}"
124             );
125         }
126         Ok(())
127     }
128 }
129 
130 fn main() {}
131