Blender  V3.3
BLI_path_util_test.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0 */
2 
3 #include "testing/testing.h"
4 
5 #include "IMB_imbuf.h"
6 
7 #include "BLI_fileops.h"
8 #include "BLI_path_util.h"
9 #include "BLI_string.h"
10 
11 /* -------------------------------------------------------------------- */
12 /* tests */
13 
14 /* BLI_path_normalize */
15 #ifndef _WIN32
16 TEST(path_util, Clean)
17 {
18  /* "/./" -> "/" */
19  {
20  char path[FILE_MAX] = "/a/./b/./c/./";
21  BLI_path_normalize(nullptr, path);
22  EXPECT_STREQ("/a/b/c/", path);
23  }
24 
25  {
26  char path[FILE_MAX] = "/./././";
27  BLI_path_normalize(nullptr, path);
28  EXPECT_STREQ("/", path);
29  }
30 
31  {
32  char path[FILE_MAX] = "/a/./././b/";
33  BLI_path_normalize(nullptr, path);
34  EXPECT_STREQ("/a/b/", path);
35  }
36 
37  /* "//" -> "/" */
38  {
39  char path[FILE_MAX] = "a////";
40  BLI_path_normalize(nullptr, path);
41  EXPECT_STREQ("a/", path);
42  }
43 
44  if (false) /* FIXME */
45  {
46  char path[FILE_MAX] = "./a////";
47  BLI_path_normalize(nullptr, path);
48  EXPECT_STREQ("./a/", path);
49  }
50 
51  /* "foo/bar/../" -> "foo/" */
52  {
53  char path[FILE_MAX] = "/a/b/c/../../../";
54  BLI_path_normalize(nullptr, path);
55  EXPECT_STREQ("/", path);
56  }
57 
58  {
59  char path[FILE_MAX] = "/a/../a/b/../b/c/../c/";
60  BLI_path_normalize(nullptr, path);
61  EXPECT_STREQ("/a/b/c/", path);
62  }
63 
64  {
65  char path[FILE_MAX] = "//../";
66  BLI_path_normalize("/a/b/c/", path);
67  EXPECT_STREQ("/a/b/", path);
68  }
69 }
70 #endif
71 
72 #define AT_INDEX(str_input, index_input, str_expect) \
73  { \
74  char path[] = str_input; \
75  const char *expect = str_expect; \
76  int index_output, len_output; \
77  const bool ret = BLI_path_name_at_index(path, index_input, &index_output, &len_output); \
78  if (expect == NULL) { \
79  EXPECT_FALSE(ret); \
80  } \
81  else { \
82  EXPECT_TRUE(ret); \
83  EXPECT_EQ(strlen(expect), len_output); \
84  path[index_output + len_output] = '\0'; \
85  EXPECT_STREQ(&path[index_output], expect); \
86  } \
87  } \
88  ((void)0)
89 
90 /* BLI_path_name_at_index */
91 TEST(path_util, NameAtIndex_Single)
92 {
93  AT_INDEX("/a", 0, "a");
94  AT_INDEX("/a/", 0, "a");
95  AT_INDEX("a/", 0, "a");
96  AT_INDEX("//a//", 0, "a");
97  AT_INDEX("a/b", 0, "a");
98 
99  AT_INDEX("/a", 1, nullptr);
100  AT_INDEX("/a/", 1, nullptr);
101  AT_INDEX("a/", 1, nullptr);
102  AT_INDEX("//a//", 1, nullptr);
103 }
104 TEST(path_util, NameAtIndex_SingleNeg)
105 {
106  AT_INDEX("/a", -1, "a");
107  AT_INDEX("/a/", -1, "a");
108  AT_INDEX("a/", -1, "a");
109  AT_INDEX("//a//", -1, "a");
110  AT_INDEX("a/b", -1, "b");
111 
112  AT_INDEX("/a", -2, nullptr);
113  AT_INDEX("/a/", -2, nullptr);
114  AT_INDEX("a/", -2, nullptr);
115  AT_INDEX("//a//", -2, nullptr);
116 }
117 
118 TEST(path_util, NameAtIndex_Double)
119 {
120  AT_INDEX("/ab", 0, "ab");
121  AT_INDEX("/ab/", 0, "ab");
122  AT_INDEX("ab/", 0, "ab");
123  AT_INDEX("//ab//", 0, "ab");
124  AT_INDEX("ab/c", 0, "ab");
125 
126  AT_INDEX("/ab", 1, nullptr);
127  AT_INDEX("/ab/", 1, nullptr);
128  AT_INDEX("ab/", 1, nullptr);
129  AT_INDEX("//ab//", 1, nullptr);
130 }
131 
132 TEST(path_util, NameAtIndex_DoublNeg)
133 {
134  AT_INDEX("/ab", -1, "ab");
135  AT_INDEX("/ab/", -1, "ab");
136  AT_INDEX("ab/", -1, "ab");
137  AT_INDEX("//ab//", -1, "ab");
138  AT_INDEX("ab/c", -1, "c");
139 
140  AT_INDEX("/ab", -2, nullptr);
141  AT_INDEX("/ab/", -2, nullptr);
142  AT_INDEX("ab/", -2, nullptr);
143  AT_INDEX("//ab//", -2, nullptr);
144 }
145 
146 TEST(path_util, NameAtIndex_Misc)
147 {
148  AT_INDEX("/how/now/brown/cow", 0, "how");
149  AT_INDEX("/how/now/brown/cow", 1, "now");
150  AT_INDEX("/how/now/brown/cow", 2, "brown");
151  AT_INDEX("/how/now/brown/cow", 3, "cow");
152  AT_INDEX("/how/now/brown/cow", 4, nullptr);
153  AT_INDEX("/how/now/brown/cow/", 4, nullptr);
154 }
155 
156 TEST(path_util, NameAtIndex_MiscNeg)
157 {
158  AT_INDEX("/how/now/brown/cow", 0, "how");
159  AT_INDEX("/how/now/brown/cow", 1, "now");
160  AT_INDEX("/how/now/brown/cow", 2, "brown");
161  AT_INDEX("/how/now/brown/cow", 3, "cow");
162  AT_INDEX("/how/now/brown/cow", 4, nullptr);
163  AT_INDEX("/how/now/brown/cow/", 4, nullptr);
164 }
165 
166 TEST(path_util, NameAtIndex_MiscComplex)
167 {
168  AT_INDEX("how//now/brown/cow", 0, "how");
169  AT_INDEX("//how///now\\/brown/cow", 1, "now");
170  AT_INDEX("/how/now\\//brown\\/cow", 2, "brown");
171  AT_INDEX("/how/now/brown/cow//\\", 3, "cow");
172  AT_INDEX("/how/now/brown/\\cow", 4, nullptr);
173  AT_INDEX("how/now/brown/\\cow\\", 4, nullptr);
174 }
175 
176 TEST(path_util, NameAtIndex_MiscComplexNeg)
177 {
178  AT_INDEX("how//now/brown/cow", -4, "how");
179  AT_INDEX("//how///now\\/brown/cow", -3, "now");
180  AT_INDEX("/how/now\\//brown\\/cow", -2, "brown");
181  AT_INDEX("/how/now/brown/cow//\\", -1, "cow");
182  AT_INDEX("/how/now/brown/\\cow", -5, nullptr);
183  AT_INDEX("how/now/brown/\\cow\\", -5, nullptr);
184 }
185 
186 TEST(path_util, NameAtIndex_NoneComplex)
187 {
188  AT_INDEX("", 0, nullptr);
189  AT_INDEX("/", 0, nullptr);
190  AT_INDEX("//", 0, nullptr);
191  AT_INDEX("///", 0, nullptr);
192 }
193 
194 TEST(path_util, NameAtIndex_NoneComplexNeg)
195 {
196  AT_INDEX("", -1, nullptr);
197  AT_INDEX("/", -1, nullptr);
198  AT_INDEX("//", -1, nullptr);
199  AT_INDEX("///", -1, nullptr);
200 }
201 
202 #undef AT_INDEX
203 
204 #define JOIN(str_expect, out_size, ...) \
205  { \
206  const char *expect = str_expect; \
207  char result[(out_size) + 1024]; \
208  /* check we don't write past the last byte */ \
209  result[out_size] = '\0'; \
210  BLI_path_join(result, out_size, __VA_ARGS__, NULL); \
211  /* simplify expected string */ \
212  BLI_str_replace_char(result, '\\', '/'); \
213  EXPECT_STREQ(result, expect); \
214  EXPECT_EQ(result[out_size], '\0'); \
215  } \
216  ((void)0)
217 
218 /* BLI_path_join */
219 TEST(path_util, JoinNop)
220 {
221  JOIN("", 100, "");
222  JOIN("", 100, "", "");
223  JOIN("", 100, "", "", "");
224  JOIN("/", 100, "/", "", "");
225  JOIN("/", 100, "/", "/");
226  JOIN("/", 100, "/", "", "/");
227  JOIN("/", 100, "/", "", "/", "");
228 }
229 
230 TEST(path_util, JoinSingle)
231 {
232  JOIN("test", 100, "test");
233  JOIN("", 100, "");
234  JOIN("a", 100, "a");
235  JOIN("/a", 100, "/a");
236  JOIN("a/", 100, "a/");
237  JOIN("/a/", 100, "/a/");
238  JOIN("/a/", 100, "/a//");
239  JOIN("//a/", 100, "//a//");
240 }
241 
242 TEST(path_util, JoinTriple)
243 {
244  JOIN("/a/b/c", 100, "/a", "b", "c");
245  JOIN("/a/b/c", 100, "/a/", "/b/", "/c");
246  JOIN("/a/b/c", 100, "/a/b/", "/c");
247  JOIN("/a/b/c", 100, "/a/b/c");
248  JOIN("/a/b/c", 100, "/", "a/b/c");
249 
250  JOIN("/a/b/c/", 100, "/a/", "/b/", "/c/");
251  JOIN("/a/b/c/", 100, "/a/b/c/");
252  JOIN("/a/b/c/", 100, "/a/b/", "/c/");
253  JOIN("/a/b/c/", 100, "/a/b/c", "/");
254  JOIN("/a/b/c/", 100, "/", "a/b/c", "/");
255 }
256 
257 TEST(path_util, JoinTruncateShort)
258 {
259  JOIN("", 1, "/");
260  JOIN("/", 2, "/");
261  JOIN("a", 2, "", "aa");
262  JOIN("a", 2, "", "a/");
263  JOIN("a/b", 4, "a", "bc");
264  JOIN("ab/", 4, "ab", "c");
265  JOIN("/a/", 4, "/a", "b");
266  JOIN("/a/", 4, "/a/", "b/");
267  JOIN("/a/", 4, "/a", "/b/");
268  JOIN("/a/", 4, "/", "a/b/");
269  JOIN("//a", 4, "//", "a/b/");
270 
271  JOIN("/a/b", 5, "/a", "b", "c");
272 }
273 
274 TEST(path_util, JoinTruncateLong)
275 {
276  JOIN("", 1, "//", "//longer", "path");
277  JOIN("/", 2, "//", "//longer", "path");
278  JOIN("//", 3, "//", "//longer", "path");
279  JOIN("//l", 4, "//", "//longer", "path");
280  /* snip */
281  JOIN("//longe", 8, "//", "//longer", "path");
282  JOIN("//longer", 9, "//", "//longer", "path");
283  JOIN("//longer/", 10, "//", "//longer", "path");
284  JOIN("//longer/p", 11, "//", "//longer", "path");
285  JOIN("//longer/pa", 12, "//", "//longer", "path");
286  JOIN("//longer/pat", 13, "//", "//longer", "path");
287  JOIN("//longer/path", 14, "//", "//longer", "path"); /* not truncated. */
288  JOIN("//longer/path", 14, "//", "//longer", "path/");
289  JOIN("//longer/path/", 15, "//", "//longer", "path/"); /* not truncated. */
290  JOIN("//longer/path/", 15, "//", "//longer", "path/", "trunc");
291  JOIN("//longer/path/t", 16, "//", "//longer", "path/", "trunc");
292 }
293 
294 TEST(path_util, JoinComplex)
295 {
296  JOIN("/a/b/c/d/e/f/g/", 100, "/", "\\a/b", "//////c/d", "", "e\\\\", "f", "g//");
297  JOIN("/aa/bb/cc/dd/ee/ff/gg/", 100, "/", "\\aa/bb", "//////cc/dd", "", "ee\\\\", "ff", "gg//");
298  JOIN("1/2/3/", 100, "1", "////////", "", "2", "3\\");
299 }
300 
301 #undef JOIN
302 
303 /* BLI_path_frame */
304 TEST(path_util, Frame)
305 {
306  bool ret;
307 
308  {
309  char path[FILE_MAX] = "";
310  ret = BLI_path_frame(path, 123, 1);
311  EXPECT_TRUE(ret);
312  EXPECT_STREQ("123", path);
313  }
314 
315  {
316  char path[FILE_MAX] = "";
317  ret = BLI_path_frame(path, 123, 12);
318  EXPECT_TRUE(ret);
319  EXPECT_STREQ("000000000123", path);
320  }
321 
322  {
323  char path[FILE_MAX] = "test_";
324  ret = BLI_path_frame(path, 123, 1);
325  EXPECT_TRUE(ret);
326  EXPECT_STREQ("test_123", path);
327  }
328 
329  {
330  char path[FILE_MAX] = "test_";
331  ret = BLI_path_frame(path, 1, 12);
332  EXPECT_TRUE(ret);
333  EXPECT_STREQ("test_000000000001", path);
334  }
335 
336  {
337  char path[FILE_MAX] = "test_############";
338  ret = BLI_path_frame(path, 1, 0);
339  EXPECT_TRUE(ret);
340  EXPECT_STREQ("test_000000000001", path);
341  }
342 
343  {
344  char path[FILE_MAX] = "test_#_#_middle";
345  ret = BLI_path_frame(path, 123, 0);
346  EXPECT_TRUE(ret);
347  EXPECT_STREQ("test_#_123_middle", path);
348  }
349 
350  /* intentionally fail */
351  {
352  char path[FILE_MAX] = "";
353  ret = BLI_path_frame(path, 123, 0);
354  EXPECT_FALSE(ret);
355  EXPECT_STREQ("", path);
356  }
357 
358  {
359  char path[FILE_MAX] = "test_middle";
360  ret = BLI_path_frame(path, 123, 0);
361  EXPECT_FALSE(ret);
362  EXPECT_STREQ("test_middle", path);
363  }
364 
365  /* negative frame numbers */
366  {
367  char path[FILE_MAX] = "test_####";
368  ret = BLI_path_frame(path, -1, 4);
369  EXPECT_TRUE(ret);
370  EXPECT_STREQ("test_-0001", path);
371  }
372  {
373  char path[FILE_MAX] = "test_####";
374  ret = BLI_path_frame(path, -100, 4);
375  EXPECT_TRUE(ret);
376  EXPECT_STREQ("test_-0100", path);
377  }
378 }
379 
380 /* BLI_split_dirfile */
381 TEST(path_util, SplitDirfile)
382 {
383  {
384  const char *path = "";
385  char dir[FILE_MAX], file[FILE_MAX];
386  BLI_split_dirfile(path, dir, file, sizeof(dir), sizeof(file));
387  EXPECT_STREQ("", dir);
388  EXPECT_STREQ("", file);
389  }
390 
391  {
392  const char *path = "/";
393  char dir[FILE_MAX], file[FILE_MAX];
394  BLI_split_dirfile(path, dir, file, sizeof(dir), sizeof(file));
395  EXPECT_STREQ("/", dir);
396  EXPECT_STREQ("", file);
397  }
398 
399  {
400  const char *path = "fileonly";
401  char dir[FILE_MAX], file[FILE_MAX];
402  BLI_split_dirfile(path, dir, file, sizeof(dir), sizeof(file));
403  EXPECT_STREQ("", dir);
404  EXPECT_STREQ("fileonly", file);
405  }
406 
407  {
408  const char *path = "dironly/";
409  char dir[FILE_MAX], file[FILE_MAX];
410  BLI_split_dirfile(path, dir, file, sizeof(dir), sizeof(file));
411  EXPECT_STREQ("dironly/", dir);
412  EXPECT_STREQ("", file);
413  }
414 
415  {
416  const char *path = "/a/b";
417  char dir[FILE_MAX], file[FILE_MAX];
418  BLI_split_dirfile(path, dir, file, sizeof(dir), sizeof(file));
419  EXPECT_STREQ("/a/", dir);
420  EXPECT_STREQ("b", file);
421  }
422 
423  {
424  const char *path = "/dirtoobig/filetoobig";
425  char dir[5], file[5];
426  BLI_split_dirfile(path, dir, file, sizeof(dir), sizeof(file));
427  EXPECT_STREQ("/dir", dir);
428  EXPECT_STREQ("file", file);
429 
430  BLI_split_dirfile(path, dir, file, 1, 1);
431  EXPECT_STREQ("", dir);
432  EXPECT_STREQ("", file);
433  }
434 }
435 
436 #define PATH_FRAME_STRIP(input_path, expect_path, expect_ext) \
437  { \
438  char path[FILE_MAX]; \
439  char ext[FILE_MAX]; \
440  BLI_strncpy(path, (input_path), FILE_MAX); \
441  BLI_path_frame_strip(path, ext, sizeof(ext)); \
442  EXPECT_STREQ(path, expect_path); \
443  EXPECT_STREQ(ext, expect_ext); \
444  } \
445  ((void)0)
446 
447 /* BLI_path_frame_strip */
448 TEST(path_util, PathFrameStrip)
449 {
450  PATH_FRAME_STRIP("", "", "");
451  PATH_FRAME_STRIP("nonum.abc", "nonum", ".abc");
452  PATH_FRAME_STRIP("fileonly.001.abc", "fileonly.###", ".abc");
453  PATH_FRAME_STRIP("/abspath/to/somefile.001.abc", "/abspath/to/somefile.###", ".abc");
454  PATH_FRAME_STRIP("/ext/longer/somefile.001.alembic", "/ext/longer/somefile.###", ".alembic");
455  PATH_FRAME_STRIP("/ext/shorter/somefile.123001.abc", "/ext/shorter/somefile.######", ".abc");
456 }
457 #undef PATH_FRAME_STRIP
458 
459 #define PATH_EXTENSION_CHECK(input_path, input_ext, expect_ext) \
460  { \
461  const bool ret = BLI_path_extension_check(input_path, input_ext); \
462  if (strcmp(input_ext, expect_ext) == 0) { \
463  EXPECT_TRUE(ret); \
464  } \
465  else { \
466  EXPECT_FALSE(ret); \
467  } \
468  } \
469  ((void)0)
470 
471 /* BLI_path_extension_check */
472 TEST(path_util, PathExtensionCheck)
473 {
474  PATH_EXTENSION_CHECK("a/b/c.exe", ".exe", ".exe");
475  PATH_EXTENSION_CHECK("correct/path/to/file.h", ".h", ".h");
476  PATH_EXTENSION_CHECK("correct/path/to/file.BLEND", ".BLEND", ".BLEND");
477  PATH_EXTENSION_CHECK("../tricky/path/to/file.h", ".h", ".h");
478  PATH_EXTENSION_CHECK("../dirty//../path\\to/file.h", ".h", ".h");
479  PATH_EXTENSION_CHECK("a/b/c.veryveryverylonglonglongextension",
480  ".veryveryverylonglonglongextension",
481  ".veryveryverylonglonglongextension");
482  PATH_EXTENSION_CHECK("filename.PNG", "pnG", "pnG");
483  PATH_EXTENSION_CHECK("a/b/c.h.exe", ".exe", ".exe");
484  PATH_EXTENSION_CHECK("a/b/c.h.exe", "exe", "exe");
485  PATH_EXTENSION_CHECK("a/b/c.exe", "c.exe", "c.exe");
486  PATH_EXTENSION_CHECK("a/b/noext", "noext", "noext");
487 
488  PATH_EXTENSION_CHECK("a/b/c.exe", ".png", ".exe");
489  PATH_EXTENSION_CHECK("a/b/c.exe", "c.png", ".exe");
490  PATH_EXTENSION_CHECK("a/b/s.l", "l.s", "s.l");
491  PATH_EXTENSION_CHECK(".hiddenfolder", "", ".hiddenfolder");
492  PATH_EXTENSION_CHECK("../dirty//../path\\to/actual.h.file.ext", ".h", ".ext");
493  PATH_EXTENSION_CHECK("..\\dirty//../path//to/.hiddenfile.JPEG", ".hiddenfile", ".JPEG");
494 }
495 #undef PATH_EXTENSION_CHECK
496 
497 #define PATH_FRAME_CHECK_CHARS(input_path, expect_hasChars) \
498  { \
499  const bool ret = BLI_path_frame_check_chars(input_path); \
500  if (expect_hasChars) { \
501  EXPECT_TRUE(ret); \
502  } \
503  else { \
504  EXPECT_FALSE(ret); \
505  } \
506  } \
507  ((void)0)
508 
509 /* BLI_path_frame_check_chars */
510 TEST(path_util, PathFrameCheckChars)
511 {
512  PATH_FRAME_CHECK_CHARS("a#", true);
513  PATH_FRAME_CHECK_CHARS("aaaaa#", true);
514  PATH_FRAME_CHECK_CHARS("#aaaaa", true);
515  PATH_FRAME_CHECK_CHARS("a##.###", true);
516  PATH_FRAME_CHECK_CHARS("####.abc#", true);
517  PATH_FRAME_CHECK_CHARS("path/to/chars/a#", true);
518  PATH_FRAME_CHECK_CHARS("path/to/chars/123#123.exe", true);
519 
520  PATH_FRAME_CHECK_CHARS("&", false);
521  PATH_FRAME_CHECK_CHARS("\35", false);
522  PATH_FRAME_CHECK_CHARS("path#/to#/chars#/$.h", false);
523  PATH_FRAME_CHECK_CHARS("path#/to#/chars#/nochars.h", false);
524  PATH_FRAME_CHECK_CHARS("..\\dirty\\path#/..//to#\\chars#/nochars.h", false);
525  PATH_FRAME_CHECK_CHARS("..\\dirty\\path#/..//to#/chars#\\nochars.h", false);
526 }
527 #undef PATH_FRAME_CHECK_CHARS
528 
529 #define PATH_FRAME_RANGE(input_path, sta, end, digits, expect_outpath) \
530  { \
531  char path[FILE_MAX]; \
532  bool ret; \
533  BLI_strncpy(path, input_path, FILE_MAX); \
534  ret = BLI_path_frame_range(path, sta, end, digits); \
535  if (expect_outpath == NULL) { \
536  EXPECT_FALSE(ret); \
537  } \
538  else { \
539  EXPECT_TRUE(ret); \
540  EXPECT_STREQ(path, expect_outpath); \
541  } \
542  } \
543  ((void)0)
544 
545 /* BLI_path_frame_range */
546 TEST(path_util, PathFrameRange)
547 {
548  int dummy = -1;
549  PATH_FRAME_RANGE("#", 1, 2, dummy, "1-2");
550  PATH_FRAME_RANGE("##", 1, 2, dummy, "01-02");
551  PATH_FRAME_RANGE("##", 1000, 2000, dummy, "1000-2000");
552  PATH_FRAME_RANGE("###", 100, 200, dummy, "100-200");
553  PATH_FRAME_RANGE("###", 8, 9, dummy, "008-009");
554 
555  PATH_FRAME_RANGE("", 100, 200, 1, "100-200");
556  PATH_FRAME_RANGE("", 123, 321, 4, "0123-0321");
557  PATH_FRAME_RANGE("", 1, 0, 20, "00000000000000000001-00000000000000000000");
558 }
559 #undef PATH_FRAME_RANGE
560 
561 #define PATH_FRAME_GET(input_path, expect_frame, expect_numdigits, expect_pathisvalid) \
562  { \
563  char path[FILE_MAX]; \
564  int out_frame = -1, out_numdigits = -1; \
565  BLI_strncpy(path, input_path, FILE_MAX); \
566  const bool ret = BLI_path_frame_get(path, &out_frame, &out_numdigits); \
567  if (expect_pathisvalid) { \
568  EXPECT_TRUE(ret); \
569  } \
570  else { \
571  EXPECT_FALSE(ret); \
572  } \
573  EXPECT_EQ(out_frame, expect_frame); \
574  EXPECT_EQ(out_numdigits, expect_numdigits); \
575  } \
576  ((void)0)
577 
578 /* BLI_path_frame_get */
579 TEST(path_util, PathFrameGet)
580 {
581  PATH_FRAME_GET("001.avi", 1, 3, true);
582  PATH_FRAME_GET("0000299.ext", 299, 7, true);
583  PATH_FRAME_GET("path/to/frame_2810.dummy_quite_long_extension", 2810, 4, true);
584  PATH_FRAME_GET("notframe_7_frame00018.bla", 18, 5, true);
585 
586  PATH_FRAME_GET("", -1, -1, false);
587 }
588 #undef PATH_FRAME_GET
589 
590 /* BLI_path_extension */
591 TEST(path_util, PathExtension)
592 {
593  EXPECT_EQ(nullptr, BLI_path_extension("some.def/file"));
594  EXPECT_EQ(nullptr, BLI_path_extension("Text"));
595  EXPECT_EQ(nullptr, BLI_path_extension("Text…001"));
596 
597  EXPECT_STREQ(".", BLI_path_extension("some/file."));
598  EXPECT_STREQ(".gz", BLI_path_extension("some/file.tar.gz"));
599  EXPECT_STREQ(".abc", BLI_path_extension("some.def/file.abc"));
600  EXPECT_STREQ(".abc", BLI_path_extension("C:\\some.def\\file.abc"));
601  EXPECT_STREQ(".001", BLI_path_extension("Text.001"));
602 }
603 
604 /* BLI_path_rel. */
605 #ifndef _WIN32
606 
607 # define PATH_REL(abs_path, ref_path, rel_path) \
608  { \
609  char path[FILE_MAX]; \
610  BLI_strncpy(path, abs_path, sizeof(path)); \
611  BLI_path_rel(path, ref_path); \
612  EXPECT_STREQ(rel_path, path); \
613  } \
614  void(0)
615 
616 TEST(path_util, PathRelPath)
617 {
618  PATH_REL("/foo/bar/blender.blend", "/foo/bar/", "//blender.blend");
619  PATH_REL("/foo/bar/blender.blend", "/foo/bar", "//bar/blender.blend");
620 
621  /* Check for potential buffer overflows. */
622  {
623  char abs_path_in[FILE_MAX];
624  abs_path_in[0] = '/';
625  for (int i = 1; i < FILE_MAX - 1; i++) {
626  abs_path_in[i] = 'A';
627  }
628  abs_path_in[FILE_MAX - 1] = '\0';
629  char abs_path_out[FILE_MAX];
630  abs_path_out[0] = '/';
631  abs_path_out[1] = '/';
632  for (int i = 2; i < FILE_MAX - 1; i++) {
633  abs_path_out[i] = 'A';
634  }
635  abs_path_out[FILE_MAX - 1] = '\0';
636  PATH_REL(abs_path_in, "/", abs_path_out);
637 
638  const char *ref_path_in = "/foo/bar/";
639  const size_t ref_path_in_len = strlen(ref_path_in);
640  strcpy(abs_path_in, ref_path_in);
641  for (int i = ref_path_in_len; i < FILE_MAX - 1; i++) {
642  abs_path_in[i] = 'A';
643  }
644  abs_path_in[FILE_MAX - 1] = '\0';
645  abs_path_out[0] = '/';
646  abs_path_out[1] = '/';
647  for (int i = 2; i < FILE_MAX - ((int)ref_path_in_len - 1); i++) {
648  abs_path_out[i] = 'A';
649  }
650  abs_path_out[FILE_MAX - (ref_path_in_len - 1)] = '\0';
651  PATH_REL(abs_path_in, ref_path_in, abs_path_out);
652  }
653 }
654 
655 # undef PATH_REL
656 
657 #endif
658 
659 /* BLI_path_contains */
660 TEST(path_util, PathContains)
661 {
662  EXPECT_TRUE(BLI_path_contains("/some/path", "/some/path")) << "A path contains itself";
663  EXPECT_TRUE(BLI_path_contains("/some/path", "/some/path/inside"))
664  << "A path contains its subdirectory";
665  EXPECT_TRUE(BLI_path_contains("/some/path", "/some/path/../path/inside"))
666  << "Paths should be normalized";
667  EXPECT_TRUE(BLI_path_contains("C:\\some\\path", "C:\\some\\path\\inside"))
668  << "Windows paths should be supported as well";
669 
670  EXPECT_FALSE(BLI_path_contains("C:\\some\\path", "C:\\some\\other\\path"))
671  << "Windows paths should be supported as well";
672  EXPECT_FALSE(BLI_path_contains("/some/path", "/"))
673  << "Root directory not be contained in a subdirectory";
674  EXPECT_FALSE(BLI_path_contains("/some/path", "/some/path/../outside"))
675  << "Paths should be normalized";
676  EXPECT_FALSE(BLI_path_contains("/some/path", "/some/path_library"))
677  << "Just sharing a suffix is not enough, path semantics should be followed";
678  EXPECT_FALSE(BLI_path_contains("/some/path", "./contents"))
679  << "Relative paths are not supported";
680 }
681 
682 #ifdef WIN32
683 TEST(path_util, PathContains_Windows_case_insensitive)
684 {
685  EXPECT_TRUE(BLI_path_contains("C:\\some\\path", "c:\\SOME\\path\\inside"))
686  << "On Windows path comparison should ignore case";
687 }
688 #endif
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
File and directory operations.
bool BLI_path_frame(char *path, int frame, int digits) ATTR_NONNULL()
Definition: path_util.c:709
const char * BLI_path_extension(const char *filepath) ATTR_NONNULL()
Definition: path_util.c:1500
void BLI_split_dirfile(const char *string, char *dir, char *file, size_t dirlen, size_t filelen)
Definition: path_util.c:1465
#define FILE_MAX
void BLI_path_normalize(const char *relabase, char *path) ATTR_NONNULL(2)
Definition: path_util.c:131
bool BLI_path_contains(const char *container_path, const char *containee_path) ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:1717
#define PATH_FRAME_RANGE(input_path, sta, end, digits, expect_outpath)
#define PATH_EXTENSION_CHECK(input_path, input_ext, expect_ext)
#define PATH_FRAME_STRIP(input_path, expect_path, expect_ext)
#define JOIN(str_expect, out_size,...)
#define AT_INDEX(str_input, index_input, str_expect)
#define PATH_FRAME_GET(input_path, expect_frame, expect_numdigits, expect_pathisvalid)
#define PATH_FRAME_CHECK_CHARS(input_path, expect_hasChars)
TEST(path_util, Clean)
#define PATH_REL(abs_path, ref_path, rel_path)
FILE * file
return ret