loro-internal 1.12.0

Loro internal library. Do not use it directly as it's not stable.
Documentation
use loro_common::{LoroResult, PeerID};
use loro_internal::{handler::TreeHandler, LoroDoc, ToJson, TreeID, TreeParentId};
use pretty_assertions::assert_eq;
use serde_json::{json, Value};

fn deep_json(doc: &LoroDoc) -> Value {
    doc.get_deep_value().to_json_value()
}

#[test]
fn detached_tree_handler_queries_and_clear_follow_contracts() -> LoroResult<()> {
    let tree = TreeHandler::new_detached();
    assert_eq!(format!("{tree:?}"), "TreeHandler Detached");
    assert!(tree.is_fractional_index_enabled());
    tree.enable_fractional_index(2);
    tree.disable_fractional_index();
    assert!(!tree.is_deleted());
    assert!(tree.is_empty());
    assert_eq!(tree.__internal__next_tree_id(), TreeID::new(PeerID::MAX, 0));

    let root = tree.create(TreeParentId::Root)?;
    let first = tree.create_at(root.into(), 0)?;
    let second = tree.create_at(root.into(), 1)?;
    let third = tree.create_at(root.into(), 2)?;

    assert_eq!(tree.__internal__next_tree_id(), TreeID::new(PeerID::MAX, 4));
    assert_eq!(tree.get_child_at(&TreeParentId::Root, 0), Some(root));
    assert_eq!(tree.get_child_at(&root.into(), 0), Some(first));
    assert_eq!(tree.get_child_at(&root.into(), 1), Some(second));
    assert_eq!(tree.get_child_at(&root.into(), 2), Some(third));
    assert_eq!(tree.get_child_at(&root.into(), 3), None);
    assert_eq!(tree.get_index_by_tree_id(&second), Some(1));
    assert!(tree.get_position_by_tree_id(&second).is_some());
    assert!(tree
        .get_position_by_tree_id(&TreeID::new(PeerID::MAX, 99))
        .is_none());
    assert!(tree.is_parent(&second, &root.into()));
    assert_eq!(tree.get_nodes_under(TreeParentId::Root).len(), 4);
    assert_eq!(tree.get_nodes_under(root.into()).len(), 3);
    assert_eq!(tree.nodes().len(), 4);

    tree.mov_before(third, first)?;
    assert_eq!(
        tree.children(&root.into()),
        Some(vec![third, first, second])
    );
    tree.mov_after(third, second)?;
    assert_eq!(
        tree.children(&root.into()),
        Some(vec![first, second, third])
    );
    tree.move_to(third, TreeParentId::Root, 0)?;
    assert_eq!(tree.children(&TreeParentId::Root), Some(vec![third, root]));

    tree.delete(third)?;
    assert!(!tree.contains(third));
    assert_eq!(tree.get_node_parent(&third), None);

    tree.clear()?;
    assert!(tree.is_empty());
    assert_eq!(tree.roots(), Vec::<TreeID>::new());
    assert_eq!(tree.nodes(), Vec::<TreeID>::new());

    Ok(())
}

#[test]
fn attached_tree_hierarchy_positions_and_diff_apply_follow_contracts() -> LoroResult<()> {
    let doc = LoroDoc::new_auto_commit();
    doc.set_peer_id(77)?;
    let tree = doc.get_tree("outline");
    tree.enable_fractional_index(2);

    let root = tree.create(TreeParentId::Root)?;
    let first = tree.create_at(root.into(), 0)?;
    let second = tree.create_at(root.into(), 1)?;
    tree.get_meta(root)?.insert("name", "root")?;
    tree.get_meta(first)?.insert("name", "first")?;
    tree.get_meta(second)?.insert("name", "second")?;

    assert!(format!("{tree:?}").contains("TreeHandler"));
    assert_eq!(tree.get_child_at(&TreeParentId::Root, 0), Some(root));
    assert_eq!(tree.get_child_at(&root.into(), 0), Some(first));
    assert_eq!(tree.get_child_at(&root.into(), 1), Some(second));
    assert_eq!(tree.get_index_by_tree_id(&second), Some(1));
    assert!(tree.get_position_by_tree_id(&second).is_some());
    assert!(tree.get_last_move_id(&root).is_some());

    let hierarchy = tree.get_all_hierarchy_nodes_under(TreeParentId::Root);
    assert_eq!(hierarchy.len(), 1);
    assert_eq!(hierarchy[0].id, root);
    assert_eq!(hierarchy[0].children.len(), 2);
    assert_eq!(hierarchy[0].children[0].id, first);
    assert_eq!(hierarchy[0].children[1].id, second);

    doc.commit_then_renew();
    let v1 = doc.state_frontiers();
    let before = deep_json(&doc);

    tree.move_to(second, TreeParentId::Root, 0)?;
    tree.delete(first)?;
    tree.get_meta(second)?.insert("status", "promoted")?;
    doc.commit_then_renew();
    let v2 = doc.state_frontiers();
    let after = deep_json(&doc);
    assert_ne!(before, after);

    let fork = doc.fork_at(&v1)?;
    assert_eq!(deep_json(&fork), before);
    fork.apply_diff(doc.diff(&v1, &v2)?)?;
    assert_eq!(deep_json(&fork), after);

    tree.clear()?;
    doc.commit_then_renew();
    assert!(tree.is_empty());
    assert_eq!(deep_json(&doc), json!({"outline": []}));

    Ok(())
}