journalmap 0.1.1

Journaling datatypes for easy undo, redo & version control
Documentation
use journalmap::JournalMap;

#[cfg(feature = "serde")]
use serde_json;

#[test]
fn test_hashmap_compat() {
    let mut ages: JournalMap<_, _, ()> = JournalMap::new();

    assert_eq!(ages.insert("Sarah", 22), None);
    assert_eq!(ages.insert("John", 21), None);
    assert_eq!(ages.insert("Mariah", 45), None);

    assert_eq!(ages.get(&"Sarah"), Some(&22));
    assert_eq!(ages.get(&"John"), Some(&21));
    assert_eq!(ages.get(&"Mariah"), Some(&45));
    assert_eq!(ages.get(&"Jimmy"), None);

    assert_eq!(ages.insert("John", 44), Some(21));

    assert_eq!(ages.get(&"John"), Some(&44));

    assert_eq!(ages.contains_key(&"Mariah"), true);
    assert_eq!(ages.contains_key(&"Jimmy"), false);

    ages.clear();

    assert_eq!(ages.len(), 0);
}

#[cfg(feature = "serde")]
#[test]
fn test_tag_serialize_deserialize() {
    let mut ages: JournalMap<String, i32, _> = JournalMap::new();

    ages.append_tag("start").unwrap();

    ages.insert("Sarah".to_string(), 22);
    ages.insert("John".to_string(), 21);
    ages.insert("Mariah".to_string(), 45);

    ages.append_tag("middle").unwrap();

    ages.insert("Steve".to_string(), 34);
    ages.insert("Carol".to_string(), 41);
    ages.insert("Ellie".to_string(), 21);
    ages.insert("Mariah".to_string(), 87);
    ages.remove("Sarah".to_string());

    ages.append_tag("end").unwrap();

    ages.reverse_to_next();

    let json_1 = serde_json::to_string(&ages.generate_journal(false)).unwrap();
    let json_2 = serde_json::to_string(&ages.generate_journal(true)).unwrap();

    let deserialized_ages_1: JournalMap<String, i32, String> =
        JournalMap::from_journal(&serde_json::from_str(&json_1).unwrap());
    let deserialized_ages_2: JournalMap<String, i32, String> =
        JournalMap::from_journal(&serde_json::from_str(&json_2).unwrap());

    assert_ne!(ages.as_hashmap(), deserialized_ages_1.as_hashmap());
    assert_eq!(ages.as_hashmap(), deserialized_ages_2.as_hashmap());

    ages.forward_to_next();

    assert_eq!(ages.as_hashmap(), deserialized_ages_1.as_hashmap());
    assert_ne!(ages.as_hashmap(), deserialized_ages_2.as_hashmap());
}

#[test]
fn test_tag_reverse() {
    let mut ages: JournalMap<&'static str, i32, _> = JournalMap::new();

    ages.append_tag("start").unwrap();

    ages.insert("Sarah", 22);
    ages.insert("John", 21);
    ages.insert("Mariah", 45);

    ages.append_tag("middle").unwrap();

    ages.insert("Steve", 34);
    ages.insert("Carol", 41);
    ages.insert("Ellie", 21);
    ages.insert("Mariah", 87);
    ages.remove("Sarah");

    ages.append_tag("end").unwrap();
    ages.append_tag("end").unwrap_err();

    assert_eq!(ages.contains_key(&"Sarah"), false);
    assert_eq!(ages.get(&"John"), Some(&21));
    assert_eq!(ages.get(&"Mariah"), Some(&87));
    assert_eq!(ages.get(&"Steve"), Some(&34));
    assert_eq!(ages.get(&"Carol"), Some(&41));
    assert_eq!(ages.get(&"Ellie"), Some(&21));

    assert_eq!(ages.reverse_to_tag(&"middle"), true);

    assert_eq!(ages.get(&"Sarah"), Some(&22));
    assert_eq!(ages.get(&"John"), Some(&21));
    assert_eq!(ages.get(&"Mariah"), Some(&45));
    assert_eq!(ages.contains_key(&"Steve"), false);
    assert_eq!(ages.contains_key(&"Carol"), false);
    assert_eq!(ages.contains_key(&"Ellie"), false);

    ages.insert("Omar", 33);

    ages.append_tag("end").unwrap();
    assert_eq!(ages.current_tag(), Some(&"end"));

    assert_eq!(ages.get(&"Sarah"), Some(&22));
    assert_eq!(ages.get(&"John"), Some(&21));
    assert_eq!(ages.get(&"Mariah"), Some(&45));
    assert_eq!(ages.get(&"Omar"), Some(&33));
    assert_eq!(ages.contains_key(&"Steve"), false);
    assert_eq!(ages.contains_key(&"Carol"), false);
    assert_eq!(ages.contains_key(&"Ellie"), false);

    assert_eq!(ages.reverse_to_next(), true);
    assert_eq!(ages.current_tag(), Some(&"middle"));

    assert_eq!(ages.get(&"Sarah"), Some(&22));
    assert_eq!(ages.get(&"John"), Some(&21));
    assert_eq!(ages.get(&"Mariah"), Some(&45));
    assert_eq!(ages.contains_key(&"Steve"), false);
    assert_eq!(ages.contains_key(&"Carol"), false);
    assert_eq!(ages.contains_key(&"Ellie"), false);
    assert_eq!(ages.contains_key(&"Omar"), false);

    assert_eq!(ages.reverse_to_next(), true);
    assert_eq!(ages.current_tag(), Some(&"start"));

    assert_eq!(ages.contains_key(&"Sarah"), false);
    assert_eq!(ages.contains_key(&"John"), false);
    assert_eq!(ages.contains_key(&"Mariah"), false);

    assert_eq!(ages.reverse_to_next(), false);
    assert_eq!(ages.current_tag(), Some(&"start"));
}

