Blender  V3.3
lib_remap_test.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2022 Blender Foundation. */
3 #include "testing/testing.h"
4 
5 #include "BLI_utildefines.h"
6 
7 #include "CLG_log.h"
8 
9 #include "DNA_mesh_types.h"
10 #include "DNA_node_types.h"
11 #include "DNA_object_types.h"
12 #include "DNA_scene_types.h"
13 
14 #include "RNA_define.h"
15 
16 #include "BKE_appdir.h"
17 #include "BKE_context.h"
18 #include "BKE_global.h"
19 #include "BKE_idtype.h"
20 #include "BKE_lib_id.h"
21 #include "BKE_lib_remap.h"
22 #include "BKE_main.h"
23 #include "BKE_mesh.h"
24 #include "BKE_node.h"
25 #include "BKE_object.h"
26 #include "BKE_scene.h"
27 
28 #include "IMB_imbuf.h"
29 
30 #include "ED_node.h"
31 
32 #include "MEM_guardedalloc.h"
33 
34 namespace blender::bke::tests {
35 
36 class TestData {
37  public:
38  Main *bmain = nullptr;
39  struct bContext *C = nullptr;
40 
41  virtual void setup()
42  {
43  if (bmain == nullptr) {
44  bmain = BKE_main_new();
45  G.main = bmain;
46  }
47 
48  if (C == nullptr) {
49  C = CTX_create();
51  }
52  }
53 
54  virtual void teardown()
55  {
56  if (bmain != nullptr) {
58  bmain = nullptr;
59  G.main = nullptr;
60  }
61 
62  if (C != nullptr) {
63  CTX_free(C);
64  C = nullptr;
65  }
66  }
67 };
68 
69 class SceneTestData : public TestData {
70  public:
71  Scene *scene = nullptr;
72  void setup() override
73  {
75  scene = BKE_scene_add(bmain, "IDRemapScene");
77  }
78 };
79 
81  public:
83  void setup() override
84  {
88  }
89 };
90 
91 class MeshTestData : public TestData {
92  public:
93  Mesh *mesh = nullptr;
94 
95  void setup() override
96  {
98  mesh = BKE_mesh_add(bmain, nullptr);
99  }
100 };
101 
103  public:
104  Mesh *other_mesh = nullptr;
105 
106  void setup() override
107  {
109  other_mesh = BKE_mesh_add(bmain, nullptr);
110  }
111 };
112 
114  public:
116  void setup() override
117  {
119 
120  object = BKE_object_add_only_object(bmain, OB_MESH, nullptr);
121  object->data = mesh;
122  }
123 };
124 
125 template<typename TestData> class Context {
126  public:
128 
130  {
131  CLG_init();
132  BKE_idtype_init();
133  RNA_init();
135  BKE_appdir_init();
136  IMB_init();
137 
138  test_data.setup();
139  }
140 
142  {
144 
146  RNA_exit();
147  IMB_exit();
148  BKE_appdir_exit();
149  CLG_exit();
150  }
151 };
152 
153 /* -------------------------------------------------------------------- */
157 TEST(lib_remap, embedded_ids_can_not_be_remapped)
158 {
160  bNodeTree *other_tree = static_cast<bNodeTree *>(BKE_id_new_nomain(ID_NT, nullptr));
161 
162  EXPECT_NE(context.test_data.scene, nullptr);
163  EXPECT_NE(context.test_data.compositor_nodetree, nullptr);
164  EXPECT_EQ(context.test_data.compositor_nodetree, context.test_data.scene->nodetree);
165 
167  context.test_data.bmain, context.test_data.compositor_nodetree, other_tree, 0);
168 
169  EXPECT_EQ(context.test_data.compositor_nodetree, context.test_data.scene->nodetree);
170  EXPECT_NE(context.test_data.scene->nodetree, other_tree);
171 
172  BKE_id_free(nullptr, other_tree);
173 }
174 
175 TEST(lib_remap, embedded_ids_can_not_be_deleted)
176 {
178 
179  EXPECT_NE(context.test_data.scene, nullptr);
180  EXPECT_NE(context.test_data.compositor_nodetree, nullptr);
181  EXPECT_EQ(context.test_data.compositor_nodetree, context.test_data.scene->nodetree);
182 
183  BKE_libblock_remap(context.test_data.bmain,
184  context.test_data.compositor_nodetree,
185  nullptr,
187 
188  EXPECT_EQ(context.test_data.compositor_nodetree, context.test_data.scene->nodetree);
189  EXPECT_NE(context.test_data.scene->nodetree, nullptr);
190 }
191 
194 /* -------------------------------------------------------------------- */
198 TEST(lib_remap, delete_when_remap_to_self_not_allowed)
199 {
201 
202  EXPECT_NE(context.test_data.mesh, nullptr);
203  EXPECT_NE(context.test_data.other_mesh, nullptr);
204  context.test_data.mesh->texcomesh = context.test_data.other_mesh;
205 
207  context.test_data.bmain, context.test_data.other_mesh, context.test_data.mesh, 0);
208 
209  EXPECT_EQ(context.test_data.mesh->texcomesh, nullptr);
210 }
211 
214 /* -------------------------------------------------------------------- */
218 TEST(lib_remap, users_are_decreased_when_not_skipping_never_null)
219 {
221 
222  EXPECT_NE(context.test_data.object, nullptr);
223  EXPECT_EQ(context.test_data.object->data, context.test_data.mesh);
224  EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0);
225  EXPECT_EQ(context.test_data.mesh->id.us, 1);
226 
227  /* This is an invalid situation, test case tests this in between value until we have a better
228  * solution. */
229  BKE_libblock_remap(context.test_data.bmain, context.test_data.mesh, nullptr, 0);
230  EXPECT_EQ(context.test_data.mesh->id.us, 0);
231  EXPECT_EQ(context.test_data.object->data, context.test_data.mesh);
232  EXPECT_NE(context.test_data.object->data, nullptr);
233  EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0);
234 }
235 
236 TEST(lib_remap, users_are_same_when_skipping_never_null)
237 {
239 
240  EXPECT_NE(context.test_data.object, nullptr);
241  EXPECT_EQ(context.test_data.object->data, context.test_data.mesh);
242  EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0);
243  EXPECT_EQ(context.test_data.mesh->id.us, 1);
244 
246  context.test_data.bmain, context.test_data.mesh, nullptr, ID_REMAP_SKIP_NEVER_NULL_USAGE);
247  EXPECT_EQ(context.test_data.mesh->id.us, 1);
248  EXPECT_EQ(context.test_data.object->data, context.test_data.mesh);
249  EXPECT_NE(context.test_data.object->data, nullptr);
250  EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0);
251 }
252 
255 /* -------------------------------------------------------------------- */
259 TEST(lib_remap, do_not_delete_when_cannot_unset)
260 {
262 
263  EXPECT_NE(context.test_data.object, nullptr);
264  EXPECT_EQ(context.test_data.object->data, context.test_data.mesh);
265 
267  context.test_data.bmain, context.test_data.mesh, nullptr, ID_REMAP_SKIP_NEVER_NULL_USAGE);
268  EXPECT_EQ(context.test_data.object->data, context.test_data.mesh);
269  EXPECT_NE(context.test_data.object->data, nullptr);
270 }
271 
272 TEST(lib_remap, force_never_null_usage)
273 {
275 
276  EXPECT_NE(context.test_data.object, nullptr);
277  EXPECT_EQ(context.test_data.object->data, context.test_data.mesh);
278 
280  context.test_data.bmain, context.test_data.mesh, nullptr, ID_REMAP_FORCE_NEVER_NULL_USAGE);
281  EXPECT_EQ(context.test_data.object->data, nullptr);
282 }
283 
284 TEST(lib_remap, never_null_usage_flag_not_requested_on_delete)
285 {
287 
288  EXPECT_NE(context.test_data.object, nullptr);
289  EXPECT_EQ(context.test_data.object->data, context.test_data.mesh);
290  EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0);
291 
292  /* Never null usage isn't requested so the flag should not be set. */
294  context.test_data.bmain, context.test_data.mesh, nullptr, ID_REMAP_SKIP_NEVER_NULL_USAGE);
295  EXPECT_EQ(context.test_data.object->data, context.test_data.mesh);
296  EXPECT_NE(context.test_data.object->data, nullptr);
297  EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0);
298 }
299 
300 TEST(lib_remap, never_null_usage_flag_requested_on_delete)
301 {
303 
304  EXPECT_NE(context.test_data.object, nullptr);
305  EXPECT_EQ(context.test_data.object->data, context.test_data.mesh);
306  EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0);
307 
308  /* Never null usage is requested so the flag should be set. */
309  BKE_libblock_remap(context.test_data.bmain,
310  context.test_data.mesh,
311  nullptr,
313  EXPECT_EQ(context.test_data.object->data, context.test_data.mesh);
314  EXPECT_NE(context.test_data.object->data, nullptr);
315  EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, LIB_TAG_DOIT);
316 }
317 
318 TEST(lib_remap, never_null_usage_flag_not_requested_on_remap)
319 {
321  Mesh *other_mesh = BKE_mesh_add(context.test_data.bmain, nullptr);
322 
323  EXPECT_NE(context.test_data.object, nullptr);
324  EXPECT_EQ(context.test_data.object->data, context.test_data.mesh);
325  EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0);
326 
327  /* Never null usage isn't requested so the flag should not be set. */
329  context.test_data.bmain, context.test_data.mesh, other_mesh, ID_REMAP_SKIP_NEVER_NULL_USAGE);
330  EXPECT_EQ(context.test_data.object->data, other_mesh);
331  EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0);
332 }
333 
334 TEST(lib_remap, never_null_usage_flag_requested_on_remap)
335 {
337  Mesh *other_mesh = BKE_mesh_add(context.test_data.bmain, nullptr);
338 
339  EXPECT_NE(context.test_data.object, nullptr);
340  EXPECT_EQ(context.test_data.object->data, context.test_data.mesh);
341  EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0);
342 
343  /* Never null usage is requested so the flag should be set. */
344  BKE_libblock_remap(context.test_data.bmain,
345  context.test_data.mesh,
346  other_mesh,
348  EXPECT_EQ(context.test_data.object->data, other_mesh);
349  EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, LIB_TAG_DOIT);
350 }
351 
354 } // namespace blender::bke::tests
void BKE_appdir_init(void)
Definition: appdir.c:88
void BKE_appdir_exit(void)
Definition: appdir.c:96
void CTX_data_scene_set(bContext *C, struct Scene *scene)
Definition: context.c:1271
bContext * CTX_create(void)
Definition: context.c:102
void CTX_free(bContext *C)
Definition: context.c:118
void CTX_data_main_set(bContext *C, struct Main *bmain)
Definition: context.c:1084
void BKE_idtype_init(void)
Definition: idtype.c:106
void * BKE_id_new_nomain(short type, const char *name)
Definition: lib_id.c:1173
void BKE_id_free(struct Main *bmain, void *idv)
@ ID_REMAP_SKIP_NEVER_NULL_USAGE
Definition: BKE_lib_remap.h:45
@ ID_REMAP_FLAG_NEVER_NULL_USAGE
Definition: BKE_lib_remap.h:50
@ ID_REMAP_FORCE_NEVER_NULL_USAGE
Definition: BKE_lib_remap.h:57
void void BKE_libblock_remap(struct Main *bmain, void *old_idv, void *new_idv, short remap_flags) ATTR_NONNULL(1
struct Main * BKE_main_new(void)
Definition: main.c:32
void BKE_main_free(struct Main *mainvar)
Definition: main.c:40
struct Mesh * BKE_mesh_add(struct Main *bmain, const char *name)
Definition: mesh.cc:963
void BKE_node_system_exit(void)
Definition: node.cc:4957
void BKE_node_system_init(void)
Definition: node.cc:4930
General operations, lookup, etc. for blender objects.
struct Object * BKE_object_add_only_object(struct Main *bmain, int type, const char *name) ATTR_RETURNS_NONNULL
Definition: object.cc:2241
struct Scene * BKE_scene_add(struct Main *bmain, const char *name)
Definition: scene.cc:2044
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
void CLG_exit(void)
Definition: clog.c:703
void CLG_init(void)
Definition: clog.c:696
@ LIB_TAG_DOIT
Definition: DNA_ID.h:707
@ ID_NT
Definition: DNA_ID_enums.h:68
Object is a sort of wrapper for general info.
@ OB_MESH
void ED_node_composit_default(const struct bContext *C, struct Scene *scene)
void IMB_init(void)
Definition: module.c:16
void IMB_exit(void)
Definition: module.c:25
Read Guarded memory(de)allocation.
#define G(x, y, z)
TEST(action_groups, ReconstructGroupsWithReordering)
Definition: action_test.cc:17
void RNA_init(void)
Definition: rna_access.c:65
void RNA_exit(void)
Definition: rna_access.c:89
Definition: BKE_main.h:121
struct bNodeTree * nodetree