Fix bug on multiple simultaneous input + tests

This commit is contained in:
Condorra 2024-09-13 21:11:20 +10:00
parent 494f89daef
commit 0c8c6d4f0c
5 changed files with 87 additions and 237 deletions

View File

@ -418,82 +418,3 @@ impl_display!(for Show);
impl_display!(for EnableBlinking); impl_display!(for EnableBlinking);
impl_display!(for DisableBlinking); impl_display!(for DisableBlinking);
impl_display!(for SetCursorStyle); impl_display!(for SetCursorStyle);
#[cfg(test)]
#[cfg(feature = "events")]
mod tests {
use std::io::{self, stdout};
use crate::execute;
use super::{
sys::position, MoveDown, MoveLeft, MoveRight, MoveTo, MoveUp, RestorePosition, SavePosition,
};
// Test is disabled, because it's failing on Travis
#[test]
#[ignore]
fn test_move_to() {
let (saved_x, saved_y) = position().unwrap();
execute!(stdout(), MoveTo(saved_x + 1, saved_y + 1)).unwrap();
assert_eq!(position().unwrap(), (saved_x + 1, saved_y + 1));
execute!(stdout(), MoveTo(saved_x, saved_y)).unwrap();
assert_eq!(position().unwrap(), (saved_x, saved_y));
}
// Test is disabled, because it's failing on Travis
#[test]
#[ignore]
fn test_move_right() {
let (saved_x, saved_y) = position().unwrap();
execute!(io::stdout(), MoveRight(1)).unwrap();
assert_eq!(position().unwrap(), (saved_x + 1, saved_y));
}
// Test is disabled, because it's failing on Travis
#[test]
#[ignore]
fn test_move_left() {
execute!(stdout(), MoveTo(2, 0), MoveLeft(2)).unwrap();
assert_eq!(position().unwrap(), (0, 0));
}
// Test is disabled, because it's failing on Travis
#[test]
#[ignore]
fn test_move_up() {
execute!(stdout(), MoveTo(0, 2), MoveUp(2)).unwrap();
assert_eq!(position().unwrap(), (0, 0));
}
// Test is disabled, because it's failing on Travis
#[test]
#[ignore]
fn test_move_down() {
execute!(stdout(), MoveTo(0, 0), MoveDown(2)).unwrap();
assert_eq!(position().unwrap(), (0, 2));
}
// Test is disabled, because it's failing on Travis
#[test]
#[ignore]
fn test_save_restore_position() {
let (saved_x, saved_y) = position().unwrap();
execute!(
stdout(),
SavePosition,
MoveTo(saved_x + 1, saved_y + 1),
RestorePosition
)
.unwrap();
let (x, y) = position().unwrap();
assert_eq!(x, saved_x);
assert_eq!(y, saved_y);
}
}

View File

