[OCaml] Mobile-friendly clone of cgit.
1
(** Configuration loading: round-tripping, backward compatibility, and rejection
2
of malformed files and out-of-range values. *)
3
4
open Test_helpers
5
6
let test_round_trip () =
7
with_temp_file "ogit" ".toml" (fun file ->
8
let config =
9
Ogit.Config.
10
{
11
user_name = "alice";
12
default_branch = "main";
13
git_project_root = "/srv/git";
14
commits_max_displayed = 25;
15
root_title = "";
16
nav_logo = "/branding/logo.svg";
17
host = "127.0.0.1";
18
port = 9000;
19
favorite_repositories = [];
20
archived_repositories = [];
21
}
22
in
23
Ogit.Config.write_file ~file (Ogit.Config.to_table config);
24
match Ogit.Config.read_file ~file () with
25
| Ok config' ->
26
Alcotest.(check string) "user_name" config.user_name config'.user_name;
27
Alcotest.(check string)
28
"branch" config.default_branch config'.default_branch;
29
Alcotest.(check string)
30
"root" config.git_project_root config'.git_project_root;
31
Alcotest.(check int)
32
"commits" config.commits_max_displayed config'.commits_max_displayed;
33
Alcotest.(check string) "host" config.host config'.host;
34
Alcotest.(check string) "nav_logo" config.nav_logo config'.nav_logo;
35
Alcotest.(check int) "port" config.port config'.port
36
| Error error -> fail_config_error error)
37
38
let test_backward_compat () =
39
with_temp_file "ogit" ".toml" (fun file ->
40
Out_channel.with_open_text file (fun channel ->
41
Printf.fprintf channel
42
"default_branch = \"main\"\n\
43
git_project_root = \"/srv/git\"\n\
44
commits_max_displayed = 10\n\
45
title = \"Legacy repositories\"\n");
46
match Ogit.Config.read_file ~file () with
47
| Ok config ->
48
Alcotest.(check string) "default user_name" "" config.user_name;
49
Alcotest.(check string)
50
"legacy title" "Legacy repositories" config.root_title;
51
Alcotest.(check string)
52
"default nav logo" "/static/git_icon.svg" config.nav_logo;
53
Alcotest.(check string) "default host" "127.0.0.1" config.host;
54
Alcotest.(check int) "default port" 8081 config.port
55
| Error error -> fail_config_error error)
56
57
(* Every key has a default, so a file overriding a single setting is valid;
58
the untouched settings keep their defaults. *)
59
let test_partial_file () =
60
with_temp_file "ogit-partial" ".toml" (fun file ->
61
Out_channel.with_open_text file (fun channel ->
62
output_string channel "port = 9999\n");
63
match Ogit.Config.read_file ~file () with
64
| Ok config ->
65
Alcotest.(check int) "overridden port" 9999 config.port;
66
Alcotest.(check string)
67
"default root" Ogit.Config.default.git_project_root
68
config.git_project_root;
69
Alcotest.(check string)
70
"default branch" Ogit.Config.default.default_branch
71
config.default_branch;
72
Alcotest.(check int)
73
"default commits" Ogit.Config.default.commits_max_displayed
74
config.commits_max_displayed
75
| Error error -> fail_config_error error)
76
77
(* A key that is present with the wrong type is still an error: only absence
78
falls back to the default. *)
79
let test_mistyped_key () =
80
with_temp_file "ogit-mistyped" ".toml" (fun file ->
81
Out_channel.with_open_text file (fun channel ->
82
output_string channel "git_project_root = 5\n");
83
match Ogit.Config.read_file ~file () with
84
| Error (Ogit.Config.Invalid_value _) -> ()
85
| Error error -> fail_config_error error
86
| Ok _ -> Alcotest.fail "mistyped key was accepted")
87
88
let test_malformed () =
89
with_temp_file "ogit-malformed" ".toml" (fun file ->
90
Out_channel.with_open_text file (fun channel ->
91
output_string channel "user = [\n");
92
match Ogit.Config.read_file ~file () with
93
| Error (Ogit.Config.Parse_error _) -> ()
94
| Error error -> fail_config_error error
95
| Ok _ -> Alcotest.fail "malformed configuration was accepted")
96
97
let test_invalid_value () =
98
with_temp_file "ogit-invalid" ".toml" (fun file ->
99
let invalid = Ogit.Config.{ default with commits_max_displayed = 0 } in
100
Ogit.Config.write_file ~file (Ogit.Config.to_table invalid);
101
match Ogit.Config.read_file ~file () with
102
| Error (Ogit.Config.Invalid_value _) -> ()
103
| Error error -> fail_config_error error
104
| Ok _ -> Alcotest.fail "invalid commit limit was accepted")
105
106
let test_invalid_port_high () =
107
with_temp_file "ogit-port-high" ".toml" (fun file ->
108
let invalid = Ogit.Config.{ default with port = 65536 } in
109
Ogit.Config.write_file ~file (Ogit.Config.to_table invalid);
110
match Ogit.Config.read_file ~file () with
111
| Error (Ogit.Config.Invalid_value _) -> ()
112
| Error error -> fail_config_error error
113
| Ok _ -> Alcotest.fail "port 65536 was accepted")
114
115
let test_invalid_port_zero () =
116
with_temp_file "ogit-port-zero" ".toml" (fun file ->
117
let invalid = Ogit.Config.{ default with port = 0 } in
118
Ogit.Config.write_file ~file (Ogit.Config.to_table invalid);
119
match Ogit.Config.read_file ~file () with
120
| Error (Ogit.Config.Invalid_value _) -> ()
121
| Error error -> fail_config_error error
122
| Ok _ -> Alcotest.fail "port 0 was accepted")
123
124
let test_directory_rejected () =
125
with_temp_directory "ogit-config-directory" (fun directory ->
126
match Ogit.Config.read_file ~file:directory () with
127
| Error (Ogit.Config.Io_error _) -> ()
128
| Error error -> fail_config_error error
129
| Ok _ -> Alcotest.fail "a directory was accepted as a config file")
130
131
let test_invalid_implicit () =
132
with_temp_directory "ogit-xdg" (fun config_home ->
133
let directory = Filename.concat config_home "ogit" in
134
Unix.mkdir directory 0o755;
135
let file = Filename.concat directory "config.toml" in
136
Out_channel.with_open_text file (fun channel ->
137
output_string channel "user = [\n");
138
with_environment "OGIT_CONFIG" "" (fun () ->
139
with_environment "XDG_CONFIG_HOME" config_home (fun () ->
140
match Ogit.Config.load () with
141
| Error (Ogit.Config.Parse_error _) -> ()
142
| Error error -> fail_config_error error
143
| Ok _ -> Alcotest.fail "invalid implicit config should fail")))
144
145
let test_explicit_missing () =
146
let missing = Filename.temp_file "ogit-missing" ".toml" in
147
Sys.remove missing;
148
with_environment "OGIT_CONFIG" missing (fun () ->
149
match Ogit.Config.load () with
150
| Error (Ogit.Config.Not_found file) ->
151
Alcotest.(check string) "path" missing file
152
| Error error -> fail_config_error error
153
| Ok _ -> Alcotest.fail "explicitly missing config should fail")
154
155
let test_location () =
156
with_environment "OGIT_CONFIG" "" (fun () ->
157
with_environment "XDG_CONFIG_HOME" "/tmp/xdg-config" (fun () ->
158
let expected =
159
Filename.concat
160
(Filename.concat "/tmp/xdg-config" "ogit")
161
"config.toml"
162
in
163
Alcotest.(check string)
164
"XDG path" expected
165
(Ogit.Config.locate_config_file ())));
166
with_environment "OGIT_CONFIG" "/tmp/custom-ogit.toml" (fun () ->
167
Alcotest.(check string)
168
"explicit path" "/tmp/custom-ogit.toml"
169
(Ogit.Config.locate_config_file ()))
170
171
let suite =
172
( "config",
173
[
174
Alcotest.test_case "round trip" `Quick test_round_trip;
175
Alcotest.test_case "backward compat" `Quick test_backward_compat;
176
Alcotest.test_case "partial file" `Quick test_partial_file;
177
Alcotest.test_case "mistyped key" `Quick test_mistyped_key;
178
Alcotest.test_case "malformed" `Quick test_malformed;
179
Alcotest.test_case "invalid value" `Quick test_invalid_value;
180
Alcotest.test_case "port too high" `Quick test_invalid_port_high;
181
Alcotest.test_case "port zero" `Quick test_invalid_port_zero;
182
Alcotest.test_case "directory rejected" `Quick test_directory_rejected;
183
Alcotest.test_case "invalid implicit" `Quick test_invalid_implicit;
184
Alcotest.test_case "explicit missing" `Quick test_explicit_missing;
185
Alcotest.test_case "location" `Quick test_location;
186
] )
187