From 1d98d3e4c1d490e727af14867a42979b14e42160 Mon Sep 17 00:00:00 2001 From: Christian Schwarz Date: Mon, 25 Sep 2023 19:16:36 +0200 Subject: [PATCH] VirtualFile::atomic_overwrite: add basic unit tests (#5191) Should have added them in the initial PR #5186. Would have been nice to test the failure cases as well, but, without mocking the FS, that's too hard / platform-dependent. --- pageserver/src/virtual_file.rs | 56 ++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/pageserver/src/virtual_file.rs b/pageserver/src/virtual_file.rs index 9612b8ec6d..dfb8d397b4 100644 --- a/pageserver/src/virtual_file.rs +++ b/pageserver/src/virtual_file.rs @@ -650,6 +650,12 @@ mod tests { File(File), } + impl From for MaybeVirtualFile { + fn from(vf: VirtualFile) -> Self { + MaybeVirtualFile::VirtualFile(vf) + } + } + impl MaybeVirtualFile { async fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> Result<(), Error> { match self { @@ -887,4 +893,54 @@ mod tests { Ok(()) } + + #[tokio::test] + async fn test_atomic_overwrite_basic() { + let testdir = crate::config::PageServerConf::test_repo_dir("test_atomic_overwrite_basic"); + std::fs::create_dir_all(&testdir).unwrap(); + + let path = testdir.join("myfile"); + let tmp_path = testdir.join("myfile.tmp"); + + VirtualFile::crashsafe_overwrite(&path, &tmp_path, b"foo") + .await + .unwrap(); + let mut file = MaybeVirtualFile::from(VirtualFile::open(&path).await.unwrap()); + let post = file.read_string().await.unwrap(); + assert_eq!(post, "foo"); + assert!(!tmp_path.exists()); + drop(file); + + VirtualFile::crashsafe_overwrite(&path, &tmp_path, b"bar") + .await + .unwrap(); + let mut file = MaybeVirtualFile::from(VirtualFile::open(&path).await.unwrap()); + let post = file.read_string().await.unwrap(); + assert_eq!(post, "bar"); + assert!(!tmp_path.exists()); + drop(file); + } + + #[tokio::test] + async fn test_atomic_overwrite_preexisting_tmp() { + let testdir = + crate::config::PageServerConf::test_repo_dir("test_atomic_overwrite_preexisting_tmp"); + std::fs::create_dir_all(&testdir).unwrap(); + + let path = testdir.join("myfile"); + let tmp_path = testdir.join("myfile.tmp"); + + std::fs::write(&tmp_path, "some preexisting junk that should be removed").unwrap(); + assert!(tmp_path.exists()); + + VirtualFile::crashsafe_overwrite(&path, &tmp_path, b"foo") + .await + .unwrap(); + + let mut file = MaybeVirtualFile::from(VirtualFile::open(&path).await.unwrap()); + let post = file.read_string().await.unwrap(); + assert_eq!(post, "foo"); + assert!(!tmp_path.exists()); + drop(file); + } }