Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions relay/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,14 @@ impl State {
}

pub fn validate_tcp_addr(address: &str) -> Result<()> {
let _parsed = address
.trim()
let trimmed = address.trim();
// An empty field is its own mistake. Reporting it as "invalid" reads as
// though something was typed wrong, when the greyed 127.0.0.1:9999 is
// placeholder text and nothing was typed at all.
if trimmed.is_empty() {
bail!("No address entered. Type one, for example 127.0.0.1:9999");
}
let _parsed = trimmed
.parse::<SocketAddr>()
.map_err(|_| anyhow!("Invalid IP address. Use format: 127.0.0.1:9999"))?;
Ok(())
Expand Down
53 changes: 52 additions & 1 deletion relay/src/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ fn connect_tcp_with_validation_and_save(state: &mut State, address: String) {
}
}
Err(e) => {
state.tcp_addr_validation_error = Some(e.to_string());
let msg = e.to_string();
// Record it like every other connection failure. This path returns
// before tcp_connect, so without this the event log never hears that
// the press did anything, and the inline hint under the field is easy
// to miss.
state.log_event(format!("TCP connect failed: {}", msg));
state.tcp_addr_validation_error = Some(msg);
}
}
}
Expand Down Expand Up @@ -426,6 +432,51 @@ mod tests {
let _ = state.tcp_disconnect();
}

#[test]
fn empty_address_is_reported_in_the_event_log() {
let mut state = State::default();
assert!(state.tcp_addr_field.is_empty(), "field should start empty");

let _ = update(&mut state, Message::ConnectTcp);

// The inline hint alone is easy to miss, so the panel has to show it too.
assert!(
state
.event_log
.iter()
.any(|e| e.contains("TCP connect failed") && e.contains("No address entered")),
"empty address missing from the event log: {:?}",
state.event_log
);
// An empty field is not the same mistake as a typo.
let inline = state
.tcp_addr_validation_error
.clone()
.expect("no inline validation error");
assert!(inline.starts_with("No address entered"), "unexpected: {inline}");
assert!(state.tcp_thread_handle.is_none(), "should not have connected");
}

#[test]
fn malformed_address_is_reported_in_the_event_log() {
let mut state = State::default();
// Deliberately not a host name: #240 may start accepting those, and this
// test is about reporting, not about which forms are valid.
state.tcp_addr_field = "127.0.0.1".to_string();

let _ = update(&mut state, Message::ConnectTcp);

assert!(
state
.event_log
.iter()
.any(|e| e.contains("TCP connect failed") && e.contains("Invalid IP address")),
"malformed address missing from the event log: {:?}",
state.event_log
);
assert!(state.tcp_thread_handle.is_none(), "should not have connected");
}

#[test]
fn send_packet_with_every_toggle_off_reports_an_error() {
let mut state = State::default();
Expand Down
Loading