(** Test the behavior of the sqlite with a in-memory database *) open OUnit2 open StdLabels let ( let* ) res cont = match res with | Ok value -> cont value | Error e -> raise e (** Test a process with a simple configuration in-memory *) let run_test ~configuration ~input ~expected name = name >:: fun _ -> (* We expect a valid configuration *) let conf = ImportConf.t_of_toml (Otoml.Parser.from_string configuration) |> Result.get_ok in let exec db = let table = List.hd @@ ImportAnalyser.Dependency.get_process_order conf in let* () = ImportSQL.Db.create_table db table in (* Prepare the statement in order to import data *) let* stmt = ImportSQL.Db.prepare_insert db table in (* Inject some data into the table *) let result, _ = List.fold_left ~init:(Ok (), 0) input ~f:(fun (_, i) data -> let result = let* () = ImportSQL.Db.insert ~id:i db stmt data in let* () = ImportSQL.Db.reset stmt in Ok () in (result, i + 1)) in let* () = result in let* () = ImportSQL.Db.finalize stmt in let expected = ref expected in (* Collect the data *) let* () = ImportSQL.Db.query db conf ~f:(fun rows -> match !expected with | [] -> () | hd :: tl -> expected := tl; let () = Array.iter2 rows hd ~f:(fun (_, value) expected -> assert_equal ~printer:ImportCSV.DataType.to_string value expected) in ()) in Ok () in (* Use a magic keyword for in-memory database *) ignore @@ ImportSQL.Db.with_db ":memory:" exec (** Simple test used to check the process *) let simple_extraction = run_test "simple_extraction" ~configuration: {|version = 1 [source] name = "source_name" file = "source_file" [sheet] columns = [ ":A ^ '_'", ":B", ":E"]|} ~input: [ [ (0, ImportCSV.DataType.Integer 123); (1, ImportCSV.DataType.Integer 2); (4, ImportCSV.DataType.Integer 5); ]; ] ~expected: [ [| ImportCSV.DataType.Content "123_"; ImportCSV.DataType.Integer 2; ImportCSV.DataType.Integer 5; |]; ] (** Ensure the behavior of the sum function when a filter is given. It is expected to accumulate the values over each line *) let sum_sort = run_test "sum_sort" ~configuration: {|version = 1 [source] name = "source_name" file = "source_file" [sheet] columns = [ ":A", "sum(:C, [:B], [:A])", ]|} ~input: [ [ (0, ImportCSV.DataType.Integer 1); (1, ImportCSV.DataType.Content "A"); (2, ImportCSV.DataType.Integer 100); ]; [ (0, ImportCSV.DataType.Integer 2); (1, ImportCSV.DataType.Content "A"); (2, ImportCSV.DataType.Integer 100); ]; [ (0, ImportCSV.DataType.Integer 3); (1, ImportCSV.DataType.Content "A"); (2, ImportCSV.DataType.Integer 100); ]; ] ~expected: [ [| ImportCSV.DataType.Integer 1; ImportCSV.DataType.Integer 100 |]; [| ImportCSV.DataType.Integer 2; ImportCSV.DataType.Integer 200 |]; [| ImportCSV.DataType.Integer 3; ImportCSV.DataType.Integer 300 |]; ] let sum_total = run_test "sum_total" ~configuration: {|version = 1 [source] name = "source_name" file = "source_file" [sheet] columns = [ ":A", "sum(:C, [], [])", ]|} ~input: [ [ (0, ImportCSV.DataType.Integer 1); (2, ImportCSV.DataType.Integer 100); ]; [ (0, ImportCSV.DataType.Integer 2); (2, ImportCSV.DataType.Integer 100); ]; ] ~expected: [ [| ImportCSV.DataType.Integer 1; ImportCSV.DataType.Integer 200 |]; [| ImportCSV.DataType.Integer 2; ImportCSV.DataType.Integer 200 |]; ] (** Ensure the behavior of the sum function when no filter is given. It is expected to get the total sum for each line *) let sum_unfiltered = run_test "sum_unfiltered" ~configuration: {|version = 1 [source] name = "source_name" file = "source_file" [sheet] columns = [ ":A", "sum(:C, [], [:A])", ]|} ~input: [ [ (0, ImportCSV.DataType.Integer 1); (2, ImportCSV.DataType.Integer 100); ]; [ (0, ImportCSV.DataType.Integer 2); (2, ImportCSV.DataType.Integer 100); ]; ] ~expected: [ [| ImportCSV.DataType.Integer 1; ImportCSV.DataType.Integer 200 |]; [| ImportCSV.DataType.Integer 2; ImportCSV.DataType.Integer 200 |]; ] let test_suit = [ simple_extraction; sum_sort; sum_total; sum_unfiltered ] let tests = "sql_db" >::: test_suit