//! What the server does when a part of it that it cannot do without fails. //! //! The local RIB's actor stops only by panicking. Before, nothing noticed: //! sessions stayed up, nothing was announced any more, and the status page //! showed an empty table. Now the server tells its peers it is going and //! stops with an error, for whatever supervises it to restart it. use std::net::Ipv4Addr; use bgp_integration_tests::TIMEOUT; use bgp_integration_tests::test_server::TestServer; use bgp_packet::errors::{BgpError, CeaseSubcode}; use bgp_rib::RibStopped; use bgp_server::error::ServerError; use eyre::Result; const LOCAL_ASN: u32 = 65000; const PEER_ASN: u32 = 65001; #[tokio::test] async fn test_losing_the_local_rib_stops_the_server_and_tells_the_peers() -> Result<()> { let mut server = TestServer::start(LOCAL_ASN).await?; let (base, _http) = server.serve_http().await?; let mut peer = server .established(PEER_ASN, Ipv4Addr::new(10, 0, 0, 1)) .await?; server.local_rib.stop_for_testing(); let outcome = tokio::time::timeout(TIMEOUT, server.stopped()).await?; assert!( matches!(outcome, Err(ServerError::RibStopped(RibStopped { rib })) if rib == "local RIB"), "{outcome:?}" ); assert_eq!( peer.expect_notification().await?.error, BgpError::Cease(CeaseSubcode::AdminShutdown) ); // The status interface says the table cannot be read, where it used to // show an empty one. let client = reqwest::Client::new(); for path in ["/api/status", "/api/routes/local", "/metricz"] { let response = client.get(format!("{base}{path}")).send().await?; assert_eq!(response.status(), 503, "{path}"); assert_eq!( response.text().await?, "the local RIB has stopped", "{path}" ); } // What does not need that table still answers. let response = client .get(format!("{base}/api/routes/received")) .send() .await?; assert_eq!(response.status(), 200); Ok(()) }