tests: clean up more tests across the project
Rust CI / cargo fmt (push) Successful in 17s
Rust CI / cargo check (x86_64-unknown-linux-gnu) (push) Successful in 33s
Rust CI / cargo clippy (push) Successful in 34s
Rust CI / cargo test (x86_64-unknown-linux-gnu) (push) Failing after 33s
Rust CI / cargo check (x86_64-unknown-linux-musl) (push) Failing after 9s
Rust CI / cargo test (x86_64-unknown-linux-musl) (push) Failing after 8s
Rust CI / cargo doc (push) Successful in 22s
Fuzz Smoke / cargo fuzz smoke (push) Failing after 27s
Supply chain / cargo-deny advisories (push) Successful in 7s
Supply chain / cargo-deny bans licenses sources (push) Successful in 6s
Supply chain / actionlint (push) Successful in 3s
Netem Interop / netem interop (push) Successful in 1m3s
Rust CI / cargo fmt (push) Successful in 17s
Rust CI / cargo check (x86_64-unknown-linux-gnu) (push) Successful in 33s
Rust CI / cargo clippy (push) Successful in 34s
Rust CI / cargo test (x86_64-unknown-linux-gnu) (push) Failing after 33s
Rust CI / cargo check (x86_64-unknown-linux-musl) (push) Failing after 9s
Rust CI / cargo test (x86_64-unknown-linux-musl) (push) Failing after 8s
Rust CI / cargo doc (push) Successful in 22s
Fuzz Smoke / cargo fuzz smoke (push) Failing after 27s
Supply chain / cargo-deny advisories (push) Successful in 7s
Supply chain / cargo-deny bans licenses sources (push) Successful in 6s
Supply chain / actionlint (push) Successful in 3s
Netem Interop / netem interop (push) Successful in 1m3s
This commit is contained in:
17 files changed
+28
-1435
No files matched your search
@@ -1264,15 +1264,6 @@ mod tests {
|
||||
assert_eq!(header.split_whitespace().next(), Some("target"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_structured_columns_always_include_target_first() {
|
||||
for format in [OutputFormat::Csv, OutputFormat::Tsv, OutputFormat::Jsonl] {
|
||||
let columns = default_columns(format, false);
|
||||
assert_eq!(columns.first(), Some(&Column::Target));
|
||||
assert_eq!(columns, ALL_COLUMNS);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn columns_default_keyword_matches_omitted_columns() {
|
||||
for format in [
|
||||
@@ -1329,83 +1320,24 @@ mod tests {
|
||||
assert!(line.starts_with("{\"target\":\"ams\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn truncate_for_table_leaves_short_value_unchanged() {
|
||||
assert_eq!(truncate_for_table("ams", 18), "ams");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn truncate_for_table_leaves_exact_width_value_unchanged() {
|
||||
let value = "a".repeat(18);
|
||||
assert_eq!(truncate_for_table(&value, 18), value);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn truncate_for_table_shortens_long_value_to_width() {
|
||||
let value = "a".repeat(40);
|
||||
let truncated = truncate_for_table(&value, 18);
|
||||
|
||||
assert_eq!(truncated.chars().count(), 18);
|
||||
assert!(truncated.len() <= 18); // ASCII: byte len matches char len
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn truncate_for_table_keeps_prefix_and_appends_ellipsis_deterministically() {
|
||||
let value = "abcdefghijklmnopqrstuvwxyz";
|
||||
let truncated = truncate_for_table(value, 18);
|
||||
|
||||
assert_eq!(truncated, "abcdefghijklmno...");
|
||||
assert_eq!(truncated.chars().count(), 18);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn truncate_for_table_does_not_split_multibyte_code_points() {
|
||||
// Each character below is multibyte in UTF-8; a byte-index slice
|
||||
// would panic or corrupt the string on a non-boundary cut.
|
||||
let value = "\u{1F600}".repeat(40); // 😀 repeated, well past width 18
|
||||
let truncated = truncate_for_table(&value, 18);
|
||||
|
||||
// Must not panic (validated by test completing) and must remain
|
||||
// valid UTF-8 with exactly 18 chars (15 prefix chars + "...").
|
||||
assert_eq!(truncated.chars().count(), 18);
|
||||
assert!(truncated.ends_with("..."));
|
||||
assert_eq!(truncated.chars().filter(|c| *c == '\u{1F600}').count(), 15);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn table_row_with_long_target_keeps_next_column_aligned() {
|
||||
let config = output_config(OutputFormat::Table, None);
|
||||
let long_target = "a".repeat(40);
|
||||
let header = config.render_header().unwrap();
|
||||
let line = config
|
||||
.render_event(
|
||||
&reply(),
|
||||
Some(&long_target),
|
||||
Some(&EventRenderStats::default()),
|
||||
)
|
||||
.unwrap();
|
||||
let event_offset = header.find("event").unwrap();
|
||||
|
||||
// Target column is truncated to its table width (18), so the
|
||||
// "event" column starts at the same offset for both a normal and an
|
||||
// overlong target label.
|
||||
let short_config = output_config(OutputFormat::Table, None);
|
||||
let short_line = short_config
|
||||
.render_event(&reply(), Some("ams"), Some(&EventRenderStats::default()))
|
||||
.unwrap();
|
||||
|
||||
let target_width = Column::Target.table_width();
|
||||
let expected_event_offset = target_width + " ".len();
|
||||
assert_eq!(&header[expected_event_offset..][..5], "event");
|
||||
// The event column ("echo_reply") starts at the same offset
|
||||
// regardless of whether the target label was short or overlong.
|
||||
assert_eq!(
|
||||
&line[expected_event_offset..][.."echo_reply".len()],
|
||||
"echo_reply"
|
||||
);
|
||||
assert_eq!(
|
||||
&short_line[expected_event_offset..][.."echo_reply".len()],
|
||||
"echo_reply"
|
||||
);
|
||||
for label in ["ams".to_owned(), "a".repeat(40), "é".repeat(40)] {
|
||||
let line = config
|
||||
.render_event(&reply(), Some(&label), Some(&EventRenderStats::default()))
|
||||
.unwrap();
|
||||
let prefix = line.split("echo_reply").next().unwrap();
|
||||
assert_eq!(prefix.chars().count(), event_offset, "{line}");
|
||||
if label.chars().count() > event_offset {
|
||||
assert!(prefix.trim_end().ends_with("..."), "{line}");
|
||||
} else {
|
||||
assert!(prefix.starts_with(&label), "{line}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1452,26 +1384,4 @@ mod tests {
|
||||
|
||||
assert_eq!(line, format!("{{\"target\":\"{long_target}\",\"seq\":7}}"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn explicit_table_columns_with_target_truncate_same_as_default() {
|
||||
let config = output_config(OutputFormat::Table, Some("target,seq"));
|
||||
let long_target = "d".repeat(40);
|
||||
let line = config
|
||||
.render_event(
|
||||
&reply(),
|
||||
Some(&long_target),
|
||||
Some(&EventRenderStats::default()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let target_width = Column::Target.table_width();
|
||||
let expected_prefix: String = long_target
|
||||
.chars()
|
||||
.take(target_width - 3)
|
||||
.chain("...".chars())
|
||||
.collect();
|
||||
assert!(line.starts_with(&expected_prefix));
|
||||
assert_eq!(&line[..target_width], expected_prefix.as_str());
|
||||
}
|
||||
}
|
||||
@@ -1052,26 +1052,6 @@ mod tests {
|
||||
assert!(mailbox.latest().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eof_and_shutdown_stop_without_waiting_for_the_stdin_reader() {
|
||||
let mailbox = StdinMailbox::default();
|
||||
let shutdown_requested = AtomicBool::new(false);
|
||||
assert!(stdin_stop_request(&shutdown_requested, &mailbox).is_none());
|
||||
|
||||
mailbox.finish();
|
||||
assert!(matches!(
|
||||
stdin_stop_request(&shutdown_requested, &mailbox),
|
||||
Some(StdinStop::Eof)
|
||||
));
|
||||
|
||||
let mailbox = StdinMailbox::default();
|
||||
shutdown_requested.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
assert!(matches!(
|
||||
stdin_stop_request(&shutdown_requested, &mailbox),
|
||||
Some(StdinStop::Interrupted)
|
||||
));
|
||||
}
|
||||
|
||||
fn status_with_targets(targets: &[TargetInstance]) -> ManagedStatus {
|
||||
ManagedStatus {
|
||||
lifecycle: ManagedLifecycle::Running,
|
||||
@@ -1209,18 +1189,6 @@ mod tests {
|
||||
assert!(finite_stats_memory_warning(&long_finite_args(), usize::MAX).is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lagged_events_are_counted_saturatingly() {
|
||||
let mut dropped = 0_u64;
|
||||
dropped = dropped.saturating_add(7);
|
||||
dropped = dropped.saturating_add(3);
|
||||
assert_eq!(dropped, 10);
|
||||
assert_eq!(u64::MAX.saturating_add(1), u64::MAX);
|
||||
assert!(dropped_event_warning(dropped)
|
||||
.unwrap()
|
||||
.contains("dropped 10 managed run events"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn target_failure_diagnostics_include_primary_and_cleanup_failures() {
|
||||
let target = ManagedTargetOutcome {
|
||||
|
||||
@@ -2,8 +2,6 @@ use std::time::Duration;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::shared::client::TimestampArg;
|
||||
use crate::shared::client::{
|
||||
parse_target, parse_test_duration, prepare_managed_run, CommonClientArgs, GroupPacingArg,
|
||||
ManagedRunSetup, TargetArg, TargetSelection,
|
||||
@@ -66,11 +64,6 @@ impl TuiArgs {
|
||||
pub fn is_continuous(&self) -> bool {
|
||||
self.duration == Duration::ZERO
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn timestamp_mode(&self) -> TimestampArg {
|
||||
self.common.tstamp
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for TuiArgs {
|
||||
@@ -156,35 +149,6 @@ mod tests {
|
||||
assert!(parse(&["ams=ams.example.com:2112"]).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duplicate_labels_are_rejected() {
|
||||
let args = parse(&["host-a:2112", "host-a:2112=host-b:2112"]).unwrap();
|
||||
let err = args.prepare().unwrap_err();
|
||||
|
||||
assert!(err.contains("duplicate target label"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duplicate_positional_target_strings_get_stable_suffixes() {
|
||||
let args = parse(&["host-a:2112", "host-a:2112"]).unwrap();
|
||||
let specs = args.prepare().unwrap().targets;
|
||||
|
||||
assert_eq!(specs[0].label, "host-a:2112");
|
||||
assert_eq!(specs[1].label, "host-a:2112#2");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duplicate_target_endpoints_are_allowed() {
|
||||
let args = parse(&["127.0.0.1:2112", "127.0.0.1"]).unwrap();
|
||||
assert_eq!(args.prepare().unwrap().target_count(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_labelled_target_syntax_is_rejected() {
|
||||
assert!(parse(&["=127.0.0.1:2112"]).unwrap().prepare().is_err());
|
||||
assert!(parse(&["label="]).unwrap().prepare().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn old_target_option_is_rejected() {
|
||||
assert!(parse(&["--target", "eu=host.example"]).is_err());
|
||||
@@ -270,14 +234,6 @@ mod tests {
|
||||
assert_eq!(shared.socket_config.ttl, tui.socket_config.ttl);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_empty_hmac_key_is_rejected_via_the_shared_args() {
|
||||
// CommonClientArgs is flattened into both the client and TUI parsers,
|
||||
// so proving rejection once here covers both without duplicating it.
|
||||
let err = parse(&["--hmac", "", "127.0.0.1:2112"]).unwrap_err();
|
||||
assert!(err.to_string().contains("HMAC key must not be empty"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tui_help_lists_multi_target_options() {
|
||||
let help = TuiArgs::command().render_help().to_string();
|
||||
|
||||
@@ -2057,19 +2057,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn graph_sample_with_timing(seq: u32, effective_ns: i128) -> GraphSample {
|
||||
GraphSample {
|
||||
timestamp: Instant::now() + Duration::from_secs(u64::from(seq)),
|
||||
seq,
|
||||
effective_ns,
|
||||
raw_ns: effective_ns + 1_000,
|
||||
adjusted_ns: Some(effective_ns + 500),
|
||||
client_to_server_ns: Some(effective_ns / 3),
|
||||
server_to_client_ns: Some(effective_ns / 2),
|
||||
server_processing_ns: Some(100_000),
|
||||
}
|
||||
}
|
||||
|
||||
fn series(data: Vec<(f64, f64)>) -> ChartSeries {
|
||||
ChartSeries {
|
||||
name: GraphMetric::EffectiveRtt.label().to_owned(),
|
||||
@@ -2131,18 +2118,6 @@ mod tests {
|
||||
assert_eq!(format_span(Duration::from_secs(90)), "1m30s");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn formats_signed_durations_and_missing_values() {
|
||||
assert_eq!(format_optional_ns_i128(Some(-1_500_000)), "-1.5ms");
|
||||
assert_eq!(format_optional_ns_i128(Some(750)), "750ns");
|
||||
assert_eq!(format_optional_ns_i128(None), "-");
|
||||
assert_eq!(format_optional_ns_i128(Some(1_500)), "1.5µs");
|
||||
assert_eq!(format_optional_span(None), "-");
|
||||
assert_eq!(format_duration(Duration::from_millis(25)), "25.0ms");
|
||||
assert_eq!(format_percent_ratio(1, 4), "25.00%");
|
||||
assert_eq!(format_optional_hex(Some(0x1f)), "0x1f");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn session_started_sets_remote_session_and_running_status() {
|
||||
let mut state = TuiState::default();
|
||||
@@ -2636,13 +2611,6 @@ mod tests {
|
||||
assert_eq!(state.recent_events.front().unwrap(), "event 5");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recent_event_visible_count_tracks_panel_inner_height() {
|
||||
assert_eq!(recent_events_visible_count(0), 0);
|
||||
assert_eq!(recent_events_visible_count(2), 0);
|
||||
assert_eq!(recent_events_visible_count(9), 7);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn visible_window_selects_samples_inside_viewport() {
|
||||
let history: VecDeque<_> = (0..300).map(|seq| graph_sample(seq, seq.into())).collect();
|
||||
@@ -2722,20 +2690,6 @@ mod tests {
|
||||
assert!(max_y > 12.0, "max_y={max_y}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn y_axis_tick_labels_use_label_count_minus_one_spacing() {
|
||||
let labels = y_axis_labels(-1.0, 1.0, 5);
|
||||
let rendered = labels
|
||||
.iter()
|
||||
.map(|span| span.content.as_ref())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(
|
||||
rendered,
|
||||
vec!["-1.00ms", "-500µs", "0.0µs", "500µs", "1.00ms"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn optional_missing_one_way_series_are_omitted_not_zero_filled() {
|
||||
let visible_samples = [graph_sample(1, 2_000_000)];
|
||||
@@ -2750,22 +2704,6 @@ mod tests {
|
||||
assert_eq!(rtt[0].name, "effective RTT");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn graph_metrics_use_readable_default_series() {
|
||||
let visible_samples = [graph_sample_with_timing(1, 3_000_000)];
|
||||
let visible: Vec<_> = visible_samples.iter().collect();
|
||||
let viewport = viewport_for_visible(&visible);
|
||||
|
||||
assert_eq!(
|
||||
graph_series(GraphMetric::EffectiveRtt, &visible, viewport)[0].data,
|
||||
vec![(0.0, 3.0)]
|
||||
);
|
||||
assert_eq!(
|
||||
graph_series(GraphMetric::ClientToServer, &visible, viewport)[0].data,
|
||||
vec![(0.0, 1.0)]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multi_target_metric_series_uses_selected_sample_field() {
|
||||
let mut target = TuiTargetState::new("alpha".to_owned(), stats_config(true));
|
||||
@@ -2848,43 +2786,6 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn graph_metric_cycling_walks_all_metrics() {
|
||||
let cases = [
|
||||
GraphMetric::EffectiveRtt,
|
||||
GraphMetric::RawRtt,
|
||||
GraphMetric::AdjustedRtt,
|
||||
GraphMetric::ClientToServer,
|
||||
GraphMetric::ServerToClient,
|
||||
GraphMetric::ServerProcessing,
|
||||
GraphMetric::EffectiveRtt,
|
||||
];
|
||||
let mut state = TuiState::default();
|
||||
for metric in cases {
|
||||
assert_eq!(state.graph_metric, metric);
|
||||
state.cycle_graph_metric();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn view_toggle_switches_between_graph_and_dashboard() {
|
||||
let mut state = TuiState::default();
|
||||
|
||||
assert_eq!(state.view, TuiView::Graph);
|
||||
state.toggle_view();
|
||||
assert_eq!(state.view, TuiView::Dashboard);
|
||||
state.toggle_view();
|
||||
assert_eq!(state.view, TuiView::Graph);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn target_label_span_uses_graph_series_style() {
|
||||
let span = target_label_span("alpha-target", 3, 16);
|
||||
|
||||
assert_eq!(span.style, target_style(3).add_modifier(Modifier::BOLD));
|
||||
assert_eq!(span.content.as_ref(), "alpha-target ");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pause_suppresses_scheduled_renders_but_allows_forced_controls() {
|
||||
let now = Instant::now();
|
||||
|
||||
Reference in new issue
Block a user