(* This file is part of licht. licht is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. licht is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with licht. If not, see . *) open OUnit2 module Option = Tools.Option let u = UTF8.from_utf8string let catalog = Functions.C.compile @@ Functions.built_in Functions.C.empty 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.Type.number @@ DataType.Num.of_int value (** Test a simple references between two cells *) let test_create_ref_1 ctx = begin let s = Sheet.create catalog in ignore @@ Sheet.add ~history:false (Expression.load @@ u"=-1") (3,3) s; ignore @@ Sheet.add ~history:false (Expression.load @@ u"=C3") (0,0) s; let _, result, _ = Sheet.get_cell (0, 0) s in let expected = Some (ScTypes.Result.Ok (build_num (-1))) in assert_equal ~msg:(_msg ~expected ~result) expected result end let test_create_ref_2 ctx = begin let s = Sheet.create catalog in ignore @@ Sheet.add ~history:false (Expression.load @@ u"=C3") (2,2) s; ignore @@ Sheet.add ~history:false (Expression.load @@ u"=A1") (3,3) s; ignore @@ Sheet.add ~history:false (Expression.load @@ u"123") (1,1) s; let _, result, _ = Sheet.get_cell (2, 2) s in let expected = Some (ScTypes.Result.Ok (build_num 123)) in assert_equal ~msg:(_msg ~expected ~result) expected result end let test_create_direct_cycle ctx = begin let s = Sheet.create catalog in ignore @@ Sheet.add ~history:false (Expression.load @@ u"=B2 + 1") (2,2) s; let _, result, _ = Sheet.get_cell (2, 2) s in let expected = Some (ScTypes.Result.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.create catalog in ignore @@ Sheet.add ~history:false (Expression.load @@ u"=B2 + 1") (2,2) s; ignore @@ Sheet.add ~history:false (Expression.load @@ u"=6") (2,2) s; let _, result, _ = Sheet.get_cell (2, 2) s in let expected = Some (ScTypes.Result.Ok (build_num (6))) in assert_equal ~msg:(_msg ~expected ~result) expected result end let test_create_indirect_cycle ctx = begin let s = Sheet.create catalog in ignore @@ Sheet.add ~history:false (Expression.load @@ u"=A1") (2,2) s; ignore @@ Sheet.add ~history:false (Expression.load @@ u"=2") (1,1) s; ignore @@ Sheet.add ~history:false (Expression.load @@ u"=B2+1") (1,1) s; ignore @@ Sheet.add ~history:false (Expression.load @@ u"=A1") (0,0) s; let _, result, _ = Sheet.get_cell (0, 0) s in let expected = Some (ScTypes.Result.Error Errors.Cycle) in assert_equal ~msg:(_msg ~expected ~result) expected result end let test_check_cycle3 ctx = begin let s = Sheet.create catalog in (* First set A1 to 3 *) ignore @@ Sheet.add ~history:false (Expression.load @@ u"=3") (1,1) s; ignore @@ Sheet.add ~history:false (Expression.load @@ u"=A1") (1,2) s; ignore @@ Sheet.add ~history:false (Expression.load @@ u"=A1") (2,2) s; ignore @@ Sheet.add ~history:false (Expression.load @@ u"=B2") (5,5) s; (* A3 = A1 + A1 = 6 *) ignore @@ Sheet.add ~history:false (Expression.load @@ u"=A2 + E5") (1,3) s; (* Then set A1 to 2 *) ignore @@ Sheet.add ~history:false (Expression.load @@ u"=2") (1,1) s; let _, result, _ = Sheet.get_cell (1, 3) s in (* A3 = A1 + A1 = 4 *) let expected = Some (ScTypes.Result.Ok (build_num 4)) in assert_equal ~msg:(_msg ~expected ~result) expected result end let test_delete ctx = begin let s = Sheet.create catalog in ignore @@ Sheet.add ~history:false (Expression.load @@ u"=C3") (2,2) s; ignore @@ Sheet.add ~history:false (Expression.load @@ u"=A1") (3,3) s; ignore @@ Sheet.delete (Selection.create (2,2)) s; ignore @@ Sheet.delete (Selection.create (3,3)) s; let _, result, _ = Sheet.get_cell (3, 3) s in let expected = None in assert_equal ~msg:(_msg ~expected ~result) expected result end let test_update_succs1 ctx = begin let s = Sheet.create catalog in ignore @@ Sheet.add ~history:false (Expression.load @@ u" =1") (1,1) s; ignore @@ Sheet.add ~history:false (Expression.load @@ u"=A2") (2,2) s; ignore @@ Sheet.add ~history:false (Expression.load @@ u"=A1/1") (1,2) s; let result = Sheet.add ~history:false (Expression.load @@ u"=2") (1,1) s 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 s = Sheet.create catalog in ignore @@ Sheet.add ~history:false (Expression.load @@ u"=1") (1,1) s; ignore @@ Sheet.add ~history:false (Expression.load @@ u"=A2") (2,2) s; ignore @@ Sheet.add ~history:false (Expression.load @@ u"=A1/0") (1,2) s; let result = Sheet.add ~history:false (Expression.load @@ u"=2") (1,1) s 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 (* The expected result for the whole test *) let expected = Some (ScTypes.Result.Ok (ScTypes.Type.number (DataType.Num.of_int 6))) in let sheet = Sheet.create catalog in ignore @@ Sheet.add ~history:false (Expression.load @@ u"=6") (2, 1) sheet; ignore @@ Sheet.add ~history:false (Expression.load @@ u"=B1") (1, 1) sheet; let _, result, _ = Sheet.get_cell (1, 1) sheet in (* Ensure the value is correctly evaluated *) assert_equal ~msg:(_msg ~expected ~result) expected result; (* Copy the cell *) ignore @@ Sheet.yank (Selection.create (1, 1)) sheet; (* Paste it on another value *) ignore @@ Sheet.paste (2, 1) sheet; (* Undo the paste *) assert_equal true (Sheet.undo sheet); let _, result, _ = Sheet.get_cell (1, 1) sheet 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; ]