1 /* Apache License, Version 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
TEST(path_util,Clean)16 TEST(path_util, Clean)
17 {
18 /* "/./" -> "/" */
19 {
20 char path[FILE_MAX] = "/a/./b/./c/./";
21 BLI_path_normalize(NULL, path);
22 EXPECT_STREQ("/a/b/c/", path);
23 }
24
25 {
26 char path[FILE_MAX] = "/./././";
27 BLI_path_normalize(NULL, path);
28 EXPECT_STREQ("/", path);
29 }
30
31 {
32 char path[FILE_MAX] = "/a/./././b/";
33 BLI_path_normalize(NULL, path);
34 EXPECT_STREQ("/a/b/", path);
35 }
36
37 /* "//" -> "/" */
38 {
39 char path[FILE_MAX] = "a////";
40 BLI_path_normalize(NULL, path);
41 EXPECT_STREQ("a/", path);
42 }
43
44 if (0) /* FIXME */
45 {
46 char path[FILE_MAX] = "./a////";
47 BLI_path_normalize(NULL, 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(NULL, path);
55 EXPECT_STREQ("/", path);
56 }
57
58 {
59 char path[FILE_MAX] = "/a/../a/b/../b/c/../c/";
60 BLI_path_normalize(NULL, 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 */
TEST(path_util,NameAtIndex_Single)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, NULL);
100 AT_INDEX("/a/", 1, NULL);
101 AT_INDEX("a/", 1, NULL);
102 AT_INDEX("//a//", 1, NULL);
103 }
TEST(path_util,NameAtIndex_SingleNeg)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, NULL);
113 AT_INDEX("/a/", -2, NULL);
114 AT_INDEX("a/", -2, NULL);
115 AT_INDEX("//a//", -2, NULL);
116 }
117
TEST(path_util,NameAtIndex_Double)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, NULL);
127 AT_INDEX("/ab/", 1, NULL);
128 AT_INDEX("ab/", 1, NULL);
129 AT_INDEX("//ab//", 1, NULL);
130 }
131
TEST(path_util,NameAtIndex_DoublNeg)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, NULL);
141 AT_INDEX("/ab/", -2, NULL);
142 AT_INDEX("ab/", -2, NULL);
143 AT_INDEX("//ab//", -2, NULL);
144 }
145
TEST(path_util,NameAtIndex_Misc)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, NULL);
153 AT_INDEX("/how/now/brown/cow/", 4, NULL);
154 }
155
TEST(path_util,NameAtIndex_MiscNeg)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, NULL);
163 AT_INDEX("/how/now/brown/cow/", 4, NULL);
164 }
165
TEST(path_util,NameAtIndex_MiscComplex)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, NULL);
173 AT_INDEX("how/now/brown/\\cow\\", 4, NULL);
174 }
175
TEST(path_util,NameAtIndex_MiscComplexNeg)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, NULL);
183 AT_INDEX("how/now/brown/\\cow\\", -5, NULL);
184 }
185
TEST(path_util,NameAtIndex_NoneComplex)186 TEST(path_util, NameAtIndex_NoneComplex)
187 {
188 AT_INDEX("", 0, NULL);
189 AT_INDEX("/", 0, NULL);
190 AT_INDEX("//", 0, NULL);
191 AT_INDEX("///", 0, NULL);
192 }
193
TEST(path_util,NameAtIndex_NoneComplexNeg)194 TEST(path_util, NameAtIndex_NoneComplexNeg)
195 {
196 AT_INDEX("", -1, NULL);
197 AT_INDEX("/", -1, NULL);
198 AT_INDEX("//", -1, NULL);
199 AT_INDEX("///", -1, NULL);
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 */
TEST(path_util,JoinNop)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
TEST(path_util,JoinSingle)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
TEST(path_util,JoinTriple)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
TEST(path_util,JoinTruncateShort)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
TEST(path_util,JoinTruncateLong)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
TEST(path_util,JoinComplex)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 */
TEST(path_util,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 */
TEST(path_util,SplitDirfile)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); \
442 EXPECT_STREQ(path, expect_path); \
443 EXPECT_STREQ(ext, expect_ext); \
444 } \
445 ((void)0)
446
447 /* BLI_path_frame_strip */
TEST(path_util,PathFrameStrip)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 */
TEST(path_util,PathExtensionCheck)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 */
TEST(path_util,PathFrameCheckChars)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 */
TEST(path_util,PathFrameRange)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 */
TEST(path_util,PathFrameGet)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 */
TEST(path_util,PathExtension)591 TEST(path_util, PathExtension)
592 {
593 EXPECT_EQ(NULL, BLI_path_extension("some.def/file"));
594 EXPECT_EQ(NULL, BLI_path_extension("Text"));
595 EXPECT_EQ(NULL, 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
TEST(path_util,PathRelPath)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