#![allow(
clippy::approx_constant,
clippy::useless_vec,
clippy::len_zero,
clippy::unnecessary_cast,
clippy::redundant_closure,
clippy::too_many_arguments,
clippy::type_complexity,
clippy::needless_borrow,
clippy::enum_variant_names,
clippy::upper_case_acronyms,
clippy::inconsistent_digit_grouping,
clippy::unit_cmp,
clippy::assertions_on_constants,
clippy::iter_on_single_items,
clippy::expect_fun_call,
clippy::redundant_pattern_matching,
variant_size_differences,
clippy::absurd_extreme_comparisons,
clippy::nonminimal_bool,
clippy::for_kv_map,
clippy::needless_range_loop,
clippy::single_match,
clippy::collapsible_if,
clippy::needless_return,
clippy::redundant_clone,
clippy::map_entry,
clippy::match_single_binding,
clippy::bool_comparison,
clippy::derivable_impls,
clippy::manual_range_contains,
clippy::needless_borrows_for_generic_args,
clippy::manual_map,
clippy::vec_init_then_push,
clippy::identity_op,
clippy::manual_flatten,
clippy::single_char_pattern,
clippy::search_is_some,
clippy::option_map_unit_fn,
clippy::while_let_on_iterator,
clippy::clone_on_copy,
clippy::box_collection,
clippy::redundant_field_names,
clippy::ptr_arg,
clippy::large_enum_variant,
clippy::match_ref_pats,
clippy::needless_pass_by_value,
clippy::unused_unit,
clippy::let_and_return,
clippy::suspicious_else_formatting,
clippy::manual_strip,
clippy::match_like_matches_macro,
clippy::from_over_into,
clippy::wrong_self_convention,
clippy::inherent_to_string,
clippy::new_without_default,
clippy::unnecessary_wraps,
clippy::field_reassign_with_default,
clippy::manual_find,
clippy::unnecessary_lazy_evaluations,
clippy::should_implement_trait,
clippy::missing_safety_doc,
clippy::unusual_byte_groupings,
clippy::bool_assert_comparison,
clippy::zero_prefixed_literal,
clippy::await_holding_lock,
clippy::manual_saturating_arithmetic,
clippy::explicit_counter_loop,
clippy::needless_lifetimes,
clippy::single_component_path_imports,
clippy::uninlined_format_args,
clippy::iter_cloned_collect,
clippy::manual_str_repeat,
clippy::excessive_precision,
clippy::precedence,
clippy::unnecessary_literal_unwrap
)]
use oxicode::versioning::{
can_migrate, check_compatibility, migration_path, CompatibilityLevel, Version,
};
#[test]
fn test_compatibility_same_version() {
let v = Version::new(1, 0, 0);
assert_eq!(
check_compatibility(v, v, None),
CompatibilityLevel::Compatible
);
}
#[test]
fn test_compatibility_patch_difference_older_data() {
let data = Version::new(1, 0, 0);
let current = Version::new(1, 0, 5);
let compat = check_compatibility(data, current, None);
assert_eq!(compat, CompatibilityLevel::Compatible);
}
#[test]
fn test_compatibility_older_minor() {
let data = Version::new(1, 0, 0);
let current = Version::new(1, 5, 0);
let compat = check_compatibility(data, current, None);
assert!(compat.is_usable());
}
#[test]
fn test_compatibility_incompatible_major() {
let data = Version::new(1, 0, 0);
let current = Version::new(2, 0, 0);
assert_eq!(
check_compatibility(data, current, None),
CompatibilityLevel::Incompatible
);
}
#[test]
fn test_compatibility_below_minimum() {
let data = Version::new(1, 1, 0);
let current = Version::new(1, 5, 0);
let min = Some(Version::new(1, 3, 0));
assert_eq!(
check_compatibility(data, current, min),
CompatibilityLevel::Incompatible
);
}
#[test]
fn test_compatibility_0x_same_minor() {
let data = Version::new(0, 1, 0);
let current = Version::new(0, 1, 9);
assert_eq!(
check_compatibility(data, current, None),
CompatibilityLevel::Compatible
);
}
#[test]
fn test_compatibility_0x_different_minor() {
let data = Version::new(0, 1, 0);
let current = Version::new(0, 2, 0);
assert_eq!(
check_compatibility(data, current, None),
CompatibilityLevel::Incompatible
);
}
#[test]
fn test_compatibility_newer_data_than_current() {
let data = Version::new(1, 9, 0);
let current = Version::new(1, 0, 0);
let compat = check_compatibility(data, current, None);
assert_eq!(compat, CompatibilityLevel::CompatibleWithWarnings);
}
#[test]
fn test_compatibility_level_methods() {
assert!(CompatibilityLevel::Compatible.is_usable());
assert!(CompatibilityLevel::Compatible.is_fully_compatible());
assert!(!CompatibilityLevel::Compatible.has_warnings());
assert!(CompatibilityLevel::CompatibleWithWarnings.is_usable());
assert!(!CompatibilityLevel::CompatibleWithWarnings.is_fully_compatible());
assert!(CompatibilityLevel::CompatibleWithWarnings.has_warnings());
assert!(!CompatibilityLevel::Incompatible.is_usable());
assert!(!CompatibilityLevel::Incompatible.is_fully_compatible());
assert!(!CompatibilityLevel::Incompatible.has_warnings());
}
#[test]
fn test_can_migrate_same_major() {
assert!(can_migrate(Version::new(1, 0, 0), Version::new(1, 9, 0)));
}
#[test]
fn test_can_migrate_forward_major() {
assert!(can_migrate(Version::new(1, 0, 0), Version::new(3, 0, 0)));
}
#[test]
fn test_cannot_migrate_backward() {
assert!(!can_migrate(Version::new(3, 0, 0), Version::new(1, 0, 0)));
}
#[test]
fn test_can_migrate_same_version() {
assert!(can_migrate(Version::new(1, 0, 0), Version::new(1, 0, 0)));
}
#[test]
fn test_migration_path_same_version() {
let path = migration_path(Version::new(1, 0, 0), Version::new(1, 0, 0));
assert!(path.is_empty());
}
#[test]
fn test_migration_path_same_major() {
let path = migration_path(Version::new(1, 0, 0), Version::new(1, 5, 0));
assert!(path.is_empty());
}
#[test]
fn test_migration_path_one_major_bump() {
let path = migration_path(Version::new(1, 0, 0), Version::new(2, 0, 0));
assert!(
path.is_empty(),
"direct migration needs no intermediate steps"
);
}
#[test]
fn test_migration_path_two_major_bumps() {
let path = migration_path(Version::new(1, 0, 0), Version::new(3, 0, 0));
assert_eq!(path.len(), 1);
assert_eq!(path[0], Version::new(2, 0, 0));
}
#[test]
fn test_migration_path_three_major_bumps() {
let path = migration_path(Version::new(1, 0, 0), Version::new(4, 0, 0));
assert_eq!(path.len(), 2);
assert_eq!(path[0], Version::new(2, 0, 0));
assert_eq!(path[1], Version::new(3, 0, 0));
}
#[test]
fn test_can_migrate_extended() {
let v1 = Version::new(1, 0, 0);
let v2 = Version::new(2, 0, 0);
assert!(can_migrate(v1, v1));
assert!(can_migrate(v1, v2));
assert!(!can_migrate(v2, v1));
}
#[test]
fn test_version_compatibility_chain() {
let versions = [
Version::new(1, 0, 0),
Version::new(1, 1, 0),
Version::new(1, 2, 0),
Version::new(1, 3, 0),
];
for (i, &from) in versions.iter().enumerate() {
for &to in &versions[i..] {
assert!(
can_migrate(from, to),
"expected can_migrate({from} -> {to})"
);
}
}
}
#[test]
fn test_can_migrate_true() {
use oxicode::versioning::{can_migrate, Version};
let v1 = Version::new(1, 0, 0);
let v2 = Version::new(2, 0, 0);
assert!(
can_migrate(v1, v2),
"forward major migration must be possible"
);
}
#[test]
fn test_can_migrate_false() {
use oxicode::versioning::{can_migrate, Version};
let v1 = Version::new(1, 0, 0);
let v2 = Version::new(2, 0, 0);
assert!(
!can_migrate(v2, v1),
"backward (downgrade) migration must not be possible"
);
}
#[test]
fn test_migration_path_chain() {
use oxicode::versioning::{migration_path, Version};
let v1 = Version::new(1, 0, 0);
let v3 = Version::new(3, 0, 0);
let path = migration_path(v1, v3);
assert_eq!(path.len(), 1, "one intermediate step between v1 and v3");
assert_eq!(
path[0],
Version::new(2, 0, 0),
"intermediate step must be v2"
);
}
#[test]
fn test_migration_chain_three_steps() {
use oxicode::versioning::{migration_path, Version};
let from = Version::new(1, 0, 0);
let to = Version::new(4, 0, 0);
let path = migration_path(from, to);
assert_eq!(path.len(), 2, "three-step chain has two intermediate nodes");
assert_eq!(path[0], Version::new(2, 0, 0));
assert_eq!(path[1], Version::new(3, 0, 0));
}
#[test]
fn test_multiple_migrations_applied() {
use oxicode::versioning::{extract_version, Version};
let v1 = Version::new(1, 0, 0);
let v2 = Version::new(2, 0, 0);
let v3 = Version::new(3, 0, 0);
let enc1 = oxicode::encode_versioned_value(&100u64, v1).expect("encode v1");
assert_eq!(extract_version(&enc1).expect("extract v1"), v1);
let (val2, _, _): (u64, _, _) = oxicode::decode_versioned_value(&enc1).expect("decode v1");
let enc2 = oxicode::encode_versioned_value(&val2, v2).expect("encode v2");
assert_eq!(extract_version(&enc2).expect("extract v2"), v2);
let (val3, _, _): (u64, _, _) = oxicode::decode_versioned_value(&enc2).expect("decode v2");
let enc3 = oxicode::encode_versioned_value(&val3, v3).expect("encode v3");
assert_eq!(extract_version(&enc3).expect("extract v3"), v3);
let (final_val, final_ver, _): (u64, _, _) =
oxicode::decode_versioned_value(&enc3).expect("decode v3");
assert_eq!(final_val, 100u64);
assert_eq!(final_ver, v3);
}