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 let build_num value = ScTypes.number @@ DataType.Num.of_int value (** 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 (build_num (-1))) 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 (build_num 123)) 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 (** Overide the value after a cycle. *) let test_recover_from_cycle ctx = begin let s = Sheet.Raw.empty |> Sheet.Raw.add (2,2) @@ Expression.load @@ u"=B2 + 1" |> snd |> Sheet.Raw.add (2,2) @@ Expression.load @@ u"=6" |> snd in let result = (Sheet.Raw.get_value (2, 2) s) in let expected = Some (ScTypes.Result (build_num (6))) 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 (build_num 4)) 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 test_paste_undo ctx = begin let empty = Sheet.create Sheet.Raw.empty in (* The expected result for the whole test *) let expected = Some (ScTypes.Result (ScTypes.number (DataType.Num.of_int 6))) in let sheet = empty |> Tools.Option.test @@ Sheet.move (Actions.Absolute (2, 1)) |> Sheet.add (Expression.load @@ u"=6") |> snd |> Tools.Option.test @@ Sheet.move (Actions.Absolute (1, 1)) |> Sheet.add (Expression.load @@ u"=B1") |> snd in let result = Sheet.Raw.get_value (1, 1) sheet.Sheet.data in (* Ensure the value is correctly evaluated *) assert_equal ~msg:(_msg ~expected ~result) expected result; let sheet2 = (* Copy the cell *) fst @@ Sheet.yank sheet |> Tools.Option.test @@ Sheet.move (Actions.Absolute (2, 1)) (* Paste it on another value *) |> Sheet.paste |> fst (* Undo the paste *) |> Tools.Option.test @@ Sheet.undo in let result = Sheet.Raw.get_value (1, 1) sheet2.Sheet.data in (* The value should be the same as the first evaluation *) assert_equal ~msg:(_msg ~expected ~result) 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_recover_cycle" >:: test_recover_from_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; "test_paste_undo" >:: test_paste_undo; ]