master
c 426 lines 11.9 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 wslpath.c
8
9 Abstract:
10
11 This file contains tests for the wslpath binary.
12
13 --*/
14
15 #include "lxtcommon.h"
16 #include "unittests.h"
17 #include <stdlib.h>
18 #include <unistd.h>
19 #include <sys/mount.h>
20
21 #define LXT_NAME "wslpath"
22
23 #define WSLPATH_ESCAPE_NAME "wslpath_foo\\:bar"
24 #define WSLPATH_ESCAPE_NAME_ESCAPED "wslpath_foo\uf05c\uf03abar"
25 #define WSLPATH_ESCAPE_DIR "/mnt/c/" WSLPATH_ESCAPE_NAME
26 #define WSLPATH_ESCAPE_DIR_ESCAPED "/mnt/c/" WSLPATH_ESCAPE_NAME_ESCAPED
27 #define WSLPATH_ESCAPE_DIR_WIN "C:\\" WSLPATH_ESCAPE_NAME_ESCAPED
28 #define WSLPATH_SYMLINK_TEST_DIR "/mnt/c/symlink_test_dir"
29 #define WSLPATH_SYMLINK_TEST_TARGET WSLPATH_SYMLINK_TEST_DIR "/target"
30 #define WSLPATH_SYMLINK_TEST_LINK WSLPATH_SYMLINK_TEST_DIR "/link"
31 #define WSLPATH_SYMLINK_TEST_DIR_WIN "C:\\symlink_test_dir"
32 #define WSLPATH_SYMLINK_TEST_TARGET_WIN WSLPATH_SYMLINK_TEST_DIR_WIN "\\target"
33 #define WSLPATH_SYMLINK_TEST_LINK_WIN WSLPATH_SYMLINK_TEST_DIR_WIN "\\link"
34 #define WSLPATH_DISTRO_PREFIX "\\\\wsl.localhost\\" LXSS_DISTRO_NAME_TEST
35 #define WSLPATH_DISTRO_COMPAT_PREFIX "\\\\wsl$\\" LXSS_DISTRO_NAME_TEST
36 #define WSLPATH_ESCAPE_LX_DIR "/data/" WSLPATH_ESCAPE_NAME
37 #define WSLPATH_ESCAPE_LX_DIR_WIN WSLPATH_DISTRO_PREFIX "\\data\\" WSLPATH_ESCAPE_NAME_ESCAPED
38 #define WSLPATH_MOUNT_POINT "/data/wslpath_mount"
39
40 LXT_VARIATION_HANDLER WslPathTestDrvFsEscaped;
41
42 LXT_VARIATION_HANDLER WslPathTestDrvFsToWinPath;
43
44 LXT_VARIATION_HANDLER WslPathTestDrvFsSymlink;
45
46 LXT_VARIATION_HANDLER WslPathTestDrvFsFromWinPath;
47
48 LXT_VARIATION_HANDLER WslPathTestInvalidMountInfo;
49
50 LXT_VARIATION_HANDLER WslPathTestLxEscaped;
51
52 LXT_VARIATION_HANDLER WslPathTestLxFromWinPath;
53
54 LXT_VARIATION_HANDLER WslPathTestLxToWinPath;
55
56 static const LXT_VARIATION g_LxtVariations[] = {
57 {"WslPath - Windows to DrvFs", WslPathTestDrvFsFromWinPath},
58 {"WslPath - DrvFs to Windows", WslPathTestDrvFsToWinPath},
59 {"WslPath - DrvFs escaped characters", WslPathTestDrvFsEscaped},
60 {"WslPath - DrvFs symlinks", WslPathTestDrvFsSymlink},
61 {"WslPath - \\\\wsl.localhost to Linux", WslPathTestLxFromWinPath},
62 {"WslPath - Linux to \\\\wsl.localhost", WslPathTestLxToWinPath},
63 {"WslPath - \\\\wsl.localhost escaped characters", WslPathTestLxEscaped},
64 {"WslPath - Invalid mountinfo line", WslPathTestInvalidMountInfo},
65 };
66
67 int WslPathTestEntry(int Argc, char* Argv[])
68
69 /*++
70
71 Routine Description:
72
73 This routine main entry point for the wslpath tests.
74
75 Arguments:
76
77 Argc - Supplies the number of command line arguments.
78
79 Argv - Supplies the command line arguments.
80
81 Return Value:
82
83 Returns 0 on success, -1 on failure.
84
85 --*/
86
87 {
88
89 LXT_ARGS Args;
90 int Result;
91
92 LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
93 LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
94
95 ErrorExit:
96 LxtUninitialize();
97 return !LXT_SUCCESS(Result);
98 }
99
100 int WslPathTestDrvFsEscaped(PLXT_ARGS Args)
101
102 /*++
103
104 Description:
105
106 This routine tests wslpath on DrvFs paths with escaped characters.
107
108 Arguments:
109
110 Args - Supplies the command line arguments.
111
112 Return Value:
113
114 Returns 0 on success, -1 on failure.
115
116 --*/
117
118 {
119
120 int Result;
121
122 LxtCheckErrno(mkdir(WSLPATH_ESCAPE_DIR, 0777));
123 LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_ESCAPE_DIR, WSLPATH_ESCAPE_DIR_WIN, false));
124
125 //
126 // Translating win to drvfs does not unescape, since the escaped characters
127 // work on drvfs.
128 //
129
130 LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_ESCAPE_DIR_WIN, WSLPATH_ESCAPE_DIR_ESCAPED, true));
131
132 ErrorExit:
133 rmdir(WSLPATH_ESCAPE_DIR);
134 return Result;
135 }
136
137 int WslPathTestDrvFsFromWinPath(PLXT_ARGS Args)
138
139 /*++
140
141 Description:
142
143 This routine tests wslpath on Windows paths.
144
145 Arguments:
146
147 Args - Supplies the command line arguments.
148
149 Return Value:
150
151 Returns 0 on success, -1 on failure.
152
153 --*/
154
155 {
156
157 int Result;
158
159 LxtCheckResult(LxtCheckWslPathTranslation("C:\\", "/mnt/c/", true));
160 LxtCheckResult(LxtCheckWslPathTranslation("C:\\Foo", "/mnt/c/Foo", true));
161 LxtCheckResult(LxtCheckWslPathTranslation("C:\\Foo\\", "/mnt/c/Foo/", true));
162 LxtCheckResult(LxtCheckWslPathTranslation("C:\\Foo\\bar", "/mnt/c/Foo/bar", true));
163 LxtCheckResult(LxtCheckWslPathTranslation("C:/Foo/bar", "/mnt/c/Foo/bar", true));
164 LxtCheckResult(LxtCheckWslPathTranslation("foo", "foo", true));
165 LxtCheckResult(LxtCheckWslPathTranslation("foo\\", "foo/", true));
166 LxtCheckResult(LxtCheckWslPathTranslation("C:\\Program Files\\Git", "/mnt/c/Program Files/Git", true));
167 LxtCheckResult(LxtCheckWslPathTranslation("C:\\Program Files\\PowerShell\\7", "/mnt/c/Program Files/PowerShell/7", true));
168 LxtCheckResult(LxtCheckWslPathTranslation("C:\\Program Files (x86)\\Common Files", "/mnt/c/Program Files (x86)/Common Files", true));
169 LxtCheckResult(LxtCheckWslPathTranslation(
170 "C:\\Users\\Test User\\AppData\\Local\\Programs\\Microsoft VS Code\\bin",
171 "/mnt/c/Users/Test User/AppData/Local/Programs/Microsoft VS Code/bin",
172 true));
173
174 ErrorExit:
175 return Result;
176 }
177
178 int WslPathTestDrvFsSymlink(PLXT_ARGS Args)
179
180 /*++
181
182 Description:
183
184 This routine tests wslpath on DrvFs paths with symlinks.
185
186 Arguments:
187
188 Args - Supplies the command line arguments.
189
190 Return Value:
191
192 Returns 0 on success, -1 on failure.
193
194 --*/
195
196 {
197
198 int Result;
199
200 LxtCheckErrnoZeroSuccess(mkdir(WSLPATH_SYMLINK_TEST_DIR, 0777));
201 LxtCheckErrnoZeroSuccess(mkdir(WSLPATH_SYMLINK_TEST_TARGET, 0777));
202 LxtCheckErrnoZeroSuccess(symlink(WSLPATH_SYMLINK_TEST_TARGET, WSLPATH_SYMLINK_TEST_LINK));
203
204 //
205 // Drvfs to Windows follows links.
206 //
207
208 LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_SYMLINK_TEST_LINK, WSLPATH_SYMLINK_TEST_TARGET_WIN, false));
209
210 //
211 // Windows to DrvFs is text based so does not.
212 //
213
214 LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_SYMLINK_TEST_LINK_WIN, WSLPATH_SYMLINK_TEST_LINK, true));
215
216 ErrorExit:
217 unlink(WSLPATH_SYMLINK_TEST_LINK);
218 rmdir(WSLPATH_SYMLINK_TEST_TARGET);
219 rmdir(WSLPATH_SYMLINK_TEST_DIR);
220
221 return Result;
222 }
223
224 int WslPathTestDrvFsToWinPath(PLXT_ARGS Args)
225
226 /*++
227
228 Description:
229
230 This routine tests wslpath on DrvFs paths.
231
232 Arguments:
233
234 Args - Supplies the command line arguments.
235
236 Return Value:
237
238 Returns 0 on success, -1 on failure.
239
240 --*/
241
242 {
243
244 int Result;
245
246 LxtCheckResult(LxtCheckWslPathTranslation("/mnt/c", "C:\\", false));
247 LxtCheckResult(LxtCheckWslPathTranslation("/mnt/c/", "C:\\", false));
248 LxtCheckResult(LxtCheckWslPathTranslation("/mnt/c/Users", "C:\\Users", false));
249 LxtCheckResult(LxtCheckWslPathTranslation("/mnt/c/Users/", "C:\\Users\\", false));
250 LxtCheckResult(LxtCheckWslPathTranslation("/mnt/c/DOESNOTEXIST/", "C:\\DOESNOTEXIST\\", false));
251 LxtCheckResult(LxtCheckWslPathTranslation("/mnt/c/Program Files/Git", "C:\\Program Files\\Git", false));
252 LxtCheckResult(LxtCheckWslPathTranslation("/mnt/c/Program Files/PowerShell/7", "C:\\Program Files\\PowerShell\\7", false));
253 LxtCheckResult(LxtCheckWslPathTranslation("/mnt/c/Program Files (x86)/Common Files", "C:\\Program Files (x86)\\Common Files", false));
254 LxtCheckResult(LxtCheckWslPathTranslation(
255 "/mnt/c/Users/Test User/AppData/Local/Programs/Microsoft VS Code/bin",
256 "C:\\Users\\Test User\\AppData\\Local\\Programs\\Microsoft VS Code\\bin",
257 false));
258
259 ErrorExit:
260 return Result;
261 }
262
263 int WslPathTestInvalidMountInfo(PLXT_ARGS Args)
264
265 /*++
266
267 Description:
268
269 This routine tests wslpath's handling of ill-formed mountinfo lines.
270
271 Arguments:
272
273 Args - Supplies the command line arguments.
274
275 Return Value:
276
277 Returns 0 on success, -1 on failure.
278
279 --*/
280
281 {
282
283 int Result;
284
285 //
286 // WSL1 does not allow using an empty string as the mount source. This is
287 // technically a minor bug in WSL1, but it also means this test is not
288 // relevant, so skip it.
289 //
290
291 if (LxtWslVersion() == 1)
292 {
293 LxtLogInfo("Test skipped on WSL1.");
294 Result = 0;
295 goto ErrorExit;
296 }
297
298 LxtCheckErrnoZeroSuccess(mkdir(WSLPATH_MOUNT_POINT, 0777));
299
300 //
301 // Using an empty string as the mount source will cause the mountinfo file
302 // to have a blank field, which neither libmount nor mountutil can parse.
303 // This should however not break wslpath.
304 //
305
306 LxtCheckErrnoZeroSuccess(mount("", WSLPATH_MOUNT_POINT, "tmpfs", 0, NULL));
307 LxtCheckResult(LxtCheckWslPathTranslation("/mnt/c", "C:\\", false));
308
309 ErrorExit:
310 umount(WSLPATH_MOUNT_POINT);
311 rmdir(WSLPATH_MOUNT_POINT);
312 return Result;
313 }
314
315 int WslPathTestLxEscaped(PLXT_ARGS Args)
316
317 /*++
318
319 Description:
320
321 This routine tests wslpath on internal Linux paths with escaped characters.
322
323 Arguments:
324
325 Args - Supplies the command line arguments.
326
327 Return Value:
328
329 Returns 0 on success, -1 on failure.
330
331 --*/
332
333 {
334
335 int Result;
336
337 LxtCheckErrno(mkdir(WSLPATH_ESCAPE_LX_DIR, 0777));
338 LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_ESCAPE_LX_DIR, WSLPATH_ESCAPE_LX_DIR_WIN, false));
339
340 //
341 // Translating \\wsl.localhost to Linux does unescape (unlike drvfs).
342 //
343
344 LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_ESCAPE_LX_DIR_WIN, WSLPATH_ESCAPE_LX_DIR, true));
345
346 ErrorExit:
347 rmdir(WSLPATH_ESCAPE_LX_DIR);
348 return Result;
349 }
350
351 int WslPathTestLxFromWinPath(PLXT_ARGS Args)
352
353 /*++
354
355 Description:
356
357 This routine tests wslpath on \\wsl.localhost paths.
358
359 Arguments:
360
361 Args - Supplies the command line arguments.
362
363 Return Value:
364
365 Returns 0 on success, -1 on failure.
366
367 --*/
368
369 {
370
371 int Result;
372
373 LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_DISTRO_PREFIX, "/", true));
374 LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_DISTRO_PREFIX "\\", "/", true));
375 LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_DISTRO_PREFIX "\\root", "/root", true));
376 LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_DISTRO_PREFIX "\\proc\\stat", "/proc/stat", true));
377 LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_DISTRO_PREFIX "/proc/stat", "/proc/stat", true));
378 LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_DISTRO_COMPAT_PREFIX "\\proc\\stat", "/proc/stat", true));
379 LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_DISTRO_COMPAT_PREFIX, "/", true));
380 LxtCheckResult(LxtCheckWslPathTranslation("\\\\?\\C:\\Users", "/mnt/c/Users", true));
381 LxtCheckResult(LxtCheckWslPathTranslation("\\\\?\\C:\\Users\\", "/mnt/c/Users/", true));
382 LxtCheckResult(LxtCheckWslPathTranslation(".", ".", true));
383
384 //
385 // Validate that distro names that only share the current distro name as a prefix are correctly treated as an error.
386 //
387
388 LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_DISTRO_PREFIX "-other\\foo", NULL, true));
389 LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_DISTRO_PREFIX "X\\foo", NULL, true));
390 LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_DISTRO_COMPAT_PREFIX "-other\\foo", NULL, true));
391 LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_DISTRO_COMPAT_PREFIX "X\\foo", NULL, true));
392
393 ErrorExit:
394 return Result;
395 }
396
397 int WslPathTestLxToWinPath(PLXT_ARGS Args)
398
399 /*++
400
401 Description:
402
403 This routine tests wslpath on internal Linux paths.
404
405 Arguments:
406
407 Args - Supplies the command line arguments.
408
409 Return Value:
410
411 Returns 0 on success, -1 on failure.
412
413 --*/
414
415 {
416
417 int Result;
418
419 LxtCheckResult(LxtCheckWslPathTranslation("/", WSLPATH_DISTRO_PREFIX "\\", false));
420 LxtCheckResult(LxtCheckWslPathTranslation("/root", WSLPATH_DISTRO_PREFIX "\\root", false));
421 LxtCheckResult(LxtCheckWslPathTranslation("/proc/stat", WSLPATH_DISTRO_PREFIX "\\proc\\stat", false));
422 LxtCheckResult(LxtCheckWslPathTranslation("/proc/1/", WSLPATH_DISTRO_PREFIX "\\proc\\1\\", false));
423
424 ErrorExit:
425 return Result;
426 }