use turbocow::EcoString;
fn inline_str() -> EcoString {
EcoString::from("hello")
}
fn spilled_str() -> EcoString {
EcoString::from("hello world, long string here!")
}
#[test]
fn test_insert_at_start_inline() {
let mut s = inline_str();
s.insert(0, 'X');
assert_eq!(s, "Xhello");
}
#[test]
fn test_insert_at_middle_inline() {
let mut s = inline_str();
s.insert(2, 'X');
assert_eq!(s, "heXllo");
}
#[test]
fn test_insert_at_end_inline() {
let mut s = inline_str();
let len = s.len();
s.insert(len, '!');
assert_eq!(s, "hello!");
}
#[test]
fn test_insert_at_start_spilled() {
let mut s = spilled_str();
s.insert(0, 'X');
assert!(s.starts_with('X'));
}
#[test]
fn test_insert_at_middle_spilled() {
let mut s = spilled_str();
s.insert(5, '_');
assert_eq!(&s.as_str()[..6], "hello_");
}
#[test]
fn test_insert_at_end_spilled() {
let mut s = spilled_str();
let expected = s.as_str().to_owned() + "!";
let len = s.len();
s.insert(len, '!');
assert_eq!(s.as_str(), expected.as_str());
}
#[test]
fn test_insert_multibyte_char_inline() {
let mut s = EcoString::from("ab");
s.insert(1, '🌱');
assert_eq!(s, "a🌱b");
}
#[test]
fn test_insert_multibyte_char_spilled() {
let mut s = spilled_str();
let mid = 5; let prefix = s.as_str()[..mid].to_owned();
let suffix = s.as_str()[mid..].to_owned();
s.insert(mid, '🌱');
let expected = format!("{prefix}🌱{suffix}");
assert_eq!(s.as_str(), expected.as_str());
}
#[test]
fn test_insert_str_at_start_inline() {
let mut s = inline_str();
s.insert_str(0, ">>>");
assert_eq!(s, ">>>hello");
}
#[test]
fn test_insert_str_at_end_inline() {
let mut s = inline_str();
let len = s.len();
s.insert_str(len, "<<<");
assert_eq!(s, "hello<<<");
}
#[test]
fn test_insert_str_at_middle_spilled() {
let mut s = spilled_str();
let before = s.as_str()[..5].to_owned();
let after = s.as_str()[5..].to_owned();
s.insert_str(5, "[MID]");
let expected = format!("{before}[MID]{after}");
assert_eq!(s.as_str(), expected.as_str());
}
#[test]
#[should_panic]
fn test_insert_out_of_bounds() {
let mut s = inline_str();
s.insert(999, 'x');
}
#[test]
#[should_panic]
fn test_insert_non_char_boundary() {
let mut s = EcoString::from("🌱abc");
s.insert(1, 'x');
}
#[test]
fn test_remove_first_char_inline() {
let mut s = inline_str(); let c = s.remove(0);
assert_eq!(c, 'h');
assert_eq!(s, "ello");
}
#[test]
fn test_remove_middle_char_inline() {
let mut s = inline_str(); let c = s.remove(2);
assert_eq!(c, 'l');
assert_eq!(s, "helo");
}
#[test]
fn test_remove_last_char_inline() {
let mut s = inline_str(); let last_idx = s.len() - 'o'.len_utf8();
let c = s.remove(last_idx);
assert_eq!(c, 'o');
assert_eq!(s, "hell");
}
#[test]
fn test_remove_multibyte_char_inline() {
let mut s = EcoString::from("a🌱b");
let c = s.remove(1);
assert_eq!(c, '🌱');
assert_eq!(s, "ab");
}
#[test]
fn test_remove_first_char_spilled() {
let mut s = spilled_str();
let first_char = s.chars().next().unwrap();
let expected = s.as_str()[first_char.len_utf8()..].to_owned();
let c = s.remove(0);
assert_eq!(c, first_char);
assert_eq!(s.as_str(), expected.as_str());
}
#[test]
fn test_remove_last_char_spilled() {
let mut s = spilled_str();
let last_char = s.chars().next_back().unwrap();
let expected_len = s.len() - last_char.len_utf8();
let expected = s.as_str()[..expected_len].to_owned();
let idx = expected_len;
let c = s.remove(idx);
assert_eq!(c, last_char);
assert_eq!(s.as_str(), expected.as_str());
}
#[test]
#[should_panic]
fn test_remove_out_of_bounds() {
let mut s = inline_str();
s.remove(999);
}
#[test]
#[should_panic]
fn test_remove_non_char_boundary() {
let mut s = EcoString::from("🌱abc");
s.remove(1); }
#[test]
fn test_insert_cow_spilled() {
let original = spilled_str();
let mut cloned = original.clone();
cloned.insert(0, 'Z');
assert_eq!(original, spilled_str());
assert!(cloned.starts_with('Z'));
}
#[test]
fn test_remove_cow_spilled() {
let original = spilled_str();
let mut cloned = original.clone();
cloned.remove(0);
assert_eq!(original, spilled_str());
assert_ne!(cloned.as_str(), original.as_str());
}
#[test]
fn test_to_eco_string_int() {
use turbocow::ToEcoString;
assert_eq!(42i32.to_eco_string(), EcoString::from("42"));
}
#[test]
fn test_to_eco_string_str() {
use turbocow::ToEcoString;
assert_eq!("hello".to_eco_string(), EcoString::from("hello"));
}
#[test]
fn test_to_eco_string_via_crate_root() {
use turbocow::ToEcoString;
assert_eq!(2.5f64.to_eco_string(), EcoString::from("2.5"));
}
#[test]
fn test_eq_after_inline_truncate() {
let mut a = EcoString::from("abcde");
a.truncate(3);
assert_eq!(a.as_str(), "abc");
assert_eq!(a, EcoString::from("abc"));
assert_eq!(EcoString::from("abc"), a);
}
#[test]
fn test_eq_after_clear_and_rebuild() {
let mut a = EcoString::from("xxxxx");
a.clear();
a.push_str("ab");
assert_eq!(a, EcoString::from("ab"));
}
#[test]
fn test_eq_inline_vs_referenced() {
let inline = EcoString::from("hello");
let referenced = EcoString::from_static("hello");
assert_eq!(inline, referenced);
assert_eq!(referenced, inline);
}
#[test]
fn test_eq_hash_contract_after_truncate() {
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(EcoString::from("abc"));
let mut probe = EcoString::from("abcde");
probe.truncate(3);
assert!(
set.contains(&probe),
"a truncated \"abc\" must hash and compare equal to a freshly-built \"abc\""
);
}