open OUnit2 module Option = Tools.Option let u = UTF8.from_utf8string let _msg ~expected ~result = begin let get_string v = match v with | None -> "Undefined" | Some x -> UTF8.raw_encode @@ ScTypes.Result.show x in Printf.sprintf "Expected %s but got %s" (get_string expected) (get_string result) end (** Test a simple references between two cells *) let test_create_ref_1 ctx = begin let s = Sheet.Raw.empty |> Sheet.Raw.add (3,3) @@ Expression.load @@ u"=-1" |> snd |> Sheet.Raw.add (0,0) @@ Expression.load @@ u"=C3" |> snd in let result = (Sheet.Raw.get_value (0, 0) s) in let expected = Some (ScTypes.Result (ScTypes.Num (Num.num_of_int (-1), None))) in assert_equal ~msg:(_msg ~expected ~result) expected result end let test_create_ref_2 ctx = begin let s = Sheet.Raw.empty |> Sheet.Raw.add (2,2) @@ Expression.load @@ u"=C3" |> snd |> Sheet.Raw.add (3,3) @@ Expression.load @@ u"=A1" |> snd |> Sheet.Raw.add (1,1) @@ Expression.load @@ u"123" |> snd in let result = (Sheet.Raw.get_value (2, 2) s) in let expected = Some (ScTypes.Result (ScTypes.Num (Num.num_of_int 123, None))) in assert_equal ~msg:(_msg ~expected ~result) expected result end let test_create_direct_cycle ctx = begin let s = Sheet.Raw.empty |> Sheet.Raw.add (2,2) @@ Expression.load @@ u"=B2 + 1" |> snd in let result = (Sheet.Raw.get_value (2, 2) s) in let expected = Some (ScTypes.Error Errors.TypeError) in assert_equal ~msg:(_msg ~expected ~result) expected result end let test_create_indirect_cycle ctx = begin let s = Sheet.Raw.empty |> Sheet.Raw.add (2,2) @@ Expression.load @@ u"=A1" |> snd |> Sheet.Raw.add (1,1) @@ Expression.load @@ u"=2" |> snd |> Sheet.Raw.add (1,1) @@ Expression.load @@ u"=B2+1" |> snd |> Sheet.Raw.add (0,0) @@ Expression.load @@ u"=A1" |> snd in let result = (Sheet.Raw.get_value (0, 0) s) in let expected = Some (ScTypes.Error Errors.Cycle) in assert_equal ~msg:(_msg ~expected ~result) expected result end let test_check_cycle3 ctx = begin let s = Sheet.Raw.empty (* First set A1 to 3 *) |> Sheet.Raw.add (1,1) @@ Expression.load @@ u"=3" |> snd |> Sheet.Raw.add (1,2) @@ Expression.load @@ u"=A1" |> snd |> Sheet.Raw.add (2,2) @@ Expression.load @@ u"=A1" |> snd |> Sheet.Raw.add (5,5) @@ Expression.load @@ u"=B2" (* A3 = A1 + A1 = 6 *) |> snd |> Sheet.Raw.add (1,3) @@ Expression.load @@ u"=A2 + E5" (* Then set A1 to 2 *) |> snd |> Sheet.Raw.add (1,1) @@ Expression.load @@ u"=2" |> snd in let result = (Sheet.Raw.get_value (1, 3) s) in (* A3 = A1 + A1 = 4 *) let expected = Some (ScTypes.Result (ScTypes.Num (Num.num_of_int 4, None))) in assert_equal ~msg:(_msg ~expected ~result) expected result end let test_delete ctx = begin let s = Sheet.Raw.empty |> Sheet.Raw.add (2,2) @@ Expression.load @@ u"=C3" |> snd |> Sheet.Raw.add (3,3) @@ Expression.load @@ u"=A1" |> snd |> Sheet.Raw.remove (2,2) |> snd |> Sheet.Raw.remove (3,3) |> snd in let result = (Sheet.Raw.get_value (3, 3) s) in let expected = None in assert_equal ~msg:(_msg ~expected ~result) expected result end let test_update_succs1 ctx = begin let result = Sheet.Raw.empty |> Sheet.Raw.add (1,1) @@ Expression.load @@ u" =1" |> snd |> Sheet.Raw.add (2,2) @@ Expression.load @@ u"=A2" |> snd |> Sheet.Raw.add (1,2) @@ Expression.load @@ u"=A1/1" |> snd |> Sheet.Raw.add (1,1) @@ Expression.load @@ u"=2" |> fst in (* All the cells are updated by the change *) let expected = Cell.Set.of_list [(1,1); (1, 2); (2,2)] in let msg = Printf.sprintf "Expected %s but got %s" (UTF8.raw_encode @@ Tools.String.print_buffer Cell.Set.printb expected) (UTF8.raw_encode @@ Tools.String.print_buffer Cell.Set.printb result) in assert_equal ~msg expected result end let test_update_succs2 ctx = begin let result = Sheet.Raw.empty |> Sheet.Raw.add (1,1) @@ Expression.load @@ u"=1" |> snd |> Sheet.Raw.add (2,2) @@ Expression.load @@ u"=A2" |> snd |> Sheet.Raw.add (1,2) @@ Expression.load @@ u"=A1/0" |> snd |> Sheet.Raw.add (1,1) @@ Expression.load @@ u"=2" |> fst in (* Only (1, 1) is updated ; (2, 2) does not change, neither (2, 2) *) let expected = Cell.Set.of_list [(1,1)] in assert_equal expected result end let tests = "sheet_test">::: [ "test_ref1" >:: test_create_ref_1; "test_ref2" >:: test_create_ref_2; "test_cycle1" >:: test_create_direct_cycle; "test_cycle2" >:: test_create_indirect_cycle; "test_cycle3" >:: test_check_cycle3; "test_delete" >:: test_delete; "test_update_succs1" >:: test_update_succs1; "test_update_succs2" >:: test_update_succs2; ]