Skip to content

Commit

Permalink
dev: add tests to health check
Browse files Browse the repository at this point in the history
  • Loading branch information
da2ce7 committed Jan 17, 2024
1 parent b310c75 commit 3f0dcea
Show file tree
Hide file tree
Showing 30 changed files with 1,182 additions and 963 deletions.
5 changes: 4 additions & 1 deletion src/bootstrap/jobs/health_check_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use torrust_tracker_configuration::HealthCheckApi;
use super::Started;
use crate::servers::health_check_api::server;
use crate::servers::registar::ServiceRegistry;
use crate::servers::signals::Halted;

/// This function starts a new Health Check API server with the provided
/// configuration.
Expand All @@ -40,12 +41,14 @@ pub async fn start_job(config: &HealthCheckApi, register: ServiceRegistry) -> Jo
.expect("it should have a valid health check bind address");

let (tx_start, rx_start) = oneshot::channel::<Started>();
let (tx_halt, rx_halt) = tokio::sync::oneshot::channel::<Halted>();
drop(tx_halt);

Check warning on line 45 in src/bootstrap/jobs/health_check_api.rs

View check run for this annotation

Codecov / codecov/patch

src/bootstrap/jobs/health_check_api.rs#L44-L45

Added lines #L44 - L45 were not covered by tests

