mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-07 12:13:19 +00:00
Remove temporary test files after failures
This commit is contained in:
Generated
+2
@@ -6100,6 +6100,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"smithay-clipboard",
|
||||
"socket2",
|
||||
"tempfile",
|
||||
"vectorcraft-engine",
|
||||
"vectorcraft-render",
|
||||
"vectorcraft-text",
|
||||
@@ -6163,6 +6164,7 @@ dependencies = [
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-text",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"vectorcraft-color",
|
||||
"vectorcraft-doc",
|
||||
"vectorcraft-engine",
|
||||
|
||||
@@ -45,5 +45,6 @@ objc2-core-foundation = { version = "0.3", default-features = false, features =
|
||||
objc2-core-text = { version = "0.3", default-features = false, features = ["std", "CTFontManager"] }
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3"
|
||||
vectorcraft-testkit = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
@@ -119,6 +119,7 @@ zbus = "=5.19.0"
|
||||
winresource = "0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3"
|
||||
# Bound socket buffers in real loopback transport deadline regressions.
|
||||
socket2 = { workspace = true }
|
||||
# src/portal_save.rs's tests build and read the portal's D-Bus values on every system.
|
||||
|
||||
@@ -978,10 +978,17 @@ mod tests {
|
||||
|
||||
use super::*;
|
||||
|
||||
fn dir(name: &str) -> PathBuf {
|
||||
let d = std::env::temp_dir().join(format!("vectorcraft-clipboard-{name}-{}", std::process::id()));
|
||||
std::fs::create_dir_all(&d).unwrap();
|
||||
d
|
||||
fn dir(name: &str) -> tempfile::TempDir {
|
||||
tempfile::Builder::new().prefix(&format!("vectorcraft-clipboard-{name}-")).tempdir().unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_directory_is_removed_when_its_handle_is_dropped() {
|
||||
let dir = dir("cleanup");
|
||||
let path = dir.path().to_path_buf();
|
||||
assert!(path.exists());
|
||||
drop(dir);
|
||||
assert!(!path.exists());
|
||||
}
|
||||
|
||||
fn png(w: u32, h: u32) -> Vec<u8> {
|
||||
@@ -993,12 +1000,12 @@ mod tests {
|
||||
#[test]
|
||||
fn the_first_copied_file_that_is_art_pastes() {
|
||||
let d = dir("art");
|
||||
let (notes, red, art) = (d.join("notes.txt"), d.join("red image.png"), d.join("art.svg"));
|
||||
let (notes, red, art) = (d.path().join("notes.txt"), d.path().join("red image.png"), d.path().join("art.svg"));
|
||||
std::fs::write(¬es, "not art").unwrap();
|
||||
std::fs::write(&red, png(3, 2)).unwrap();
|
||||
std::fs::write(&art, "<svg xmlns=\"http://www.w3.org/2000/svg\"/>").unwrap();
|
||||
// Missing files, folders and text are skipped.
|
||||
let f = copied_file(vec![d.join("gone.png"), d.clone(), notes.clone(), red.clone(), art.clone()], &PASTE_ORDER).unwrap();
|
||||
let f = copied_file(vec![d.path().join("gone.png"), d.path().to_path_buf(), notes.clone(), red.clone(), art.clone()], &PASTE_ORDER).unwrap();
|
||||
assert_eq!((f.mime, f.data), (PNG, png(3, 2)));
|
||||
assert_eq!(copied_file(vec![art.clone(), red.clone()], &PASTE_ORDER).map(|f| f.mime), Some(SVG));
|
||||
// Only what Paste asks for.
|
||||
@@ -1032,7 +1039,8 @@ mod tests {
|
||||
/// An .eps file copied in a file manager pastes as EPS.
|
||||
#[test]
|
||||
fn a_copied_eps_file_pastes() {
|
||||
let eps = dir("eps").join("equation.eps");
|
||||
let d = dir("eps");
|
||||
let eps = d.path().join("equation.eps");
|
||||
std::fs::write(&eps, "%!PS-Adobe-3.0 EPSF-3.0\n%%BoundingBox: 0 0 10 10\n0 0 10 10 rectfill\n").unwrap();
|
||||
assert_eq!(copied_file(vec![eps.clone()], &PASTE_ORDER).map(|f| f.mime), Some(EPS));
|
||||
assert!(copied_file(vec![eps], &[BITMAP, TEXT]).is_none());
|
||||
@@ -1040,7 +1048,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn a_crlf_left_by_the_uri_list_is_ignored() {
|
||||
let red = dir("crlf").join("red.png");
|
||||
let d = dir("crlf");
|
||||
let red = d.path().join("red.png");
|
||||
std::fs::write(&red, png(2, 2)).unwrap();
|
||||
let with_cr = PathBuf::from(format!("{}\r", red.display()));
|
||||
assert_eq!(copied_file(vec![with_cr], &PASTE_ORDER).map(|f| f.mime), Some(PNG));
|
||||
|
||||
@@ -150,18 +150,16 @@ mod tests {
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn the_gpu_behind_a_device_number_comes_from_sysfs() -> std::io::Result<()> {
|
||||
let dir = std::env::temp_dir().join(format!("vectorcraft-dev-char-{}", std::process::id()));
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
let dir = tempfile::Builder::new().prefix("vectorcraft-dev-char-").tempdir()?;
|
||||
// /sys/dev/char/226:128 links to the render node, whose `device` is the PCI GPU.
|
||||
std::fs::create_dir_all(dir.join("226:128/device"))?;
|
||||
std::fs::write(dir.join("226:128/device/vendor"), "0x10de\n")?;
|
||||
std::fs::write(dir.join("226:128/device/device"), "0x25ac\n")?;
|
||||
std::fs::create_dir_all(dir.path().join("226:128/device"))?;
|
||||
std::fs::write(dir.path().join("226:128/device/vendor"), "0x10de\n")?;
|
||||
std::fs::write(dir.path().join("226:128/device/device"), "0x25ac\n")?;
|
||||
// A device that isn't a PCI GPU (a virtual one) has no ids.
|
||||
std::fs::create_dir_all(dir.join("226:0/device"))?;
|
||||
let render = super::pci_ids(&dir, makedev(226, 128));
|
||||
let virtual_gpu = super::pci_ids(&dir, makedev(226, 0));
|
||||
let missing = super::pci_ids(&dir, makedev(226, 1));
|
||||
std::fs::remove_dir_all(&dir)?;
|
||||
std::fs::create_dir_all(dir.path().join("226:0/device"))?;
|
||||
let render = super::pci_ids(dir.path(), makedev(226, 128));
|
||||
let virtual_gpu = super::pci_ids(dir.path(), makedev(226, 0));
|
||||
let missing = super::pci_ids(dir.path(), makedev(226, 1));
|
||||
assert_eq!(render, Some((0x10de, 0x25ac)));
|
||||
assert_eq!(virtual_gpu, None);
|
||||
assert_eq!(missing, None);
|
||||
|
||||
@@ -242,8 +242,8 @@ fn internal_panels_are_edp_lvds_and_dsi_connectors() {
|
||||
/// PCI ids. Each GPU is listed once, the one with the panel as primary.
|
||||
#[test]
|
||||
fn linux_display_gpus_come_from_the_connected_connectors() -> std::io::Result<()> {
|
||||
let dir = std::env::temp_dir().join(format!("vectorcraft-drm-{}", std::process::id()));
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
let temp = tempfile::Builder::new().prefix("vectorcraft-drm-").tempdir()?;
|
||||
let dir = temp.path();
|
||||
let card = |name: &str, (vendor, device): (u32, u32)| -> std::io::Result<()> {
|
||||
std::fs::create_dir_all(dir.join(name).join("device"))?;
|
||||
std::fs::write(dir.join(name).join("device/vendor"), format!("{vendor:#06x}\n"))?;
|
||||
@@ -262,11 +262,11 @@ fn linux_display_gpus_come_from_the_connected_connectors() -> std::io::Result<()
|
||||
connector("card1-DP-2", "connected")?;
|
||||
connector("card2-Virtual-1", "connected")?;
|
||||
std::fs::write(dir.join("renderD128"), "")?;
|
||||
let mut gpus = linux_display_gpus(&dir);
|
||||
let mut gpus = linux_display_gpus(dir);
|
||||
gpus.sort_by_key(|g| g.pci);
|
||||
assert_eq!(gpus, [primary(AMD_IGPU), monitor(NVIDIA_3090)]);
|
||||
assert!(linux_display_gpus(&dir.join("no such dir")).is_empty());
|
||||
std::fs::remove_dir_all(&dir)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -616,11 +616,26 @@ fn a_normal_exit_or_another_failure_does_not_restart() {
|
||||
/// A log folder of its own for each test, and the guard that keeps other tests from starting a
|
||||
/// program while it runs: the test releases the start file's lock and takes it again, and a child
|
||||
/// starting meanwhile would keep it held (`crate::no_spawns`).
|
||||
fn start_dir(tag: &str) -> (std::path::PathBuf, std::sync::RwLockReadGuard<'static, ()>) {
|
||||
struct TestDir(tempfile::TempDir);
|
||||
|
||||
impl std::ops::Deref for TestDir {
|
||||
type Target = std::path::Path;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.0.path()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<std::path::Path> for TestDir {
|
||||
fn as_ref(&self) -> &std::path::Path {
|
||||
self.0.path()
|
||||
}
|
||||
}
|
||||
|
||||
fn start_dir(tag: &str) -> (TestDir, std::sync::RwLockReadGuard<'static, ()>) {
|
||||
let spawns = crate::no_spawns();
|
||||
let d = std::env::temp_dir().join(format!("vectorcraft-gpu-start-{tag}-{}", std::process::id()));
|
||||
let _ = std::fs::remove_dir_all(&d);
|
||||
(d, spawns)
|
||||
let dir = tempfile::Builder::new().prefix(&format!("vectorcraft-gpu-start-{tag}-")).tempdir().unwrap();
|
||||
(TestDir(dir), spawns)
|
||||
}
|
||||
|
||||
/// What a start in `dir` leaves out; it then ends without crashing.
|
||||
@@ -670,7 +685,6 @@ fn a_start_that_never_showed_a_frame_leaves_its_adapter_out_of_the_next() {
|
||||
assert_eq!(left_out.adapters, ["Dx12:8086:3184"], "kept");
|
||||
assert_eq!(left_out.crash, None, "the note is shown once");
|
||||
third.ended();
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
/// A start whose first frame reached the screen, or that ended without crashing (a normal exit,
|
||||
@@ -693,7 +707,6 @@ fn a_start_that_showed_its_first_frame_or_ended_is_cleared() {
|
||||
assert!(finish(Ok(Ok(())), &first).is_ok());
|
||||
drop(first);
|
||||
assert_eq!(next_start(&dir, false), LeftOut::default());
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
/// The process ended while the adapters were being listed (wgpu's DX12 backend creates a
|
||||
@@ -721,7 +734,6 @@ fn a_crash_while_listing_lists_opengl_alone() {
|
||||
second.none_left();
|
||||
second.ended();
|
||||
assert_eq!(next_start(&dir, false), LeftOut::default());
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
/// `WGPU_BACKEND` or `WGPU_ADAPTER_NAME` choose for a start whatever crashed before; when that
|
||||
@@ -742,7 +754,6 @@ fn wgpu_backend_or_adapter_name_ignores_the_crashes() {
|
||||
explicit.picked(&c[0].key, &c[0].name, true);
|
||||
explicit.presented();
|
||||
assert_eq!(next_start(&dir, false), LeftOut::default(), "a new driver shows the window");
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
/// A damaged record, a file that can't be opened and one another starting copy of the app holds
|
||||
@@ -777,10 +788,9 @@ fn a_damaged_or_unreadable_start_file_is_ignored() {
|
||||
assert_eq!(next_start(&dir, false).adapters, ["Dx12:8086:3184"]);
|
||||
|
||||
// A folder in the file's place.
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
std::fs::remove_file(dir.join(START_FILE)).unwrap();
|
||||
std::fs::create_dir_all(dir.join(START_FILE)).unwrap();
|
||||
assert_eq!(next_start(&dir, false), LeftOut::default());
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -214,22 +214,9 @@ fn read_file_head(path: &str, max: usize) -> Result<Vec<u8>, String> {
|
||||
#[test]
|
||||
fn read_file_head_reads_no_more_than_it_is_asked_for() {
|
||||
use std::io::Write as _;
|
||||
/// Removes the file when the test ends, a failed assertion included.
|
||||
struct Remove(std::path::PathBuf);
|
||||
impl Drop for Remove {
|
||||
fn drop(&mut self) {
|
||||
let _ = std::fs::remove_file(&self.0);
|
||||
}
|
||||
}
|
||||
let path = std::env::temp_dir().join(format!("vectorcraft-read-head-{}", std::process::id()));
|
||||
// A leftover file or link at the path is removed (never followed), and the new file is created
|
||||
// exclusively.
|
||||
let _ = std::fs::remove_file(&path);
|
||||
let mut f = std::fs::OpenOptions::new().write(true).create_new(true).open(&path).unwrap();
|
||||
let guard = Remove(path);
|
||||
let mut f = tempfile::Builder::new().prefix("vectorcraft-read-head-").tempfile().unwrap();
|
||||
f.write_all(b"0123456789").unwrap();
|
||||
drop(f);
|
||||
let p = guard.0.to_string_lossy();
|
||||
let p = f.path().to_string_lossy();
|
||||
assert_eq!(read_file_head(&p, 4).unwrap(), b"0123");
|
||||
assert_eq!(read_file_head(&p, 20).unwrap(), b"0123456789", "a shorter file is read whole");
|
||||
assert!(read_file_head(&std::env::temp_dir().to_string_lossy(), 4).is_err(), "a folder is not read");
|
||||
@@ -608,22 +595,20 @@ mod open_with_tests {
|
||||
use super::{check_app, find_photocraft, photocraft_candidates, registered_path, windows_candidates};
|
||||
|
||||
/// A fresh, empty folder under the system's temporary folder.
|
||||
fn scratch(name: &str) -> std::path::PathBuf {
|
||||
let d = std::env::temp_dir().join(format!("vc-open-with-{name}-{}", std::process::id()));
|
||||
let _ = std::fs::remove_dir_all(&d);
|
||||
std::fs::create_dir_all(&d).unwrap();
|
||||
d
|
||||
fn scratch(name: &str) -> tempfile::TempDir {
|
||||
tempfile::Builder::new().prefix(&format!("vc-open-with-{name}-")).tempdir().unwrap()
|
||||
}
|
||||
|
||||
/// #5236: only an application counts as PhotoCraft, never a document, a folder or a missing
|
||||
/// path.
|
||||
#[test]
|
||||
fn only_applications_are_started() {
|
||||
let d = scratch("check");
|
||||
let temp = scratch("check");
|
||||
let d = temp.path();
|
||||
let doc = d.join("notes.txt");
|
||||
std::fs::write(&doc, "hi").unwrap();
|
||||
assert!(check_app(&doc).is_err(), "a document");
|
||||
assert!(check_app(&d).is_err(), "a folder");
|
||||
assert!(check_app(d).is_err(), "a folder");
|
||||
assert!(check_app(&d.join("Missing.app")).is_err(), "a missing path");
|
||||
if cfg!(target_os = "macos") {
|
||||
let app = d.join("Editor.app");
|
||||
@@ -639,19 +624,19 @@ mod open_with_tests {
|
||||
std::fs::set_permissions(&tool, std::fs::Permissions::from_mode(0o755)).unwrap();
|
||||
assert!(check_app(&tool).is_ok(), "an executable file");
|
||||
}
|
||||
let _ = std::fs::remove_dir_all(&d);
|
||||
}
|
||||
|
||||
/// PhotoCraft is looked for only where it installs.
|
||||
#[test]
|
||||
fn photocraft_is_found_where_it_installs() {
|
||||
let d = scratch("find");
|
||||
let temp = scratch("find");
|
||||
let d = temp.path();
|
||||
if cfg!(target_os = "macos") {
|
||||
let candidates = photocraft_candidates(Some(&d), None);
|
||||
let candidates = photocraft_candidates(Some(d), None);
|
||||
assert_eq!(candidates.first().map(|p| p.to_string_lossy().into_owned()).as_deref(), Some("/Applications/PhotoCraft.app"));
|
||||
assert!(candidates.contains(&d.join("Applications/PhotoCraft.app")), "{candidates:?}");
|
||||
std::fs::create_dir_all(d.join("Applications/PhotoCraft.app")).unwrap();
|
||||
assert!(find_photocraft(Some(&d), None).unwrap().ends_with("PhotoCraft.app"));
|
||||
assert!(find_photocraft(Some(d), None).unwrap().ends_with("PhotoCraft.app"));
|
||||
} else {
|
||||
let bin = d.join("bin");
|
||||
std::fs::create_dir_all(&bin).unwrap();
|
||||
@@ -675,7 +660,6 @@ mod open_with_tests {
|
||||
assert_eq!(find_photocraft(None, Some(&path_var)), Some(exe));
|
||||
}
|
||||
}
|
||||
let _ = std::fs::remove_dir_all(&d);
|
||||
}
|
||||
|
||||
/// #5327 review: on Windows PhotoCraft is looked for where its installer puts it: the path it
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
use super::*;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::time::{Duration, UNIX_EPOCH};
|
||||
|
||||
fn temp_dir(tag: &str) -> PathBuf {
|
||||
static N: AtomicUsize = AtomicUsize::new(0);
|
||||
let d = std::env::temp_dir().join(format!("vectorcraft-logging-{tag}-{}-{}", std::process::id(), N.fetch_add(1, Ordering::Relaxed)));
|
||||
let _ = std::fs::remove_dir_all(&d);
|
||||
d
|
||||
struct TestPath {
|
||||
_parent: tempfile::TempDir,
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
impl std::ops::Deref for TestPath {
|
||||
type Target = Path;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.path
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Path> for TestPath {
|
||||
fn as_ref(&self) -> &Path {
|
||||
&self.path
|
||||
}
|
||||
}
|
||||
|
||||
fn temp_dir(tag: &str) -> TestPath {
|
||||
let parent = tempfile::Builder::new().prefix(&format!("vectorcraft-logging-{tag}-")).tempdir().unwrap();
|
||||
let path = parent.path().join("log");
|
||||
TestPath { _parent: parent, path }
|
||||
}
|
||||
|
||||
fn read(path: &Path) -> String {
|
||||
|
||||
@@ -63,11 +63,10 @@ mod tests {
|
||||
/// fonts, is listed while it is registered.
|
||||
#[test]
|
||||
fn fonts_registered_from_other_folders_are_listed() {
|
||||
let dir = std::env::temp_dir().join(format!("vectorcraft-mac-fonts-{}", std::process::id()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let dir = tempfile::Builder::new().prefix("vectorcraft-mac-fonts-").tempdir().unwrap();
|
||||
// A space in the name: the URL's escapes are decoded. The bundled serif isn't a font macOS
|
||||
// installs.
|
||||
let file = dir.join("Registered Font.ttf");
|
||||
let file = dir.path().join("Registered Font.ttf");
|
||||
std::fs::copy(concat!(env!("CARGO_MANIFEST_DIR"), "/../../assets/fonts/SourceSerif4-Regular.ttf"), &file).unwrap();
|
||||
let want = std::fs::canonicalize(&file).unwrap();
|
||||
let listed = || super::font_files().iter().any(|f| f.ends_with("/Registered Font.ttf") && std::fs::canonicalize(f).is_ok_and(|p| p == want));
|
||||
@@ -78,7 +77,6 @@ mod tests {
|
||||
let registered = listed();
|
||||
// SAFETY: as above.
|
||||
unsafe { CTFontManagerUnregisterFontsForURL(&url, CTFontManagerScope::Process, std::ptr::null_mut()) };
|
||||
std::fs::remove_dir_all(&dir).unwrap();
|
||||
assert!(registered);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,13 +335,11 @@ mod tests {
|
||||
#[test]
|
||||
fn a_kept_preferences_copy_is_owner_only() {
|
||||
use std::os::unix::fs::PermissionsExt as _;
|
||||
let dir = std::env::temp_dir().join(format!("vc-prefs-copy-{}", std::process::id()));
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let temp = tempfile::Builder::new().prefix("vc-prefs-copy-").tempdir().unwrap();
|
||||
let dir = temp.path();
|
||||
super::keep_prefs_copy(&dir.join("ui.json"), b"{}", "ui.unreadable");
|
||||
let mode = std::fs::metadata(dir.join("ui.unreadable.json")).unwrap().permissions().mode() & 0o777;
|
||||
assert_eq!(mode, 0o600);
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -192,7 +192,22 @@ fn copy_dir_into(from: &Path, to: &Path, skip: &mut impl FnMut(String)) {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
struct TestDir(tempfile::TempDir);
|
||||
|
||||
impl std::ops::Deref for TestDir {
|
||||
type Target = Path;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.0.path()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Path> for TestDir {
|
||||
fn as_ref(&self) -> &Path {
|
||||
self.0.path()
|
||||
}
|
||||
}
|
||||
|
||||
fn environment(key: &str) -> Option<OsString> {
|
||||
match key {
|
||||
@@ -287,12 +302,8 @@ mod tests {
|
||||
assert_eq!(install_dir("macos", mounted, &appimage), Some("/tmp/.mount_vc/usr/bin".into()));
|
||||
}
|
||||
|
||||
fn temp(tag: &str) -> PathBuf {
|
||||
static N: AtomicUsize = AtomicUsize::new(0);
|
||||
let d = std::env::temp_dir().join(format!("vectorcraft-profile-{tag}-{}-{}", std::process::id(), N.fetch_add(1, Ordering::Relaxed)));
|
||||
let _ = std::fs::remove_dir_all(&d);
|
||||
std::fs::create_dir_all(&d).unwrap();
|
||||
d
|
||||
fn temp(tag: &str) -> TestDir {
|
||||
TestDir(tempfile::Builder::new().prefix(&format!("vectorcraft-profile-{tag}-")).tempdir().unwrap())
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -263,15 +263,23 @@ mod tests {
|
||||
|
||||
use super::*;
|
||||
|
||||
struct TestDir(tempfile::TempDir);
|
||||
|
||||
impl std::ops::Deref for TestDir {
|
||||
type Target = Path;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.0.path()
|
||||
}
|
||||
}
|
||||
|
||||
/// A fresh folder for one test, with an existing file in it.
|
||||
fn folder(name: &str) -> (PathBuf, PathBuf, String) {
|
||||
let dir = std::env::temp_dir().join(format!("vc-single-instance-{}-{name}", std::process::id()));
|
||||
let _ = fs::remove_dir_all(&dir);
|
||||
fs::create_dir_all(&dir).unwrap();
|
||||
let file = dir.join("a b.svg");
|
||||
fn folder(name: &str) -> (PathBuf, TestDir, String) {
|
||||
let dir = tempfile::Builder::new().prefix(&format!("vc-single-instance-{name}-")).tempdir().unwrap();
|
||||
let file = dir.path().join("a b.svg");
|
||||
fs::write(&file, "<svg/>").unwrap();
|
||||
let file = file.to_string_lossy().into_owned();
|
||||
(dir.join(FILE_NAME), dir, file)
|
||||
(dir.path().join(FILE_NAME), TestDir(dir), file)
|
||||
}
|
||||
|
||||
fn primary(path: &Path) -> (Primary, mpsc::Receiver<Vec<String>>) {
|
||||
@@ -303,12 +311,11 @@ mod tests {
|
||||
assert_eq!(rx.recv_timeout(CLIENT_TIMEOUT).unwrap(), [file]);
|
||||
drop(primary);
|
||||
assert!(!path.exists(), "the endpoint file goes with the app");
|
||||
let _ = fs::remove_dir_all(dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_wrong_token_garbage_and_oversized_messages_are_refused() {
|
||||
let (path, dir, file) = folder("refused");
|
||||
let (path, _dir, file) = folder("refused");
|
||||
let (_primary, rx) = primary(&path);
|
||||
let token = read_endpoint(&path).unwrap().token;
|
||||
let wrong = format!("{}\n", json!({ "token": "0".repeat(token.len()), "files": [file] }));
|
||||
@@ -323,12 +330,11 @@ mod tests {
|
||||
// The listener still serves a launch with the right token.
|
||||
forward(&path, std::slice::from_ref(&file)).unwrap();
|
||||
assert_eq!(rx.recv_timeout(CLIENT_TIMEOUT).unwrap(), [file]);
|
||||
let _ = fs::remove_dir_all(dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_stale_endpoint_file_is_ignored_and_replaced() {
|
||||
let (path, dir, file) = folder("stale");
|
||||
let (path, _dir, file) = folder("stale");
|
||||
// The recorded app is gone: whatever holds the port closes without a greeting. (A freed
|
||||
// port can be taken by another test's listener meanwhile, which would then accept this
|
||||
// connection in place of its own client's.)
|
||||
@@ -357,18 +363,16 @@ mod tests {
|
||||
let (_primary, rx) = primary(&path);
|
||||
forward(&path, std::slice::from_ref(&file)).unwrap();
|
||||
assert_eq!(rx.recv_timeout(CLIENT_TIMEOUT).unwrap(), [file]);
|
||||
let _ = fs::remove_dir_all(dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_replaced_endpoint_file_stays_when_the_earlier_app_ends() {
|
||||
let (path, dir, _) = folder("replaced");
|
||||
let (path, _dir, _) = folder("replaced");
|
||||
let (first, _rx1) = primary(&path);
|
||||
let (_second, _rx2) = primary(&path);
|
||||
let second_token = read_endpoint(&path).unwrap().token;
|
||||
drop(first);
|
||||
assert_eq!(read_endpoint(&path).map(|e| e.token), Some(second_token));
|
||||
let _ = fs::remove_dir_all(dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -383,9 +387,8 @@ mod tests {
|
||||
#[test]
|
||||
fn the_endpoint_file_is_the_users_alone() {
|
||||
use std::os::unix::fs::PermissionsExt as _;
|
||||
let (path, dir, _) = folder("mode");
|
||||
let (path, _dir, _) = folder("mode");
|
||||
let _primary = primary(&path);
|
||||
assert_eq!(fs::metadata(&path).unwrap().permissions().mode() & 0o777, 0o600);
|
||||
let _ = fs::remove_dir_all(dir);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,8 +284,8 @@ mod tests {
|
||||
#[test]
|
||||
fn fonts_only_gdi_has_loaded_are_listed_by_their_files() {
|
||||
use windows::Win32::Graphics::Gdi::{AddFontResourceExW, FR_PRIVATE, RemoveFontResourceExW};
|
||||
let dir = std::env::temp_dir().join(format!("vc-gdi-fonts-{}", std::process::id()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let temp = tempfile::Builder::new().prefix("vc-gdi-fonts-").tempdir().unwrap();
|
||||
let dir = temp.path();
|
||||
let file = dir.join("29457");
|
||||
let source = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("../../assets/fonts/SourceSans3-Regular.ttf");
|
||||
let mut data = std::fs::read(source).unwrap();
|
||||
@@ -303,7 +303,6 @@ mod tests {
|
||||
assert_eq!(unsafe { AddFontResourceExW(&path, FR_PRIVATE, None) }, 1);
|
||||
let files = super::font_files();
|
||||
let _ = unsafe { RemoveFontResourceExW(&path, FR_PRIVATE.0, None) };
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
let wanted = file.to_string_lossy().to_lowercase();
|
||||
assert!(files.iter().any(|f| f.to_lowercase() == wanted), "{wanted} not in {} files", files.len());
|
||||
}
|
||||
|
||||
@@ -99,9 +99,8 @@ fn unreadable_saved_docking_keeps_preferences_and_every_workspace() {
|
||||
|
||||
#[test]
|
||||
fn an_unreadable_ui_json_is_kept_beside_it() {
|
||||
let stamp = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_nanos();
|
||||
let dir = std::env::temp_dir().join(format!("vectorcraft-ui-prefs-{}-{stamp}", std::process::id()));
|
||||
std::fs::create_dir(&dir).unwrap();
|
||||
let temp = tempfile::Builder::new().prefix("vectorcraft-ui-prefs-").tempdir().unwrap();
|
||||
let dir = temp.path();
|
||||
let path = dir.join("ui.json");
|
||||
super::keep_prefs_copy(&path, b"{\"docking\": {\"root\": {\"FutureNode\": {}}}}", "ui.unreadable");
|
||||
super::keep_prefs_copy(&path, b"not json", "ui.unreadable");
|
||||
@@ -109,7 +108,6 @@ fn an_unreadable_ui_json_is_kept_beside_it() {
|
||||
let first = std::fs::read(dir.join("ui.unreadable.json")).unwrap();
|
||||
let second = std::fs::read(dir.join("ui.unreadable-2.json")).unwrap();
|
||||
let before = std::fs::read(dir.join("ui.before-layout-migration.json")).unwrap();
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
assert!(first.starts_with(b"{\"docking\""), "the first copy is not replaced");
|
||||
assert_eq!(second, b"not json");
|
||||
assert_eq!(before, b"{}");
|
||||
|
||||
Reference in New Issue
Block a user