Merge branch 'blender2.7'
[blender.git] / tests / gtests / blenlib / BLI_path_util_test.cc
1 /* Apache License, Version 2.0 */
2
3 #include "testing/testing.h"
4
5 extern "C" {
6 #include "BLI_fileops.h"
7 #include "BLI_path_util.h"
8 #include "BLI_string.h"
9 #include "../../../source/blender/imbuf/IMB_imbuf.h"
10
11 #ifdef _WIN32
12 #  include "../../../source/blender/blenkernel/BKE_global.h"
13 #endif
14
15 }
16
17 /* -------------------------------------------------------------------- */
18 /* stubs */
19
20 extern "C" {
21
22 #if _WIN32
23 Global G = {0};
24 #endif
25
26 const char *GHOST_getUserDir(int version, const char *versionstr);
27 const char *GHOST_getSystemDir(int version, const char *versionstr);
28 #ifdef __linux__
29 char *zLhm65070058860608_br_find_exe(const char *default_exe);
30 #endif
31
32 const char *GHOST_getUserDir(int version, const char *versionstr)
33 {
34         return "/home/user";
35 }
36
37 const char *GHOST_getSystemDir(int version, const char *versionstr)
38 {
39         return "/system/path";
40 }
41
42 struct ImBuf;
43 void IMB_freeImBuf(struct ImBuf *ibuf) {}
44 struct ImBuf *IMB_dupImBuf(const ImBuf *ibuf) {return NULL;}
45
46 #ifdef __linux__
47 char *zLhm65070058860608_br_find_exe(const char *default_exe)
48 {
49         return NULL;
50 }
51 #endif
52
53 }
54
55
56 /* -------------------------------------------------------------------- */
57 /* tests */
58
59 /* BLI_cleanup_path */
60 #ifndef _WIN32
61 TEST(path_util, Clean)
62 {
63         /* "/./" -> "/" */
64         {
65                 char path[FILE_MAX] = "/a/./b/./c/./";
66                 BLI_cleanup_path(NULL, path);
67                 EXPECT_STREQ("/a/b/c/", path);
68         }
69
70         {
71                 char path[FILE_MAX] = "/./././";
72                 BLI_cleanup_path(NULL, path);
73                 EXPECT_STREQ("/", path);
74         }
75
76         {
77                 char path[FILE_MAX] = "/a/./././b/";
78                 BLI_cleanup_path(NULL, path);
79                 EXPECT_STREQ("/a/b/", path);
80         }
81
82         /* "//" -> "/" */
83         {
84                 char path[FILE_MAX] = "a////";
85                 BLI_cleanup_path(NULL, path);
86                 EXPECT_STREQ("a/", path);
87         }
88
89         if (0)  /* FIXME */
90         {
91                 char path[FILE_MAX] = "./a////";
92                 BLI_cleanup_path(NULL, path);
93                 EXPECT_STREQ("./a/", path);
94         }
95
96         /* "foo/bar/../" -> "foo/" */
97         {
98                 char path[FILE_MAX] = "/a/b/c/../../../";
99                 BLI_cleanup_path(NULL, path);
100                 EXPECT_STREQ("/", path);
101         }
102
103         {
104                 char path[FILE_MAX] = "/a/../a/b/../b/c/../c/";
105                 BLI_cleanup_path(NULL, path);
106                 EXPECT_STREQ("/a/b/c/", path);
107         }
108
109         {
110                 char path[FILE_MAX] = "//../";
111                 BLI_cleanup_path("/a/b/c/", path);
112                 EXPECT_STREQ("/a/b/", path);
113         }
114 }
115 #endif
116
117
118 #define AT_INDEX(str_input, index_input, str_expect) \
119         { \
120                 char path[] = str_input; \
121                 const char *expect = str_expect; \
122                 int index_output, len_output; \
123                 const bool ret = BLI_path_name_at_index(path, index_input, &index_output, &len_output); \
124                 if (expect == NULL) { \
125                         EXPECT_EQ(ret, false); \
126                 } \
127                 else { \
128                         EXPECT_EQ(ret, true); \
129                         EXPECT_EQ(strlen(expect), len_output); \
130                         path[index_output + len_output] = '\0'; \
131                         EXPECT_STREQ(&path[index_output], expect); \
132                 } \
133         }((void)0)
134
135 /* BLI_path_name_at_index */
136 TEST(path_util, NameAtIndex_Single)
137 {
138         AT_INDEX("/a", 0, "a");
139         AT_INDEX("/a/", 0, "a");
140         AT_INDEX("a/", 0, "a");
141         AT_INDEX("//a//", 0, "a");
142         AT_INDEX("a/b", 0, "a");
143
144         AT_INDEX("/a", 1, NULL);
145         AT_INDEX("/a/", 1, NULL);
146         AT_INDEX("a/", 1, NULL);
147         AT_INDEX("//a//", 1, NULL);
148 }
149 TEST(path_util, NameAtIndex_SingleNeg)
150 {
151         AT_INDEX("/a", -1, "a");
152         AT_INDEX("/a/", -1, "a");
153         AT_INDEX("a/", -1, "a");
154         AT_INDEX("//a//", -1, "a");
155         AT_INDEX("a/b", -1, "b");
156
157         AT_INDEX("/a", -2, NULL);
158         AT_INDEX("/a/", -2, NULL);
159         AT_INDEX("a/", -2, NULL);
160         AT_INDEX("//a//", -2, NULL);
161 }
162
163 TEST(path_util, NameAtIndex_Double)
164 {
165         AT_INDEX("/ab", 0, "ab");
166         AT_INDEX("/ab/", 0, "ab");
167         AT_INDEX("ab/", 0, "ab");
168         AT_INDEX("//ab//", 0, "ab");
169         AT_INDEX("ab/c", 0, "ab");
170
171         AT_INDEX("/ab", 1, NULL);
172         AT_INDEX("/ab/", 1, NULL);
173         AT_INDEX("ab/", 1, NULL);
174         AT_INDEX("//ab//", 1, NULL);
175 }
176
177 TEST(path_util, NameAtIndex_DoublNeg)
178 {
179         AT_INDEX("/ab", -1, "ab");
180         AT_INDEX("/ab/", -1, "ab");
181         AT_INDEX("ab/", -1, "ab");
182         AT_INDEX("//ab//", -1, "ab");
183         AT_INDEX("ab/c", -1, "c");
184
185         AT_INDEX("/ab", -2, NULL);
186         AT_INDEX("/ab/", -2, NULL);
187         AT_INDEX("ab/", -2, NULL);
188         AT_INDEX("//ab//", -2, NULL);
189 }
190
191 TEST(path_util, NameAtIndex_Misc)
192 {
193         AT_INDEX("/how/now/brown/cow", 0, "how");
194         AT_INDEX("/how/now/brown/cow", 1, "now");
195         AT_INDEX("/how/now/brown/cow", 2, "brown");
196         AT_INDEX("/how/now/brown/cow", 3, "cow");
197         AT_INDEX("/how/now/brown/cow", 4, NULL);
198         AT_INDEX("/how/now/brown/cow/", 4, NULL);
199 }
200
201 TEST(path_util, NameAtIndex_MiscNeg)
202 {
203         AT_INDEX("/how/now/brown/cow", 0, "how");
204         AT_INDEX("/how/now/brown/cow", 1, "now");
205         AT_INDEX("/how/now/brown/cow", 2, "brown");
206         AT_INDEX("/how/now/brown/cow", 3, "cow");
207         AT_INDEX("/how/now/brown/cow", 4, NULL);
208         AT_INDEX("/how/now/brown/cow/", 4, NULL);
209 }
210
211 TEST(path_util, NameAtIndex_MiscComplex)
212 {
213         AT_INDEX("how//now/brown/cow", 0, "how");
214         AT_INDEX("//how///now\\/brown/cow", 1, "now");
215         AT_INDEX("/how/now\\//brown\\/cow", 2, "brown");
216         AT_INDEX("/how/now/brown/cow//\\", 3, "cow");
217         AT_INDEX("/how/now/brown/\\cow", 4, NULL);
218         AT_INDEX("how/now/brown/\\cow\\", 4, NULL);
219 }
220
221 TEST(path_util, NameAtIndex_MiscComplexNeg)
222 {
223         AT_INDEX("how//now/brown/cow", -4, "how");
224         AT_INDEX("//how///now\\/brown/cow", -3, "now");
225         AT_INDEX("/how/now\\//brown\\/cow", -2, "brown");
226         AT_INDEX("/how/now/brown/cow//\\", -1, "cow");
227         AT_INDEX("/how/now/brown/\\cow", -5, NULL);
228         AT_INDEX("how/now/brown/\\cow\\", -5, NULL);
229 }
230
231 TEST(path_util, NameAtIndex_NoneComplex)
232 {
233         AT_INDEX("", 0, NULL);
234         AT_INDEX("/", 0, NULL);
235         AT_INDEX("//", 0, NULL);
236         AT_INDEX("///", 0, NULL);
237 }
238
239 TEST(path_util, NameAtIndex_NoneComplexNeg)
240 {
241         AT_INDEX("", -1, NULL);
242         AT_INDEX("/", -1, NULL);
243         AT_INDEX("//", -1, NULL);
244         AT_INDEX("///", -1, NULL);
245 }
246
247 #undef AT_INDEX
248
249 #define JOIN(str_expect, out_size, ...) \
250         { \
251                 const char *expect = str_expect; \
252                 char result[(out_size) + 1024]; \
253                 /* check we don't write past the last byte */ \
254                 result[out_size] = '\0'; \
255                 BLI_path_join(result, out_size, __VA_ARGS__, NULL); \
256                 /* simplify expected string */ \
257                 BLI_str_replace_char(result, '\\', '/'); \
258                 EXPECT_STREQ(result, expect); \
259                 EXPECT_EQ(result[out_size], '\0'); \
260         } ((void)0)
261
262 /* BLI_path_join */
263 TEST(path_util, JoinNop)
264 {
265         JOIN("", 100, "");
266         JOIN("", 100, "", "");
267         JOIN("", 100, "", "", "");
268         JOIN("/", 100, "/", "", "");
269         JOIN("/", 100, "/", "/");
270         JOIN("/", 100, "/", "", "/");
271         JOIN("/", 100, "/", "", "/", "");
272 }
273
274 TEST(path_util, JoinSingle)
275 {
276         JOIN("test", 100, "test");
277         JOIN("", 100, "");
278         JOIN("a", 100, "a");
279         JOIN("/a", 100, "/a");
280         JOIN("a/", 100, "a/");
281         JOIN("/a/", 100, "/a/");
282         JOIN("/a/", 100, "/a//");
283         JOIN("//a/", 100, "//a//");
284 }
285
286 TEST(path_util, JoinTriple)
287 {
288         JOIN("/a/b/c", 100, "/a", "b", "c");
289         JOIN("/a/b/c", 100, "/a/", "/b/", "/c");
290         JOIN("/a/b/c", 100, "/a/b/", "/c");
291         JOIN("/a/b/c", 100, "/a/b/c");
292         JOIN("/a/b/c", 100, "/", "a/b/c");
293
294         JOIN("/a/b/c/", 100, "/a/", "/b/", "/c/");
295         JOIN("/a/b/c/", 100, "/a/b/c/");
296         JOIN("/a/b/c/", 100, "/a/b/", "/c/");
297         JOIN("/a/b/c/", 100, "/a/b/c", "/");
298         JOIN("/a/b/c/", 100, "/", "a/b/c", "/");
299 }
300
301 TEST(path_util, JoinTruncateShort)
302 {
303         JOIN("", 1, "/");
304         JOIN("/", 2, "/");
305         JOIN("a", 2, "", "aa");
306         JOIN("a", 2, "", "a/");
307         JOIN("a/b", 4, "a", "bc");
308         JOIN("ab/", 4, "ab", "c");
309         JOIN("/a/", 4, "/a", "b");
310         JOIN("/a/", 4, "/a/", "b/");
311         JOIN("/a/", 4, "/a", "/b/");
312         JOIN("/a/", 4, "/", "a/b/");
313         JOIN("//a", 4, "//", "a/b/");
314
315         JOIN("/a/b", 5, "/a", "b", "c");
316 }
317
318 TEST(path_util, JoinTruncateLong)
319 {
320         JOIN("", 1, "//", "//longer", "path");
321         JOIN("/", 2, "//", "//longer", "path");
322         JOIN("//", 3, "//", "//longer", "path");
323         JOIN("//l", 4, "//", "//longer", "path");
324         /* snip */
325         JOIN("//longe", 8, "//", "//longer", "path");
326         JOIN("//longer", 9, "//", "//longer", "path");
327         JOIN("//longer/", 10, "//", "//longer", "path");
328         JOIN("//longer/p", 11, "//", "//longer", "path");
329         JOIN("//longer/pa", 12, "//", "//longer", "path");
330         JOIN("//longer/pat", 13, "//", "//longer", "path");
331         JOIN("//longer/path", 14, "//", "//longer", "path"); // not truncated
332         JOIN("//longer/path", 14, "//", "//longer", "path/");
333         JOIN("//longer/path/", 15, "//", "//longer", "path/"); // not truncated
334         JOIN("//longer/path/", 15, "//", "//longer", "path/", "trunc");
335         JOIN("//longer/path/t", 16, "//", "//longer", "path/", "trunc");
336 }
337
338 TEST(path_util, JoinComplex)
339 {
340         JOIN("/a/b/c/d/e/f/g/", 100, "/", "\\a/b", "//////c/d", "", "e\\\\", "f", "g//");
341         JOIN("/aa/bb/cc/dd/ee/ff/gg/", 100, "/", "\\aa/bb", "//////cc/dd", "", "ee\\\\", "ff", "gg//");
342         JOIN("1/2/3/", 100, "1", "////////", "", "2", "3\\");
343 }
344
345 #undef JOIN
346
347 /* BLI_path_frame */
348 TEST(path_util, Frame)
349 {
350         bool ret;
351
352         {
353                 char path[FILE_MAX] = "";
354                 ret = BLI_path_frame(path, 123, 1);
355                 EXPECT_EQ(ret, 1);
356                 EXPECT_STREQ("123", path);
357         }
358
359         {
360                 char path[FILE_MAX] = "";
361                 ret = BLI_path_frame(path, 123, 12);
362                 EXPECT_EQ(ret, 1);
363                 EXPECT_STREQ("000000000123", path);
364         }
365
366         {
367                 char path[FILE_MAX] = "test_";
368                 ret = BLI_path_frame(path, 123, 1);
369                 EXPECT_EQ(ret, 1);
370                 EXPECT_STREQ("test_123", path);
371         }
372
373         {
374                 char path[FILE_MAX] = "test_";
375                 ret = BLI_path_frame(path, 1, 12);
376                 EXPECT_EQ(ret, 1);
377                 EXPECT_STREQ("test_000000000001", path);
378         }
379
380         {
381                 char path[FILE_MAX] = "test_############";
382                 ret = BLI_path_frame(path, 1, 0);
383                 EXPECT_EQ(ret, 1);
384                 EXPECT_STREQ("test_000000000001", path);
385         }
386
387         {
388                 char path[FILE_MAX] = "test_#_#_middle";
389                 ret = BLI_path_frame(path, 123, 0);
390                 EXPECT_EQ(ret, 1);
391                 EXPECT_STREQ("test_#_123_middle", path);
392         }
393
394         /* intentionally fail */
395         {
396                 char path[FILE_MAX] = "";
397                 ret = BLI_path_frame(path, 123, 0);
398                 EXPECT_EQ(ret, 0);
399                 EXPECT_STREQ("", path);
400         }
401
402         {
403                 char path[FILE_MAX] = "test_middle";
404                 ret = BLI_path_frame(path, 123, 0);
405                 EXPECT_EQ(ret, 0);
406                 EXPECT_STREQ("test_middle", path);
407         }
408 }
409
410 /* BLI_split_dirfile */
411 TEST(path_util, SplitDirfile)
412 {
413         {
414                 const char *path = "";
415                 char dir[FILE_MAX], file[FILE_MAX];
416                 BLI_split_dirfile(path, dir, file, sizeof(dir), sizeof(file));
417                 EXPECT_STREQ("", dir);
418                 EXPECT_STREQ("", file);
419         }
420
421         {
422                 const char *path = "/";
423                 char dir[FILE_MAX], file[FILE_MAX];
424                 BLI_split_dirfile(path, dir, file, sizeof(dir), sizeof(file));
425                 EXPECT_STREQ("/", dir);
426                 EXPECT_STREQ("", file);
427         }
428
429         {
430                 const char *path = "fileonly";
431                 char dir[FILE_MAX], file[FILE_MAX];
432                 BLI_split_dirfile(path, dir, file, sizeof(dir), sizeof(file));
433                 EXPECT_STREQ("", dir);
434                 EXPECT_STREQ("fileonly", file);
435         }
436
437         {
438                 const char *path = "dironly/";
439                 char dir[FILE_MAX], file[FILE_MAX];
440                 BLI_split_dirfile(path, dir, file, sizeof(dir), sizeof(file));
441                 EXPECT_STREQ("dironly/", dir);
442                 EXPECT_STREQ("", file);
443         }
444
445         {
446                 const char *path = "/a/b";
447                 char dir[FILE_MAX], file[FILE_MAX];
448                 BLI_split_dirfile(path, dir, file, sizeof(dir), sizeof(file));
449                 EXPECT_STREQ("/a/", dir);
450                 EXPECT_STREQ("b", file);
451         }
452
453         {
454                 const char *path = "/dirtoobig/filetoobig";
455                 char dir[5], file[5];
456                 BLI_split_dirfile(path, dir, file, sizeof(dir), sizeof(file));
457                 EXPECT_STREQ("/dir", dir);
458                 EXPECT_STREQ("file", file);
459
460                 BLI_split_dirfile(path, dir, file, 1, 1);
461                 EXPECT_STREQ("", dir);
462                 EXPECT_STREQ("", file);
463         }
464 }