1# Unit tests for lib.path functions. Use `nix-build` in this directory to
2# run these
3{ libpath }:
4let
5 lib = import libpath;
6 inherit (lib.path)
7 hasPrefix
8 removePrefix
9 append
10 splitRoot
11 hasStorePathPrefix
12 subpath
13 ;
14
15 # This is not allowed generally, but we're in the tests here, so we'll allow ourselves.
16 storeDirPath = /. + builtins.storeDir;
17
18 cases = lib.runTests {
19 # Test examples from the lib.path.append documentation
20 testAppendExample1 = {
21 expr = append /foo "bar/baz";
22 expected = /foo/bar/baz;
23 };
24 testAppendExample2 = {
25 expr = append /foo "./bar//baz/./";
26 expected = /foo/bar/baz;
27 };
28 testAppendExample3 = {
29 expr = append /. "foo/bar";
30 expected = /foo/bar;
31 };
32 testAppendExample4 = {
33 expr = (builtins.tryEval (append "/foo" "bar")).success;
34 expected = false;
35 };
36 testAppendExample5 = {
37 expr = (builtins.tryEval (append /foo /bar)).success;
38 expected = false;
39 };
40 testAppendExample6 = {
41 expr = (builtins.tryEval (append /foo "")).success;
42 expected = false;
43 };
44 testAppendExample7 = {
45 expr = (builtins.tryEval (append /foo "/bar")).success;
46 expected = false;
47 };
48 testAppendExample8 = {
49 expr = (builtins.tryEval (append /foo "../bar")).success;
50 expected = false;
51 };
52
53 testHasPrefixExample1 = {
54 expr = hasPrefix /foo /foo/bar;
55 expected = true;
56 };
57 testHasPrefixExample2 = {
58 expr = hasPrefix /foo /foo;
59 expected = true;
60 };
61 testHasPrefixExample3 = {
62 expr = hasPrefix /foo/bar /foo;
63 expected = false;
64 };
65 testHasPrefixExample4 = {
66 expr = hasPrefix /. /foo;
67 expected = true;
68 };
69
70 testRemovePrefixExample1 = {
71 expr = removePrefix /foo /foo/bar/baz;
72 expected = "./bar/baz";
73 };
74 testRemovePrefixExample2 = {
75 expr = removePrefix /foo /foo;
76 expected = "./.";
77 };
78 testRemovePrefixExample3 = {
79 expr = (builtins.tryEval (removePrefix /foo/bar /foo)).success;
80 expected = false;
81 };
82 testRemovePrefixExample4 = {
83 expr = removePrefix /. /foo;
84 expected = "./foo";
85 };
86
87 testSplitRootExample1 = {
88 expr = splitRoot /foo/bar;
89 expected = {
90 root = /.;
91 subpath = "./foo/bar";
92 };
93 };
94 testSplitRootExample2 = {
95 expr = splitRoot /.;
96 expected = {
97 root = /.;
98 subpath = "./.";
99 };
100 };
101 testSplitRootExample3 = {
102 expr = splitRoot /foo/../bar;
103 expected = {
104 root = /.;
105 subpath = "./bar";
106 };
107 };
108 testSplitRootExample4 = {
109 expr = (builtins.tryEval (splitRoot "/foo/bar")).success;
110 expected = false;
111 };
112
113 # Root path (empty path components list)
114 testHasStorePathPrefixRoot = {
115 expr = hasStorePathPrefix /.;
116 expected = false;
117 };
118
119 testHasStorePathPrefixExample1 = {
120 expr = hasStorePathPrefix (storeDirPath + "/nvl9ic0pj1fpyln3zaqrf4cclbqdfn1j-foo/bar/baz");
121 expected = true;
122 };
123 testHasStorePathPrefixExample2 = {
124 expr = hasStorePathPrefix storeDirPath;
125 expected = false;
126 };
127 testHasStorePathPrefixExample3 = {
128 expr = hasStorePathPrefix (storeDirPath + "/nvl9ic0pj1fpyln3zaqrf4cclbqdfn1j-foo");
129 expected = true;
130 };
131 testHasStorePathPrefixExample4 = {
132 expr = hasStorePathPrefix /home/user;
133 expected = false;
134 };
135 testHasStorePathPrefixExample5 = {
136 expr = hasStorePathPrefix (
137 storeDirPath + "/.links/10gg8k3rmbw8p7gszarbk7qyd9jwxhcfq9i6s5i0qikx8alkk4hq"
138 );
139 expected = false;
140 };
141 testHasStorePathPrefixExample6 = {
142 expr = hasStorePathPrefix (storeDirPath + "/nvl9ic0pj1fpyln3zaqrf4cclbqdfn1j-foo.drv");
143 expected = true;
144 };
145
146 # Test paths for content‐addressed derivations
147 testHasStorePathPrefixExample7 = {
148 expr = hasStorePathPrefix (/. + "/1121rp0gvr1qya7hvy925g5kjwg66acz6sn1ra1hca09f1z5dsab");
149 expected = true;
150 };
151 testHasStorePathPrefixExample8 = {
152 expr = hasStorePathPrefix (/. + "/1121rp0gvr1qya7hvy925g5kjwg66acz6sn1ra1hca09f1z5dsab/foo/bar");
153 expected = true;
154 };
155
156 # Test examples from the lib.path.subpath.isValid documentation
157 testSubpathIsValidExample1 = {
158 expr = subpath.isValid null;
159 expected = false;
160 };
161 testSubpathIsValidExample2 = {
162 expr = subpath.isValid "";
163 expected = false;
164 };
165 testSubpathIsValidExample3 = {
166 expr = subpath.isValid "/foo";
167 expected = false;
168 };
169 testSubpathIsValidExample4 = {
170 expr = subpath.isValid "../foo";
171 expected = false;
172 };
173 testSubpathIsValidExample5 = {
174 expr = subpath.isValid "foo/bar";
175 expected = true;
176 };
177 testSubpathIsValidExample6 = {
178 expr = subpath.isValid "./foo//bar/";
179 expected = true;
180 };
181 # Some extra tests
182 testSubpathIsValidTwoDotsEnd = {
183 expr = subpath.isValid "foo/..";
184 expected = false;
185 };
186 testSubpathIsValidTwoDotsMiddle = {
187 expr = subpath.isValid "foo/../bar";
188 expected = false;
189 };
190 testSubpathIsValidTwoDotsPrefix = {
191 expr = subpath.isValid "..foo";
192 expected = true;
193 };
194 testSubpathIsValidTwoDotsSuffix = {
195 expr = subpath.isValid "foo..";
196 expected = true;
197 };
198 testSubpathIsValidTwoDotsPrefixComponent = {
199 expr = subpath.isValid "foo/..bar/baz";
200 expected = true;
201 };
202 testSubpathIsValidTwoDotsSuffixComponent = {
203 expr = subpath.isValid "foo/bar../baz";
204 expected = true;
205 };
206 testSubpathIsValidThreeDots = {
207 expr = subpath.isValid "...";
208 expected = true;
209 };
210 testSubpathIsValidFourDots = {
211 expr = subpath.isValid "....";
212 expected = true;
213 };
214 testSubpathIsValidThreeDotsComponent = {
215 expr = subpath.isValid "foo/.../bar";
216 expected = true;
217 };
218 testSubpathIsValidFourDotsComponent = {
219 expr = subpath.isValid "foo/..../bar";
220 expected = true;
221 };
222
223 # Test examples from the lib.path.subpath.join documentation
224 testSubpathJoinExample1 = {
225 expr = subpath.join [
226 "foo"
227 "bar/baz"
228 ];
229 expected = "./foo/bar/baz";
230 };
231 testSubpathJoinExample2 = {
232 expr = subpath.join [
233 "./foo"
234 "."
235 "bar//./baz/"
236 ];
237 expected = "./foo/bar/baz";
238 };
239 testSubpathJoinExample3 = {
240 expr = subpath.join [ ];
241 expected = "./.";
242 };
243 testSubpathJoinExample4 = {
244 expr = (builtins.tryEval (subpath.join [ /foo ])).success;
245 expected = false;
246 };
247 testSubpathJoinExample5 = {
248 expr = (builtins.tryEval (subpath.join [ "" ])).success;
249 expected = false;
250 };
251 testSubpathJoinExample6 = {
252 expr = (builtins.tryEval (subpath.join [ "/foo" ])).success;
253 expected = false;
254 };
255 testSubpathJoinExample7 = {
256 expr = (builtins.tryEval (subpath.join [ "../foo" ])).success;
257 expected = false;
258 };
259
260 # Test examples from the lib.path.subpath.normalise documentation
261 testSubpathNormaliseExample1 = {
262 expr = subpath.normalise "foo//bar";
263 expected = "./foo/bar";
264 };
265 testSubpathNormaliseExample2 = {
266 expr = subpath.normalise "foo/./bar";
267 expected = "./foo/bar";
268 };
269 testSubpathNormaliseExample3 = {
270 expr = subpath.normalise "foo/bar";
271 expected = "./foo/bar";
272 };
273 testSubpathNormaliseExample4 = {
274 expr = subpath.normalise "foo/bar/";
275 expected = "./foo/bar";
276 };
277 testSubpathNormaliseExample5 = {
278 expr = subpath.normalise "foo/bar/.";
279 expected = "./foo/bar";
280 };
281 testSubpathNormaliseExample6 = {
282 expr = subpath.normalise ".";
283 expected = "./.";
284 };
285 testSubpathNormaliseExample7 = {
286 expr = (builtins.tryEval (subpath.normalise "foo/../bar")).success;
287 expected = false;
288 };
289 testSubpathNormaliseExample8 = {
290 expr = (builtins.tryEval (subpath.normalise "")).success;
291 expected = false;
292 };
293 testSubpathNormaliseExample9 = {
294 expr = (builtins.tryEval (subpath.normalise "/foo")).success;
295 expected = false;
296 };
297 # Some extra tests
298 testSubpathNormaliseIsValidDots = {
299 expr = subpath.normalise "./foo/.bar/.../baz...qux";
300 expected = "./foo/.bar/.../baz...qux";
301 };
302 testSubpathNormaliseWrongType = {
303 expr = (builtins.tryEval (subpath.normalise null)).success;
304 expected = false;
305 };
306 testSubpathNormaliseTwoDots = {
307 expr = (builtins.tryEval (subpath.normalise "..")).success;
308 expected = false;
309 };
310
311 testSubpathComponentsExample1 = {
312 expr = subpath.components ".";
313 expected = [ ];
314 };
315 testSubpathComponentsExample2 = {
316 expr = subpath.components "./foo//bar/./baz/";
317 expected = [
318 "foo"
319 "bar"
320 "baz"
321 ];
322 };
323 testSubpathComponentsExample3 = {
324 expr = (builtins.tryEval (subpath.components "/foo")).success;
325 expected = false;
326 };
327 };
328in
329if cases == [ ] then
330 "Unit tests successful"
331else
332 throw "Path unit tests failed: ${lib.generators.toPretty { } cases}"