@ -928,6 +928,41 @@ impl Display for KeyCode {
} }
} }
pub struct TerminalState {
char_buffer: VecDeque<u8>,
}
impl TerminalState {
pub fn new() -> Self {
Self {
char_buffer: VecDeque::<u8>::new(),
}
}
pub fn events_for_input(&mut self, input: &[u8]) -> std::io::Result<Vec<Event>> {
let mut result: Vec<Event> = Vec::new();
self.char_buffer.extend(input);
let mut buf: Vec<u8> = Vec::new();
loop {
match self.char_buffer.pop_front() {
None => return Ok(result),
Some(c) => {
buf.push(c);
match parse_event(&buf, true)? {
None => continue,
Some(e) => {
result.push(e);
buf.clear();
}
}
}
}
}
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::collections::hash_map::DefaultHasher; use std::collections::hash_map::DefaultHasher;
@ -1035,36 +1070,51 @@ mod tests {
assert_eq!(format!("{}", Modifier(RightAlt)), "Right Alt"); assert_eq!(format!("{}", Modifier(RightAlt)), "Right Alt");
assert_eq!(format!("{}", Modifier(RightSuper)), "Right Super"); assert_eq!(format!("{}", Modifier(RightSuper)), "Right Super");
} }
}
pub struct TerminalState { #[test]
char_buffer: VecDeque<u8>, pub fn terminalstate_event_parser_works() {
} let mut ts = TerminalState::new();
use KeyEventKind::*;
impl TerminalState { assert_eq!(
pub fn new() -> Self { ts.events_for_input(b"Hello\n").unwrap(),
Self { vec![
char_buffer: VecDeque::<u8>::new(), Event::Key(KeyEvent {
} code: Char('H'),
} modifiers: KeyModifiers::SHIFT,
kind: Press,
pub fn events_for_input(&mut self, input: &[u8]) -> std::io::Result<Vec<Event>> { state: KeyEventState::NONE
let mut result: Vec<Event> = Vec::new(); }),
Event::Key(KeyEvent {
self.char_buffer.extend(input); code: Char('e'),
let mut buf: Vec<u8> = Vec::new(); modifiers: KeyModifiers::NONE,
kind: Press,
loop { state: KeyEventState::NONE
match self.char_buffer.pop_front() { }),
None => return Ok(result), Event::Key(KeyEvent {
Some(c) => { code: Char('l'),
buf.push(c); modifiers: KeyModifiers::NONE,
match parse_event(&buf, true)? { kind: Press,
None => continue, state: KeyEventState::NONE
Some(e) => result.push(e), }),
} Event::Key(KeyEvent {
} code: Char('l'),
} modifiers: KeyModifiers::NONE,
} kind: Press,
state: KeyEventState::NONE
}),
Event::Key(KeyEvent {
code: Char('o'),
modifiers: KeyModifiers::NONE,
kind: Press,
state: KeyEventState::NONE
}),
Event::Key(KeyEvent {
code: Char('j'),
modifiers: KeyModifiers::CONTROL,
kind: Press,
state: KeyEventState::NONE
})
]
);
} }
} }

View File

