Commit: 04feaa8bd0569a5453bec7a282f3f4a593eeb6ff Author: Jeroen Bakker Date: Mon Jan 17 12:44:55 2022 +0100 Branches: master https://developer.blender.org/rB04feaa8bd0569a5453bec7a282f3f4a593eeb6ff
Core: Library Remap test cases. For an upcoming refactoring of library remapping we want to be able to test if the logic won't change. It also increased my experience inside the remapping codebase and find out what exactly needed to be refactored. This patch adds test cases for the core functionality of `foreach_libblock_remap_callback`. The test cases don't cover of all the branches. Also pre-, post-processing, referencing and proxies are not tested. Reviewed By: mont29 Differential Revision: https://developer.blender.org/D13815 =================================================================== M source/blender/blenkernel/CMakeLists.txt A source/blender/blenkernel/intern/lib_remap_test.cc =================================================================== diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 4449a1bce62..7f8a917e002 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -819,6 +819,7 @@ if(WITH_GTESTS) intern/lattice_deform_test.cc intern/layer_test.cc intern/lib_id_test.cc + intern/lib_remap_test.cc intern/tracking_test.cc ) set(TEST_INC diff --git a/source/blender/blenkernel/intern/lib_remap_test.cc b/source/blender/blenkernel/intern/lib_remap_test.cc new file mode 100644 index 00000000000..f803e600787 --- /dev/null +++ b/source/blender/blenkernel/intern/lib_remap_test.cc @@ -0,0 +1,369 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2022 by Blender Foundation. + */ +#include "testing/testing.h" + +#include "BLI_utildefines.h" + +#include "CLG_log.h" + +#include "DNA_mesh_types.h" +#include "DNA_node_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "RNA_define.h" + +#include "BKE_appdir.h" +#include "BKE_context.h" +#include "BKE_global.h" +#include "BKE_idtype.h" +#include "BKE_lib_id.h" +#include "BKE_lib_remap.h" +#include "BKE_main.h" +#include "BKE_mesh.h" +#include "BKE_node.h" +#include "BKE_object.h" +#include "BKE_scene.h" + +#include "IMB_imbuf.h" + +#include "ED_node.h" + +#include "MEM_guardedalloc.h" + +namespace blender::bke::tests { + +class TestData { + public: + Main *bmain = nullptr; + struct bContext *C = nullptr; + + virtual void setup() + { + if (bmain == nullptr) { + bmain = BKE_main_new(); + G.main = bmain; + } + + if (C == nullptr) { + C = CTX_create(); + CTX_data_main_set(C, bmain); + } + } + + virtual void teardown() + { + if (bmain != nullptr) { + BKE_main_free(bmain); + bmain = nullptr; + G.main = nullptr; + } + + if (C != nullptr) { + CTX_free(C); + C = nullptr; + } + } +}; + +class SceneTestData : public TestData { + public: + Scene *scene = nullptr; + void setup() override + { + TestData::setup(); + scene = BKE_scene_add(bmain, "IDRemapScene"); + CTX_data_scene_set(C, scene); + } +}; + +class CompositorTestData : public SceneTestData { + public: + bNodeTree *compositor_nodetree = nullptr; + void setup() override + { + SceneTestData::setup(); + ED_node_composit_default(C, scene); + compositor_nodetree = scene->nodetree; + } +}; + +class MeshTestData : public TestData { + public: + Mesh *mesh = nullptr; + + void setup() override + { + TestData::setup(); + mesh = BKE_mesh_add(bmain, nullptr); + } +}; + +class TwoMeshesTestData : public MeshTestData { + public: + Mesh *other_mesh = nullptr; + + void setup() override + { + MeshTestData::setup(); + other_mesh = BKE_mesh_add(bmain, nullptr); + } +}; + +class MeshObjectTestData : public MeshTestData { + public: + Object *object; + void setup() override + { + MeshTestData::setup(); + + object = BKE_object_add_only_object(bmain, OB_MESH, nullptr); + object->data = mesh; + } +}; + +template<typename TestData> class Context { + public: + TestData test_data; + + Context() + { + CLG_init(); + BKE_idtype_init(); + RNA_init(); + BKE_node_system_init(); + BKE_appdir_init(); + IMB_init(); + + test_data.setup(); + } + + ~Context() + { + test_data.teardown(); + + BKE_node_system_exit(); + RNA_exit(); + IMB_exit(); + BKE_appdir_exit(); + CLG_exit(); + } +}; + +/* -------------------------------------------------------------------- */ +/** \name Embedded IDs + * \{ */ + +TEST(lib_remap, embedded_ids_can_not_be_remapped) +{ + Context<CompositorTestData> context; + bNodeTree *other_tree = static_cast<bNodeTree *>(BKE_id_new_nomain(ID_NT, nullptr)); + + EXPECT_NE(context.test_data.scene, nullptr); + EXPECT_NE(context.test_data.compositor_nodetree, nullptr); + EXPECT_EQ(context.test_data.compositor_nodetree, context.test_data.scene->nodetree); + + BKE_libblock_remap( + context.test_data.bmain, context.test_data.compositor_nodetree, other_tree, 0); + + EXPECT_EQ(context.test_data.compositor_nodetree, context.test_data.scene->nodetree); + EXPECT_NE(context.test_data.scene->nodetree, other_tree); + + BKE_id_free(nullptr, other_tree); +} + +TEST(lib_remap, embedded_ids_can_not_be_deleted) +{ + Context<CompositorTestData> context; + + EXPECT_NE(context.test_data.scene, nullptr); + EXPECT_NE(context.test_data.compositor_nodetree, nullptr); + EXPECT_EQ(context.test_data.compositor_nodetree, context.test_data.scene->nodetree); + + BKE_libblock_remap(context.test_data.bmain, + context.test_data.compositor_nodetree, + nullptr, + ID_REMAP_SKIP_NEVER_NULL_USAGE); + + EXPECT_EQ(context.test_data.compositor_nodetree, context.test_data.scene->nodetree); + EXPECT_NE(context.test_data.scene->nodetree, nullptr); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Remap to self + * \{ */ + +TEST(lib_remap, delete_when_remap_to_self_not_allowed) +{ + Context<TwoMeshesTestData> context; + + EXPECT_NE(context.test_data.mesh, nullptr); + EXPECT_NE(context.test_data.other_mesh, nullptr); + context.test_data.mesh->texcomesh = context.test_data.other_mesh; + + BKE_libblock_remap( + context.test_data.bmain, context.test_data.other_mesh, context.test_data.mesh, 0); + + EXPECT_EQ(context.test_data.mesh->texcomesh, nullptr); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Userref counting + * \{ */ + +TEST(lib_remap, users_are_decreased_when_not_skipping_never_null) +{ + Context<MeshObjectTestData> context; + + EXPECT_NE(context.test_data.object, nullptr); + EXPECT_EQ(context.test_data.object->data, context.test_data.mesh); + EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0); + EXPECT_EQ(context.test_data.mesh->id.us, 1); + + /* This is an invalid situation, test case tests this in between value until we have a better + * solution. */ + BKE_libblock_remap(context.test_data.bmain, context.test_data.mesh, nullptr, 0); + EXPECT_EQ(context.test_data.mesh->id.us, 0); + EXPECT_EQ(context.test_data.object->data, context.test_data.mesh); + EXPECT_NE(context.test_data.object->data, nullptr); + EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0); +} + +TEST(lib_remap, users_are_same_when_skipping_never_null) +{ + Context<MeshObjectTestData> context; + + EXPECT_NE(context.test_data.object, nullptr); + EXPECT_EQ(context.test_data.object->data, context.test_data.mesh); + EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0); + EXPECT_EQ(context.test_data.mesh->id.us, 1); + + BKE_libblock_remap( + context.test_data.bmain, context.test_data.mesh, nullptr, ID_REMAP_SKIP_NEVER_NULL_USAGE); + EXPECT_EQ(context.test_data.mesh->id.us, 1); + EXPECT_EQ(context.test_data.object->data, context.test_data.mesh); + EXPECT_NE(context.test_data.object->data, nullptr); + EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Never Null + * \{ */ + +TEST(lib_remap, do_not_delete_when_cannot_unset) +{ + Context<MeshObjectTestData> context; + + EXPECT_NE(context.test_data.object, nullptr); + EXPECT_EQ(context.test_data.object->data, context.test_data.mesh); + + BKE_libblock_remap( + context.test_data.bmain, context.test_data.mesh, nullptr, ID_REMAP_SKIP_NEVER_NULL_USAGE); + EXPECT_EQ(context.test_data.object->data, context.test_data.mesh); + EXPECT_NE(context.test_data.object->data, nullptr); +} + +TEST(lib_remap, force_never_null_usage) +{ + Context<MeshObjectTestData> context; + + EXPECT_NE(context.test_data.object, nullptr); + EXPECT_EQ(context.test_data.object->data, context.test_data.mesh); + + BKE_libblock_remap( + context.test_data.bmain, context.test_data.mesh, nullptr, ID_REMAP_FORCE_NEVER_NULL_USAGE); + EXPECT_EQ(context.test_data.object->data, nullptr); +} + +TEST(lib_remap, never_null_usage_flag_not_requested_on_delete) +{ + Context<MeshObjectTestData> context; + + EXPECT_NE(context.test_data.object, nullptr); + EXPECT_EQ(context.test_data.object->data, context.test_data.mesh); + EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0); + + /* Never null usage isn't requested so the flag should not be set.*/ + BKE_libblock_remap( + context.test_data.bmain, context.test_data.mesh, nullptr, ID_REMAP_SKIP_NEVER_NULL_USAGE); + EXPECT_EQ(context.test_data.object->data, context.test_data.mesh); + EXPECT_NE(context.test_data.object->data, nullptr); + EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0); +} + +TEST(lib_remap, never_null_usage_flag_requested_on_delete) +{ + Context<MeshObjectTestData> context; + + EXPECT_NE(context.test_data.object, nullptr); + EXPECT_EQ(context.test_data.object->data, context.test_data.mesh); + EXPECT_EQ(context.test_data.object->id.tag & LIB_TAG_DOIT, 0); + + /* Never null usage is requested so the flag should be set. */ + BKE_libblock_remap(context.test_data.bmain, + context.test_data.mesh, + nullptr, + ID_REMAP_SKIP_NEVER_NULL_USAGE | ID_REMAP_FLAG_NEVER_NULL_USAGE); + EXPECT_EQ(context.test_data.object->data, context.test_data.mesh); + EXPECT_NE(context.test_data.object->data, nullptr); + EXPECT_EQ(context. @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs