From 8da70bb6e247e81588ee22fb76896c5f93119807 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Fri, 9 Mar 2018 17:24:48 -0800 Subject: [PATCH] Run all discovery tests for HTTP/1 as well as HTTP/2 (#556) In order to ensure we catch discovery and routing issues arising from different logic for HTTP/1 and HTTP/2 requests, I've modified tests/discovery.rs to run all applicable tests with both HTTP/1 and HTTP/2 requests. The tests themselves are largely unchanged, but now there are separate modules containing HTTP/1 and HTTP/2 versions of a majority of the tests. --- proxy/tests/discovery.rs | 253 +++++++++++++++++++-------------------- 1 file changed, 121 insertions(+), 132 deletions(-) diff --git a/proxy/tests/discovery.rs b/proxy/tests/discovery.rs index 2888b261f..e730a21d3 100644 --- a/proxy/tests/discovery.rs +++ b/proxy/tests/discovery.rs @@ -1,96 +1,140 @@ mod support; use self::support::*; -use std::thread; +macro_rules! generate_tests { + (server: $make_server:path, client: $make_client:path) => { + #[test] + fn outbound_asks_controller_api() { + let _ = env_logger::try_init(); + let srv = $make_server().route("/", "hello").route("/bye", "bye").run(); + let ctrl = controller::new() + .destination("disco.test.svc.cluster.local", srv.addr) + .run(); + let proxy = proxy::new().controller(ctrl).outbound(srv).run(); + let client = $make_client(proxy.outbound, "disco.test.svc.cluster.local"); -#[test] -fn outbound_asks_controller_api() { - let _ = env_logger::try_init(); + assert_eq!(client.get("/"), "hello"); + assert_eq!(client.get("/bye"), "bye"); + } - let srv = server::new().route("/", "hello").route("/bye", "bye").run(); - let ctrl = controller::new() - .destination("disco.test.svc.cluster.local", srv.addr) - .run(); - let proxy = proxy::new().controller(ctrl).outbound(srv).run(); - let client = client::new(proxy.outbound, "disco.test.svc.cluster.local"); + #[test] + fn outbound_reconnects_if_controller_stream_ends() { + let _ = env_logger::try_init(); - assert_eq!(client.get("/"), "hello"); - assert_eq!(client.get("/bye"), "bye"); + let srv = $make_server().route("/recon", "nect").run(); + let ctrl = controller::new() + .destination_close("disco.test.svc.cluster.local") + .destination("disco.test.svc.cluster.local", srv.addr) + .run(); + let proxy = proxy::new().controller(ctrl).outbound(srv).run(); + let client = $make_client(proxy.outbound, "disco.test.svc.cluster.local"); + + assert_eq!(client.get("/recon"), "nect"); + } + + #[test] + #[cfg_attr(not(feature = "flaky_tests"), ignore)] + fn outbound_times_out() { + use std::thread; + let _ = env_logger::try_init(); + let mut env = config::TestEnv::new(); + + // set the bind timeout to 100 ms. + env.put(config::ENV_BIND_TIMEOUT, "100".to_owned()); + + let srv = $make_server().route("/hi", "hello").run(); + let addr = srv.addr.clone(); + let ctrl = controller::new() + // when the proxy requests the destination, sleep for 500 ms, and then + // return the correct destination + .destination_fn("disco.test.svc.cluster.local", move || { + thread::sleep(Duration::from_millis(500)); + Some(controller::destination_update(addr)) + }) + .run(); + + let proxy = proxy::new() + .controller(ctrl) + .outbound(srv) + .run_with_test_env(env); + + let client = $make_client(proxy.outbound, "disco.test.svc.cluster.local"); + let mut req = client.request_builder("/"); + let rsp = client.request(req.method("GET")); + // the request should time out + assert_eq!(rsp.status(), http::StatusCode::INTERNAL_SERVER_ERROR); + } + + #[test] + fn outbound_uses_orig_dst_if_not_local_svc() { + let _ = env_logger::try_init(); + + let srv = $make_server() + .route("/", "hello") + .route("/bye", "bye") + .run(); + let ctrl = controller::new() + // no controller rule for srv + .run(); + let proxy = proxy::new() + .controller(ctrl) + // set outbound orig_dst to srv + .outbound(srv) + .run(); + let client = $make_client(proxy.outbound, "versioncheck.conduit.io"); + + assert_eq!(client.get("/"), "hello"); + assert_eq!(client.get("/bye"), "bye"); + } + + #[test] + fn outbound_asks_controller_without_orig_dst() { + let _ = env_logger::try_init(); + + let srv = $make_server() + .route("/", "hello") + .route("/bye", "bye") + .run(); + let ctrl = controller::new() + .destination("disco.test.svc.cluster.local", srv.addr) + .run(); + let proxy = proxy::new() + .controller(ctrl) + // don't set srv as outbound(), so that SO_ORIGINAL_DST isn't + // used as a backup + .run(); + let client = $make_client(proxy.outbound, "disco.test.svc.cluster.local"); + + assert_eq!(client.get("/"), "hello"); + assert_eq!(client.get("/bye"), "bye"); + } + } } -#[test] -fn outbound_asks_controller_about_authority() { - let _ = env_logger::try_init(); +mod http2 { + use super::support::*; - let srv = server::new().route("/", "hello").route("/bye", "bye").run(); - let ctrl = controller::new() - .destination("disco.test.svc.cluster.local", srv.addr) - .run(); - let proxy = proxy::new().controller(ctrl).run(); - let client = client::new(proxy.outbound, "disco.test.svc.cluster.local"); + generate_tests! { server: server::new, client: client::new } - assert_eq!(client.get("/"), "hello"); - assert_eq!(client.get("/bye"), "bye"); } -#[test] -fn outbound_reconnects_if_controller_stream_ends() { - let _ = env_logger::try_init(); +mod http1 { + use super::support::*; - let srv = server::new().route("/recon", "nect").run(); - let ctrl = controller::new() - .destination_close("disco.test.svc.cluster.local") - .destination("disco.test.svc.cluster.local", srv.addr) - .run(); - let proxy = proxy::new().controller(ctrl).outbound(srv).run(); - let client = client::new(proxy.outbound, "disco.test.svc.cluster.local"); + generate_tests! { server: server::http1, client: client::http1 } + + mod absolute_uris { + use super::super::support::*; + + generate_tests! { + server: server::http1, + client: client::http1_absolute_uris + } + + } - assert_eq!(client.get("/recon"), "nect"); } -#[test] -fn outbound_http1_asks_controller_about_host() { - let _ = env_logger::try_init(); - - let srv = server::http1() - .route("/", "hello") - .route("/bye", "bye") - .run(); - let ctrl = controller::new() - .destination("disco.test.svc.cluster.local", srv.addr) - .run(); - let proxy = proxy::new() - .controller(ctrl) - // don't set srv as outbound(), so that SO_ORIGINAL_DST isn't - // used as a backup - .run(); - let client = client::http1(proxy.outbound, "disco.test.svc.cluster.local"); - - assert_eq!(client.get("/"), "hello"); - assert_eq!(client.get("/bye"), "bye"); -} - -#[test] -fn outbound_http1_asks_controller_api() { - let _ = env_logger::try_init(); - - let srv = server::http1() - .route("/", "hello") - .route("/bye", "bye") - .run(); - let ctrl = controller::new() - .destination("disco.test.svc.cluster.local", srv.addr) - .run(); - let proxy = proxy::new() - .controller(ctrl) - // don't set srv as outbound(), so that SO_ORIGINAL_DST isn't - // used as a backup - .run(); - let client = client::http1(proxy.outbound, "disco.test.svc.cluster.local"); - - assert_eq!(client.get("/"), "hello"); - assert_eq!(client.get("/bye"), "bye"); -} #[test] fn outbound_updates_newer_services() { @@ -114,58 +158,3 @@ fn outbound_updates_newer_services() { let client2 = client::http1(proxy.outbound, "disco.test.svc.cluster.local"); assert_eq!(client2.get("/h1"), "hello h1"); } - -#[test] -#[cfg_attr(not(feature = "flaky_tests"), ignore)] -fn outbound_times_out() { - let _ = env_logger::try_init(); - let mut env = config::TestEnv::new(); - - // set the bind timeout to 100 ms. - env.put(config::ENV_BIND_TIMEOUT, "100".to_owned()); - - let srv = server::http1().route("/h1", "hello h1").run(); - let addr = srv.addr.clone(); - let ctrl = controller::new() - // when the proxy requests the destination, sleep for 500 ms, and then - // return the correct destination - .destination_fn("disco.test.svc.cluster.local", move || { - thread::sleep(Duration::from_millis(500)); - Some(controller::destination_update(addr)) - }) - .run(); - - let proxy = proxy::new() - .controller(ctrl) - .outbound(srv) - .run_with_test_env(env); - - let client = client::http2(proxy.outbound, "disco.test.svc.cluster.local"); - let mut req = client.request_builder("/"); - let rsp = client.request(req.method("GET")); - - // the request should time out - assert_eq!(rsp.status(), http::StatusCode::INTERNAL_SERVER_ERROR); -} - -#[test] -fn outbound_uses_orig_dst_if_not_local_svc() { - let _ = env_logger::try_init(); - - let srv = server::new() - .route("/", "hello") - .route("/bye", "bye") - .run(); - let ctrl = controller::new() - // no controller rule for srv - .run(); - let proxy = proxy::new() - .controller(ctrl) - // set outbound orig_dst to srv - .outbound(srv) - .run(); - let client = client::new(proxy.outbound, "versioncheck.conduit.io"); - - assert_eq!(client.get("/"), "hello"); - assert_eq!(client.get("/bye"), "bye"); -}