A fork of mtelver's day10 project
1(** Unit tests for Day10_lib.Run_log module. *)
2
3let test_dir = ref ""
4
5let setup () =
6 let dir = Filename.temp_dir "test-run-log-" "" in
7 test_dir := dir;
8 Day10_lib.Run_log.set_log_base_dir dir;
9 dir
10
11let teardown () =
12 if !test_dir <> "" then begin
13 ignore (Sys.command (Printf.sprintf "rm -rf %s" !test_dir));
14 test_dir := ""
15 end
16
17let file_exists path = Sys.file_exists path
18
19let read_file path =
20 In_channel.with_open_text path In_channel.input_all
21
22(** Test: start_run creates directory structure *)
23let test_start_run_creates_dirs () =
24 let base_dir = setup () in
25 let run_info = Day10_lib.Run_log.start_run () in
26
27 (* Check runs directory exists *)
28 assert (file_exists (Filename.concat base_dir "runs"));
29
30 (* Check run-specific directories exist *)
31 let runs_dir = Filename.concat base_dir "runs" in
32 let entries = Sys.readdir runs_dir in
33 assert (Array.length entries = 1);
34
35 let run_dir = Filename.concat runs_dir entries.(0) in
36 assert (file_exists (Filename.concat run_dir "build"));
37 assert (file_exists (Filename.concat run_dir "docs"));
38
39 ignore run_info;
40 teardown ();
41 Printf.printf "PASS: test_start_run_creates_dirs\n%!"
42
43(** Test: finish_run creates summary.json *)
44let test_finish_run_creates_summary () =
45 let base_dir = setup () in
46 let run_info = Day10_lib.Run_log.start_run () in
47
48 let summary = Day10_lib.Run_log.finish_run run_info
49 ~targets_requested:10
50 ~solutions_found:8
51 ~build_success:7
52 ~build_failed:1
53 ~doc_success:5
54 ~doc_failed:1
55 ~doc_skipped:1
56 ~failures:[("bad-pkg.1.0.0", "build failed")] in
57
58 (* Check summary.json exists *)
59 let runs_dir = Filename.concat base_dir "runs" in
60 let entries = Sys.readdir runs_dir in
61 let run_dir = Filename.concat runs_dir entries.(0) in
62 let summary_file = Filename.concat run_dir "summary.json" in
63 assert (file_exists summary_file);
64
65 (* Check summary content *)
66 let content = read_file summary_file in
67 assert (String.length content > 0);
68 let json = Yojson.Safe.from_string content in
69 let open Yojson.Safe.Util in
70 assert (json |> member "targets_requested" |> to_int = 10);
71 assert (json |> member "build_success" |> to_int = 7);
72 assert (json |> member "build_failed" |> to_int = 1);
73
74 ignore summary;
75 teardown ();
76 Printf.printf "PASS: test_finish_run_creates_summary\n%!"
77
78(** Test: finish_run creates latest symlink *)
79let test_finish_run_creates_latest () =
80 let base_dir = setup () in
81 let run_info = Day10_lib.Run_log.start_run () in
82
83 let _ = Day10_lib.Run_log.finish_run run_info
84 ~targets_requested:1
85 ~solutions_found:1
86 ~build_success:1
87 ~build_failed:0
88 ~doc_success:1
89 ~doc_failed:0
90 ~doc_skipped:0
91 ~failures:[] in
92
93 (* Check latest symlink exists *)
94 let latest = Filename.concat base_dir "latest" in
95 assert (file_exists latest);
96
97 (* Check it's a symlink *)
98 let stats = Unix.lstat latest in
99 assert (stats.Unix.st_kind = Unix.S_LNK);
100
101 teardown ();
102 Printf.printf "PASS: test_finish_run_creates_latest\n%!"
103
104(** Test: add_build_log creates symlink *)
105let test_add_build_log () =
106 let base_dir = setup () in
107 let run_info = Day10_lib.Run_log.start_run () in
108
109 (* Create a source log file *)
110 let source_log = Filename.concat base_dir "source-build.log" in
111 Out_channel.with_open_text source_log (fun oc ->
112 Out_channel.output_string oc "Build output here\n");
113
114 Day10_lib.Run_log.add_build_log run_info ~package:"test-pkg.1.0.0" ~source_log;
115
116 (* Check log was linked/copied *)
117 let runs_dir = Filename.concat base_dir "runs" in
118 let entries = Sys.readdir runs_dir in
119 let run_dir = Filename.concat runs_dir entries.(0) in
120 let dest_log = Filename.concat (Filename.concat run_dir "build") "test-pkg.1.0.0.log" in
121 assert (file_exists dest_log);
122
123 teardown ();
124 Printf.printf "PASS: test_add_build_log\n%!"
125
126(** Test: add_doc_log creates symlink *)
127let test_add_doc_log () =
128 let base_dir = setup () in
129 let run_info = Day10_lib.Run_log.start_run () in
130
131 (* Create a source log file *)
132 let source_log = Filename.concat base_dir "source-doc.log" in
133 Out_channel.with_open_text source_log (fun oc ->
134 Out_channel.output_string oc "Doc output here\n");
135
136 Day10_lib.Run_log.add_doc_log run_info ~package:"test-pkg.1.0.0" ~source_log ();
137
138 (* Check log was linked/copied *)
139 let runs_dir = Filename.concat base_dir "runs" in
140 let entries = Sys.readdir runs_dir in
141 let run_dir = Filename.concat runs_dir entries.(0) in
142 let dest_log = Filename.concat (Filename.concat run_dir "docs") "test-pkg.1.0.0.log" in
143 assert (file_exists dest_log);
144
145 teardown ();
146 Printf.printf "PASS: test_add_doc_log\n%!"
147
148(** Test: summary_to_json produces valid JSON *)
149let test_summary_to_json () =
150 let summary : Day10_lib.Run_log.summary = {
151 run_id = "2026-02-04-120000";
152 start_time = "2026-02-04T12:00:00";
153 end_time = "2026-02-04T12:30:00";
154 duration_seconds = 1800.0;
155 targets_requested = 100;
156 solutions_found = 95;
157 build_success = 90;
158 build_failed = 5;
159 doc_success = 80;
160 doc_failed = 5;
161 doc_skipped = 5;
162 failures = [("pkg1.1.0", "error1"); ("pkg2.2.0", "error2")];
163 } in
164
165 let json = Day10_lib.Run_log.summary_to_json summary in
166 let str = Yojson.Safe.to_string json in
167 assert (String.length str > 0);
168
169 (* Parse back and verify *)
170 let parsed = Yojson.Safe.from_string str in
171 let open Yojson.Safe.Util in
172 assert (parsed |> member "run_id" |> to_string = "2026-02-04-120000");
173 assert (parsed |> member "targets_requested" |> to_int = 100);
174 assert (parsed |> member "failures" |> to_list |> List.length = 2);
175
176 Printf.printf "PASS: test_summary_to_json\n%!"
177
178let () =
179 Printf.printf "Running Run_log tests...\n%!";
180 test_start_run_creates_dirs ();
181 test_finish_run_creates_summary ();
182 test_finish_run_creates_latest ();
183 test_add_build_log ();
184 test_add_doc_log ();
185 test_summary_to_json ();
186 Printf.printf "\nAll Run_log tests passed!\n%!"