// Run the API server
let join_handle = tokio::spawn(async move {
info!(target: "Health Check API", "Starting on: http://{}", bind_addr);

let handle = server::start(bind_addr, tx_start, register);
let handle = server::start(bind_addr, tx_start, rx_halt, register);

Check warning on line 51 in src/bootstrap/jobs/health_check_api.rs

View check run for this annotation

Codecov / codecov/patch

src/bootstrap/jobs/health_check_api.rs#L51

Added line #L51 was not covered by tests

if let Ok(()) = handle.await {
info!(target: "Health Check API", "Stopped server running on: http://{}", bind_addr);
Expand Down
5 changes: 5 additions & 0 deletions src/servers/health_check_api/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ pub(crate) async fn health_check_handler(State(register): State<ServiceRegistry>
checks = mutex.await.values().map(ServiceRegistration::spawn_check).collect();
}

// if we do not have any checks, lets return a `none` result.
if checks.is_empty() {
return responses::none();
}

let jobs = checks.drain(..).map(|c| {
tokio::spawn(async move {
CheckReport {
Expand Down
10 changes: 10 additions & 0 deletions src/servers/health_check_api/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use serde::{Deserialize, Serialize};
pub enum Status {
Ok,
Error,
None,
}

#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -34,6 +35,15 @@ pub struct Report {
}

impl Report {
#[must_use]
pub fn none() -> Report {
Self {
status: Status::None,
message: String::new(),
details: Vec::default(),
}
}

#[must_use]
pub fn ok(details: Vec<CheckReport>) -> Report {
Self {
Expand Down
4 changes: 4 additions & 0 deletions src/servers/health_check_api/responses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ pub fn ok(details: Vec<CheckReport>) -> Json<Report> {
pub fn error(message: String, details: Vec<CheckReport>) -> Json<Report> {
Json(Report::error(message, details))
}

pub fn none() -> Json<Report> {
Json(Report::none())
}
28 changes: 14 additions & 14 deletions src/servers/health_check_api/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,44 +8,44 @@ use axum::routing::get;
use axum::{Json, Router};
use axum_server::Handle;
use futures::Future;
use log::info;
use serde_json::json;
use tokio::sync::oneshot::Sender;
use tokio::sync::oneshot::{Receiver, Sender};

use crate::bootstrap::jobs::Started;
use crate::servers::health_check_api::handlers::health_check_handler;
use crate::servers::registar::ServiceRegistry;
use crate::servers::signals::{graceful_shutdown, Halted};

/// Starts Health Check API server.
///
/// # Panics
///
/// Will panic if binding to the socket address fails.
pub fn start(
address: SocketAddr,
bind_to: SocketAddr,
tx: Sender<Started>,
rx_halt: Receiver<Halted>,
register: ServiceRegistry,
) -> impl Future<Output = Result<(), std::io::Error>> {
let app = Router::new()
let router = Router::new()
.route("/", get(|| async { Json(json!({})) }))
.route("/health_check", get(health_check_handler))
.with_state(register);

let handle = Handle::new();
let cloned_handle = handle.clone();

let socket = std::net::TcpListener::bind(address).expect("Could not bind tcp_listener to address.");
let socket = std::net::TcpListener::bind(bind_to).expect("Could not bind tcp_listener to address.");
let address = socket.local_addr().expect("Could not get local_addr from tcp_listener.");

tokio::task::spawn(async move {
tokio::signal::ctrl_c().await.expect("Failed to listen to shutdown signal.");
info!("Stopping Torrust Health Check API server o http://{} ...", address);
cloned_handle.shutdown();
});
let handle = Handle::new();

tokio::task::spawn(graceful_shutdown(
handle.clone(),
rx_halt,
format!("shutting down http server on socket address: {address}"),
));

let running = axum_server::from_tcp(socket)
.handle(handle)
.serve(app.into_make_service_with_connect_info::<SocketAddr>());
.serve(router.into_make_service_with_connect_info::<SocketAddr>());

tx.send(Started { address })
.expect("the Health Check API server should not be dropped");
Expand Down
26 changes: 21 additions & 5 deletions src/shared/bit_torrent/tracker/udp/client.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use std::io::Cursor;
use std::net::SocketAddr;
use std::sync::Arc;
use std::time::Duration;

use aquatic_udp_protocol::{ConnectRequest, Request, Response, TransactionId};
use tokio::net::UdpSocket;
use tokio::time;

use crate::shared::bit_torrent::tracker::udp::{source_address, MAX_PACKET_SIZE};

Expand Down Expand Up @@ -112,6 +114,8 @@ pub async fn new_udp_tracker_client_connected(remote_address: &str) -> UdpTracke
/// # Errors
///
/// It will return an error if unable to connect to the UDP service.
///
/// # Panics
pub async fn check(binding: &SocketAddr) -> Result<String, String> {
let client = new_udp_tracker_client_connected(binding.to_string().as_str()).await;

Expand All @@ -121,11 +125,23 @@ pub async fn check(binding: &SocketAddr) -> Result<String, String> {

client.send(connect_request.into()).await;

let response = client.receive().await;
let process = move |response| {
if matches!(response, Response::Connect(_connect_response)) {
Ok("Connected".to_string())
} else {
Err("Did not Connect".to_string())

Check warning on line 132 in src/shared/bit_torrent/tracker/udp/client.rs

View check run for this annotation

Codecov / codecov/patch

src/shared/bit_torrent/tracker/udp/client.rs#L132

Added line #L132 was not covered by tests
}
};

let sleep = time::sleep(Duration::from_millis(2000));
tokio::pin!(sleep);

if matches!(response, Response::Connect(_connect_response)) {
Ok("Connected".to_string())
} else {
Err("Did not Connect".to_string())
tokio::select! {
() = &mut sleep => {
Err("Timed Out".to_string())
}
response = client.receive() => {
process(response)
}
}
}
8 changes: 0 additions & 8 deletions tests/common/app.rs

This file was deleted.

1 change: 0 additions & 1 deletion tests/common/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
pub mod app;
pub mod fixtures;
pub mod http;
pub mod udp;
94 changes: 94 additions & 0 deletions tests/servers/api/environment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use std::net::SocketAddr;
use std::sync::Arc;

use futures::executor::block_on;
use torrust_tracker::bootstrap::app::initialize_with_configuration;
use torrust_tracker::bootstrap::jobs::make_rust_tls;
use torrust_tracker::core::peer::Peer;
use torrust_tracker::core::Tracker;
use torrust_tracker::servers::apis::server::{ApiServer, Launcher, Running, Stopped};
use torrust_tracker::servers::registar::Registar;
use torrust_tracker::shared::bit_torrent::info_hash::InfoHash;
use torrust_tracker_configuration::{Configuration, HttpApi};

use super::connection_info::ConnectionInfo;

pub struct Environment<S> {
pub config: Arc<HttpApi>,
pub tracker: Arc<Tracker>,
pub registar: Registar,
pub server: ApiServer<S>,
}

impl<S> Environment<S> {
/// Add a torrent to the tracker
pub async fn add_torrent_peer(&self, info_hash: &InfoHash, peer: &Peer) {
self.tracker.update_torrent_with_peer_and_get_stats(info_hash, peer).await;
}
}

impl Environment<Stopped> {
pub fn new(configuration: &Arc<Configuration>) -> Self {
let tracker = initialize_with_configuration(configuration);

let config = Arc::new(configuration.http_api.clone());

let bind_to = config
.bind_address
.parse::<std::net::SocketAddr>()
.expect("Tracker API bind_address invalid.");

let tls = block_on(make_rust_tls(config.ssl_enabled, &config.ssl_cert_path, &config.ssl_key_path))
.map(|tls| tls.expect("tls config failed"));

let server = ApiServer::new(Launcher::new(bind_to, tls));

Self {
config,
tracker,
registar: Registar::default(),
server,
}
}

pub async fn start(self) -> Environment<Running> {
let access_tokens = Arc::new(self.config.access_tokens.clone());

Environment {
config: self.config,
tracker: self.tracker.clone(),
registar: self.registar.clone(),
server: self
.server
.start(self.tracker, self.registar.give_form(), access_tokens)
.await
.unwrap(),
}
}
}

impl Environment<Running> {
pub async fn new(configuration: &Arc<Configuration>) -> Self {
Environment::<Stopped>::new(configuration).start().await
}

pub async fn stop(self) -> Environment<Stopped> {
Environment {
config: self.config,
tracker: self.tracker,
registar: Registar::default(),
server: self.server.stop().await.unwrap(),
}
}

pub fn get_connection_info(&self) -> ConnectionInfo {
ConnectionInfo {
bind_address: self.server.state.binding.to_string(),
api_token: self.config.access_tokens.get("admin").cloned(),
}
}

pub fn bind_address(&self) -> SocketAddr {
self.server.state.binding
}
}
5 changes: 4 additions & 1 deletion tests/servers/api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use std::sync::Arc;

use torrust_tracker::core::Tracker;
use torrust_tracker::servers::apis::server;

pub mod connection_info;
pub mod test_environment;
pub mod environment;
pub mod v1;

pub type Started = environment::Environment<server::Running>;

/// It forces a database error by dropping all tables.
/// That makes any query fail.
/// code-review: alternatively we could inject a database mock in the future.
Expand Down
Loading

0 comments on commit 3f0dcea

Please sign in to comment.