diff options
author | Skyler Hawthorne | 2022-05-01 00:47:53 +0000 |
---|---|---|
committer | Skyler Hawthorne | 2022-06-19 03:54:03 +0000 |
commit | 40120967e9ba48d2e8b5fb4976a6ca1ce8993704 (patch) | |
tree | 784f59fed20a32e3e2d0417a16f9c7b7f9db2889 | |
parent | 07fc80aece221233b4a986b0c5a03e2056cc1307 (diff) |
tests for buffer-close
-rw-r--r-- | helix-term/tests/integration/commands.rs | 80 | ||||
-rw-r--r-- | helix-term/tests/integration/helpers.rs | 12 | ||||
-rw-r--r-- | helix-term/tests/integration/write.rs | 48 | ||||
-rw-r--r-- | helix-view/src/editor.rs | 9 |
4 files changed, 137 insertions, 12 deletions
diff --git a/helix-term/tests/integration/commands.rs b/helix-term/tests/integration/commands.rs index ec60ac96..7da180b9 100644 --- a/helix-term/tests/integration/commands.rs +++ b/helix-term/tests/integration/commands.rs @@ -1,3 +1,9 @@ +use std::{ + io::{Read, Write}, + ops::RangeInclusive, + time::Duration, +}; + use helix_core::diagnostic::Severity; use helix_term::application::Application; @@ -13,7 +19,7 @@ async fn test_write_quit_fail() -> anyhow::Result<()> { }, Config::default(), )?, - "ihello<esc>:wq<ret>", + Some("ihello<esc>:wq<ret>"), Some(&|app| { assert_eq!(&Severity::Error, app.editor.get_status().unwrap().1); }), @@ -23,3 +29,75 @@ async fn test_write_quit_fail() -> anyhow::Result<()> { Ok(()) } + +#[tokio::test] +async fn test_buffer_close() -> anyhow::Result<()> { + test_key_sequences( + &mut Application::new(Args::default(), Config::default())?, + vec![ + ( + None, + Some(&|app| { + assert_eq!(1, app.editor.documents().count()); + assert!(!app.editor.is_err()); + }), + ), + ( + Some("ihello<esc>:new<ret>"), + Some(&|app| { + assert_eq!(2, app.editor.documents().count()); + assert!(!app.editor.is_err()); + }), + ), + ( + Some(":buffer<minus>close<ret>"), + Some(&|app| { + assert_eq!(1, app.editor.documents().count()); + assert!(!app.editor.is_err()); + }), + ), + ], + None, + ) + .await?; + + // verify if writes are queued up, it finishes them before closing the buffer + let mut file = tempfile::NamedTempFile::new().unwrap(); + let mut command = String::new(); + const RANGE: RangeInclusive<i32> = 1..=10; + + for i in RANGE { + let cmd = format!("%c{}<esc>:w<ret>", i); + command.push_str(&cmd); + } + + command.push_str(":buffer<minus>close<ret>"); + + test_key_sequence( + &mut Application::new( + Args { + files: vec![(file.path().to_path_buf(), Position::default())], + ..Default::default() + }, + Config::default(), + )?, + Some(&command), + Some(&|app| { + assert!(!app.editor.is_err(), "error: {:?}", app.editor.get_status()); + + let doc = app.editor.document_by_path(file.path()); + assert!(doc.is_none(), "found doc: {:?}", doc); + }), + Some(Duration::from_millis(5000)), + ) + .await?; + + file.as_file_mut().flush()?; + file.as_file_mut().sync_all()?; + + let mut file_content = String::new(); + file.as_file_mut().read_to_string(&mut file_content)?; + assert_eq!(RANGE.end().to_string(), file_content); + + Ok(()) +} diff --git a/helix-term/tests/integration/helpers.rs b/helix-term/tests/integration/helpers.rs index 60bfa331..18a3517c 100644 --- a/helix-term/tests/integration/helpers.rs +++ b/helix-term/tests/integration/helpers.rs @@ -34,7 +34,7 @@ impl<S: Into<String>> From<(S, S, S)> for TestCase { #[inline] pub async fn test_key_sequence( app: &mut Application, - in_keys: &str, + in_keys: Option<&str>, test_fn: Option<&dyn Fn(&Application)>, timeout: Option<Duration>, ) -> anyhow::Result<()> { @@ -43,7 +43,7 @@ pub async fn test_key_sequence( pub async fn test_key_sequences( app: &mut Application, - inputs: Vec<(&str, Option<&dyn Fn(&Application)>)>, + inputs: Vec<(Option<&str>, Option<&dyn Fn(&Application)>)>, timeout: Option<Duration>, ) -> anyhow::Result<()> { let timeout = timeout.unwrap_or(Duration::from_millis(500)); @@ -51,8 +51,10 @@ pub async fn test_key_sequences( let mut rx_stream = UnboundedReceiverStream::new(rx); for (in_keys, test_fn) in inputs { - for key_event in parse_macro(&in_keys)?.into_iter() { - tx.send(Ok(Event::Key(KeyEvent::from(key_event))))?; + if let Some(in_keys) = in_keys { + for key_event in parse_macro(&in_keys)?.into_iter() { + tx.send(Ok(Event::Key(KeyEvent::from(key_event))))?; + } } let event_loop = app.event_loop(&mut rx_stream); @@ -100,7 +102,7 @@ pub async fn test_key_sequence_with_input_text<T: Into<TestCase>>( view.id, ); - test_key_sequence(&mut app, &test_case.in_keys, Some(test_fn), timeout).await + test_key_sequence(&mut app, Some(&test_case.in_keys), Some(test_fn), timeout).await } /// Use this for very simple test cases where there is one input diff --git a/helix-term/tests/integration/write.rs b/helix-term/tests/integration/write.rs index 27f97a45..365e6b8d 100644 --- a/helix-term/tests/integration/write.rs +++ b/helix-term/tests/integration/write.rs @@ -1,5 +1,6 @@ use std::{ io::{Read, Write}, + ops::RangeInclusive, time::Duration, }; @@ -21,7 +22,7 @@ async fn test_write() -> anyhow::Result<()> { }, Config::default(), )?, - "ii can eat glass, it will not hurt me<ret><esc>:w<ret>", + Some("ii can eat glass, it will not hurt me<ret><esc>:w<ret>"), None, Some(Duration::from_millis(1000)), ) @@ -38,6 +39,41 @@ async fn test_write() -> anyhow::Result<()> { } #[tokio::test] +async fn test_write_concurrent() -> anyhow::Result<()> { + let mut file = tempfile::NamedTempFile::new().unwrap(); + let mut command = String::new(); + const RANGE: RangeInclusive<i32> = 1..=5000; + + for i in RANGE { + let cmd = format!("%c{}<esc>:w<ret>", i); + command.push_str(&cmd); + } + + test_key_sequence( + &mut Application::new( + Args { + files: vec![(file.path().to_path_buf(), Position::default())], + ..Default::default() + }, + Config::default(), + )?, + Some(&command), + None, + Some(Duration::from_millis(10000)), + ) + .await?; + + file.as_file_mut().flush()?; + file.as_file_mut().sync_all()?; + + let mut file_content = String::new(); + file.as_file_mut().read_to_string(&mut file_content)?; + assert_eq!(RANGE.end().to_string(), file_content); + + Ok(()) +} + +#[tokio::test] async fn test_write_fail_mod_flag() -> anyhow::Result<()> { test_key_sequences( &mut Application::new( @@ -49,21 +85,21 @@ async fn test_write_fail_mod_flag() -> anyhow::Result<()> { )?, vec![ ( - "", + None, Some(&|app| { let doc = doc!(app.editor); assert!(!doc.is_modified()); }), ), ( - "ihello<esc>", + Some("ihello<esc>"), Some(&|app| { let doc = doc!(app.editor); assert!(doc.is_modified()); }), ), ( - ":w<ret>", + Some(":w<ret>"), Some(&|app| { assert_eq!(&Severity::Error, app.editor.get_status().unwrap().1); @@ -86,7 +122,7 @@ async fn test_write_fail_new_path() -> anyhow::Result<()> { &mut Application::new(Args::default(), Config::default())?, vec![ ( - "", + None, Some(&|app| { let doc = doc!(app.editor); assert_eq!(None, app.editor.get_status()); @@ -94,7 +130,7 @@ async fn test_write_fail_new_path() -> anyhow::Result<()> { }), ), ( - ":w /foo<ret>", + Some(":w /foo<ret>"), Some(&|app| { let doc = doc!(app.editor); assert_eq!(&Severity::Error, app.editor.get_status().unwrap().1); diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index d828f9ec..e8603221 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -576,6 +576,15 @@ impl Editor { self.status_msg.as_ref().map(|(status, sev)| (status, sev)) } + /// Returns true if the current status is an error + #[inline] + pub fn is_err(&self) -> bool { + self.status_msg + .as_ref() + .map(|(_, sev)| *sev == Severity::Error) + .unwrap_or(false) + } + pub fn set_theme(&mut self, theme: Theme) { // `ui.selection` is the only scope required to be able to render a theme. if theme.find_scope_index("ui.selection").is_none() { |