|
@@ -0,0 +1,153 @@
|
|
|
+use crate::*;
|
|
|
+
|
|
|
+use hyper::{
|
|
|
+ body,
|
|
|
+ header::HeaderValue,
|
|
|
+ service::{make_service_fn, service_fn},
|
|
|
+ Body, Client, Method, Request, Response, Server,
|
|
|
+};
|
|
|
+use std::{convert::Infallible, net::SocketAddr, time::Duration};
|
|
|
+use tokio::{spawn, time::sleep};
|
|
|
+
|
|
|
+use lox_library::bridge_table::BridgeLine;
|
|
|
+use rand::RngCore;
|
|
|
+
|
|
|
+// Prepare HTTP Response for successful Server Request
|
|
|
+fn prepare_header(response: String) -> Response<Body> {
|
|
|
+ let mut resp = Response::new(Body::from(response));
|
|
|
+ resp.headers_mut()
|
|
|
+ .insert("Access-Control-Allow-Origin", HeaderValue::from_static("*"));
|
|
|
+ resp
|
|
|
+}
|
|
|
+
|
|
|
+// Lets the client get or set the simulated date
|
|
|
+async fn date_server(req: Request<Body>) -> Result<Response<Body>, Infallible> {
|
|
|
+ match req.method() {
|
|
|
+ &Method::OPTIONS => Ok(Response::builder()
|
|
|
+ .header("Access-Control-Allow-Origin", HeaderValue::from_static("*"))
|
|
|
+ .header("Access-Control-Allow-Headers", "accept, content-type")
|
|
|
+ .header("Access-Control-Allow-Methods", "POST")
|
|
|
+ .status(200)
|
|
|
+ .body(Body::from("Allow POST"))
|
|
|
+ .unwrap()),
|
|
|
+ _ => match req.uri().path() {
|
|
|
+ "/getdate" => Ok::<_, Infallible>(prepare_header(get_date().to_string())),
|
|
|
+ "/setdate" => Ok::<_, Infallible>({
|
|
|
+ let bytes = body::to_bytes(req.into_body()).await.unwrap();
|
|
|
+ let date: u32 = std::str::from_utf8(&bytes).unwrap().parse().unwrap();
|
|
|
+ set_simulated_date(date);
|
|
|
+ prepare_header("OK".to_string())
|
|
|
+ }),
|
|
|
+ _ => Ok::<_, Infallible>(prepare_header("Wrong path".to_string())),
|
|
|
+ },
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// Serves the function to let the client get or set the simulated date
|
|
|
+async fn server() {
|
|
|
+ let addr = SocketAddr::from(([127, 0, 0, 1], 9999));
|
|
|
+
|
|
|
+ let make_svc = make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn(date_server)) });
|
|
|
+
|
|
|
+ let server = Server::bind(&addr).serve(make_svc);
|
|
|
+
|
|
|
+ if let Err(e) = server.await {
|
|
|
+ eprintln!("server error: {}", e);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async fn get_date_from_server() -> u32 {
|
|
|
+ download("http://localhost:9999/getdate")
|
|
|
+ .await
|
|
|
+ .unwrap()
|
|
|
+ .parse()
|
|
|
+ .unwrap()
|
|
|
+}
|
|
|
+
|
|
|
+async fn set_date_on_server(date: u32) {
|
|
|
+ let client = Client::new();
|
|
|
+ let req = Request::builder()
|
|
|
+ .method(Method::POST)
|
|
|
+ .uri(
|
|
|
+ "http://localhost:9999/setdate"
|
|
|
+ .parse::<hyper::Uri>()
|
|
|
+ .unwrap(),
|
|
|
+ )
|
|
|
+ .body(Body::from(date.to_string()))
|
|
|
+ .unwrap();
|
|
|
+ client.request(req).await.unwrap();
|
|
|
+}
|
|
|
+
|
|
|
+#[tokio::test]
|
|
|
+async fn test_simulated_time() {
|
|
|
+ // Reset date in case we had a previous simulated date
|
|
|
+ reset_simulated_date();
|
|
|
+
|
|
|
+ // Get date
|
|
|
+ let date = get_date();
|
|
|
+
|
|
|
+ // Check that simulated date matches real date
|
|
|
+ let real_date: u32 = time::OffsetDateTime::now_utc()
|
|
|
+ .date()
|
|
|
+ .to_julian_day()
|
|
|
+ .try_into()
|
|
|
+ .unwrap();
|
|
|
+
|
|
|
+ assert_eq!(date, real_date);
|
|
|
+
|
|
|
+ // Check that incrementing simulated date works
|
|
|
+ increment_simulated_date();
|
|
|
+ assert_eq!(date + 1, get_date());
|
|
|
+
|
|
|
+ // Create dummy bridge
|
|
|
+ let mut rng = rand::thread_rng();
|
|
|
+ let mut bl = BridgeLine::default();
|
|
|
+ rng.fill_bytes(&mut bl.fingerprint);
|
|
|
+ let negative_report =
|
|
|
+ NegativeReport::from_bridgeline(bl, "ru".to_string(), BridgeDistributor::Lox);
|
|
|
+
|
|
|
+ // No issue
|
|
|
+ let negative_report = negative_report
|
|
|
+ .to_serializable_report()
|
|
|
+ .to_report()
|
|
|
+ .unwrap();
|
|
|
+
|
|
|
+ // Advance time so the report is no longer valid
|
|
|
+ set_simulated_date(get_date() + MAX_BACKDATE + 1);
|
|
|
+
|
|
|
+ // Report fails to deserialize
|
|
|
+ let negative_report_result = negative_report.to_serializable_report().to_report();
|
|
|
+ assert!(negative_report_result.is_err());
|
|
|
+
|
|
|
+ // Ensure one thread CAN influence the time for other threads
|
|
|
+ spawn(async move {
|
|
|
+ server().await;
|
|
|
+ });
|
|
|
+
|
|
|
+ // Give server time to start
|
|
|
+ sleep(Duration::new(1, 0)).await;
|
|
|
+
|
|
|
+ // Increment date
|
|
|
+ increment_simulated_date();
|
|
|
+ let date = get_date();
|
|
|
+
|
|
|
+ // Get date from server
|
|
|
+ let remote_date = get_date_from_server().await;
|
|
|
+ assert_eq!(date, remote_date);
|
|
|
+
|
|
|
+ // Increase date a lot
|
|
|
+ set_simulated_date(get_date() + 100);
|
|
|
+ let date = get_date();
|
|
|
+
|
|
|
+ // Check that date from server matches
|
|
|
+ let remote_date = get_date_from_server().await;
|
|
|
+ assert_eq!(date, remote_date);
|
|
|
+
|
|
|
+ // Have server increase date
|
|
|
+ let old_date = get_date();
|
|
|
+ let new_date = old_date + 500;
|
|
|
+ set_date_on_server(new_date).await;
|
|
|
+
|
|
|
+ // Check that we have the date as changed in the other thread
|
|
|
+ assert_eq!(get_date(), new_date);
|
|
|
+}
|