@ -52,19 +52,19 @@ impl Filter for EventFilter {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{ use super::{
super::Event, CursorPositionFilter, Event, EventFilter, Filter, InternalEventFilter, super::Event, CursorPositionFilter, EventFilter, Filter, KeyboardEnhancementFlagsFilter,
KeyboardEnhancementFlagsFilter, PrimaryDeviceAttributesFilter, PrimaryDeviceAttributesFilter,
}; };
#[test] #[test]
fn test_cursor_position_filter_filters_cursor_position() { fn test_cursor_position_filter_filters_cursor_position() {
assert!(!CursorPositionFilter.eval(&Event::Event(Event::Resize(10, 10)))); assert!(!CursorPositionFilter.eval(&Event::Resize(10, 10)));
assert!(CursorPositionFilter.eval(&Event::CursorPosition(0, 0))); assert!(CursorPositionFilter.eval(&Event::CursorPosition(0, 0)));
} }
#[test] #[test]
fn test_keyboard_enhancement_status_filter_filters_keyboard_enhancement_status() { fn test_keyboard_enhancement_status_filter_filters_keyboard_enhancement_status() {
assert!(!KeyboardEnhancementFlagsFilter.eval(&Event::Event(Event::Resize(10, 10)))); assert!(!KeyboardEnhancementFlagsFilter.eval(&Event::Resize(10, 10)));
assert!( assert!(
KeyboardEnhancementFlagsFilter.eval(&Event::KeyboardEnhancementFlags( KeyboardEnhancementFlagsFilter.eval(&Event::KeyboardEnhancementFlags(
crate::event::KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES crate::event::KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES
@ -75,19 +75,13 @@ mod tests {
#[test] #[test]
fn test_primary_device_attributes_filter_filters_primary_device_attributes() { fn test_primary_device_attributes_filter_filters_primary_device_attributes() {
assert!(!PrimaryDeviceAttributesFilter.eval(&Event::Event(Event::Resize(10, 10)))); assert!(!PrimaryDeviceAttributesFilter.eval(&Event::Resize(10, 10)));
assert!(PrimaryDeviceAttributesFilter.eval(&Event::PrimaryDeviceAttributes)); assert!(PrimaryDeviceAttributesFilter.eval(&Event::PrimaryDeviceAttributes));
} }
#[test] #[test]
fn test_event_filter_filters_events() { fn test_event_filter_filters_events() {
assert!(EventFilter.eval(&Event::Event(Event::Resize(10, 10)))); assert!(EventFilter.eval(&Event::Resize(10, 10)));
assert!(!EventFilter.eval(&Event::CursorPosition(0, 0))); assert!(EventFilter.eval(&Event::CursorPosition(0, 0)));
}
#[test]
fn test_event_filter_filters_internal_events() {
assert!(InternalEventFilter.eval(&Event::Event(Event::Resize(10, 10))));
assert!(InternalEventFilter.eval(&Event::CursorPosition(0, 0)));
} }
} }

View File

@ -125,49 +125,6 @@ impl fmt::Display for Colored {
mod tests { mod tests {
use crate::style::{Color, Colored}; use crate::style::{Color, Colored};
fn check_format_color(colored: Colored, expected: &str) {
Colored::set_ansi_color_disabled(true);
assert_eq!(colored.to_string(), "");
Colored::set_ansi_color_disabled(false);
assert_eq!(colored.to_string(), expected);
}
#[test]
fn test_format_fg_color() {
let colored = Colored::ForegroundColor(Color::Red);
check_format_color(colored, "38;5;9");
}
#[test]
fn test_format_bg_color() {
let colored = Colored::BackgroundColor(Color::Red);
check_format_color(colored, "48;5;9");
}
#[test]
fn test_format_reset_fg_color() {
let colored = Colored::ForegroundColor(Color::Reset);
check_format_color(colored, "39");
}
#[test]
fn test_format_reset_bg_color() {
let colored = Colored::BackgroundColor(Color::Reset);
check_format_color(colored, "49");
}
#[test]
fn test_format_fg_rgb_color() {
let colored = Colored::BackgroundColor(Color::Rgb { r: 1, g: 2, b: 3 });
check_format_color(colored, "48;2;1;2;3");
}
#[test]
fn test_format_fg_ansi_color() {
let colored = Colored::ForegroundColor(Color::AnsiValue(255));
check_format_color(colored, "38;5;255");
}
#[test] #[test]
fn test_parse_ansi_fg() { fn test_parse_ansi_fg() {
test_parse_ansi(Colored::ForegroundColor) test_parse_ansi(Colored::ForegroundColor)
@ -274,16 +231,4 @@ mod tests {
test("48;2;0;2;25;"); test("48;2;0;2;25;");
test("48;2;0;2;25;3"); test("48;2;0;2;25;3");
} }
#[test]
fn test_no_color() {
std::env::set_var("NO_COLOR", "1");
assert!(Colored::ansi_color_disabled());
std::env::set_var("NO_COLOR", "XXX");
assert!(Colored::ansi_color_disabled());
std::env::set_var("NO_COLOR", "");
assert!(!Colored::ansi_color_disabled());
std::env::remove_var("NO_COLOR");
assert!(!Colored::ansi_color_disabled());
}
} }

View File

@ -405,63 +405,3 @@ impl_display!(for ScrollUp);
impl_display!(for ScrollDown); impl_display!(for ScrollDown);
impl_display!(for SetSize); impl_display!(for SetSize);
impl_display!(for Clear); impl_display!(for Clear);
#[cfg(test)]
mod tests {
use std::{io::stdout, thread, time};
use crate::execute;
use super::*;
// Test is disabled, because it's failing on Travis CI
#[test]
#[ignore]
fn test_resize_ansi() {
let (width, height) = size().unwrap();
execute!(stdout(), SetSize(35, 35)).unwrap();
// see issue: https://github.com/eminence/terminal-size/issues/11
thread::sleep(time::Duration::from_millis(30));
assert_eq!((35, 35), size().unwrap());
// reset to previous size
execute!(stdout(), SetSize(width, height)).unwrap();
// see issue: https://github.com/eminence/terminal-size/issues/11
thread::sleep(time::Duration::from_millis(30));
assert_eq!((width, height), size().unwrap());
}
#[test]
fn test_raw_mode() {
// check we start from normal mode (may fail on some test harnesses)
assert!(!is_raw_mode_enabled().unwrap());
// enable the raw mode
if enable_raw_mode().is_err() {
// Enabling raw mode doesn't work on the ci
// So we just ignore it
return;
}
// check it worked (on unix it doesn't really check the underlying
// tty but rather check that the code is consistent)
assert!(is_raw_mode_enabled().unwrap());
// enable it again, this should not change anything
enable_raw_mode().unwrap();
// check we're still in raw mode
assert!(is_raw_mode_enabled().unwrap());
// now let's disable it
disable_raw_mode().unwrap();
// check we're back to normal mode
assert!(!is_raw_mode_enabled().unwrap());
}
}