XDG library path support for OCaml via Eio capabilities
linux
macos
ocaml
xdg
1(*---------------------------------------------------------------------------
2 Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
3 SPDX-License-Identifier: ISC
4 ---------------------------------------------------------------------------*)
5
6let test_path_validation () =
7 Printf.printf "Testing XDG path validation...\n";
8 (* Test absolute path validation for environment variables *)
9 let test_relative_path_rejection env_var relative_path =
10 Printf.printf "Testing rejection of relative path in %s...\n" env_var;
11 Unix.putenv env_var relative_path;
12 try
13 Eio_main.run @@ fun env ->
14 let _ = Xdge.create env#fs "test_validation" in
15 Printf.printf "ERROR: Should have rejected relative path\n";
16 false
17 with
18 | Xdge.Invalid_xdg_path msg ->
19 Printf.printf "SUCCESS: Correctly rejected relative path: %s\n" msg;
20 true
21 | exn ->
22 Printf.printf "ERROR: Wrong exception: %s\n" (Printexc.to_string exn);
23 false
24 in
25 let old_config_home = Sys.getenv_opt "XDG_CONFIG_HOME" in
26 let old_data_dirs = Sys.getenv_opt "XDG_DATA_DIRS" in
27 let success1 =
28 test_relative_path_rejection "XDG_CONFIG_HOME" "relative/path"
29 in
30 let success2 =
31 test_relative_path_rejection "XDG_DATA_DIRS" "rel1:rel2:/abs/path"
32 in
33 (* Restore original env vars *)
34 (match old_config_home with
35 | Some v -> Unix.putenv "XDG_CONFIG_HOME" v
36 | None -> ( try Unix.putenv "XDG_CONFIG_HOME" "" with _ -> ()));
37 (match old_data_dirs with
38 | Some v -> Unix.putenv "XDG_DATA_DIRS" v
39 | None -> ( try Unix.putenv "XDG_DATA_DIRS" "" with _ -> ()));
40 success1 && success2
41
42let test_file_search () =
43 Printf.printf "\nTesting XDG file search...\n";
44 Eio_main.run @@ fun env ->
45 let xdg = Xdge.create env#fs "search_test" in
46 (* Create test files *)
47 let config_file = Eio.Path.(Xdge.config_dir xdg / "test.conf") in
48 let data_file = Eio.Path.(Xdge.data_dir xdg / "test.dat") in
49 Eio.Path.save ~create:(`Or_truncate 0o644) config_file "config content";
50 Eio.Path.save ~create:(`Or_truncate 0o644) data_file "data content";
51 (* Test finding existing files *)
52 (match Xdge.find_config_file xdg "test.conf" with
53 | Some path ->
54 let content = Eio.Path.load path in
55 Printf.printf "Found config file: %s\n" (String.trim content)
56 | None -> Printf.printf "ERROR: Config file not found\n");
57 (match Xdge.find_data_file xdg "test.dat" with
58 | Some path ->
59 let content = Eio.Path.load path in
60 Printf.printf "Found data file: %s\n" (String.trim content)
61 | None -> Printf.printf "ERROR: Data file not found\n");
62 (* Test non-existent file *)
63 match Xdge.find_config_file xdg "nonexistent.conf" with
64 | Some _ -> Printf.printf "ERROR: Should not have found nonexistent file\n"
65 | None -> Printf.printf "Correctly handled nonexistent file\n"
66
67let () =
68 (* Check if we should run validation tests *)
69 if Array.length Sys.argv > 1 && Sys.argv.(1) = "--validate" then (
70 let validation_success = test_path_validation () in
71 test_file_search ();
72 if validation_success then
73 Printf.printf "\nAll path validation tests passed!\n"
74 else Printf.printf "\nSome validation tests failed!\n")
75 else
76 (* Run original simple functionality test *)
77 Eio_main.run @@ fun env ->
78 let xdg = Xdge.create env#fs "path_test" in
79 (* Test config subdirectory *)
80 let profiles_path = Eio.Path.(Xdge.config_dir xdg / "profiles") in
81 let profile_file = Eio.Path.(profiles_path / "default.json") in
82 (try
83 let content = Eio.Path.load profile_file in
84 Printf.printf "config file content: %s" (String.trim content)
85 with exn ->
86 Printf.printf "config file error: %s" (Printexc.to_string exn));
87 (* Test data subdirectory *)
88 let db_path = Eio.Path.(Xdge.data_dir xdg / "databases") in
89 let db_file = Eio.Path.(db_path / "main.db") in
90 (try
91 let content = Eio.Path.load db_file in
92 Printf.printf "\ndata file content: %s" (String.trim content)
93 with exn ->
94 Printf.printf "\ndata file error: %s" (Printexc.to_string exn));
95 (* Test cache subdirectory *)
96 let cache_path = Eio.Path.(Xdge.cache_dir xdg / "thumbnails") in
97 let cache_file = Eio.Path.(cache_path / "thumb1.png") in
98 (try
99 let content = Eio.Path.load cache_file in
100 Printf.printf "\ncache file content: %s" (String.trim content)
101 with exn ->
102 Printf.printf "\ncache file error: %s" (Printexc.to_string exn));
103 (* Test state subdirectory *)
104 let logs_path = Eio.Path.(Xdge.state_dir xdg / "logs") in
105 let log_file = Eio.Path.(logs_path / "app.log") in
106 try
107 let content = Eio.Path.load log_file in
108 Printf.printf "\nstate file content: %s\n" (String.trim content)
109 with exn ->
110 Printf.printf "\nstate file error: %s\n" (Printexc.to_string exn)