#[test]
fn test_tag_forward() {
    let mut ages: JournalMap<&'static str, i32, _> = JournalMap::new();

    ages.append_tag("start").unwrap();

    ages.insert("Sarah", 22);
    ages.insert("John", 21);
    ages.insert("Mariah", 45);

    ages.append_tag("middle").unwrap();

    ages.insert("Steve", 34);
    ages.insert("Carol", 41);
    ages.insert("Ellie", 21);
    ages.insert("Mariah", 87);

    ages.append_tag("end").unwrap();

    ages.reverse_to_tag(&"middle");

    assert_eq!(ages.get(&"Sarah"), Some(&22));
    assert_eq!(ages.get(&"John"), Some(&21));
    assert_eq!(ages.get(&"Mariah"), Some(&45));
    assert_eq!(ages.contains_key(&"Steve"), false);
    assert_eq!(ages.contains_key(&"Carol"), false);
    assert_eq!(ages.contains_key(&"Ellie"), false);

    assert_eq!(ages.forward_to_tag(&"end"), true);

    assert_eq!(ages.get(&"Sarah"), Some(&22));
    assert_eq!(ages.get(&"John"), Some(&21));
    assert_eq!(ages.get(&"Mariah"), Some(&87));
    assert_eq!(ages.get(&"Steve"), Some(&34));
    assert_eq!(ages.get(&"Carol"), Some(&41));
    assert_eq!(ages.get(&"Ellie"), Some(&21));

    ages.reverse_to_next();

    ages.insert("Omar", 33);

    ages.append_tag("end").unwrap();

    ages.reverse_to_next();

    assert_eq!(ages.forward_to_next(), true);

    assert_eq!(ages.get(&"Sarah"), Some(&22));
    assert_eq!(ages.get(&"John"), Some(&21));
    assert_eq!(ages.get(&"Mariah"), Some(&45));
    assert_eq!(ages.get(&"Omar"), Some(&33));
    assert_eq!(ages.contains_key(&"Steve"), false);
    assert_eq!(ages.contains_key(&"Carol"), false);
    assert_eq!(ages.contains_key(&"Ellie"), false);

    assert_eq!(ages.forward_to_next(), false);
}

#[test]
fn test_tag_retention() {
    let mut ages: JournalMap<&'static str, i32, _> = JournalMap::new();

    ages.append_tag("start").unwrap();
    ages.append_tag("middle").unwrap();
    ages.append_tag("end").unwrap();

    ages.reverse_to_tag(&"middle");

    ages.retain_tags(|tag| tag != &"middle");

    ages.reverse_to_next();

    assert_eq!(ages.current_tag(), Some(&"end"));

    ages.reverse_to_next();

    assert_eq!(ages.current_tag(), Some(&"start"));
}