@@ -1,5 +1,5 @@
11use std::{
2− io::{Read, Seek, SeekFrom, Write},
2+ io::{Read, Seek, Write},
33 ops::RangeInclusive,
44};
55
@@ -8,6 +8,96 @@ use helix_view::doc;
88
99use super::*;
1010
11+#[tokio::test(flavor = "multi_thread")]
12+async fn test_write_quit_fail() -> anyhow::Result<()> {
13+ let file = helpers::new_readonly_tempfile()?;
14+ let mut app = helpers::AppBuilder::new()
15+ .with_file(file.path(), None)
16+ .build()?;
17+
18+ test_key_sequence(
19+ &mut app,
20+ Some("ihello<esc>:wq<ret>"),
21+ Some(&|app| {
22+ let mut docs: Vec<_> = app.editor.documents().collect();
23+ assert_eq!(1, docs.len());
24+
25+ let doc = docs.pop().unwrap();
26+ assert_eq!(Some(file.path()), doc.path().map(PathBuf::as_path));
27+ assert_eq!(&Severity::Error, app.editor.get_status().unwrap().1);
28+ }),
29+ false,
30+ )
31+ .await?;
32+
33+ Ok(())
34+}
35+
36+#[tokio::test(flavor = "multi_thread")]
37+async fn test_buffer_close_concurrent() -> anyhow::Result<()> {
38+ test_key_sequences(
39+ &mut helpers::AppBuilder::new().build()?,
40+ vec![
41+ (
42+ None,
43+ Some(&|app| {
44+ assert_eq!(1, app.editor.documents().count());
45+ assert!(!app.editor.is_err());
46+ }),
47+ ),
48+ (
49+ Some("ihello<esc>:new<ret>"),
50+ Some(&|app| {
51+ assert_eq!(2, app.editor.documents().count());
52+ assert!(!app.editor.is_err());
53+ }),
54+ ),
55+ (
56+ Some(":buffer<minus>close<ret>"),
57+ Some(&|app| {
58+ assert_eq!(1, app.editor.documents().count());
59+ assert!(!app.editor.is_err());
60+ }),
61+ ),
62+ ],
63+ false,
64+ )
65+ .await?;
66+
67+ // verify if writes are queued up, it finishes them before closing the buffer
68+ let mut file = tempfile::NamedTempFile::new()?;
69+ let mut command = String::new();
70+ const RANGE: RangeInclusive<i32> = 1..=1000;
71+
72+ for i in RANGE {
73+ let cmd = format!("%c{}<esc>:w!<ret>", i);
74+ command.push_str(&cmd);
75+ }
76+
77+ command.push_str(":buffer<minus>close<ret>");
78+
79+ let mut app = helpers::AppBuilder::new()
80+ .with_file(file.path(), None)
81+ .build()?;
82+
83+ test_key_sequence(
84+ &mut app,
85+ Some(&command),
86+ Some(&|app| {
87+ assert!(!app.editor.is_err(), "error: {:?}", app.editor.get_status());
88+
89+ let doc = app.editor.document_by_path(file.path());
90+ assert!(doc.is_none(), "found doc: {:?}", doc);
91+ }),
92+ false,
93+ )
94+ .await?;
95+
96+ helpers::assert_file_has_content(file.as_file_mut(), &RANGE.end().to_string())?;
97+
98+ Ok(())
99+}
100+
11101#[tokio::test(flavor = "multi_thread")]
12102async fn test_write() -> anyhow::Result<()> {
13103 let mut file = tempfile::NamedTempFile::new()?;
@@ -57,7 +147,7 @@ async fn test_overwrite_protection() -> anyhow::Result<()> {
57147 file.as_file_mut().flush()?;
58148 file.as_file_mut().sync_all()?;
59149
60− file.seek(SeekFrom::Start(0))?;
150+ file.rewind()?;
61151 let mut file_content = String::new();
62152 file.as_file_mut().read_to_string(&mut file_content)?;
63153