Merge branch 'blender2.7'
[blender.git] / tests / gtests / blenlib / BLI_string_test.cc
1 /* Apache License, Version 2.0 */
2
3 #include "testing/testing.h"
4
5 extern "C" {
6 #include "BLI_utildefines.h"
7 #include "BLI_string.h"
8 #include "BLI_string_utf8.h"
9 }
10
11 /* -------------------------------------------------------------------- */
12 /* stubs */
13
14 extern "C" {
15
16 int mk_wcwidth(wchar_t ucs);
17 int mk_wcswidth(const wchar_t *pwcs, size_t n);
18
19 int mk_wcwidth(wchar_t ucs)
20 {
21         return 0;
22 }
23
24 int mk_wcswidth(const wchar_t *pwcs, size_t n)
25 {
26         return 0;
27 }
28
29 }
30
31
32 /* -------------------------------------------------------------------- */
33 /* tests */
34
35 /* BLI_str_partition */
36 TEST(string, StrPartition)
37 {
38         const char delim[] = {'-', '.', '_', '~', '\\', '\0'};
39         const char *sep, *suf;
40         size_t pre_ln;
41
42         {
43                 const char *str = "mat.e-r_ial";
44
45                 /* "mat.e-r_ial" -> "mat", '.', "e-r_ial", 3 */
46                 pre_ln = BLI_str_partition(str, delim, &sep, &suf);
47                 EXPECT_EQ(pre_ln, 3);
48                 EXPECT_EQ(&str[3], sep);
49                 EXPECT_STREQ("e-r_ial", suf);
50         }
51
52         /* Corner cases. */
53         {
54                 const char *str = ".mate-rial--";
55
56                 /* ".mate-rial--" -> "", '.', "mate-rial--", 0 */
57                 pre_ln = BLI_str_partition(str, delim, &sep, &suf);
58                 EXPECT_EQ(pre_ln, 0);
59                 EXPECT_EQ(&str[0], sep);
60                 EXPECT_STREQ("mate-rial--", suf);
61         }
62
63         {
64                 const char *str = ".__.--_";
65
66                 /* ".__.--_" -> "", '.', "__.--_", 0 */
67                 pre_ln = BLI_str_partition(str, delim, &sep, &suf);
68                 EXPECT_EQ(pre_ln, 0);
69                 EXPECT_EQ(&str[0], sep);
70                 EXPECT_STREQ("__.--_", suf);
71         }
72
73         {
74                 const char *str = "";
75
76                 /* "" -> "", NULL, NULL, 0 */
77                 pre_ln = BLI_str_partition(str, delim, &sep, &suf);
78                 EXPECT_EQ(pre_ln, 0);
79                 EXPECT_EQ(sep, (void*)NULL);
80                 EXPECT_EQ(suf, (void*)NULL);
81         }
82
83         {
84                 const char *str = "material";
85
86                 /* "material" -> "material", NULL, NULL, 8 */
87                 pre_ln = BLI_str_partition(str, delim, &sep, &suf);
88                 EXPECT_EQ(pre_ln, 8);
89                 EXPECT_EQ(sep, (void*)NULL);
90                 EXPECT_EQ(suf, (void*)NULL);
91         }
92 }
93
94 /* BLI_str_rpartition */
95 TEST(string, StrRPartition)
96 {
97         const char delim[] = {'-', '.', '_', '~', '\\', '\0'};
98         const char *sep, *suf;
99         size_t pre_ln;
100
101         {
102                 const char *str = "mat.e-r_ial";
103
104                 /* "mat.e-r_ial" -> "mat.e-r", '_', "ial", 7 */
105                 pre_ln = BLI_str_rpartition(str, delim, &sep, &suf);
106                 EXPECT_EQ(pre_ln, 7);
107                 EXPECT_EQ(&str[7], sep);
108                 EXPECT_STREQ("ial", suf);
109         }
110
111         /* Corner cases. */
112         {
113                 const char *str = ".mate-rial--";
114
115                 /* ".mate-rial--" -> ".mate-rial-", '-', "", 11 */
116                 pre_ln = BLI_str_rpartition(str, delim, &sep, &suf);
117                 EXPECT_EQ(pre_ln, 11);
118                 EXPECT_EQ(&str[11], sep);
119                 EXPECT_STREQ("", suf);
120         }
121
122         {
123                 const char *str = ".__.--_";
124
125                 /* ".__.--_" -> ".__.--", '_', "", 6 */
126                 pre_ln = BLI_str_rpartition(str, delim, &sep, &suf);
127                 EXPECT_EQ(pre_ln, 6);
128                 EXPECT_EQ(&str[6], sep);
129                 EXPECT_STREQ("", suf);
130         }
131
132         {
133                 const char *str = "";
134
135                 /* "" -> "", NULL, NULL, 0 */
136                 pre_ln = BLI_str_rpartition(str, delim, &sep, &suf);
137                 EXPECT_EQ(pre_ln, 0);
138                 EXPECT_EQ(sep, (void*)NULL);
139                 EXPECT_EQ(suf, (void*)NULL);
140         }
141
142         {
143                 const char *str = "material";
144
145                 /* "material" -> "material", NULL, NULL, 8 */
146                 pre_ln = BLI_str_rpartition(str, delim, &sep, &suf);
147                 EXPECT_EQ(pre_ln, 8);
148                 EXPECT_EQ(sep, (void*)NULL);
149                 EXPECT_EQ(suf, (void*)NULL);
150         }
151 }
152
153 /* BLI_str_partition_ex */
154 TEST(string, StrPartitionEx)
155 {
156         const char delim[] = {'-', '.', '_', '~', '\\', '\0'};
157         const char *sep, *suf;
158         size_t pre_ln;
159
160         /* Only considering 'from_right' cases here. */
161
162         {
163                 const char *str = "mat.e-r_ia.l";
164
165                 /* "mat.e-r_ia.l" over "mat.e-r" -> "mat.e", '.', "r_ia.l", 3 */
166                 pre_ln = BLI_str_partition_ex(str, str + 6, delim, &sep, &suf, true);
167                 EXPECT_EQ(pre_ln, 5);
168                 EXPECT_EQ(&str[5], sep);
169                 EXPECT_STREQ("r_ia.l", suf);
170         }
171
172         /* Corner cases. */
173         {
174                 const char *str = "mate.rial";
175
176                 /* "mate.rial" over "mate" -> "mate.rial", NULL, NULL, 4 */
177                 pre_ln = BLI_str_partition_ex(str, str + 4, delim, &sep, &suf, true);
178                 EXPECT_EQ(pre_ln, 4);
179                 EXPECT_EQ(sep, (void*)NULL);
180                 EXPECT_EQ(suf, (void*)NULL);
181         }
182 }
183
184 /* BLI_str_partition_utf8 */
185 TEST(string, StrPartitionUtf8)
186 {
187         const unsigned int delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'};
188         const char *sep, *suf;
189         size_t pre_ln;
190
191         {
192                 const char *str = "ma\xc3\xb1te-r\xe2\x98\xafial";
193
194                 /* "ma\xc3\xb1te-r\xe2\x98\xafial" -> "ma", '\xc3\xb1', "te-r\xe2\x98\xafial", 2 */
195                 pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf);
196                 EXPECT_EQ(pre_ln, 2);
197                 EXPECT_EQ(&str[2], sep);
198                 EXPECT_STREQ("te-r\xe2\x98\xafial", suf);
199         }
200
201         /* Corner cases. */
202         {
203                 const char *str = "\xe2\x98\xafmate-rial-\xc3\xb1";
204
205                 /* "\xe2\x98\xafmate-rial-\xc3\xb1" -> "", '\xe2\x98\xaf', "mate-rial-\xc3\xb1", 0 */
206                 pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf);
207                 EXPECT_EQ(pre_ln, 0);
208                 EXPECT_EQ(&str[0], sep);
209                 EXPECT_STREQ("mate-rial-\xc3\xb1", suf);
210         }
211
212         {
213                 const char *str = "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1";
214
215                 /* "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1" -> "", '\xe2\x98\xaf', ".\xc3\xb1_.--\xc3\xb1", 0 */
216                 pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf);
217                 EXPECT_EQ(pre_ln, 0);
218                 EXPECT_EQ(&str[0], sep);
219                 EXPECT_STREQ(".\xc3\xb1_.--\xc3\xb1", suf);
220         }
221
222         {
223                 const char *str = "";
224
225                 /* "" -> "", NULL, NULL, 0 */
226                 pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf);
227                 EXPECT_EQ(pre_ln, 0);
228                 EXPECT_EQ(sep, (void*)NULL);
229                 EXPECT_EQ(suf, (void*)NULL);
230         }
231
232         {
233                 const char *str = "material";
234
235                 /* "material" -> "material", NULL, NULL, 8 */
236                 pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf);
237                 EXPECT_EQ(pre_ln, 8);
238                 EXPECT_EQ(sep, (void*)NULL);
239                 EXPECT_EQ(suf, (void*)NULL);
240         }
241 }
242
243 /* BLI_str_rpartition_utf8 */
244 TEST(string, StrRPartitionUtf8)
245 {
246         const unsigned int delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'};
247         const char *sep, *suf;
248         size_t pre_ln;
249
250         {
251                 const char *str = "ma\xc3\xb1te-r\xe2\x98\xafial";
252
253                 /* "ma\xc3\xb1te-r\xe2\x98\xafial" -> "mat\xc3\xb1te-r", '\xe2\x98\xaf', "ial", 8 */
254                 pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf);
255                 EXPECT_EQ(pre_ln, 8);
256                 EXPECT_EQ(&str[8], sep);
257                 EXPECT_STREQ("ial", suf);
258         }
259
260         /* Corner cases. */
261         {
262                 const char *str = "\xe2\x98\xafmate-rial-\xc3\xb1";
263
264                 /* "\xe2\x98\xafmate-rial-\xc3\xb1" -> "\xe2\x98\xafmate-rial-", '\xc3\xb1', "", 13 */
265                 pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf);
266                 EXPECT_EQ(pre_ln, 13);
267                 EXPECT_EQ(&str[13], sep);
268                 EXPECT_STREQ("", suf);
269         }
270
271         {
272                 const char *str = "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1";
273
274                 /* "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1" -> "\xe2\x98\xaf.\xc3\xb1_.--", '\xc3\xb1', "", 10 */
275                 pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf);
276                 EXPECT_EQ(pre_ln, 10);
277                 EXPECT_EQ(&str[10], sep);
278                 EXPECT_STREQ("", suf);
279         }
280
281         {
282                 const char *str = "";
283
284                 /* "" -> "", NULL, NULL, 0 */
285                 pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf);
286                 EXPECT_EQ(pre_ln, 0);
287                 EXPECT_EQ(sep, (void*)NULL);
288                 EXPECT_EQ(suf, (void*)NULL);
289         }
290
291         {
292                 const char *str = "material";
293
294                 /* "material" -> "material", NULL, NULL, 8 */
295                 pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf);
296                 EXPECT_EQ(pre_ln, 8);
297                 EXPECT_EQ(sep, (void*)NULL);
298                 EXPECT_EQ(suf, (void*)NULL);
299         }
300 }
301
302 /* BLI_str_partition_ex_utf8 */
303 TEST(string, StrPartitionExUtf8)
304 {
305         const unsigned int delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'};
306         const char *sep, *suf;
307         size_t pre_ln;
308
309         /* Only considering 'from_right' cases here. */
310
311         {
312                 const char *str = "ma\xc3\xb1te-r\xe2\x98\xafial";
313
314                 /* "ma\xc3\xb1te-r\xe2\x98\xafial" over "ma\xc3\xb1te" -> "ma", '\xc3\xb1', "te-r\xe2\x98\xafial", 2 */
315                 pre_ln = BLI_str_partition_ex_utf8(str, str + 6, delim, &sep, &suf, true);
316                 EXPECT_EQ(pre_ln, 2);
317                 EXPECT_EQ(&str[2], sep);
318                 EXPECT_STREQ("te-r\xe2\x98\xafial", suf);
319         }
320
321         /* Corner cases. */
322         {
323                 const char *str = "mate\xe2\x98\xafrial";
324
325                 /* "mate\xe2\x98\xafrial" over "mate" -> "mate\xe2\x98\xafrial", NULL, NULL, 4 */
326                 pre_ln = BLI_str_partition_ex_utf8(str, str + 4, delim, &sep, &suf, true);
327                 EXPECT_EQ(pre_ln, 4);
328                 EXPECT_EQ(sep, (void*)NULL);
329                 EXPECT_EQ(suf, (void*)NULL);
330         }
331 }
332
333 /* BLI_str_format_int_grouped */
334 TEST(string, StrFormatIntGrouped)
335 {
336         char num_str[16];
337         int num;
338
339         BLI_str_format_int_grouped(num_str, num = 0);
340         EXPECT_STREQ("0", num_str);
341
342         BLI_str_format_int_grouped(num_str, num = 1);
343         EXPECT_STREQ("1", num_str);
344
345         BLI_str_format_int_grouped(num_str, num = -1);
346         EXPECT_STREQ("-1", num_str);
347
348         BLI_str_format_int_grouped(num_str, num = -2147483648);
349         EXPECT_STREQ("-2,147,483,648", num_str);
350
351         BLI_str_format_int_grouped(num_str, num = 2147483647);
352         EXPECT_STREQ("2,147,483,647", num_str);
353
354         BLI_str_format_int_grouped(num_str, num = 1000);
355         EXPECT_STREQ("1,000", num_str);
356
357         BLI_str_format_int_grouped(num_str, num = -1000);
358         EXPECT_STREQ("-1,000", num_str);
359
360         BLI_str_format_int_grouped(num_str, num = 999);
361         EXPECT_STREQ("999", num_str);
362
363         BLI_str_format_int_grouped(num_str, num = -999);
364         EXPECT_STREQ("-999", num_str);
365 }
366
367 /* BLI_str_format_byte_unit */
368 TEST(string, StrFormatByteUnits)
369 {
370         char size_str[15];
371         long long int size;
372
373         /* Base 10 */
374         BLI_str_format_byte_unit(size_str, size = 0, true);
375         EXPECT_STREQ("0 B", size_str);
376         BLI_str_format_byte_unit(size_str, size = -0, true);
377         EXPECT_STREQ("0 B", size_str);
378
379         BLI_str_format_byte_unit(size_str, size = 1, true);
380         EXPECT_STREQ("1 B", size_str);
381         BLI_str_format_byte_unit(size_str, size = -1, true);
382         EXPECT_STREQ("-1 B", size_str);
383
384         BLI_str_format_byte_unit(size_str, size = 1000, true);
385         EXPECT_STREQ("1 KB", size_str);
386         BLI_str_format_byte_unit(size_str, size = -1000, true);
387         EXPECT_STREQ("-1 KB", size_str);
388
389         BLI_str_format_byte_unit(size_str, size = 1024, true);
390         EXPECT_STREQ("1 KB", size_str);
391         BLI_str_format_byte_unit(size_str, size = -1024, true);
392         EXPECT_STREQ("-1 KB", size_str);
393
394         BLI_str_format_byte_unit(size_str, size = 9223372036854775807, true); /* LLONG_MAX - largest possible value */
395         EXPECT_STREQ("9223.372 PB", size_str);
396         BLI_str_format_byte_unit(size_str, size = -9223372036854775807, true);
397         EXPECT_STREQ("-9223.372 PB", size_str);
398
399
400         /* Base 2 */
401         BLI_str_format_byte_unit(size_str, size = 0, false);
402         EXPECT_STREQ("0 B", size_str);
403         BLI_str_format_byte_unit(size_str, size = -0, false);
404         EXPECT_STREQ("0 B", size_str);
405
406         BLI_str_format_byte_unit(size_str, size = 1, false);
407         EXPECT_STREQ("1 B", size_str);
408         BLI_str_format_byte_unit(size_str, size = -1, false);
409         EXPECT_STREQ("-1 B", size_str);
410
411         BLI_str_format_byte_unit(size_str, size = 1000, false);
412         EXPECT_STREQ("1000 B", size_str);
413         BLI_str_format_byte_unit(size_str, size = -1000, false);
414         EXPECT_STREQ("-1000 B", size_str);
415
416         BLI_str_format_byte_unit(size_str, size = 1024, false);
417         EXPECT_STREQ("1 KiB", size_str);
418         BLI_str_format_byte_unit(size_str, size = -1024, false);
419         EXPECT_STREQ("-1 KiB", size_str);
420
421         BLI_str_format_byte_unit(size_str, size = 9223372036854775807, false); /* LLONG_MAX - largest possible value */
422         EXPECT_STREQ("8192.0 PiB", size_str);
423         BLI_str_format_byte_unit(size_str, size = -9223372036854775807, false);
424         EXPECT_STREQ("-8192.0 PiB", size_str);
425
426         /* Test maximum string length. */
427         BLI_str_format_byte_unit(size_str, size = -9223200000000000000, false);
428         EXPECT_STREQ("-8191.8472 PiB", size_str);
429 }
430
431
432
433 #define STRING_FIND_SPLIT_WORDS_EX(word_str_src, word_str_src_len, limit_words, ...) \
434 { \
435         int word_info[][2] = \
436                 {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}}; \
437         const int word_cmp[][2] = __VA_ARGS__; \
438         const int word_cmp_size_input = ARRAY_SIZE(word_cmp) - (limit_words ? 1 : 0); \
439         const int word_cmp_size = ARRAY_SIZE(word_cmp); \
440         const int word_num = BLI_string_find_split_words( \
441                 word_str_src, word_str_src_len, ' ', word_info, word_cmp_size_input); \
442         EXPECT_EQ(word_cmp_size - 1, word_num); \
443         EXPECT_EQ_ARRAY_ND<const int[2]>(word_cmp, word_info, word_cmp_size, 2); \
444 } ((void)0)
445
446 #define STRING_FIND_SPLIT_WORDS(word_str_src, ...) \
447         STRING_FIND_SPLIT_WORDS_EX(word_str_src, strlen(word_str_src), false, __VA_ARGS__)
448
449 /* BLI_string_find_split_words */
450 TEST(string, StringFindSplitWords_Single)
451 {
452         STRING_FIND_SPLIT_WORDS("t",    {{0, 1}, {-1, -1}});
453         STRING_FIND_SPLIT_WORDS("test", {{0, 4}, {-1, -1}});
454 }
455 TEST(string, StringFindSplitWords_Triple)
456 {
457         STRING_FIND_SPLIT_WORDS("f t w",            {{0, 1}, {2, 1}, {4, 1}, {-1, -1}});
458         STRING_FIND_SPLIT_WORDS("find three words", {{0, 4}, {5, 5}, {11, 5}, {-1, -1}});
459 }
460 TEST(string, StringFindSplitWords_Spacing)
461 {
462         STRING_FIND_SPLIT_WORDS("# ## ### ####",   {{0, 1}, {2, 2}, {5, 3}, {9, 4}, {-1, -1}});
463         STRING_FIND_SPLIT_WORDS("#  #   #    #",   {{0, 1}, {3, 1}, {7, 1}, {12, 1}, {-1, -1}});
464 }
465 TEST(string, StringFindSplitWords_Trailing_Left)
466 {
467         STRING_FIND_SPLIT_WORDS("   t",    {{3, 1}, {-1, -1}});
468         STRING_FIND_SPLIT_WORDS("   test", {{3, 4}, {-1, -1}});
469 }
470 TEST(string, StringFindSplitWords_Trailing_Right)
471 {
472         STRING_FIND_SPLIT_WORDS("t   ",    {{0, 1}, {-1, -1}});
473         STRING_FIND_SPLIT_WORDS("test   ", {{0, 4}, {-1, -1}});
474 }
475 TEST(string, StringFindSplitWords_Trailing_LeftRight)
476 {
477         STRING_FIND_SPLIT_WORDS("   surrounding space test   123   ", {{3, 11}, {15, 5}, {21, 4}, {28, 3}, {-1, -1}});
478 }
479 TEST(string, StringFindSplitWords_Blank)
480 {
481         STRING_FIND_SPLIT_WORDS("", {{-1, -1}});
482 }
483 TEST(string, StringFindSplitWords_Whitespace)
484 {
485         STRING_FIND_SPLIT_WORDS(" ",    {{-1, -1}});
486         STRING_FIND_SPLIT_WORDS("    ", {{-1, -1}});
487 }
488 TEST(string, StringFindSplitWords_LimitWords)
489 {
490         const char *words = "too many words";
491         const int words_len = strlen(words);
492         STRING_FIND_SPLIT_WORDS_EX(words, words_len, false, {{0, 3}, {4, 4}, {9, 5}, {-1, -1}});
493         STRING_FIND_SPLIT_WORDS_EX(words, words_len, true,  {{0, 3}, {4, 4}, {-1, -1}});
494         STRING_FIND_SPLIT_WORDS_EX(words, words_len, true,  {{0, 3}, {-1, -1}});
495         STRING_FIND_SPLIT_WORDS_EX(words, words_len, true,  {{-1, -1}});
496 }
497 TEST(string, StringFindSplitWords_LimitChars)
498 {
499         const char *words = "too many chars";
500         const int words_len = strlen(words);
501         STRING_FIND_SPLIT_WORDS_EX(words, words_len,      false, {{0, 3}, {4, 4}, {9, 5}, {-1, -1}});
502         STRING_FIND_SPLIT_WORDS_EX(words, words_len -  1, false, {{0, 3}, {4, 4}, {9, 4}, {-1, -1}});
503         STRING_FIND_SPLIT_WORDS_EX(words, words_len -  5, false, {{0, 3}, {4, 4}, {-1, -1}});
504         STRING_FIND_SPLIT_WORDS_EX(words, 1,              false, {{0, 1}, {-1, -1}});
505         STRING_FIND_SPLIT_WORDS_EX(words, 0,              false, {{-1, -1}});
506 }
507
508 #undef STRING_FIND_SPLIT_WORDS
509
510
511 /* BLI_strncasestr */
512 TEST(string, StringStrncasestr)
513 {
514         const char *str_test0 = "search here";
515         const char *res;
516
517         res = BLI_strncasestr(str_test0, "", 0);
518         EXPECT_EQ(res, str_test0);
519
520         res = BLI_strncasestr(str_test0, " ", 1);
521         EXPECT_EQ(res, str_test0 + 6);
522
523         res = BLI_strncasestr(str_test0, "her", 3);
524         EXPECT_EQ(res, str_test0 + 7);
525
526         res = BLI_strncasestr(str_test0, "ARCh", 4);
527         EXPECT_EQ(res, str_test0 + 2);
528
529         res = BLI_strncasestr(str_test0, "earcq", 4);
530         EXPECT_EQ(res, str_test0 + 1);
531
532         res = BLI_strncasestr(str_test0, "not there", 9);
533         EXPECT_EQ(res, (void*)NULL);
534 }