use chrono::{DateTime, Utc};
use colored::*;
use serde::{Deserialize, Serialize};
use std::fmt::{self, Display, Formatter};
use crate::build_info::BuildInfo;
use crate::utils::env::Environment;
mod config;
mod errors;
mod identity;
mod measurement;
mod result;
mod suite;
pub use config::*;
pub use errors::*;
pub use identity::*;
pub use measurement::*;
pub use result::*;
pub use suite::*;
pub const REPORT_SCHEMA_VERSION: u32 = 8;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TestReport {
pub schema_version: u32,
pub start_time: DateTime<Utc>,
pub config: TestConfig,
pub result: TestResult,
pub timestamp: DateTime<Utc>,
pub build: BuildInfo,
pub environment: Environment,
pub peers: Peers,
}
impl TestReport {
pub fn new(
start_time: DateTime<Utc>,
config: TestConfig,
result: TestResult,
timestamp: DateTime<Utc>,
) -> Self {
Self {
schema_version: REPORT_SCHEMA_VERSION,
start_time,
config,
result,
timestamp,
build: BuildInfo::current(),
environment: Environment::capture(),
peers: Peers::local_only(),
}
}
}
impl<T, C, R> From<(T, C, R, T)> for TestReport
where
T: Into<DateTime<Utc>>,
C: Into<TestConfig>,
R: Into<TestResult>,
{
fn from((start_time, config, result, timestamp): (T, C, R, T)) -> Self {
Self {
schema_version: REPORT_SCHEMA_VERSION,
start_time: start_time.into(),
config: config.into(),
result: result.into(),
timestamp: timestamp.into(),
build: BuildInfo::current(),
environment: Environment::capture(),
peers: Peers::local_only(),
}
}
}
impl<T, C, R> From<(T, C, R)> for TestReport
where
T: Into<DateTime<Utc>>,
C: Into<TestConfig>,
R: Into<TestResult>,
{
fn from((start_time, config, result): (T, C, R)) -> Self {
Self::new(start_time.into(), config.into(), result.into(), Utc::now())
}
}
pub(crate) fn write_build_info(f: &mut Formatter<'_>, build: &BuildInfo) -> fmt::Result {
writeln!(
f,
"{}: {}",
"Version".bright_white().bold(),
build.summary().green()
)?;
let commit = match &build.git_commit {
Some(c) => {
let dirty = match build.git_dirty {
Some(true) => " (dirty)",
Some(false) => "",
None => " (dirty: unknown)",
};
format!("{c}{dirty}")
}
None => "unknown".to_string(),
};
writeln!(f, " {} {}", "commit:".bright_white(), commit.yellow())?;
writeln!(
f,
" {} {}",
"rustc: ".bright_white(),
build.rustc.yellow()
)?;
writeln!(
f,
" {} {}",
"built: ".bright_white(),
build.build_timestamp.yellow()
)
}
impl Display for TestReport {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
writeln!(
f,
"{}",
"═══ Speed CLI Test Report ═══".bright_cyan().bold()
)?;
write_build_info(f, &self.build)?;
writeln!(
f,
"{}: {}",
"Start Time".bright_white().bold(),
self.start_time
.format("%Y-%m-%d %H:%M:%S UTC")
.to_string()
.yellow()
)?;
writeln!(
f,
"{}: {}",
"Report Time".bright_white().bold(),
self.timestamp
.format("%Y-%m-%d %H:%M:%S UTC")
.to_string()
.yellow()
)?;
writeln!(f)?;
writeln!(f, "{}", "Environment:".bright_white().bold().underline())?;
write!(f, "{}", self.environment)?;
writeln!(f)?;
writeln!(f, "{}", "Peers:".bright_white().bold().underline())?;
write!(f, "{}", self.peers)?;
writeln!(f)?;
writeln!(f, "{}", "Configuration:".bright_white().bold().underline())?;
write!(f, "{}", self.config)?;
writeln!(f)?;
writeln!(f, "{}", "Results:".bright_white().bold().underline())?;
write!(f, "{}", self.result)?;
Ok(())
}
}