open OUnit2 open StdLabels module A = ImportAnalyser.Dependency module Cont = ImportContainers module Syntax = ImportConf.Syntax module Expression = ImportExpression.T module Table = ImportDataTypes.Table open ConfLoader let test_order = "Order" >:: fun _ -> let order = A.get_process_order conf |> List.map ~f:A.table in let expected_order = [ external_table_last; external_table_other; external_table_source ] in assert_equal ~cmp:(cmp_list cmp_source) ~printer:show_sources expected_order order let test_columns = "Columns" >:: fun _ -> let expected_colums = Cont.IntSet.of_list [ 1; 2 ] in let columns = A.get_process_order conf |> List.find ~f:(fun v -> A.table v = external_table_source) |> A.columns in assert_equal ~cmp:(fun a b -> 0 = Cont.IntSet.compare a b) ~printer:Cont.show_intSet expected_colums columns let test_keys = "Keys" >:: fun _ -> (* We should have one key in the table other, because it is referenced as a source in last file *) let expected_keys = A. [ { name = "other"; expression = Expression.Path 3; columns = lazy (Cont.IntSet.singleton 3); }; ] in let keys = A.get_process_order conf |> List.find ~f:(fun v -> A.table v = external_table_other) |> A.keys in assert_equal ~cmp:(cmp_list key_cmp) ~printer:keys_printer expected_keys keys let test_keys_missing = "Keys missing" >:: fun _ -> (* We have no key in last_file because the key is declared as missing *) let expected_keys = A. [ { name = "last_file"; expression = Expression.Path 3; columns = lazy (Cont.IntSet.singleton 3); }; ] in let keys = A.get_process_order conf |> List.find ~f:(fun v -> A.table v = external_table_last) |> A.keys in assert_equal ~cmp:(cmp_list key_cmp) ~printer:keys_printer expected_keys keys let test_unknow_source = "Unknown source" >:: fun _ -> let conf = { conf with externals = [] } in assert_raises (ImportErrors.Unknown_source "last_file") (fun () -> A.get_process_order conf) let test_unordered = "Unorderd references" >:: fun _ -> (* Externals not described in the right order shall not raise any error. *) let conf = load {|version = 1 [source] file = "source.xlsx" name = "source" [externals.last_file] intern_key = ":other.A" file = "last.xlsx" extern_key = ":C" allow_missing = true [externals.other] intern_key = ":A" file = "other.xlsx" extern_key = ":C" allow_missing = false [sheet] columns = []|} in assert_raises (ImportErrors.Unknown_source "other") (fun () -> A.get_process_order conf) let test_circular = "Unlinked reference" >:: fun _ -> (* A reference to itself should be understood *) let conf = load {|version = 1 [source] file = "source.xlsx" name = "source" [externals.circular] intern_key = ":circular.A" file = "last.xlsx" extern_key = ":A" allow_missing = true [sheet] columns = []|} in let elements = A.get_process_order conf in assert_equal ~printer:string_of_int 1 (List.length elements) let test_unlinked = "Circular reference" >:: fun _ -> (* An element linked to anything (except itself) should be ignored *) let conf = Syntax. { version = 1; source = external_table_source; externals = [ { intern_key = Path { alias = Some "circular2"; column = 1 }; target = { file = "other.xlsx"; tab = 1; name = "circular" }; extern_key = Path 3; allow_missing = true; match_rule = None; }; { intern_key = Path { alias = Some "circular"; column = 1 }; target = { file = "other2.xlsx"; tab = 1; name = "circular2" }; extern_key = Path 3; allow_missing = true; match_rule = None; }; ]; columns = []; filters = []; sort = []; uniq = []; } in assert_raises (ImportErrors.Unknown_source "circular2") (fun () -> A.get_process_order conf |> List.map ~f:A.table) let conf_with_unlinked = Syntax. { version = 1; source = external_table_source; externals = [ { intern_key = Path { alias = None; column = 1 }; target = { file = "other.xlsx"; tab = 1; name = "other" }; extern_key = Path 3; allow_missing = false; match_rule = None; }; ]; columns = [ Concat [ Path { alias = None; column = 1 }; Literal "_"; Empty ]; Path { alias = None; column = 2 }; ]; filters = []; sort = []; uniq = []; } (** A table referenced only in a filter list shall be loaded correctly *) let test_order_filter = "Order filter" >:: fun _ -> let order = { conf_with_unlinked with filters = [ Path { alias = Some "other"; column = 5 } ]; } |> A.get_process_order |> List.map ~f:A.table in let expected_order = [ external_table_other; external_table_source ] in assert_equal ~printer:show_sources expected_order order (** A table referenced only in the order list shall be loaded correctly *) let test_order_sort = "Order sort" >:: fun _ -> let order = { conf_with_unlinked with sort = [ Path { alias = Some "other"; column = 5 } ]; } |> A.get_process_order |> List.map ~f:A.table in let expected_order = [ external_table_other; external_table_source ] in assert_equal ~printer:show_sources expected_order order (** A table referenced only in the uniq list shall be loaded correctly *) let test_order_uniq = "Order uniq" >:: fun _ -> let order = { conf_with_unlinked with uniq = [ Path { alias = Some "other"; column = 5 } ]; } |> A.get_process_order |> List.map ~f:A.table in let expected_order = [ external_table_other; external_table_source ] in assert_equal ~printer:show_sources expected_order order let tests = "analyser_dependency" >::: [ test_order; test_columns; test_keys; test_keys_missing; test_unknow_source; test_unordered; test_circular; test_unlinked; test_order_filter; test_order_sort; test_order_uniq; ]