Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests support control chars widths 0 or 1 #789

Merged
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ jobs:
- name: Run tests
run: >
cargo test --features "toml markdown ansi termion-backend crossterm-backend" --no-default-features --verbose &&
cargo test --example select_test -- --nocapture
cargo test --example select_test
4 changes: 2 additions & 2 deletions cursive-core/src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,12 +193,12 @@ impl PrintBuffer {
let width = g.width();
if width == 0 {
// Any zero-width grapheme can be ignored.
// With unicode_segmentation < 0.1.13, this includes control chars.
// With unicode-width < 0.1.13, this includes control chars.
continue;
}

if is_control_char(g) {
// With unicode_segmentation >= 0.1.13, control chars have non-zero width (in
// With unicode-width >= 0.1.13, control chars have non-zero width (in
// practice width = 1).
debug_assert_eq!(
1, width,
Expand Down
9 changes: 4 additions & 5 deletions cursive-core/src/utils/lines/spans/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ fn test_replacement_char_has_width_1() {
}

#[test]
fn test_control_chars_have_width_1() {
fn test_control_chars_have_width_0_or_1() {
use unicode_width::UnicodeWidthStr;
let control_chars = [
"\u{0000}", "\u{0001}", "\u{0002}", "\u{0003}", "\u{0004}", "\u{0005}", "\u{0006}",
Expand All @@ -52,10 +52,9 @@ fn test_control_chars_have_width_1() {
"it's supposed to be a string of 1 char"
);
let unicode_escape = format!("\\u{{{:04X}}}", c.chars().last().unwrap() as u32);
assert_eq!(
width, 1,
"Width of control character {} is not 1",
unicode_escape
assert!(
(0..=1).contains(&width),
"Width of control character {unicode_escape} is not 0 or 1, it's {width}"
);
}
}
Expand Down
160 changes: 103 additions & 57 deletions cursive/examples/select_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ pub mod tests {
select.add_item_str("8A\u{008A}\u{008B}\u{008C}\u{008D}\u{008E}\u{008F}\u{0090}\u{0091}\u{0092}\u{0093}thru93");
select.add_item_str("94\u{0094}\u{0095}\u{0096}\u{0097}\u{0098}\u{0099}\u{009A}\u{009B}\u{009C}\u{009D}thru9D");
select.add_item_str("9E\u{009E}\u{009F}thru9F");
//XXX: can't add more lines here, it would cause them to go off view thus fail the is-it-on-screen tests, unless the dialog is made bigger below!

// Sets the callback for when "Enter" is pressed.
select.set_on_submit(show_next_window);
Expand Down Expand Up @@ -125,68 +126,113 @@ pub mod tests {
}

#[test]
fn nuls_become_replacement_char() {
let mut s = BasicSetup::new();
s.hit_keystroke(Key::End);
let screen = s.last_screen().unwrap();
s.dump_debug();
assert_eq!(
screen
.find_occurences("short \u{fffd}nul\u{FFFD} 1str")
.len(),
1,
"nuls aka \\0 in strings are supposed to become the replacement char '\u{fffd}'"
);
}
#[test]
fn control_chars_become_replacement_char() {
fn control_chars_including_nul_when_on_screen() {
let mut s = BasicSetup::new();
s.hit_keystroke(Key::End);
let screen = s.last_screen().unwrap();
s.dump_debug();
let replacement_char = "\u{FFFD} aka \\u{FFFD}";
assert_eq!(
screen.find_occurences("tab�and�newline").len(),
1,
"tabs and newline should've been replaced with replacement char {}",
replacement_char
);
assert_eq!(
screen.find_occurences("b�����������thru15").len(),
1,
"control chars \\x0B thru \\x15 should've been replaced with the replacement char {}",
replacement_char
);
assert_eq!(
screen.find_occurences("16����������thru1F").len(),
1,
"control chars \\x16 thru \\x1F should've been replaced with the replacement char {}",
replacement_char
);
assert_eq!(
screen.find_occurences("7F�only").len(),
1,
"control char \\x7F should've been replaced with the replacement char {}",
replacement_char
);
assert_eq!(
screen.find_occurences("80����������thru89").len(),
1,
"control chars \\x80 thru \\x89 should've been replaced with the replacement char {}",
replacement_char
);
assert_eq!(
screen.find_occurences("8A����������thru93").len(),
1,
"control chars \\x8A thru \\x93 should've been replaced with the replacement char {}",
replacement_char
);
assert_eq!(
screen.find_occurences("9E��thru9F").len(),
1,
"control chars \\x9E thru \\x9F should've been replaced with the replacement char {}",
replacement_char
);
use unicode_width::UnicodeWidthStr;
let width_of_nul = "\0".width();
if !(0..=1).contains(&width_of_nul) {
panic!(
"nul aka \\0 has a width of '{width_of_nul}' instead of the expected one of 0 or 1"
);
}
//we assume that all other control chars have same width as nul for chosing
//which test to perform on them which depends on which unicode-width crate
//version was used: the <=0.1.12 (width==0) or >=0.1.13 (width==1)
//for width==0 we expect control chars to have been deleted from on-screen output
//for width==1 we expect they were replaced with the width 1 replacement char: �
if width_of_nul == 1 {
// unicode-width version =1.1.13 or maybe later too
assert_eq!(
screen
.find_occurences("short \u{fffd}nul\u{FFFD} 1str")
.len(),
1,
"nuls aka \\0 in strings are supposed to become the replacement char '\u{fffd}'"
);
assert_eq!(
screen.find_occurences("tab�and�newline").len(),
1,
"tabs and newline should've been replaced with replacement char {replacement_char}"
);
assert_eq!(
screen.find_occurences("b�����������thru15").len(),
1,
"control chars \\x0B thru \\x15 should've been replaced with the replacement char {replacement_char}",
);
assert_eq!(
screen.find_occurences("16����������thru1F").len(),
1,
"control chars \\x16 thru \\x1F should've been replaced with the replacement char {replacement_char}",
);
assert_eq!(
screen.find_occurences("7F�only").len(),
1,
"control char \\x7F should've been replaced with the replacement char {replacement_char}",
);
assert_eq!(
screen.find_occurences("80����������thru89").len(),
1,
"control chars \\x80 thru \\x89 should've been replaced with the replacement char {replacement_char}",
);
assert_eq!(
screen.find_occurences("8A����������thru93").len(),
1,
"control chars \\x8A thru \\x93 should've been replaced with the replacement char {replacement_char}",
);
assert_eq!(
screen.find_occurences("9E��thru9F").len(),
1,
"control chars \\x9E thru \\x9F should've been replaced with the replacement char {replacement_char}",
);
} else if width_of_nul == 0 {
// unicode-width version <=1.1.12
assert_eq!(
screen.find_occurences("short nul 1str").len(),
1,
"nuls aka \\0 in strings are supposed to deleted from output"
);
assert_eq!(
screen.find_occurences("tabandnewline").len(),
1,
"tabs and newline should've been deleted from output"
);
assert_eq!(
screen.find_occurences("bthru15").len(),
1,
"control chars \\x0B thru \\x15 should've been deleted from output"
);
assert_eq!(
screen.find_occurences("16thru1F").len(),
1,
"control chars \\x16 thru \\x1F should've been deleted from output"
);
assert_eq!(
screen.find_occurences("7Fonly").len(),
1,
"control char \\x7F should've been deleted from output"
);
assert_eq!(
screen.find_occurences("80thru89").len(),
1,
"control chars \\x80 thru \\x89 should've been deleted from output"
);
assert_eq!(
screen.find_occurences("8Athru93").len(),
1,
"control chars \\x8A thru \\x93 should've been deleted from output"
);
assert_eq!(
screen.find_occurences("9Ethru9F").len(),
1,
"control chars \\x9E thru \\x9F should've been deleted from output"
);
} else {
unreachable!();
}
}

#[test]
Expand Down