use super::*;
#[test]
fn test_registry_register() {
let registry = OptionRegistry::new();
let result =
registry.register(OptionSpec::new("number", "Show line numbers", OptionValue::bool(false)));
assert!(result.is_ok());
assert!(registry.contains("number"));
}
#[test]
fn test_registry_register_duplicate() {
let registry = OptionRegistry::new();
assert!(
registry
.register(OptionSpec::new("number", "desc", OptionValue::bool(false)))
.is_ok()
);
let result = registry.register(OptionSpec::new("number", "desc2", OptionValue::bool(true)));
assert!(matches!(result, Err(OptionError::AlreadyExists(_))));
}
#[test]
fn test_registry_alias() {
let registry = OptionRegistry::new();
assert!(
registry
.register(
OptionSpec::new("number", "Show line numbers", OptionValue::bool(false))
.with_short("nu"),
)
.is_ok()
);
assert!(registry.contains("number"));
assert!(registry.contains("nu"));
assert_eq!(registry.resolve_name("nu"), Some("number".to_string()));
}
#[test]
fn test_registry_get_default() {
let registry = OptionRegistry::new();
assert!(
registry
.register(OptionSpec::new("tabwidth", "Tab width", OptionValue::int(4)))
.is_ok()
);
let value = registry.get("tabwidth", OptionScopeId::Global);
assert_eq!(value, Some(OptionValue::int(4)));
}
#[test]
fn test_registry_set_and_get() {
let registry = OptionRegistry::new();
assert!(
registry
.register(OptionSpec::new("tabwidth", "Tab width", OptionValue::int(4)))
.is_ok()
);
assert!(
registry
.set("tabwidth", OptionValue::int(8), OptionScopeId::Global)
.is_ok()
);
let value = registry.get("tabwidth", OptionScopeId::Global);
assert_eq!(value, Some(OptionValue::int(8)));
}
#[test]
fn test_registry_buffer_local() {
let registry = OptionRegistry::new();
assert!(
registry
.register(
OptionSpec::new("tabwidth", "Tab width", OptionValue::int(4))
.with_scope(OptionScope::Buffer),
)
.is_ok()
);
let buffer1 = BufferId::new();
let buffer2 = BufferId::new();
assert!(
registry
.set_for_buffer("tabwidth", OptionValue::int(2), buffer1)
.is_ok()
);
assert_eq!(registry.get_for_buffer("tabwidth", buffer1), Some(OptionValue::int(2)));
assert_eq!(registry.get_for_buffer("tabwidth", buffer2), Some(OptionValue::int(4)));
}
#[test]
fn test_registry_window_local() {
let registry = OptionRegistry::new();
assert!(
registry
.register(
OptionSpec::new("number", "Show line numbers", OptionValue::bool(false))
.with_scope(OptionScope::Window),
)
.is_ok()
);
let window1 = WindowId::new();
let window2 = WindowId::new();
assert!(
registry
.set_for_window("number", OptionValue::bool(true), window1)
.is_ok()
);
assert_eq!(registry.get_for_window("number", window1), Some(OptionValue::bool(true)));
assert_eq!(registry.get_for_window("number", window2), Some(OptionValue::bool(false)));
}
#[test]
fn test_registry_scope_mismatch() {
let registry = OptionRegistry::new();
assert!(
registry
.register(
OptionSpec::new("theme", "Color theme", OptionValue::string("default"))
.with_scope(OptionScope::Global),
)
.is_ok()
);
let result = registry.set_for_buffer("theme", OptionValue::string("dark"), BufferId::new());
assert!(matches!(result, Err(OptionError::ScopeMismatch { .. })));
}
#[test]
fn test_registry_reset() {
let registry = OptionRegistry::new();
assert!(
registry
.register(OptionSpec::new("tabwidth", "Tab width", OptionValue::int(4)))
.is_ok()
);
assert!(
registry
.set("tabwidth", OptionValue::int(8), OptionScopeId::Global)
.is_ok()
);
assert_eq!(registry.get("tabwidth", OptionScopeId::Global), Some(OptionValue::int(8)));
assert!(registry.reset("tabwidth", OptionScopeId::Global).is_ok());
assert_eq!(registry.get("tabwidth", OptionScopeId::Global), Some(OptionValue::int(4)));
}
#[test]
fn test_registry_toggle() {
let registry = OptionRegistry::new();
assert!(
registry
.register(OptionSpec::new("number", "Show line numbers", OptionValue::bool(false)))
.is_ok()
);
let result = registry.toggle("number", OptionScopeId::Global);
assert!(result.is_ok());
assert!(result.is_ok_and(|v| v));
let result = registry.toggle("number", OptionScopeId::Global);
assert!(result.is_ok());
assert!(result.is_ok_and(|v| !v));
}
#[test]
fn test_registry_list_matching() {
let registry = OptionRegistry::new();
assert!(
registry
.register(OptionSpec::new("number", "desc", OptionValue::bool(false)))
.is_ok()
);
assert!(
registry
.register(OptionSpec::new("numberwidth", "desc", OptionValue::int(4)))
.is_ok()
);
assert!(
registry
.register(OptionSpec::new("wrap", "desc", OptionValue::bool(true)))
.is_ok()
);
let matches = registry.list_matching("num");
assert_eq!(matches.len(), 2);
}
#[test]
fn test_registry_clear_buffer() {
let registry = OptionRegistry::new();
assert!(
registry
.register(
OptionSpec::new("tabwidth", "Tab width", OptionValue::int(4))
.with_scope(OptionScope::Buffer),
)
.is_ok()
);
let buffer = BufferId::new();
assert!(
registry
.set_for_buffer("tabwidth", OptionValue::int(2), buffer)
.is_ok()
);
assert_eq!(registry.get_for_buffer("tabwidth", buffer), Some(OptionValue::int(2)));
registry.clear_buffer(buffer);
assert_eq!(registry.get_for_buffer("tabwidth", buffer), Some(OptionValue::int(4)));
}
#[test]
fn test_registry_validation_on_set() {
let registry = OptionRegistry::new();
assert!(
registry
.register(
OptionSpec::new("tabwidth", "Tab width", OptionValue::int(4))
.with_constraint(OptionConstraint::range(1, 32)),
)
.is_ok()
);
assert!(
registry
.set("tabwidth", OptionValue::int(8), OptionScopeId::Global)
.is_ok()
);
assert!(
registry
.set("tabwidth", OptionValue::int(100), OptionScopeId::Global)
.is_err()
);
}
#[test]
fn test_registry_toggle_non_boolean() {
let registry = OptionRegistry::new();
assert!(
registry
.register(OptionSpec::new("tabwidth", "desc", OptionValue::int(4)))
.is_ok()
);
let result = registry.toggle("tabwidth", OptionScopeId::Global);
assert!(matches!(result, Err(OptionError::TypeMismatch { .. })));
}
#[test]
fn test_registry_list_matching_alias() {
let registry = OptionRegistry::new();
assert!(
registry
.register(OptionSpec::new("number", "desc", OptionValue::bool(false)).with_short("nu"),)
.is_ok()
);
let matches = registry.list_matching("nu");
assert_eq!(matches.len(), 1);
assert_eq!(matches[0].name, "number");
}
#[test]
fn test_registry_list_by_scope() {
let registry = OptionRegistry::new();
assert!(
registry
.register(
OptionSpec::new("number", "desc", OptionValue::bool(false))
.with_scope(OptionScope::Window),
)
.is_ok()
);
assert!(
registry
.register(
OptionSpec::new("tabwidth", "desc", OptionValue::int(4))
.with_scope(OptionScope::Buffer),
)
.is_ok()
);
assert!(
registry
.register(
OptionSpec::new("theme", "desc", OptionValue::string("dark"))
.with_scope(OptionScope::Global),
)
.is_ok()
);
let window_opts = registry.list_by_scope(OptionScope::Window);
assert_eq!(window_opts.len(), 1);
assert_eq!(window_opts[0].name, "number");
let buffer_opts = registry.list_by_scope(OptionScope::Buffer);
assert_eq!(buffer_opts.len(), 1);
let global_opts = registry.list_by_scope(OptionScope::Global);
assert_eq!(global_opts.len(), 1);
}
#[test]
fn test_registry_clear_window() {
let registry = OptionRegistry::new();
assert!(
registry
.register(
OptionSpec::new("number", "desc", OptionValue::bool(false))
.with_scope(OptionScope::Window),
)
.is_ok()
);
let window = WindowId::new();
assert!(
registry
.set_for_window("number", OptionValue::bool(true), window)
.is_ok()
);
assert_eq!(registry.get_for_window("number", window), Some(OptionValue::bool(true)));
registry.clear_window(window);
assert_eq!(registry.get_for_window("number", window), Some(OptionValue::bool(false)));
}
#[test]
fn test_registry_reset_buffer_scope() {
let registry = OptionRegistry::new();
assert!(
registry
.register(
OptionSpec::new("tabwidth", "desc", OptionValue::int(4))
.with_scope(OptionScope::Buffer),
)
.is_ok()
);
let buffer = BufferId::new();
assert!(
registry
.set_for_buffer("tabwidth", OptionValue::int(8), buffer)
.is_ok()
);
let removed = registry.reset("tabwidth", OptionScopeId::Buffer(buffer));
assert!(removed.is_ok());
assert_eq!(removed.unwrap(), Some(OptionValue::int(8)));
assert_eq!(registry.get_for_buffer("tabwidth", buffer), Some(OptionValue::int(4)));
}
#[test]
fn test_registry_reset_window_scope() {
let registry = OptionRegistry::new();
assert!(
registry
.register(
OptionSpec::new("number", "desc", OptionValue::bool(false))
.with_scope(OptionScope::Window),
)
.is_ok()
);
let window = WindowId::new();
assert!(
registry
.set_for_window("number", OptionValue::bool(true), window)
.is_ok()
);
let removed = registry.reset("number", OptionScopeId::Window(window));
assert!(removed.is_ok());
assert_eq!(removed.unwrap(), Some(OptionValue::bool(true)));
}
#[test]
fn test_registry_alias_conflicts_with_name() {
let registry = OptionRegistry::new();
assert!(
registry
.register(OptionSpec::new("nu", "desc", OptionValue::bool(false)))
.is_ok()
);
let result = registry
.register(OptionSpec::new("number", "desc", OptionValue::bool(false)).with_short("nu"));
assert!(matches!(result, Err(OptionError::AliasConflict(_))));
}
#[test]
fn test_registry_alias_conflicts_with_alias() {
let registry = OptionRegistry::new();
assert!(
registry
.register(OptionSpec::new("number", "desc", OptionValue::bool(false)).with_short("nu"),)
.is_ok()
);
let result = registry
.register(OptionSpec::new("numbers", "desc", OptionValue::bool(false)).with_short("nu"));
assert!(matches!(result, Err(OptionError::AliasConflict(_))));
}
#[test]
fn test_registry_scope_mismatch_window_on_global() {
let registry = OptionRegistry::new();
assert!(
registry
.register(
OptionSpec::new("theme", "desc", OptionValue::string("dark"))
.with_scope(OptionScope::Global),
)
.is_ok()
);
let result = registry.set_for_window("theme", OptionValue::string("light"), WindowId::new());
assert!(matches!(result, Err(OptionError::ScopeMismatch { .. })));
}
#[test]
fn test_registry_get_spec_via_alias() {
let registry = OptionRegistry::new();
assert!(
registry
.register(OptionSpec::new("number", "desc", OptionValue::bool(false)).with_short("nu"),)
.is_ok()
);
let spec = registry.get_spec("nu");
assert!(spec.is_some());
assert_eq!(spec.unwrap().name, "number");
let spec = registry.get_spec("number");
assert!(spec.is_some());
}
#[test]
fn test_registry_get_spec_nonexistent() {
let registry = OptionRegistry::new();
assert!(registry.get_spec("nope").is_none());
}
#[test]
fn test_registry_get_global_convenience() {
let registry = OptionRegistry::new();
assert!(
registry
.register(OptionSpec::new("tabwidth", "desc", OptionValue::int(4)))
.is_ok()
);
let val = registry.get_global("tabwidth");
assert_eq!(val, Some(OptionValue::int(4)));
let val = registry.get_global("nonexistent");
assert_eq!(val, None);
}
#[test]
fn test_registry_set_global_convenience() {
let registry = OptionRegistry::new();
assert!(
registry
.register(OptionSpec::new("tabwidth", "desc", OptionValue::int(4)))
.is_ok()
);
assert!(registry.set_global("tabwidth", OptionValue::int(8)).is_ok());
assert_eq!(registry.get_global("tabwidth"), Some(OptionValue::int(8)));
}
#[test]
fn test_registry_set_not_found() {
let registry = OptionRegistry::new();
let result = registry.set("nonexistent", OptionValue::int(1), OptionScopeId::Global);
assert!(matches!(result, Err(OptionError::NotFound(_))));
}
#[test]
fn test_registry_toggle_not_found() {
let registry = OptionRegistry::new();
let result = registry.toggle("nonexistent", OptionScopeId::Global);
assert!(matches!(result, Err(OptionError::NotFound(_))));
}
#[test]
fn test_registry_reset_not_found() {
let registry = OptionRegistry::new();
let result = registry.reset("nonexistent", OptionScopeId::Global);
assert!(matches!(result, Err(OptionError::NotFound(_))));
}
#[test]
fn test_registry_list_matching_alias_prefix() {
let registry = OptionRegistry::new();
assert!(
registry
.register(OptionSpec::new("number", "desc", OptionValue::bool(false)).with_short("nu"),)
.is_ok()
);
assert!(
registry
.register(OptionSpec::new("numberwidth", "desc", OptionValue::int(4)))
.is_ok()
);
let matches = registry.list_matching("nu");
assert!(matches.len() >= 2);
}
#[test]
fn test_registry_len_and_is_empty() {
let registry = OptionRegistry::new();
assert!(registry.is_empty());
assert_eq!(registry.len(), 0);
assert!(
registry
.register(OptionSpec::new("number", "desc", OptionValue::bool(false)))
.is_ok()
);
assert!(!registry.is_empty());
assert_eq!(registry.len(), 1);
}
#[test]
fn test_registry_set_via_alias() {
let registry = OptionRegistry::new();
assert!(
registry
.register(OptionSpec::new("number", "desc", OptionValue::bool(false)).with_short("nu"),)
.is_ok()
);
assert!(
registry
.set("nu", OptionValue::bool(true), OptionScopeId::Global)
.is_ok()
);
assert_eq!(registry.get("number", OptionScopeId::Global), Some(OptionValue::bool(true)));
}
#[test]
fn test_registry_list_all() {
let registry = OptionRegistry::new();
assert!(
registry
.register(OptionSpec::new("a", "desc", OptionValue::bool(false)))
.is_ok()
);
assert!(
registry
.register(OptionSpec::new("b", "desc", OptionValue::int(1)))
.is_ok()
);
let all = registry.list_all();
assert_eq!(all.len(), 2);
assert!(all.contains(&"a".to_string()));
assert!(all.contains(&"b".to_string()));
}
#[test]
fn test_registry_register_already_exists_error() {
let registry = OptionRegistry::new();
let spec = OptionSpec::new("tabstop", "Tab stop width", OptionValue::int(8));
assert!(registry.register(spec).is_ok());
let dup = OptionSpec::new("tabstop", "Duplicate", OptionValue::int(4));
let result = registry.register(dup);
assert!(matches!(result, Err(OptionError::AlreadyExists(name)) if name == "tabstop"));
}
#[test]
fn test_registry_register_alias_conflicts_with_existing_spec_name() {
let registry = OptionRegistry::new();
assert!(
registry
.register(OptionSpec::new("ts", "Existing spec", OptionValue::int(4)))
.is_ok()
);
let result =
registry.register(OptionSpec::new("tabstop", "desc", OptionValue::int(8)).with_short("ts"));
assert!(matches!(result, Err(OptionError::AliasConflict(alias)) if alias == "ts"));
}
#[test]
fn test_registry_register_alias_conflicts_with_existing_alias() {
let registry = OptionRegistry::new();
assert!(
registry
.register(
OptionSpec::new("number", "Line numbers", OptionValue::bool(false))
.with_short("nu"),
)
.is_ok()
);
let result = registry.register(
OptionSpec::new("numberwidth", "Number column width", OptionValue::int(4)).with_short("nu"),
);
assert!(matches!(result, Err(OptionError::AliasConflict(alias)) if alias == "nu"));
}
#[test]
fn test_resolve_name_returns_direct_spec_name() {
let registry = OptionRegistry::new();
assert!(
registry
.register(OptionSpec::new("wrap", "Line wrap", OptionValue::bool(true)))
.is_ok()
);
let resolved = registry.resolve_name("wrap");
assert_eq!(resolved, Some("wrap".to_string()));
}
#[test]
fn test_get_returns_window_local_value_when_set() {
let registry = OptionRegistry::new();
assert!(
registry
.register(
OptionSpec::new("number", "Line numbers", OptionValue::bool(false))
.with_scope(OptionScope::Window),
)
.is_ok()
);
let window_id = WindowId::new();
assert!(
registry
.set_for_window("number", OptionValue::bool(true), window_id)
.is_ok()
);
let value = registry.get("number", OptionScopeId::Window(window_id));
assert_eq!(value, Some(OptionValue::bool(true)));
}
#[test]
fn test_get_returns_buffer_local_value_when_set() {
let registry = OptionRegistry::new();
assert!(
registry
.register(
OptionSpec::new("tabstop", "Tab width", OptionValue::int(4))
.with_scope(OptionScope::Buffer),
)
.is_ok()
);
let buffer_id = BufferId::new();
assert!(
registry
.set_for_buffer("tabstop", OptionValue::int(2), buffer_id)
.is_ok()
);
let value = registry.get("tabstop", OptionScopeId::Buffer(buffer_id));
assert_eq!(value, Some(OptionValue::int(2)));
}
#[test]
fn test_get_returns_global_override_when_set() {
let registry = OptionRegistry::new();
assert!(
registry
.register(OptionSpec::new("tabstop", "Tab width", OptionValue::int(4)))
.is_ok()
);
assert!(registry.set_global("tabstop", OptionValue::int(8)).is_ok());
let value = registry.get("tabstop", OptionScopeId::Global);
assert_eq!(value, Some(OptionValue::int(8)));
}