Blender V5.0
main_test.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4#include "testing/testing.h"
5
6#include "CLG_log.h"
7
8#include "BLI_listbase.h"
9#include "BLI_path_utils.hh"
10#include "BLI_string.h"
11
12#include "BKE_collection.hh"
13#include "BKE_idtype.hh"
14#include "BKE_lib_id.hh"
15#include "BKE_library.hh"
16#include "BKE_main.hh"
17
18#include "DNA_ID.h"
20#include "DNA_object_types.h"
21
22namespace blender::bke::tests {
23
24class BMainTest : public testing::Test {
25 public:
26 static void SetUpTestSuite()
27 {
28 CLG_init();
30 }
31 static void TearDownTestSuite()
32 {
33 CLG_exit();
34 }
35};
36
37class BMainMergeTest : public BMainTest {
38 public:
39 void SetUp() override
40 {
43 }
44
45 void TearDown() override
46 {
47 if (bmain_src) {
49 }
50 if (bmain_dst) {
52 }
53 }
54
57};
58
60{
61 EXPECT_TRUE(BLI_listbase_is_empty(&bmain_dst->libraries));
62 EXPECT_TRUE(BLI_listbase_is_empty(&bmain_dst->collections));
63 EXPECT_TRUE(BLI_listbase_is_empty(&bmain_dst->objects));
64
65 EXPECT_TRUE(BLI_listbase_is_empty(&bmain_src->libraries));
66 EXPECT_TRUE(BLI_listbase_is_empty(&bmain_src->collections));
67 EXPECT_TRUE(BLI_listbase_is_empty(&bmain_src->objects));
68
69 BKE_id_new(bmain_dst, ID_GR, "Coll_dst");
70 Collection *coll = BKE_id_new<Collection>(bmain_src, "Coll_src");
71 Object *ob = BKE_id_new<Object>(bmain_src, "Ob_src");
72 BKE_collection_object_add(bmain_src, coll, ob);
73
74 EXPECT_EQ(1, BLI_listbase_count(&bmain_dst->collections));
75 EXPECT_EQ(0, BLI_listbase_count(&bmain_dst->objects));
76 EXPECT_EQ(1, BLI_listbase_count(&bmain_src->collections));
77 EXPECT_EQ(1, BLI_listbase_count(&bmain_src->objects));
78
79 MainMergeReport reports = {};
80 BKE_main_merge(bmain_dst, &bmain_src, reports);
81
82 EXPECT_EQ(2, BLI_listbase_count(&bmain_dst->collections));
83 EXPECT_EQ(1, BLI_listbase_count(&bmain_dst->objects));
84 EXPECT_EQ(2, reports.num_merged_ids);
85 EXPECT_EQ(0, reports.num_unknown_ids);
86 EXPECT_EQ(0, reports.num_remapped_ids);
88 EXPECT_EQ(nullptr, bmain_src);
89
90 bmain_src = BKE_main_new();
91 Collection *coll_2 = BKE_id_new<Collection>(bmain_src, "Coll_src_2");
92 Object *ob_2 = BKE_id_new<Object>(bmain_src, "Ob_src");
93 BKE_collection_object_add(bmain_src, coll_2, ob_2);
94
95 EXPECT_EQ(2, BLI_listbase_count(&bmain_dst->collections));
96 EXPECT_EQ(1, BLI_listbase_count(&bmain_dst->objects));
97 EXPECT_EQ(1, BLI_listbase_count(&bmain_src->collections));
98 EXPECT_EQ(1, BLI_listbase_count(&bmain_src->objects));
99
100 reports = {};
101 BKE_main_merge(bmain_dst, &bmain_src, reports);
102
103 /* The second `Ob_src` object in `bmain_src` cannot be merged in `bmain_dst`, since its name
104 * would collide with the first object. */
105 EXPECT_EQ(3, BLI_listbase_count(&bmain_dst->collections));
106 EXPECT_EQ(1, BLI_listbase_count(&bmain_dst->objects));
107 EXPECT_EQ(1, reports.num_merged_ids);
108 EXPECT_EQ(0, reports.num_unknown_ids);
109 EXPECT_EQ(1, reports.num_remapped_ids);
111 EXPECT_EQ(nullptr, bmain_src);
112
113 /* `Coll_src_2` should have been remapped to using `Ob_src` in `bmain_dst`, instead of `Ob_src`
114 * in `bmain_src`. */
116 EXPECT_EQ(ob, static_cast<CollectionObject *>(coll_2->gobject.first)->ob);
117}
118
120{
121#ifdef WIN32
122# define ABS_ROOT "C:" SEP_STR
123#else
124# define ABS_ROOT SEP_STR
125#endif
126 constexpr char DST_PATH[] = ABS_ROOT "tmp" SEP_STR "dst" SEP_STR "dst.blend";
127 constexpr char SRC_PATH[] = ABS_ROOT "tmp" SEP_STR "src" SEP_STR "src.blend";
128 constexpr char LIB_PATH[] = ABS_ROOT "tmp" SEP_STR "lib" SEP_STR "lib.blend";
129
130 constexpr char LIB_PATH_RELATIVE[] = "//lib" SEP_STR "lib.blend";
131 constexpr char LIB_PATH_RELATIVE_ABS_SRC[] = ABS_ROOT "tmp" SEP_STR "src" SEP_STR "lib" SEP_STR
132 "lib.blend";
133
134 EXPECT_TRUE(BLI_listbase_is_empty(&bmain_dst->libraries));
135 EXPECT_TRUE(BLI_listbase_is_empty(&bmain_dst->collections));
136 EXPECT_TRUE(BLI_listbase_is_empty(&bmain_dst->objects));
137
138 EXPECT_TRUE(BLI_listbase_is_empty(&bmain_src->libraries));
139 EXPECT_TRUE(BLI_listbase_is_empty(&bmain_src->collections));
140 EXPECT_TRUE(BLI_listbase_is_empty(&bmain_src->objects));
141
142 STRNCPY(bmain_dst->filepath, DST_PATH);
143 STRNCPY(bmain_src->filepath, SRC_PATH);
144
145 BKE_id_new<Collection>(bmain_dst, "Coll_dst");
146
147 Collection *coll_1 = BKE_id_new<Collection>(bmain_src, "Coll_src");
148 Object *ob_1 = BKE_id_new<Object>(bmain_src, "Ob_src");
149 BKE_collection_object_add(bmain_src, coll_1, ob_1);
150 Library *lib_src_1 = BKE_id_new<Library>(bmain_src, LIB_PATH);
151 BKE_library_filepath_set(bmain_src, lib_src_1, LIB_PATH);
152 ob_1->id.lib = lib_src_1;
153
154 EXPECT_EQ(1, BLI_listbase_count(&bmain_dst->collections));
155 EXPECT_EQ(0, BLI_listbase_count(&bmain_dst->objects));
156 EXPECT_EQ(0, BLI_listbase_count(&bmain_dst->libraries));
157 EXPECT_EQ(1, BLI_listbase_count(&bmain_src->collections));
158 EXPECT_EQ(1, BLI_listbase_count(&bmain_src->objects));
159 EXPECT_EQ(1, BLI_listbase_count(&bmain_src->libraries));
160
161 MainMergeReport reports = {};
162 BKE_main_merge(bmain_dst, &bmain_src, reports);
163
164 EXPECT_EQ(2, BLI_listbase_count(&bmain_dst->collections));
165 EXPECT_EQ(1, BLI_listbase_count(&bmain_dst->objects));
166 EXPECT_EQ(1, BLI_listbase_count(&bmain_dst->libraries));
167 EXPECT_EQ(ob_1, bmain_dst->objects.first);
168 EXPECT_EQ(lib_src_1, bmain_dst->libraries.first);
169 EXPECT_EQ(ob_1->id.lib, lib_src_1);
170 EXPECT_EQ(3, reports.num_merged_ids);
171 EXPECT_EQ(0, reports.num_unknown_ids);
172 EXPECT_EQ(0, reports.num_remapped_ids);
174 EXPECT_EQ(nullptr, bmain_src);
175
176 /* Try another merge, with the same library path - second library should be skipped, destination
177 * merge should still have only one library ID. */
178 bmain_src = BKE_main_new();
179 STRNCPY(bmain_src->filepath, SRC_PATH);
180
181 Collection *coll_2 = BKE_id_new<Collection>(bmain_src, "Coll_src_2");
182 Object *ob_2 = BKE_id_new<Object>(bmain_src, "Ob_src_2");
183 BKE_collection_object_add(bmain_src, coll_2, ob_2);
184 Library *lib_src_2 = BKE_id_new<Library>(bmain_src, LIB_PATH);
185 BKE_library_filepath_set(bmain_src, lib_src_2, LIB_PATH);
186 std::cout << lib_src_1->runtime->filepath_abs << "\n";
187 std::cout << lib_src_2->runtime->filepath_abs << "\n";
188 ob_2->id.lib = lib_src_2;
189
190 EXPECT_EQ(1, BLI_listbase_count(&bmain_src->collections));
191 EXPECT_EQ(1, BLI_listbase_count(&bmain_src->objects));
192 EXPECT_EQ(1, BLI_listbase_count(&bmain_src->libraries));
193
194 reports = {};
195 BKE_main_merge(bmain_dst, &bmain_src, reports);
196
197 EXPECT_EQ(3, BLI_listbase_count(&bmain_dst->collections));
198 EXPECT_EQ(2, BLI_listbase_count(&bmain_dst->objects));
199 EXPECT_EQ(1, BLI_listbase_count(&bmain_dst->libraries));
200 EXPECT_EQ(ob_1, bmain_dst->objects.first);
201 EXPECT_EQ(ob_2, bmain_dst->objects.last);
202 EXPECT_EQ(lib_src_1, bmain_dst->libraries.first);
203 EXPECT_EQ(ob_1->id.lib, lib_src_1);
204 EXPECT_EQ(ob_2->id.lib, lib_src_1);
205 EXPECT_EQ(2, reports.num_merged_ids);
206 EXPECT_EQ(0, reports.num_unknown_ids);
207 EXPECT_EQ(0, reports.num_remapped_ids);
209 EXPECT_EQ(nullptr, bmain_src);
210
211 /* Use a relative library path. Since this is a different library, even though the object re-use
212 * the same name, it should still be moved into `bmain_dst`. The library filepath should also be
213 * updated and become relative the path of bmain_dst too. */
214 bmain_src = BKE_main_new();
215 STRNCPY(bmain_src->filepath, SRC_PATH);
216
217 Collection *coll_3 = BKE_id_new<Collection>(bmain_src, "Coll_src_3");
218 Object *ob_3 = BKE_id_new<Object>(bmain_src, "Ob_src");
219 BKE_collection_object_add(bmain_src, coll_3, ob_3);
220 Library *lib_src_3 = BKE_id_new<Library>(bmain_src, LIB_PATH_RELATIVE);
221 BKE_library_filepath_set(bmain_src, lib_src_3, LIB_PATH_RELATIVE);
222 ob_3->id.lib = lib_src_3;
223
224 EXPECT_EQ(1, BLI_listbase_count(&bmain_src->collections));
225 EXPECT_EQ(1, BLI_listbase_count(&bmain_src->objects));
226 EXPECT_EQ(1, BLI_listbase_count(&bmain_src->libraries));
227 EXPECT_TRUE(STREQ(lib_src_3->filepath, LIB_PATH_RELATIVE));
228 EXPECT_TRUE(STREQ(lib_src_3->runtime->filepath_abs, LIB_PATH_RELATIVE_ABS_SRC));
229
230 reports = {};
231 BKE_main_merge(bmain_dst, &bmain_src, reports);
232
233 EXPECT_EQ(4, BLI_listbase_count(&bmain_dst->collections));
234 EXPECT_EQ(3, BLI_listbase_count(&bmain_dst->objects));
235 EXPECT_EQ(2, BLI_listbase_count(&bmain_dst->libraries));
236 EXPECT_EQ(ob_1, bmain_dst->objects.first);
237 EXPECT_EQ(ob_3, bmain_dst->objects.last);
238 EXPECT_EQ(lib_src_3, bmain_dst->libraries.first);
239 EXPECT_EQ(lib_src_1, bmain_dst->libraries.last);
240 EXPECT_EQ(ob_1->id.lib, lib_src_1);
241 EXPECT_EQ(ob_2->id.lib, lib_src_1);
242 EXPECT_EQ(ob_3->id.lib, lib_src_3);
243 EXPECT_FALSE(STREQ(lib_src_3->filepath, LIB_PATH_RELATIVE));
244 EXPECT_TRUE(STREQ(lib_src_3->runtime->filepath_abs, LIB_PATH_RELATIVE_ABS_SRC));
245 EXPECT_EQ(3, reports.num_merged_ids);
246 EXPECT_EQ(0, reports.num_unknown_ids);
247 EXPECT_EQ(0, reports.num_remapped_ids);
249 EXPECT_EQ(nullptr, bmain_src);
250
251 /* Try another merge, with the library path set to the path of the destination bmain. That source
252 * library should also be skipped, and the 'linked' object in source bmain should become a local
253 * object in destination bmain. */
254 bmain_src = BKE_main_new();
255 STRNCPY(bmain_src->filepath, SRC_PATH);
256
257 Collection *coll_4 = BKE_id_new<Collection>(bmain_src, "Coll_src");
258 Object *ob_4 = BKE_id_new<Object>(bmain_src, "Ob_src_4");
259 BKE_collection_object_add(bmain_src, coll_4, ob_4);
260 Library *lib_src_4 = BKE_id_new<Library>(bmain_src, DST_PATH);
261 BKE_library_filepath_set(bmain_src, lib_src_4, DST_PATH);
262 coll_4->id.lib = lib_src_4;
263 ob_4->id.lib = lib_src_4;
264
265 EXPECT_EQ(1, BLI_listbase_count(&bmain_src->collections));
266 EXPECT_EQ(1, BLI_listbase_count(&bmain_src->objects));
267 EXPECT_EQ(1, BLI_listbase_count(&bmain_src->libraries));
268
269 reports = {};
270 BKE_main_merge(bmain_dst, &bmain_src, reports);
271
272 /* `bmain_dst` is unchanged, since both `coll_4` and `ob_4` were defined as linked from
273 * `bmain_dst`. */
274 EXPECT_EQ(4, BLI_listbase_count(&bmain_dst->collections));
275 EXPECT_EQ(3, BLI_listbase_count(&bmain_dst->objects));
276 EXPECT_EQ(2, BLI_listbase_count(&bmain_dst->libraries));
277 EXPECT_EQ(lib_src_3, bmain_dst->libraries.first);
278 EXPECT_EQ(lib_src_1, bmain_dst->libraries.last);
279 EXPECT_EQ(ob_1->id.lib, lib_src_1);
280 EXPECT_EQ(ob_2->id.lib, lib_src_1);
281 EXPECT_EQ(ob_3->id.lib, lib_src_3);
282 EXPECT_EQ(0, reports.num_merged_ids);
283 EXPECT_EQ(1, reports.num_unknown_ids);
284 EXPECT_EQ(1, reports.num_remapped_ids);
286 EXPECT_EQ(nullptr, bmain_src);
287}
288
289} // namespace blender::bke::tests
bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
void BKE_idtype_init()
Definition idtype.cc:121
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1514
void BKE_library_filepath_set(Main *bmain, Library *lib, const char *filepath)
Definition library.cc:229
void BKE_main_merge(Main *bmain_dst, Main **r_bmain_src, MainMergeReport &reports)
Definition main.cc:326
Main * BKE_main_new()
Definition main.cc:89
void BKE_main_free(Main *bmain)
Definition main.cc:192
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
#define STREQ(a, b)
void CLG_exit()
Definition clog.cc:880
void CLG_init()
Definition clog.cc:873
ID and Library types, which are fundamental for SDNA.
@ ID_GR
Object groups, one object can be in many groups at once.
Object is a sort of wrapper for general info.
#define ABS_ROOT
TEST_F(ArmatureDeformTest, MeshDeform)
struct Library * lib
Definition DNA_ID.h:420
char filepath[1024]
Definition DNA_ID.h:552
LibraryRuntimeHandle * runtime
Definition DNA_ID.h:579
void * first
int num_remapped_libraries
Definition BKE_main.hh:394
#define SEP_STR
Definition unit.cc:39