Blender V4.5
lib_id_test.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2020 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4#include "testing/testing.h"
5
6#include "BLI_listbase.h"
7#include "BLI_string.h"
8#include "BLI_string_ref.hh"
9
10#include "BKE_idtype.hh"
11#include "BKE_lib_id.hh"
12#include "BKE_main.hh"
13#include "BKE_main_namemap.hh"
14
15#include "DNA_ID.h"
16
17namespace blender::bke::tests {
18
32
33static void test_lib_id_main_sort_check_order(std::initializer_list<ID *> list)
34{
35 ID *prev_id = nullptr;
36 for (ID *id : list) {
37 EXPECT_EQ(id->prev, prev_id);
38 if (prev_id != nullptr) {
39 EXPECT_EQ(prev_id->next, id);
40 }
41 prev_id = id;
42 }
43 EXPECT_EQ(prev_id->next, nullptr);
44}
45
46TEST(lib_id_main_sort, local_ids_1)
47{
49 EXPECT_TRUE(BLI_listbase_is_empty(&ctx.bmain->libraries));
50
51 ID *id_c = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_C"));
52 ID *id_a = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_A"));
53 ID *id_b = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_B"));
54 EXPECT_TRUE(ctx.bmain->objects.first == id_a);
55 EXPECT_TRUE(ctx.bmain->objects.last == id_c);
56 test_lib_id_main_sort_check_order({id_a, id_b, id_c});
57
58 EXPECT_EQ(ctx.bmain->name_map_global, nullptr);
59}
60
61static void change_lib(Main *bmain, ID *id, Library *lib)
62{
63 if (id->lib == lib) {
64 return;
65 }
66 BKE_main_namemap_remove_id(*bmain, *id);
67 id->lib = lib;
68 BKE_main_namemap_get_unique_name(*bmain, *id, id->name + 2);
69}
70
71static IDNewNameResult change_name(Main *bmain, ID *id, const char *name, const IDNewNameMode mode)
72{
73 return BKE_libblock_rename(*bmain, *id, name, mode);
74}
75
76TEST(lib_id_main_sort, linked_ids_1)
77{
79 EXPECT_TRUE(BLI_listbase_is_empty(&ctx.bmain->libraries));
80
81 Library *lib_a = static_cast<Library *>(BKE_id_new(ctx.bmain, ID_LI, "LI_A"));
82 Library *lib_b = static_cast<Library *>(BKE_id_new(ctx.bmain, ID_LI, "LI_B"));
83 ID *id_c = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_C"));
84 ID *id_a = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_A"));
85 ID *id_b = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_B"));
86
87 change_lib(ctx.bmain, id_a, lib_a);
88 id_sort_by_name(&ctx.bmain->objects, id_a, nullptr);
89 change_lib(ctx.bmain, id_b, lib_a);
90 id_sort_by_name(&ctx.bmain->objects, id_b, nullptr);
91 EXPECT_TRUE(ctx.bmain->objects.first == id_c);
92 EXPECT_TRUE(ctx.bmain->objects.last == id_b);
93 test_lib_id_main_sort_check_order({id_c, id_a, id_b});
94
95 change_lib(ctx.bmain, id_a, lib_b);
96 id_sort_by_name(&ctx.bmain->objects, id_a, nullptr);
97 EXPECT_TRUE(ctx.bmain->objects.first == id_c);
98 EXPECT_TRUE(ctx.bmain->objects.last == id_a);
99 test_lib_id_main_sort_check_order({id_c, id_b, id_a});
100
101 change_lib(ctx.bmain, id_b, lib_b);
102 id_sort_by_name(&ctx.bmain->objects, id_b, nullptr);
103 EXPECT_TRUE(ctx.bmain->objects.first == id_c);
104 EXPECT_TRUE(ctx.bmain->objects.last == id_b);
105 test_lib_id_main_sort_check_order({id_c, id_a, id_b});
106
107 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
108
109 EXPECT_EQ(ctx.bmain->name_map_global, nullptr);
110}
111
112TEST(lib_id_main_unique_name, local_ids_rename_existing_never)
113{
115 EXPECT_TRUE(BLI_listbase_is_empty(&ctx.bmain->libraries));
116
117 ID *id_c = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_C"));
118 ID *id_a = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_A"));
119 ID *id_b = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_B"));
120 test_lib_id_main_sort_check_order({id_a, id_b, id_c});
121
122 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
123
125
126 /* Rename to different root name. */
128
130 // EXPECT_EQ(result.other_id, id_a); /* other_id purposely not looked-up currently. */
131 EXPECT_EQ(result.other_id, nullptr);
132 EXPECT_STREQ(id_c->name + 2, "OB_A.001");
133 EXPECT_STREQ(id_a->name + 2, "OB_A");
134 EXPECT_TRUE(ctx.bmain->objects.first == id_a);
135 EXPECT_TRUE(ctx.bmain->objects.last == id_b);
136 test_lib_id_main_sort_check_order({id_a, id_c, id_b});
137
138 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
139
140 /* Rename to same root name. */
142
144 // EXPECT_EQ(result.other_id, id_a); /* other_id purposely not looked-up currently. */
145 EXPECT_EQ(result.other_id, nullptr);
146 EXPECT_STREQ(id_c->name + 2, "OB_A.001");
147 EXPECT_STREQ(id_a->name + 2, "OB_A");
148 EXPECT_TRUE(ctx.bmain->objects.first == id_a);
149 EXPECT_TRUE(ctx.bmain->objects.last == id_b);
150 test_lib_id_main_sort_check_order({id_a, id_c, id_b});
151
152 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
153
154 EXPECT_EQ(ctx.bmain->name_map_global, nullptr);
155
156 /* Test lower-level #BKE_main_namemap_get_unique_name itself. */
157 /* Name already in use, needs additional numeric suffix. */
158 char future_name[MAX_ID_NAME - 2];
159 STRNCPY(future_name, "OB_B");
160 EXPECT_TRUE(BKE_main_namemap_get_unique_name(*ctx.bmain, *id_c, future_name));
161 EXPECT_STREQ(future_name, "OB_B.001");
162 /* Name not already in use, no need to alter it. */
163 STRNCPY(future_name, "OB_BBBB");
164 EXPECT_FALSE(BKE_main_namemap_get_unique_name(*ctx.bmain, *id_c, future_name));
165 EXPECT_STREQ(future_name, "OB_BBBB");
166 /* Name too long, needs to be truncated. */
167 STRNCPY(future_name, "OB_BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB");
169 EXPECT_STREQ(id_a->name + 2, future_name);
170 EXPECT_STREQ(future_name, "OB_BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB");
171 EXPECT_TRUE(BKE_main_namemap_get_unique_name(*ctx.bmain, *id_c, future_name));
172 EXPECT_STREQ(future_name, "OB_BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB");
173}
174
175TEST(lib_id_main_unique_name, local_ids_rename_existing_always)
176{
178 EXPECT_TRUE(BLI_listbase_is_empty(&ctx.bmain->libraries));
179
180 ID *id_c = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_C"));
181 ID *id_a = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_A"));
182 ID *id_b = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_B"));
183 test_lib_id_main_sort_check_order({id_a, id_b, id_c});
184
185 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
186
188
189 /* Rename to different root name. */
191
193 EXPECT_EQ(result.other_id, id_a);
194 EXPECT_STREQ(id_c->name + 2, "OB_A");
195 EXPECT_STREQ(id_a->name + 2, "OB_A.001");
196 EXPECT_TRUE(ctx.bmain->objects.first == id_c);
197 EXPECT_TRUE(ctx.bmain->objects.last == id_b);
198 test_lib_id_main_sort_check_order({id_c, id_a, id_b});
199
200 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
201
202 /* Rename to same root name. */
204
206 EXPECT_EQ(result.other_id, id_c);
207 EXPECT_STREQ(id_c->name + 2, "OB_A.001");
208 EXPECT_STREQ(id_a->name + 2, "OB_A");
209 EXPECT_TRUE(ctx.bmain->objects.first == id_a);
210 EXPECT_TRUE(ctx.bmain->objects.last == id_b);
211 test_lib_id_main_sort_check_order({id_a, id_c, id_b});
212
213 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
214
215 EXPECT_EQ(ctx.bmain->name_map_global, nullptr);
216}
217
218TEST(lib_id_main_unique_name, local_ids_rename_existing_same_root)
219{
221 EXPECT_TRUE(BLI_listbase_is_empty(&ctx.bmain->libraries));
222
223 ID *id_c = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_C"));
224 ID *id_a = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_A"));
225 ID *id_b = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_B"));
226 test_lib_id_main_sort_check_order({id_a, id_b, id_c});
227
228 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
229
231
232 /* Rename to different root name. */
234
236 // EXPECT_EQ(result.other_id, id_a); /* other_id purposely not looked-up currently. */
237 EXPECT_EQ(result.other_id, nullptr);
238 EXPECT_STREQ(id_c->name + 2, "OB_A.001");
239 EXPECT_STREQ(id_a->name + 2, "OB_A");
240 EXPECT_TRUE(ctx.bmain->objects.first == id_a);
241 EXPECT_TRUE(ctx.bmain->objects.last == id_b);
242 test_lib_id_main_sort_check_order({id_a, id_c, id_b});
243
244 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
245
246 /* Rename to same root name. */
248
250 EXPECT_EQ(result.other_id, id_a);
251 EXPECT_STREQ(id_c->name + 2, "OB_A");
252 EXPECT_STREQ(id_a->name + 2, "OB_A.001");
253 EXPECT_TRUE(ctx.bmain->objects.first == id_c);
254 EXPECT_TRUE(ctx.bmain->objects.last == id_b);
255 test_lib_id_main_sort_check_order({id_c, id_a, id_b});
256
257 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
258
259 EXPECT_EQ(ctx.bmain->name_map_global, nullptr);
260}
261
262TEST(lib_id_main_unique_name, linked_ids_1)
263{
265 EXPECT_TRUE(BLI_listbase_is_empty(&ctx.bmain->libraries));
266
267 Library *lib_a = static_cast<Library *>(BKE_id_new(ctx.bmain, ID_LI, "LI_A"));
268 Library *lib_b = static_cast<Library *>(BKE_id_new(ctx.bmain, ID_LI, "LI_B"));
269 ID *id_c = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_C"));
270 ID *id_a = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_A"));
271 ID *id_b = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_B"));
272
273 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
274
275 change_lib(ctx.bmain, id_a, lib_a);
276 id_sort_by_name(&ctx.bmain->objects, id_a, nullptr);
277 change_lib(ctx.bmain, id_b, lib_a);
278 id_sort_by_name(&ctx.bmain->objects, id_b, nullptr);
279
281 EXPECT_STREQ(id_b->name + 2, "OB_A.001");
282 EXPECT_STREQ(id_a->name + 2, "OB_A");
283 EXPECT_TRUE(ctx.bmain->objects.first == id_c);
284 EXPECT_TRUE(ctx.bmain->objects.last == id_b);
285 test_lib_id_main_sort_check_order({id_c, id_a, id_b});
286
287 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
288
289 change_lib(ctx.bmain, id_b, lib_b);
290 id_sort_by_name(&ctx.bmain->objects, id_b, nullptr);
292 EXPECT_STREQ(id_b->name + 2, "OB_A");
293 EXPECT_STREQ(id_a->name + 2, "OB_A");
294 EXPECT_TRUE(ctx.bmain->objects.first == id_c);
295 EXPECT_TRUE(ctx.bmain->objects.last == id_b);
296 test_lib_id_main_sort_check_order({id_c, id_a, id_b});
297
298 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
299
300 EXPECT_EQ(ctx.bmain->name_map_global, nullptr);
301}
302
303static void change_name_global(Main *bmain, ID *id, const char *name)
304{
305 BKE_main_namemap_remove_id(*bmain, *id);
306 BLI_strncpy(id->name + 2, name, MAX_NAME);
307
308 BKE_main_global_namemap_get_unique_name(*bmain, *id, id->name + 2);
309
310 id_sort_by_name(&bmain->objects, id, nullptr);
311}
312
313TEST(lib_id_main_global_unique_name, linked_ids_1)
314{
316 EXPECT_TRUE(BLI_listbase_is_empty(&ctx.bmain->libraries));
317
318 Library *lib_a = static_cast<Library *>(BKE_id_new(ctx.bmain, ID_LI, "LI_A"));
319 Library *lib_b = static_cast<Library *>(BKE_id_new(ctx.bmain, ID_LI, "LI_B"));
320 ID *id_c = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_C"));
321 ID *id_a = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_A"));
322 ID *id_b = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_B"));
323
324 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
325
326 change_lib(ctx.bmain, id_a, lib_a);
327 id_sort_by_name(&ctx.bmain->objects, id_a, nullptr);
328 change_lib(ctx.bmain, id_b, lib_b);
329 id_sort_by_name(&ctx.bmain->objects, id_b, nullptr);
330
331 change_name_global(ctx.bmain, id_b, "OB_A");
332 EXPECT_NE(ctx.bmain->name_map_global, nullptr);
333 EXPECT_STREQ(id_b->name + 2, "OB_A.001");
334 EXPECT_STREQ(id_a->name + 2, "OB_A");
335 EXPECT_TRUE(ctx.bmain->objects.first == id_c);
336 EXPECT_TRUE(ctx.bmain->objects.last == id_b);
337 test_lib_id_main_sort_check_order({id_c, id_a, id_b});
338
339 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
340
341 change_lib(ctx.bmain, id_b, lib_a);
342 id_sort_by_name(&ctx.bmain->objects, id_b, nullptr);
343 change_name_global(ctx.bmain, id_b, "OB_C");
344 EXPECT_STREQ(id_b->name + 2, "OB_C.001");
345 EXPECT_STREQ(id_a->name + 2, "OB_A");
346 EXPECT_STREQ(id_c->name + 2, "OB_C");
347 change_name_global(ctx.bmain, id_a, "OB_C");
348 EXPECT_STREQ(id_b->name + 2, "OB_C.001");
349 EXPECT_STREQ(id_a->name + 2, "OB_C.002");
350 EXPECT_STREQ(id_c->name + 2, "OB_C");
351 EXPECT_TRUE(ctx.bmain->objects.first == id_c);
352 EXPECT_TRUE(ctx.bmain->objects.last == id_a);
353 test_lib_id_main_sort_check_order({id_c, id_b, id_a});
354
355 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
356
358 EXPECT_STREQ(id_b->name + 2, "OB_C");
359 EXPECT_STREQ(id_a->name + 2, "OB_C.002");
360 EXPECT_STREQ(id_c->name + 2, "OB_C");
361 EXPECT_TRUE(ctx.bmain->objects.first == id_c);
362 EXPECT_TRUE(ctx.bmain->objects.last == id_a);
363 test_lib_id_main_sort_check_order({id_c, id_b, id_a});
364
365 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
366}
367
368TEST(lib_id_main_unique_name, ids_sorted_by_default)
369{
371
372 ID *id_foo = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo"));
373 ID *id_bar = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Bar"));
374 ID *id_baz = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Baz"));
375 ID *id_yes = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Yes"));
376 test_lib_id_main_sort_check_order({id_bar, id_baz, id_foo, id_yes});
377
378 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
379
380 EXPECT_EQ(ctx.bmain->name_map_global, nullptr);
381}
382
383static ID *add_id_in_library(Main *bmain, const char *name, Library *lib)
384{
385 ID *id = static_cast<ID *>(BKE_id_new(bmain, ID_OB, name));
386 change_lib(bmain, id, lib);
387 id_sort_by_name(&bmain->objects, id, nullptr);
388 return id;
389}
390
391TEST(lib_id_main_unique_name, ids_sorted_by_default_with_libraries)
392{
394
395 Library *lib_one = static_cast<Library *>(BKE_id_new(ctx.bmain, ID_LI, "LibOne"));
396 Library *lib_two = static_cast<Library *>(BKE_id_new(ctx.bmain, ID_LI, "LibTwo"));
397
398 ID *id_foo = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo"));
399 ID *id_bar = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Bar"));
400
401 ID *id_l1c = add_id_in_library(ctx.bmain, "C", lib_one);
402 ID *id_l2b = add_id_in_library(ctx.bmain, "B", lib_two);
403 ID *id_l1a = add_id_in_library(ctx.bmain, "A", lib_one);
404
405 ID *id_baz = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Baz"));
406 ID *id_yes = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Yes"));
407
408 test_lib_id_main_sort_check_order({id_bar, id_baz, id_foo, id_yes, id_l1a, id_l1c, id_l2b});
409
410 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
411
412 EXPECT_EQ(ctx.bmain->name_map_global, nullptr);
413}
414
415TEST(lib_id_main_unique_name, name_too_long_handling)
416{
418 const char *name_a = "Long_Name_That_Does_Not_Fit_Into_Max_Name_Limit_And_Should_Get_Truncated";
419 const char *name_b = "Another_Long_Name_That_Does_Not_Fit_And_Has_A_Number_Suffix.123456";
420 const char *name_c = "Name_That_Has_Too_Long_Number_Suffix.1234567890";
421
422 ID *id_a = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, name_a));
423 ID *id_b = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, name_b));
424 ID *id_c = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, name_c));
425
426 EXPECT_STREQ(id_a->name + 2, "Long_Name_That_Does_Not_Fit_Into_Max_Name_Limit_And_Should_Get_");
427 EXPECT_STREQ(id_b->name + 2, "Another_Long_Name_That_Does_Not_Fit_And_Has_A_Number_Suffix.123");
428 EXPECT_STREQ(id_c->name + 2, "Name_That_Has_Too_Long_Number_Suffix.1234567890"); /* Unchanged */
429
430 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
431
432 EXPECT_EQ(ctx.bmain->name_map_global, nullptr);
433}
434
435TEST(lib_id_main_unique_name, create_equivalent_numeric_suffixes)
436{
438
439 /* Create names where many of their numeric suffixes are
440 * the same number, yet the names are different and thus
441 * should be allowed as-is. */
442 ID *id_a = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.123"));
443 ID *id_b = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.000"));
444 ID *id_c = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.003"));
445 ID *id_d = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.3"));
446 ID *id_e = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.0"));
447 ID *id_f = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo."));
448 ID *id_g = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.0123"));
449 ID *id_h = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo"));
450 ID *id_i = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.."));
451 ID *id_j = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo..001"));
452 ID *id_k = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo..000"));
453
454 EXPECT_STREQ(id_a->name + 2, "Foo.123");
455 EXPECT_STREQ(id_b->name + 2, "Foo.000");
456 EXPECT_STREQ(id_c->name + 2, "Foo.003");
457 EXPECT_STREQ(id_d->name + 2, "Foo.3");
458 EXPECT_STREQ(id_e->name + 2, "Foo.0");
459 EXPECT_STREQ(id_f->name + 2, "Foo.");
460 EXPECT_STREQ(id_g->name + 2, "Foo.0123");
461 EXPECT_STREQ(id_h->name + 2, "Foo");
462 EXPECT_STREQ(id_i->name + 2, "Foo..");
463 EXPECT_STREQ(id_j->name + 2, "Foo..001");
464 EXPECT_STREQ(id_k->name + 2, "Foo..000");
465
466 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
467
468 /* Now create their exact duplicates again, and check what happens. */
469 id_a = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.123"));
470 id_b = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.000"));
471 id_c = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.003"));
472 id_d = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.3"));
473 id_e = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.0"));
474 id_f = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo."));
475 id_g = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.0123"));
476 id_h = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo"));
477 id_i = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.."));
478 id_j = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo..001"));
479 id_k = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo..000"));
480
481 EXPECT_STREQ(id_a->name + 2, "Foo.001");
482 EXPECT_STREQ(id_b->name + 2, "Foo.002");
483 EXPECT_STREQ(id_c->name + 2, "Foo.004");
484 EXPECT_STREQ(id_d->name + 2, "Foo.005");
485 EXPECT_STREQ(id_e->name + 2, "Foo.006");
486 EXPECT_STREQ(id_f->name + 2, "Foo..002");
487 EXPECT_STREQ(id_g->name + 2, "Foo.007");
488 EXPECT_STREQ(id_h->name + 2, "Foo.008");
489 EXPECT_STREQ(id_i->name + 2, "Foo...001");
490 EXPECT_STREQ(id_j->name + 2, "Foo..003");
491 EXPECT_STREQ(id_k->name + 2, "Foo..004");
492
493 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
494
495 EXPECT_EQ(ctx.bmain->name_map_global, nullptr);
496}
497
498TEST(lib_id_main_unique_name, re_create_equivalent_numeric_suffixes)
499{
501
502 /* Create names where many of their numeric suffixes are
503 * the same number, yet the names are different and thus
504 * should be allowed as-is. */
505 ID *id_a = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.123"));
506 ID *id_b = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.001"));
507 ID *id_c = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.01"));
508 ID *id_d = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.1"));
509 ID *id_e = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo"));
510
511 EXPECT_STREQ(BKE_id_name(*id_a), "Foo.123");
512 EXPECT_STREQ(BKE_id_name(*id_b), "Foo.001");
513 EXPECT_STREQ(BKE_id_name(*id_c), "Foo.01");
514 EXPECT_STREQ(BKE_id_name(*id_d), "Foo.1");
515 EXPECT_STREQ(BKE_id_name(*id_e), "Foo");
516
517 /* Deleting 'Foo.1' will _not_ mark number `1` as available, since its internal multi-usages
518 * counter will still be at `2`, for the 'Foo.01' and 'Foo.001' IDs still present.
519 *
520 * So the number `1` is not available, and since `123` is also used, the next free value is `2`.
521 */
522 BKE_id_delete(ctx.bmain, id_d);
523 id_d = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.123"));
524 EXPECT_STREQ(BKE_id_name(*id_d), "Foo.002");
525
526 /* However, while deleting 'Foo.001' will _not_ mark number `1` as available, it _will_ remove
527 * the exact name from the full names map.
528 *
529 * So adding again 'Foo.001' will succeed and not modify the name at all. */
530 BKE_id_delete(ctx.bmain, id_b);
531 id_b = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.001"));
532 EXPECT_STREQ(BKE_id_name(*id_b), "Foo.001");
533
534 /* Finally, removing the last two users of number `1` makes it available again. */
535 BKE_id_delete(ctx.bmain, id_b);
536 BKE_id_delete(ctx.bmain, id_c);
537 id_b = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo"));
538 EXPECT_STREQ(BKE_id_name(*id_b), "Foo.001");
539 id_c = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.01"));
540 EXPECT_STREQ(BKE_id_name(*id_c), "Foo.01");
541
542 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
543
544 EXPECT_EQ(ctx.bmain->name_map_global, nullptr);
545}
546
547TEST(lib_id_main_unique_name, zero_suffix_is_never_assigned)
548{
550
551 /* Creating these should assign 002 to the first one, but the next
552 * ones should start numbers starting from 1: 001 and 003. */
553 ID *id_002 = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.002"));
554 ID *id_001 = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.002"));
555 ID *id_003 = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.002"));
556
557 EXPECT_STREQ(id_002->name + 2, "Foo.002");
558 EXPECT_STREQ(id_001->name + 2, "Foo.001");
559 EXPECT_STREQ(id_003->name + 2, "Foo.003");
560
561 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
562
563 EXPECT_EQ(ctx.bmain->name_map_global, nullptr);
564}
565
566TEST(lib_id_main_unique_name, remove_after_dup_get_original_name)
567{
569
570 ID *id_a = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo"));
571 ID *id_b = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo"));
572
573 EXPECT_STREQ(id_a->name + 2, "Foo");
574 EXPECT_STREQ(id_b->name + 2, "Foo.001");
575 BKE_id_free(ctx.bmain, id_a);
576
577 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
578
579 id_a = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo"));
580 EXPECT_STREQ(id_a->name + 2, "Foo");
581
582 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
583
584 EXPECT_EQ(ctx.bmain->name_map_global, nullptr);
585}
586
587TEST(lib_id_main_unique_name, name_number_suffix_assignment)
588{
590
591 /* Create <1k objects first. */
592 const int total_object_count = 1200;
593 ID *ids[total_object_count] = {};
594 for (int i = 0; i < total_object_count / 2; ++i) {
595 ids[i] = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo"));
596 }
597
598 /* They should get assigned sequential numeric suffixes. */
599 EXPECT_STREQ(ids[0]->name + 2, "Foo");
600 EXPECT_STREQ(ids[1]->name + 2, "Foo.001");
601 EXPECT_STREQ(ids[total_object_count / 2 - 1]->name + 2, "Foo.599");
602
603 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
604
605 /* Free some of the objects. */
606 BKE_id_free(ctx.bmain, ids[10]);
607 BKE_id_free(ctx.bmain, ids[20]);
608 BKE_id_free(ctx.bmain, ids[30]);
609
610 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
611
612 /* Create objects again; they should get suffixes that were just freed up. */
613 ID *id_010 = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo"));
614 EXPECT_STREQ(id_010->name + 2, "Foo.010");
615 ID *id_020 = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.123"));
616 EXPECT_STREQ(id_020->name + 2, "Foo.020");
617 /* Suffixes >1k do not get the "use the most proper free one" treatment. */
618 ID *id_2000 = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.2000"));
619 EXPECT_STREQ(id_2000->name + 2, "Foo.2000");
620 /* But smaller than 1k suffixes do get proper empty spots. */
621 ID *id_030 = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo"));
622 EXPECT_STREQ(id_030->name + 2, "Foo.030");
623 ID *id_600 = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo"));
624 EXPECT_STREQ(id_600->name + 2, "Foo.600");
625
626 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
627
628 /* Max possible numeric suffix. */
629 ID *id_max = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.999999999"));
630 EXPECT_STREQ(id_max->name + 2, "Foo.999999999");
631 /* Try with max. possible suffix again: will assign free suffix under 1k. */
632 ID *id_max1 = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.999999999"));
633 EXPECT_STREQ(id_max1->name + 2, "Foo.601");
634
635 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
636
637 /* Now create the rest of objects, to use all the suffixes up to 1k.
638 * Once all the ones up to 1k are used, the logic will fall back to
639 * "use largest number seen + 1", but the largest one is already the max
640 * possible. So it will modify the name part and restart the counter,
641 * i.e. "Foo_001.001". */
642 for (int i = total_object_count / 2; i < total_object_count; ++i) {
643 ids[i] = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo"));
644 }
645 /* At this point creating "Foo" based objects will always result in names extended with a 3 or
646 * more digits numeric suffix, e.g. "Foo_001.001".
647 *
648 * NOTE: The random 3-digits suffix added to the base name is expected to be stable, as the
649 * requested base name remains the same. This is why the added numeric suffixes can be predicted
650 * here. */
651 ID *id_foo_001_178 = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo"));
652 EXPECT_STREQ(BKE_id_name(*id_foo_001_178), "Foo_001.178");
653 ID *id_foo_001_179 = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.2000"));
654 EXPECT_STREQ(BKE_id_name(*id_foo_001_179), "Foo_001.179");
655 ID *id_foo_001_180 = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo.999999999"));
656 EXPECT_STREQ(BKE_id_name(*id_foo_001_180), "Foo_001.180");
657
658 /* Longer names will be shortened, when no more numeric suffixes are available. */
659 for (int i = 0; i < total_object_count; ++i) {
660 ids[i] = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "ALongerName"));
661 }
662 /* Max possible numeric suffix. */
663 id_max = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "ALongerName.999999999"));
664 EXPECT_STREQ(BKE_id_name(*id_max), "ALongerName.999999999");
665
666 ID *id_alongernam = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "ALongerName"));
667 EXPECT_STREQ(BKE_id_name(*id_alongernam), "ALongerNam");
668 ID *id_alongernam001 = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "ALongerName"));
669 EXPECT_STREQ(BKE_id_name(*id_alongernam001), "ALongerNam.001");
670
671 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
672
673 EXPECT_EQ(ctx.bmain->name_map_global, nullptr);
674}
675
676TEST(lib_id_main_unique_name, renames_with_duplicates)
677{
679
680 ID *id_a = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo"));
681 ID *id_b = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo"));
682 ID *id_c = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Bar"));
683
684 EXPECT_STREQ(id_a->name + 2, "Foo");
685 EXPECT_STREQ(id_b->name + 2, "Foo.001");
686 EXPECT_STREQ(id_c->name + 2, "Bar");
687
688 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
689
690 BKE_libblock_rename(*ctx.bmain, *id_a, "Foo.002");
691 EXPECT_STREQ(id_a->name + 2, "Foo.002");
692 BKE_libblock_rename(*ctx.bmain, *id_b, "Bar");
693 EXPECT_STREQ(id_b->name + 2, "Bar.001");
694 BKE_libblock_rename(*ctx.bmain, *id_c, "Foo");
695 EXPECT_STREQ(id_c->name + 2, "Foo");
696 BKE_libblock_rename(*ctx.bmain, *id_b, "Bar");
697 EXPECT_STREQ(id_b->name + 2, "Bar");
698
699 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
700
701 EXPECT_EQ(ctx.bmain->name_map_global, nullptr);
702}
703
704TEST(lib_id_main_unique_name, names_are_unique_per_id_type)
705{
707
708 ID *id_a = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo"));
709 ID *id_b = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_CA, "Foo"));
710 ID *id_c = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "Foo"));
711
712 EXPECT_STREQ(id_a->name + 2, "Foo");
713 EXPECT_STREQ(id_b->name + 2, "Foo"); /* Different types (OB & CA) can have the same name. */
714 EXPECT_STREQ(id_c->name + 2, "Foo.001");
715
716 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
717
718 EXPECT_EQ(ctx.bmain->name_map_global, nullptr);
719}
720
721TEST(lib_id_main_unique_name, name_huge_number_suffix)
722{
724
725 /* Use numeric suffix that is really large: should come through
726 * fine, since no duplicates with other names. */
727 ID *id_a = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "SuperLong.1234567890"));
728 EXPECT_STREQ(id_a->name + 2, "SuperLong.1234567890");
729 /* Now create with the same name again: should get 001 suffix. */
730 ID *id_b = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "SuperLong.1234567890"));
731 EXPECT_STREQ(id_b->name + 2, "SuperLong.001");
732
733 EXPECT_TRUE(BKE_main_namemap_validate(*ctx.bmain));
734
735 EXPECT_EQ(ctx.bmain->name_map_global, nullptr);
736}
737
738TEST(lib_id_make_local, brush)
739{
741
742 Library *lib_a = static_cast<Library *>(BKE_id_new(ctx.bmain, ID_LI, "LI_A"));
743 ID *br_a = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_BR, "BR_A"));
744
745 change_lib(ctx.bmain, br_a, lib_a);
746
748 EXPECT_NE(br_a->newid, nullptr);
749
750 EXPECT_TRUE(br_a->newid->flag & ID_FLAG_FAKEUSER);
751 EXPECT_EQ(br_a->newid->us, 1);
752}
753
754} // namespace blender::bke::tests
void BKE_idtype_init()
Definition idtype.cc:122
void BKE_id_delete(Main *bmain, void *idv) ATTR_NONNULL()
IDNewNameMode
void BKE_id_free(Main *bmain, void *idv)
void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint)
Definition lib_id.cc:1770
IDNewNameResult BKE_libblock_rename(Main &bmain, ID &id, blender::StringRefNull name, const IDNewNameMode mode=IDNewNameMode::RenameExistingNever)
Definition lib_id.cc:2350
bool BKE_lib_id_make_local(Main *bmain, ID *id, int flags)
Definition lib_id.cc:586
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1495
@ LIB_ID_MAKELOCAL_FORCE_COPY
const char * BKE_id_name(const ID &id)
Main * BKE_main_new()
Definition main.cc:48
void BKE_main_free(Main *bmain)
Definition main.cc:175
void BKE_main_namemap_remove_id(Main &bmain, ID &id)
bool BKE_main_namemap_get_unique_name(Main &bmain, ID &id, char *r_name)
bool BKE_main_global_namemap_get_unique_name(Main &bmain, ID &id, char *r_name)
bool BKE_main_namemap_validate(Main &bmain)
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
ID and Library types, which are fundamental for SDNA.
@ ID_FLAG_FAKEUSER
Definition DNA_ID.h:682
@ ID_CA
@ ID_LI
@ ID_BR
@ ID_OB
#define MAX_ID_NAME
#define MAX_NAME
static ID * add_id_in_library(Main *bmain, const char *name, Library *lib)
static void change_lib(Main *bmain, ID *id, Library *lib)
TEST(action_groups, ReconstructGroupsWithReordering)
static void change_name_global(Main *bmain, ID *id, const char *name)
static IDNewNameResult change_name(Main *bmain, ID *id, const char *name, const IDNewNameMode mode)
static void test_lib_id_main_sort_check_order(std::initializer_list< ID * > list)
Definition DNA_ID.h:404
int us
Definition DNA_ID.h:425
struct ID * newid
Definition DNA_ID.h:408
short flag
Definition DNA_ID.h:420
void * next
Definition DNA_ID.h:407
char name[66]
Definition DNA_ID.h:415
void * last
void * first
UniqueName_Map * name_map_global
Definition BKE_main.hh:310
ListBase libraries
Definition BKE_main.hh:246
ListBase objects
Definition BKE_main.hh:247
i
Definition text_draw.cc:230
static DynamicLibrary lib