ocaml-containers/tests/test_RoseTree.ml

597 lines
17 KiB
OCaml

open Containers_misc
open OUnit
let format_node = Format.pp_print_int
let string_of_tree tree =
CCFormat.sprintf "%a" (RoseTree.print format_node) tree
let assert_equal_tree expected_tree_rep tree =
let expected_tree_rep_string =
(String.concat "\n" expected_tree_rep) ^ "\n"
in
let tree_as_string = string_of_tree tree in
assert_equal ~printer:(fun x -> x) expected_tree_rep_string tree_as_string
let assert_equal_zipper expected_tree_rep zipper =
assert_equal_tree expected_tree_rep (RoseTree.Zipper.tree zipper)
let single_node_tree = `Node (10, [])
let single_tree_strings = ["10"]
let normal_tree =
`Node (0, [
`Node (1, [
`Node (10, []) ;
]) ;
`Node (2, [
`Node (20, []) ;
`Node (21, []) ;
]) ;
`Node (3, [
`Node (30, []) ;
`Node (31, []) ;
`Node (32, []) ;
]) ;
])
let normal_tree_strings = [
"0" ;
"|- 1" ;
"| '- 10" ;
"|- 2" ;
"| |- 20" ;
"| '- 21" ;
"'- 3" ;
" |- 30" ;
" |- 31" ;
" '- 32" ;
]
let new_tree =
`Node (100, [
`Node (1000, [
`Node (10000, []) ;
]) ;
`Node (1001, [
`Node (10010, []) ;
`Node (10012, []) ;
]) ;
])
let new_tree_strings = [
"100" ;
"|- 1000" ;
"| '- 10000" ;
"'- 1001" ;
" |- 10010" ;
" '- 10012" ;
]
let test_print_single_node_tree () =
let expected = single_tree_strings in
assert_equal_tree expected single_node_tree
let test_print_normal_tree () =
let expected = normal_tree_strings in
assert_equal_tree expected normal_tree
let test_fold_single_node_tree () =
let tree_double_sum = RoseTree.fold ~f:(fun value acc -> acc + value * 2) 0 single_node_tree
in
assert_equal 20 tree_double_sum
let test_fold_normal_tree () =
let tree_sum = RoseTree.fold ~f:(fun value acc -> acc + value) 0 normal_tree
in
assert_equal 150 tree_sum
let test_base_zipper_single_node_tree () =
let expected = single_tree_strings in
assert_equal_zipper expected (RoseTree.Zipper.zipper single_node_tree)
let test_base_zipper_normal_tree () =
let expected = normal_tree_strings in
assert_equal_zipper expected (RoseTree.Zipper.zipper normal_tree)
let test_zipper_nth_child_0 () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 0
|> CCOpt.get_exn
in
let expected = [
"1" ;
"'- 10" ;
]
in
assert_equal_zipper expected zipper
let test_zipper_nth_child_1 () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 1
|> CCOpt.get_exn
in
let expected = [
"2" ;
"|- 20" ;
"'- 21" ;
]
in
assert_equal_zipper expected zipper
let test_zipper_nth_child_2 () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 2
|> CCOpt.get_exn
in
let expected = [
"3" ;
"|- 30" ;
"|- 31" ;
"'- 32" ;
]
in
assert_equal_zipper expected zipper
let test_zipper_nth_child_does_not_exist () =
let maybe_zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 3
in
assert_equal false (CCOpt.is_some maybe_zipper)
let test_zipper_nth_child_negative_index () =
let maybe_zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child (-2)
in
assert_equal false (CCOpt.is_some maybe_zipper)
let test_zipper_nth_child_plus_parent_is_noop () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 2
|> CCOpt.get_exn
|> RoseTree.Zipper.parent
|> CCOpt.get_exn
in
let expected = normal_tree_strings in
assert_equal_zipper expected zipper
let test_zipper_left_sibling () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 2
|> CCOpt.get_exn
|> RoseTree.Zipper.left_sibling
|> CCOpt.get_exn
in
let expected = [
"2" ;
"|- 20" ;
"'- 21" ;
]
in
assert_equal_zipper expected zipper
let test_zipper_left_sibling_twice () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 2
|> CCOpt.get_exn
|> RoseTree.Zipper.left_sibling
|> CCOpt.get_exn
|> RoseTree.Zipper.left_sibling
|> CCOpt.get_exn
in
let expected = [
"1" ;
"'- 10" ;
]
in
assert_equal_zipper expected zipper
let test_zipper_left_sibling_does_not_exist () =
let maybe_zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 2
|> CCOpt.get_exn
|> RoseTree.Zipper.left_sibling
|> CCOpt.get_exn
|> RoseTree.Zipper.left_sibling
|> CCOpt.get_exn
|> RoseTree.Zipper.left_sibling
in
assert_equal false (CCOpt.is_some maybe_zipper)
let test_zipper_nth_child_plus_left_sibling_plus_parent_is_noop () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 2
|> CCOpt.get_exn
|> RoseTree.Zipper.left_sibling
|> CCOpt.get_exn
|> RoseTree.Zipper.parent
|> CCOpt.get_exn
in
let expected = normal_tree_strings in
assert_equal_zipper expected zipper
let test_zipper_right_sibling () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 0
|> CCOpt.get_exn
|> RoseTree.Zipper.right_sibling
|> CCOpt.get_exn
in
let expected = [
"2" ;
"|- 20" ;
"'- 21" ;
]
in
assert_equal_zipper expected zipper
let test_zipper_right_sibling_twice () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 0
|> CCOpt.get_exn
|> RoseTree.Zipper.right_sibling
|> CCOpt.get_exn
|> RoseTree.Zipper.right_sibling
|> CCOpt.get_exn
in
let expected = [
"3" ;
"|- 30" ;
"|- 31" ;
"'- 32" ;
]
in
assert_equal_zipper expected zipper
let test_zipper_right_sibling_does_not_exist () =
let maybe_zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 0
|> CCOpt.get_exn
|> RoseTree.Zipper.right_sibling
|> CCOpt.get_exn
|> RoseTree.Zipper.right_sibling
|> CCOpt.get_exn
|> RoseTree.Zipper.right_sibling
in
assert_equal false (CCOpt.is_some maybe_zipper)
let test_zipper_nth_child_plus_right_sibling_plus_parent_is_noop () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 0
|> CCOpt.get_exn
|> RoseTree.Zipper.right_sibling
|> CCOpt.get_exn
|> RoseTree.Zipper.parent
|> CCOpt.get_exn
in
let expected = normal_tree_strings in
assert_equal_zipper expected zipper
let test_parent () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 0
|> CCOpt.get_exn
|> RoseTree.Zipper.nth_child 0
|> CCOpt.get_exn
|> RoseTree.Zipper.parent
|> CCOpt.get_exn
in
let expected = [
"1" ;
"'- 10" ;
] in
assert_equal_zipper expected zipper
let test_parent_on_root () =
let maybe_zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.parent
in
assert_equal false (CCOpt.is_some maybe_zipper)
let test_root () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 0
|> CCOpt.get_exn
|> RoseTree.Zipper.nth_child 0
|> CCOpt.get_exn
|> RoseTree.Zipper.root
in
let expected = normal_tree_strings in
assert_equal_zipper expected zipper
let test_root_on_root () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.root
in
let expected = normal_tree_strings in
assert_equal_zipper expected zipper
let test_insert_left_sibling () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 0
|> CCOpt.get_exn
|> RoseTree.Zipper.nth_child 0
|> CCOpt.get_exn
|> RoseTree.Zipper.insert_left_sibling new_tree
|> CCOpt.get_exn
|> RoseTree.Zipper.root
in
let expected = [
"0" ;
"|- 1" ;
"| |- 100" ;
"| | |- 1000" ;
"| | | '- 10000" ;
"| | '- 1001" ;
"| | |- 10010" ;
"| | '- 10012" ;
"| '- 10" ;
"|- 2" ;
"| |- 20" ;
"| '- 21" ;
"'- 3" ;
" |- 30" ;
" |- 31" ;
" '- 32" ;
] in
assert_equal_zipper expected zipper
let test_insert_left_sibling_focuses_on_new_tree () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 0
|> CCOpt.get_exn
|> RoseTree.Zipper.nth_child 0
|> CCOpt.get_exn
|> RoseTree.Zipper.insert_left_sibling new_tree
|> CCOpt.get_exn
in
let expected = new_tree_strings
in
assert_equal_zipper expected zipper
let test_insert_left_sibling_on_root () =
let maybe_zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.insert_left_sibling new_tree
in
assert_equal false (CCOpt.is_some maybe_zipper)
let test_insert_right_sibling () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 0
|> CCOpt.get_exn
|> RoseTree.Zipper.nth_child 0
|> CCOpt.get_exn
|> RoseTree.Zipper.insert_right_sibling new_tree
|> CCOpt.get_exn
|> RoseTree.Zipper.root
in
let expected = [
"0" ;
"|- 1" ;
"| |- 10" ;
"| '- 100" ;
"| |- 1000" ;
"| | '- 10000" ;
"| '- 1001" ;
"| |- 10010" ;
"| '- 10012" ;
"|- 2" ;
"| |- 20" ;
"| '- 21" ;
"'- 3" ;
" |- 30" ;
" |- 31" ;
" '- 32" ;
] in
assert_equal_zipper expected zipper
let test_insert_right_sibling_focuses_on_new_tree () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 0
|> CCOpt.get_exn
|> RoseTree.Zipper.nth_child 0
|> CCOpt.get_exn
|> RoseTree.Zipper.insert_right_sibling new_tree
|> CCOpt.get_exn
in
let expected = new_tree_strings
in
assert_equal_zipper expected zipper
let test_insert_right_sibling_on_root () =
let maybe_zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.insert_right_sibling new_tree
in
assert_equal false (CCOpt.is_some maybe_zipper)
let test_append_child () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 2
|> CCOpt.get_exn
|> RoseTree.Zipper.append_child new_tree
|> RoseTree.Zipper.root
in
let expected = [
"0" ;
"|- 1" ;
"| '- 10" ;
"|- 2" ;
"| |- 20" ;
"| '- 21" ;
"'- 3" ;
" |- 30" ;
" |- 31" ;
" |- 32" ;
" '- 100" ;
" |- 1000" ;
" | '- 10000" ;
" '- 1001" ;
" |- 10010" ;
" '- 10012" ;
]
in
assert_equal_zipper expected zipper
let test_append_child_focuses_on_new_tree () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 2
|> CCOpt.get_exn
|> RoseTree.Zipper.append_child new_tree
in
let expected = new_tree_strings
in
assert_equal_zipper expected zipper
let test_replace () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 1
|> CCOpt.get_exn
|> RoseTree.Zipper.replace new_tree
|> RoseTree.Zipper.root
in
let expected = [
"0" ;
"|- 1" ;
"| '- 10" ;
"|- 100" ;
"| |- 1000" ;
"| | '- 10000" ;
"| '- 1001" ;
"| |- 10010" ;
"| '- 10012" ;
"'- 3" ;
" |- 30" ;
" |- 31" ;
" '- 32" ;
]
in
assert_equal_zipper expected zipper
let test_replace_focuses_on_new_tree () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 1
|> CCOpt.get_exn
|> RoseTree.Zipper.replace new_tree
in
let expected = new_tree_strings in
assert_equal_zipper expected zipper
let test_replace_root () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.replace new_tree
in
let expected = new_tree_strings in
assert_equal_zipper expected zipper
let test_delete () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 1
|> CCOpt.get_exn
|> RoseTree.Zipper.delete
|> CCOpt.get_exn
|> RoseTree.Zipper.root
in
let expected = [
"0" ;
"|- 1" ;
"| '- 10" ;
"'- 3" ;
" |- 30" ;
" |- 31" ;
" '- 32" ;
]
in
assert_equal_zipper expected zipper
let test_delete_focuses_on_leftmost_sibling_if_possible () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 1
|> CCOpt.get_exn
|> RoseTree.Zipper.delete
|> CCOpt.get_exn
in
let expected = [
"1" ;
"'- 10" ;
]
in
assert_equal_zipper expected zipper
let test_delete_focuses_on_rightmost_sibling_if_no_left_sibling () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 0
|> CCOpt.get_exn
|> RoseTree.Zipper.delete
|> CCOpt.get_exn
in
let expected = [
"2" ;
"|- 20" ;
"'- 21" ;
]
in
assert_equal_zipper expected zipper
let test_delete_focuses_on_parent_if_no_more_siblings () =
let zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.nth_child 0
|> CCOpt.get_exn
|> RoseTree.Zipper.nth_child 0
|> CCOpt.get_exn
|> RoseTree.Zipper.delete
|> CCOpt.get_exn
in
let expected = ["1"] in
assert_equal_zipper expected zipper
let test_delete_root () =
let maybe_zipper = RoseTree.Zipper.zipper normal_tree
|> RoseTree.Zipper.delete
in
assert_equal false (CCOpt.is_some maybe_zipper)
let suite =
"test_RoseTree" >:::
[
"test_print_single_node_tree" >:: test_print_single_node_tree ;
"test_print_normal_tree" >:: test_print_normal_tree ;
"test_fold_single_node_tree" >:: test_fold_single_node_tree ;
"test_fold_normal_tree" >:: test_fold_normal_tree ;
"test_base_zipper_single_node_tree" >:: test_base_zipper_single_node_tree ;
"test_base_zipper_normal_tree" >:: test_base_zipper_normal_tree ;
"test_zipper_nth_child_0" >:: test_zipper_nth_child_0 ;
"test_zipper_nth_child_1" >:: test_zipper_nth_child_1 ;
"test_zipper_nth_child_2" >:: test_zipper_nth_child_2 ;
"test_zipper_nth_child_does_not_exist" >:: test_zipper_nth_child_does_not_exist ;
"test_zipper_nth_child_negative_index" >:: test_zipper_nth_child_negative_index ;
"test_zipper_nth_child_plus_parent_is_noop" >:: test_zipper_nth_child_plus_parent_is_noop ;
"test_zipper_left_sibling" >:: test_zipper_left_sibling ;
"test_zipper_left_sibling_twice" >:: test_zipper_left_sibling_twice ;
"test_zipper_left_sibling_does_not_exist" >:: test_zipper_left_sibling_does_not_exist ;
"test_zipper_nth_child_plus_left_sibling_plus_parent_is_noop" >:: test_zipper_nth_child_plus_left_sibling_plus_parent_is_noop ;
"test_zipper_right_sibling" >:: test_zipper_right_sibling ;
"test_zipper_right_sibling_twice" >:: test_zipper_right_sibling_twice ;
"test_zipper_right_sibling_does_not_exist" >:: test_zipper_right_sibling_does_not_exist ;
"test_zipper_nth_child_plus_right_sibling_plus_parent_is_noop" >:: test_zipper_nth_child_plus_right_sibling_plus_parent_is_noop ;
"test_parent" >:: test_parent ;
"test_parent_on_root" >:: test_parent_on_root ;
"test_root" >:: test_root ;
"test_root_on_root" >:: test_root_on_root ;
"test_insert_left_sibling" >:: test_insert_left_sibling ;
"test_insert_left_sibling_focuses_on_new_tree" >:: test_insert_left_sibling_focuses_on_new_tree ;
"test_insert_left_sibling_on_root" >:: test_insert_left_sibling_on_root ;
"test_insert_right_sibling" >:: test_insert_right_sibling ;
"test_insert_right_sibling_focuses_on_new_tree" >:: test_insert_right_sibling_focuses_on_new_tree ;
"test_insert_right_sibling_on_root" >:: test_insert_right_sibling_on_root ;
"test_append_child" >:: test_append_child ;
"test_append_child_focuses_on_new_tree" >:: test_append_child_focuses_on_new_tree ;
"test_replace" >:: test_replace ;
"test_replace_focuses_on_new_tree" >:: test_replace_focuses_on_new_tree ;
"test_replace_root" >:: test_replace_root ;
"test_delete" >:: test_delete ;
"test_delete_focuses_on_leftmost_sibling_if_possible" >:: test_delete_focuses_on_leftmost_sibling_if_possible ;
"test_delete_focuses_on_rightmost_sibling_if_no_left_sibling" >:: test_delete_focuses_on_rightmost_sibling_if_no_left_sibling ;
"test_delete_focuses_on_parent_if_no_more_siblings" >:: test_delete_focuses_on_parent_if_no_more_siblings ;
"test_delete_root" >:: test_delete_root ;
]