Fix timestamp formats conflict
This commit is contained in:
@@ -9,6 +9,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::thread;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use crossterm::event::KeyCode;
|
||||
use wireguard_admin::app::{FirstIssueAttempt, RestartChoice, RestartStage};
|
||||
use wireguard_admin::backup::BackupReason;
|
||||
use wireguard_admin::config::{ResolvedSettings, SettingsFile};
|
||||
@@ -19,6 +20,7 @@ use wireguard_admin::tui::events::{
|
||||
ApplicationWorker, CommandResult, FirstIssueStatus, QrStatus, SecretText, SensitiveCommand,
|
||||
ShutdownProgress, StatisticsReader, UiCommand, WorkerConfig, WorkerEvent,
|
||||
};
|
||||
use wireguard_admin::tui::forms::{FormAction, FormController};
|
||||
use wireguard_admin::vault::WireGuardPrivateKey;
|
||||
|
||||
const SETTINGS: &str = r#"
|
||||
@@ -528,6 +530,110 @@ fn worker_setup_create_commit_and_delivery_keep_saved_and_runtime_boundaries() {
|
||||
finish(worker);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_form_submits_automatic_dual_stack_client_without_changing_saved_state() {
|
||||
let fixture = fixture();
|
||||
let reader = CountingStatistics::default();
|
||||
let reads = Arc::clone(&reader.0);
|
||||
let mut worker = worker(&fixture, reader);
|
||||
|
||||
let setup = worker
|
||||
.submit_sensitive(SensitiveCommand::PrepareInitialSetup(SecretText::new(
|
||||
"synthetic vault password".to_owned(),
|
||||
)))
|
||||
.expect("setup submitted");
|
||||
assert!(matches!(
|
||||
wait_for(&mut worker, setup.request_id),
|
||||
WorkerEvent::OperationFinished {
|
||||
result: Ok(CommandResult::InitialSetupPrepared(_)),
|
||||
..
|
||||
}
|
||||
));
|
||||
let saved_before_create = fixture.store.read_saved().expect("saved state reads");
|
||||
|
||||
let mut form = FormController::default();
|
||||
form.open_create();
|
||||
for character in "form-created device".chars() {
|
||||
assert!(matches!(
|
||||
form.handle_key(KeyCode::Char(character)),
|
||||
FormAction::None
|
||||
));
|
||||
}
|
||||
assert!(matches!(form.handle_key(KeyCode::Enter), FormAction::None));
|
||||
assert!(matches!(form.handle_key(KeyCode::Enter), FormAction::None));
|
||||
let FormAction::Submit(command @ UiCommand::CreateClient { .. }) =
|
||||
form.handle_key(KeyCode::Enter)
|
||||
else {
|
||||
panic!("blank address fields submit an automatically addressed client");
|
||||
};
|
||||
let UiCommand::CreateClient {
|
||||
alias,
|
||||
manual_addresses,
|
||||
created_utc,
|
||||
} = &command
|
||||
else {
|
||||
unreachable!();
|
||||
};
|
||||
assert_eq!(alias, "form-created device");
|
||||
assert!(manual_addresses.is_none());
|
||||
let timestamp = created_utc.as_deref().expect("form includes creation time");
|
||||
assert!(wireguard_admin::wireguard::metadata::render_block(alias, Some(timestamp)).is_ok());
|
||||
|
||||
let operation = worker.submit(command).expect("form command accepted");
|
||||
let (identity, view) = match wait_for(&mut worker, operation.request_id) {
|
||||
WorkerEvent::OperationFinished { result, view, .. } => {
|
||||
let CommandResult::ClientCreated(identity) = result.expect("create succeeds") else {
|
||||
panic!("create returns client identity");
|
||||
};
|
||||
(identity, view)
|
||||
}
|
||||
_ => unreachable!("wait_for returns the requested completion"),
|
||||
};
|
||||
let row = view
|
||||
.client_states
|
||||
.get(&identity)
|
||||
.expect("created client appears in draft projection");
|
||||
assert!(
|
||||
row.saved.is_none(),
|
||||
"client remains absent from saved state"
|
||||
);
|
||||
let draft = row.draft.as_ref().expect("created client is in draft");
|
||||
assert_eq!(draft.alias, "form-created device");
|
||||
assert_eq!(
|
||||
draft.addresses.ipv4,
|
||||
"10.20.0.2".parse::<std::net::Ipv4Addr>().unwrap()
|
||||
);
|
||||
let ipv6_range = "fd20::/64".parse::<ipnet::Ipv6Net>().unwrap();
|
||||
assert!(
|
||||
draft
|
||||
.addresses
|
||||
.ipv6
|
||||
.is_some_and(|address| ipv6_range.contains(&address)),
|
||||
"automatic allocation includes an address from the configured IPv6 range"
|
||||
);
|
||||
let saved_after_create = fixture
|
||||
.store
|
||||
.read_saved()
|
||||
.expect("saved state remains readable");
|
||||
assert_eq!(saved_after_create.settings, saved_before_create.settings);
|
||||
assert_eq!(
|
||||
saved_after_create.server_config,
|
||||
saved_before_create.server_config
|
||||
);
|
||||
assert_eq!(
|
||||
saved_after_create.internal_state,
|
||||
saved_before_create.internal_state
|
||||
);
|
||||
assert_eq!(saved_after_create.vault, saved_before_create.vault);
|
||||
assert_eq!(
|
||||
reads.load(Ordering::SeqCst),
|
||||
0,
|
||||
"no runtime restart/read occurs"
|
||||
);
|
||||
|
||||
finish(worker);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn worker_backup_restore_preview_cancel_and_confirm_are_separate_saved_operations() {
|
||||
let fixture = fixture();
|
||||
|
||||
Reference in New Issue
Block a user