cueward-adapter-macos 0.5.0

macOS adapter for Cueward with Safari, Notes, Messages, Reminders, Calendar, Screenshot, Clipboard, and OCR integrations.
use super::*;
use cueward_core::files::relocation::{
    RelocationPlatform, RelocationReceipt, RelocationRequest, RenameOutcome,
};
use cueward_core::files::{FilePlatform, FileStamp, ResourceMetadata};
use std::fs::{File, Metadata};
use std::hash::{Hash, Hasher};
use std::io;

struct ShortRevisions;
impl FilePlatform for ShortRevisions {
    fn stamp(&self, metadata: &Metadata) -> FileStamp {
        let mut stamp = MacFiles.stamp(metadata);
        let mut hash = std::collections::hash_map::DefaultHasher::new();
        stamp.version.hash(&mut hash);
        stamp.version = hash.finish().to_string();
        stamp
    }
    fn open_regular(&self, path: &Path) -> io::Result<File> {
        MacFiles.open_regular(path)
    }
    fn resource_metadata(
        &self,
        path: &Path,
        metadata: &Metadata,
    ) -> Result<ResourceMetadata, FileError> {
        MacFiles.resource_metadata(path, metadata)
    }
}
impl BatchRenamePlatform for ShortRevisions {
    fn names_may_collide(&self, a: &str, b: &str) -> bool {
        MacFiles.names_may_collide(a, b)
    }
}
impl RelocationPlatform for ShortRevisions {
    fn open_directory(&self, path: &Path) -> Result<File, FileError> {
        RelocationPlatform::open_directory(&MacFiles, path)
    }
    fn same_filesystem(&self, a: &Metadata, b: &Metadata) -> bool {
        RelocationPlatform::same_filesystem(&MacFiles, a, b)
    }
    fn prepare_rename(&self, _: &Path, _: &RelocationReceipt) -> Result<(), FileError> {
        panic!("dense conflicts must not prepare a rename")
    }
    fn rename(&self, _: &File, _: &RelocationRequest) -> RenameOutcome {
        panic!("dense conflicts must not submit a rename")
    }
}
#[test]
fn batch_execute_count_ceiling_conflicts_save_not_started_without_any_child() {
    let root = fixture();
    let mut request = request(root.path(), &[("a", "a")]);
    request.entries[0].expected_version = ShortRevisions
        .stamp(&root.path().join("a").metadata().unwrap())
        .version;
    request.entries[0].expected_parent_version = ShortRevisions
        .stamp(&root.path().metadata().unwrap())
        .version;
    request.entries = vec![request.entries[0].clone(); 64];
    assert!(serde_json::to_vec(&request).unwrap().len() <= 16384);
    let prepared = prepare(&request);
    let result = execute_prepared(
        &ShortRevisions,
        &BatchExecutionWorkerRequest {
            operation_id: prepared.operation_id.clone(),
        },
    );
    let stored = read_receipt(&prepared.operation_id).unwrap();
    let bytes = fs::metadata(&prepared.receipt_path).unwrap().len();
    cleanup(&stored);
    let receipt =
        result.expect("every accepted dense-conflict request must save authoritative evidence");
    let value = serde_json::to_value(&receipt).unwrap();
    assert_eq!(receipt.status, RelocationStatus::NotStarted);
    assert_eq!(
        receipt.error.as_ref().unwrap().code,
        FileErrorCode::Conflict
    );
    assert_eq!(receipt.items.len(), 64);
    assert!(
        receipt
            .items
            .iter()
            .all(|i| i.operation_id.is_none() && !i.mutation_attempted)
    );
    assert!(value["omitted_issue_count"].as_u64().unwrap() > 0);
    assert_eq!(
        receipt.issues.len() + value["omitted_issue_count"].as_u64().unwrap() as usize,
        3 * 64 * 63 / 2
    );
    assert_eq!(serde_json::to_value(&stored).unwrap(), value);
    assert!(bytes <= 256 * 1024);
    assert_eq!(fs::read(root.path().join("a")).unwrap(), b"OWNED a\0");
    assert_eq!(fs::read_dir(root.path()).unwrap().count(), 2);
}