diff --git a/Cargo.lock b/Cargo.lock index c2eaad3..8f10e85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3291,9 +3291,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4378ea89513870b6e2303ec50618e97da0fa43cdd9ded83ad3b6bad2693c08c6" +checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" [[package]] name = "ryu" diff --git a/src/constants.rs b/src/constants.rs index a4e0404..f28a082 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -310,7 +310,7 @@ mod test { } #[test] - fn git_commit_is_41_chars() { - assert_eq!(crate::COMMIT.len(), 41); + fn git_commit_eq_or_gt_40_chars() { + assert!(crate::COMMIT.len() >= 40); } } diff --git a/src/disk.rs b/src/disk.rs index a115128..b4c6299 100644 --- a/src/disk.rs +++ b/src/disk.rs @@ -248,7 +248,7 @@ impl State { // leaving behind old keys+values and updating [default] with old valid ones. pub fn merge(old: &str) -> Result { let default = toml::ser::to_string(&Self::new()).unwrap(); - let new: Self = match Figment::from(Toml::string(&default)).merge(Toml::string(&old)).extract() { + let new: Self = match Figment::from(Toml::string(&default)).merge(Toml::string(old)).extract() { Ok(new) => { info!("State | TOML merge ... OK"); new }, Err(err) => { error!("State | Couldn't merge default + old TOML"); return Err(TomlError::Merge(err)) }, }; @@ -696,7 +696,7 @@ impl Default for P2pool { } impl Xmrig { fn with_threads(max_threads: usize, current_threads: usize) -> Self { - let mut xmrig = Self::default(); + let xmrig = Self::default(); Self { max_threads, current_threads, diff --git a/src/helper.rs b/src/helper.rs index 4484948..623dafd 100644 --- a/src/helper.rs +++ b/src/helper.rs @@ -1116,7 +1116,7 @@ impl Helper { // Code taken from [https://docs.rs/humantime/] and edited to remove sub-second time, change spacing and some words. use std::time::Duration; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct HumanTime(Duration); impl Default for HumanTime { @@ -1186,7 +1186,7 @@ impl std::fmt::Display for HumanTime { // Percent | [0.001] -> [0%] | Rounds down, removes redundant zeros // Hashrate | [123.0, 311.2, null] -> [123, 311, ???] | Casts, replaces null with [???] // CPU Load | [12.0, 11.4, null] -> [12.0, 11.4, ???] | No change, just into [String] form -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct HumanNumber(String); impl std::fmt::Display for HumanNumber { @@ -1216,11 +1216,6 @@ impl HumanNumber { buf.write_formatted(&(f as u128), &LOCALE); Self(buf.as_str().to_string()) } - fn from_u8(u: u8) -> Self { - let mut buf = num_format::Buffer::new(); - buf.write_formatted(&u, &LOCALE); - Self(buf.as_str().to_string()) - } fn from_u16(u: u16) -> Self { let mut buf = num_format::Buffer::new(); buf.write_formatted(&u, &LOCALE); @@ -1272,7 +1267,7 @@ impl HumanNumber { let mut n = 0; for i in array { match i { - Some(f) => string.push_str(format!("{}", f).as_str()), + Some(f) => string.push_str(format!("{:.2}", f).as_str()), None => string.push_str("???"), } if n != 2 { @@ -1336,6 +1331,12 @@ pub struct ImgP2pool { pub log_level: String, // What log level? } +impl Default for ImgP2pool { + fn default() -> Self { + Self::new() + } +} + impl ImgP2pool { pub fn new() -> Self { Self { @@ -1554,6 +1555,12 @@ pub struct ImgXmrig { pub url: String, } +impl Default for ImgXmrig { + fn default() -> Self { + Self::new() + } +} + impl ImgXmrig { pub fn new() -> Self { Self { @@ -1717,6 +1724,90 @@ impl Hashrate { //---------------------------------------------------------------------------------------------------- TESTS #[cfg(test)] mod test { + #[test] + fn human_number() { + use crate::HumanNumber; + assert!(HumanNumber::to_percent(0.001).to_string() == "0%"); + assert!(HumanNumber::to_percent(12.123123123123).to_string() == "12.12%"); + assert!(HumanNumber::from_hashrate([Some(123.1), Some(11111.1), None]).to_string() == "[123 H/s, 11,111 H/s, ??? H/s]"); + assert!(HumanNumber::from_hashrate([None, Some(1.123), Some(123123.312)]).to_string() == "[??? H/s, 1 H/s, 123,123 H/s]"); + assert!(HumanNumber::from_load([Some(123.1234), Some(321.321), None]).to_string() == "[123.12, 321.32, ???]"); + assert!(HumanNumber::from_load([None, Some(4321.43), Some(1234.1)]).to_string() == "[???, 4321.43, 1234.10]"); + assert!(HumanNumber::from_f32(123_123.123123123).to_string() == "123,123"); + assert!(HumanNumber::from_f64(123_123_123.123123123123123).to_string() == "123,123,123"); + assert!(HumanNumber::from_u16(1_000).to_string() == "1,000"); + assert!(HumanNumber::from_u16(65_535).to_string() == "65,535"); + assert!(HumanNumber::from_u32(65_536).to_string() == "65,536"); + assert!(HumanNumber::from_u32(100_000).to_string() == "100,000"); + assert!(HumanNumber::from_u32(1_000_000).to_string() == "1,000,000"); + assert!(HumanNumber::from_u32(10_000_000).to_string() == "10,000,000"); + assert!(HumanNumber::from_u32(100_000_000).to_string() == "100,000,000"); + assert!(HumanNumber::from_u32(1_000_000_000).to_string() == "1,000,000,000"); + assert!(HumanNumber::from_u32(4_294_967_295).to_string() == "4,294,967,295"); + assert!(HumanNumber::from_u64(4_294_967_296).to_string() == "4,294,967,296"); + assert!(HumanNumber::from_u64(10_000_000_000).to_string() == "10,000,000,000"); + assert!(HumanNumber::from_u64(100_000_000_000).to_string() == "100,000,000,000"); + assert!(HumanNumber::from_u64(1_000_000_000_000).to_string() == "1,000,000,000,000"); + assert!(HumanNumber::from_u64(10_000_000_000_000).to_string() == "10,000,000,000,000"); + assert!(HumanNumber::from_u64(100_000_000_000_000).to_string() == "100,000,000,000,000"); + assert!(HumanNumber::from_u64(1_000_000_000_000_000).to_string() == "1,000,000,000,000,000"); + assert!(HumanNumber::from_u64(10_000_000_000_000_000).to_string() == "10,000,000,000,000,000"); + assert!(HumanNumber::from_u64(18_446_744_073_709_551_615).to_string() == "18,446,744,073,709,551,615"); + assert!(HumanNumber::from_u128(18_446_744_073_709_551_616).to_string() == "18,446,744,073,709,551,616"); + assert!(HumanNumber::from_u128(100_000_000_000_000_000_000).to_string() == "100,000,000,000,000,000,000"); + assert_eq!( + HumanNumber::from_u128(340_282_366_920_938_463_463_374_607_431_768_211_455).to_string(), + "340,282,366,920,938,463,463,374,607,431,768,211,455", + ); + } + + #[test] + fn human_time() { + use crate::HumanTime; + use std::time::Duration; + assert!(HumanTime::into_human(Duration::from_secs(0)).to_string() == "0 seconds"); + assert!(HumanTime::into_human(Duration::from_secs(1)).to_string() == "1 second"); + assert!(HumanTime::into_human(Duration::from_secs(2)).to_string() == "2 seconds"); + assert!(HumanTime::into_human(Duration::from_secs(59)).to_string() == "59 seconds"); + assert!(HumanTime::into_human(Duration::from_secs(60)).to_string() == "1 minute"); + assert!(HumanTime::into_human(Duration::from_secs(61)).to_string() == "1 minute, 1 second"); + assert!(HumanTime::into_human(Duration::from_secs(62)).to_string() == "1 minute, 2 seconds"); + assert!(HumanTime::into_human(Duration::from_secs(120)).to_string() == "2 minutes"); + assert!(HumanTime::into_human(Duration::from_secs(121)).to_string() == "2 minutes, 1 second"); + assert!(HumanTime::into_human(Duration::from_secs(122)).to_string() == "2 minutes, 2 seconds"); + assert!(HumanTime::into_human(Duration::from_secs(179)).to_string() == "2 minutes, 59 seconds"); + assert!(HumanTime::into_human(Duration::from_secs(3599)).to_string() == "59 minutes, 59 seconds"); + assert!(HumanTime::into_human(Duration::from_secs(3600)).to_string() == "1 hour"); + assert!(HumanTime::into_human(Duration::from_secs(3601)).to_string() == "1 hour, 1 second"); + assert!(HumanTime::into_human(Duration::from_secs(3602)).to_string() == "1 hour, 2 seconds"); + assert!(HumanTime::into_human(Duration::from_secs(3660)).to_string() == "1 hour, 1 minute"); + assert!(HumanTime::into_human(Duration::from_secs(3720)).to_string() == "1 hour, 2 minutes"); + assert!(HumanTime::into_human(Duration::from_secs(86399)).to_string() == "23 hours, 59 minutes, 59 seconds"); + assert!(HumanTime::into_human(Duration::from_secs(86400)).to_string() == "1 day"); + assert!(HumanTime::into_human(Duration::from_secs(86401)).to_string() == "1 day, 1 second"); + assert!(HumanTime::into_human(Duration::from_secs(86402)).to_string() == "1 day, 2 seconds"); + assert!(HumanTime::into_human(Duration::from_secs(86460)).to_string() == "1 day, 1 minute"); + assert!(HumanTime::into_human(Duration::from_secs(86520)).to_string() == "1 day, 2 minutes"); + assert!(HumanTime::into_human(Duration::from_secs(90000)).to_string() == "1 day, 1 hour"); + assert!(HumanTime::into_human(Duration::from_secs(93600)).to_string() == "1 day, 2 hours"); + assert!(HumanTime::into_human(Duration::from_secs(604799)).to_string() == "6 days, 23 hours, 59 minutes, 59 seconds"); + assert!(HumanTime::into_human(Duration::from_secs(604800)).to_string() == "7 days"); + assert!(HumanTime::into_human(Duration::from_secs(2630016)).to_string() == "1 month"); + assert!(HumanTime::into_human(Duration::from_secs(3234815)).to_string() == "1 month, 6 days, 23 hours, 59 minutes, 59 seconds"); + assert!(HumanTime::into_human(Duration::from_secs(5260032)).to_string() == "2 months"); + assert!(HumanTime::into_human(Duration::from_secs(31557600)).to_string() == "1 year"); + assert!(HumanTime::into_human(Duration::from_secs(63115200)).to_string() == "2 years"); + assert_eq!( + HumanTime::into_human(Duration::from_secs(18446744073709551615)).to_string(), + "584542046090 years, 7 months, 15 days, 17 hours, 5 minutes, 3 seconds", + ); + } + + #[test] + fn build_p2pool_regex() { + crate::helper::P2poolRegex::new(); + } + #[test] fn calc_payouts_and_xmr_from_output_p2pool() { use crate::helper::{PubP2poolApi,P2poolRegex}; diff --git a/src/main.rs b/src/main.rs index 9937cc2..12deba5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1222,7 +1222,7 @@ impl eframe::App for App { let color = if hide { BLACK } else { BRIGHT_YELLOW }; if ui.add_sized([box_width, height], Button::new(RichText::new("👁").color(color))).on_hover_text(PASSWORD_HIDE).clicked() { sudo.hide = !sudo.hide; } }); - if (key.is_esc() && !sudo.testing) || ui.add_sized([width, height*4.0], Button::new("Leave")).clicked() { self.error_state.reset(); }; + if (key.is_esc() && !sudo.testing) || ui.add_sized([width, height*4.0], Button::new("Leave")).on_hover_text(PASSWORD_LEAVE).clicked() { self.error_state.reset(); }; // If [test_sudo()] finished, reset error state. if sudo.success { self.error_state.reset(); @@ -1571,7 +1571,21 @@ mod test { #[test] fn build_regex() { - crate::Regexes::new(); + use regex::Regex; + let r = crate::Regexes::new(); + assert!(Regex::is_match(&r.name, "_this_ is... a n-a-m-e.")); + assert!(Regex::is_match(&r.address, "44hintoFpuo3ugKfcqJvh5BmrsTRpnTasJmetKC4VXCt6QDtbHVuixdTtsm6Ptp7Y8haXnJ6j8Gj2dra8CKy5ewz7Vi9CYW")); + assert!(Regex::is_match(&r.ipv4, "192.168.1.2")); + assert!(Regex::is_match(&r.ipv4, "127.0.0.1")); + assert!(Regex::is_match(&r.domain, "my.node.com")); + assert!(Regex::is_match(&r.domain, "my.monero-node123.net")); + assert!(Regex::is_match(&r.domain, "www.my-node.org")); + assert!(Regex::is_match(&r.domain, "www.my-monero-node123.io")); + for i in 1..=65535 { + assert!(Regex::is_match(&r.port, &i.to_string())); + } + assert!(!Regex::is_match(&r.port, "0")); + assert!(!Regex::is_match(&r.port, "65536")); } #[test] diff --git a/src/update.rs b/src/update.rs index 1e84423..98fd544 100644 --- a/src/update.rs +++ b/src/update.rs @@ -412,7 +412,7 @@ impl Update { *update.lock().unwrap().prog.lock().unwrap() = 5.0; // Create Tor/HTTPS client - let mut lock = update.lock().unwrap(); + let lock = update.lock().unwrap(); let tor = lock.tor; if tor { let msg = MSG_TOR.to_string();