use qubit_fs::error::FsErrorKind;
use qubit_fs::metadata::AtomicityRequirement;
use qubit_fs::metadata::Checksum;
use qubit_fs::metadata::ChecksumAlgorithm;
use qubit_fs::metadata::DurabilityRequirement;
use qubit_fs::metadata::FileSystemCapabilities;
use qubit_fs::metadata::FileSystemCapability;
use qubit_fs::metadata::ResourceVersion;
use qubit_fs::metadata::UserMetadata;
use qubit_fs::write::WriteDisposition;
use qubit_fs::write::WriteOptions;
use qubit_fs::write::WritePrecondition;
#[test]
fn test_write_options_full_configuration_is_usable() {
let checksum = Checksum::new(ChecksumAlgorithm::Sha256, "abc");
let options = WriteOptions::default()
.with_create_parent(true)
.with_disposition(WriteDisposition::CreateOrReplace)
.with_atomicity(AtomicityRequirement::Required)
.with_durability(DurabilityRequirement::Preferred)
.with_precondition(WritePrecondition::IfMatch(ResourceVersion::new("v1")))
.with_content_type(Some("text/plain".to_owned()))
.with_checksum(Some(checksum));
assert!(options.create_parent());
assert_eq!(Some("text/plain"), options.content_type());
assert!(options.checksum().is_some());
assert_eq!(AtomicityRequirement::Required, options.atomicity());
assert_eq!(DurabilityRequirement::Preferred, options.durability());
assert_eq!(WriteDisposition::CreateOrReplace, options.disposition());
assert!(matches!(options.precondition(), WritePrecondition::IfMatch(_)));
assert!(options.user_metadata().is_empty());
assert!(options.validate().is_ok());
}
#[test]
fn write_requirements_are_checked_against_typed_capabilities() {
let atomic = WriteOptions::default().with_atomicity(AtomicityRequirement::Required);
let error = atomic.validate_against(FileSystemCapabilities::default()).unwrap_err();
assert_eq!(Some(FileSystemCapability::AtomicReplace), error.required_capability());
let append = WriteOptions::default()
.with_disposition(WriteDisposition::Append)
.with_atomicity(AtomicityRequirement::NotRequired);
let error = append.validate_against(FileSystemCapabilities::default()).unwrap_err();
assert_eq!(Some(FileSystemCapability::Append), error.required_capability());
let conditional = WriteOptions::default().with_precondition(WritePrecondition::IfAbsent);
let error = conditional
.validate_against(FileSystemCapabilities::default())
.unwrap_err();
assert_eq!(
Some(FileSystemCapability::ConditionalWrite),
error.required_capability(),
);
let capabilities = FileSystemCapabilities::default()
.with_guaranteed(FileSystemCapability::AtomicReplace)
.with_guaranteed(FileSystemCapability::Append)
.with_guaranteed(FileSystemCapability::ConditionalWrite);
assert!(atomic.validate_against(capabilities).is_ok());
assert!(append.validate_against(capabilities).is_ok());
assert!(conditional.validate_against(capabilities).is_ok());
let durable = WriteOptions::default().with_durability(DurabilityRequirement::Required);
let error = durable
.validate_against(FileSystemCapabilities::default())
.expect_err("required durability must be preflighted");
assert_eq!(Some(FileSystemCapability::DurableWrite), error.required_capability());
let capabilities = capabilities.with_guaranteed(FileSystemCapability::DurableWrite);
assert!(durable.validate_against(capabilities).is_ok());
}
#[test]
fn append_cannot_request_atomic_publication() {
let options = WriteOptions::default()
.with_disposition(WriteDisposition::Append)
.with_atomicity(AtomicityRequirement::Required);
let error = options
.validate()
.expect_err("append plus required publication atomicity is invalid");
assert_eq!(FsErrorKind::InvalidOptions, error.kind());
}
#[test]
fn append_rejects_version_preconditions_but_allows_plain_append() {
let invalid = WriteOptions::default()
.with_disposition(WriteDisposition::Append)
.with_precondition(WritePrecondition::IfMatch(ResourceVersion::new("v1")));
assert!(invalid.validate().is_err());
let valid = WriteOptions::default()
.with_disposition(WriteDisposition::Append)
.with_atomicity(AtomicityRequirement::NotRequired);
assert!(valid.validate().is_ok());
}
#[test]
fn create_new_rejects_if_match_precondition() {
let options = WriteOptions::default()
.with_disposition(WriteDisposition::CreateNew)
.with_precondition(WritePrecondition::IfMatch(ResourceVersion::new("v1")));
let error = options
.validate()
.expect_err("CreateNew and IfMatch cannot both be satisfied");
assert_eq!(FsErrorKind::InvalidOptions, error.kind());
}
#[test]
fn write_options_preserve_validated_user_metadata() {
let options = WriteOptions::default().with_user_metadata(
UserMetadata::new()
.with("category", "private-category")
.expect("ordinary user metadata key must be accepted"),
);
assert!(options.user_metadata().contains_key("category"));
assert!(!format!("{options:?}").contains("private-category"));
}