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