Blender V4.3
asset_library_service_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
6
7#include "BLI_fileops.h" /* For PATH_MAX (at least on Windows). */
8#include "BLI_path_utils.hh"
9#include "BLI_string.h"
10
11#include "BKE_appdir.hh"
12#include "BKE_callbacks.hh"
13#include "BKE_main.hh"
14
15#include "DNA_asset_types.h"
16
17#include "CLG_log.h"
18
19#include "testing/testing.h"
20
22
23const bUUID UUID_POSES_ELLIE("df60e1f6-2259-475b-93d9-69a1b4a8db78");
24
25class AssetLibraryServiceTest : public testing::Test {
26 public:
29
30 static void SetUpTestSuite()
31 {
32 CLG_init();
34 }
35 static void TearDownTestSuite()
36 {
37 CLG_exit();
39 }
40
41 void SetUp() override
42 {
43 const std::string test_files_dir = blender::tests::flags_test_asset_dir();
44 if (test_files_dir.empty()) {
45 FAIL();
46 }
47 asset_library_root_ = test_files_dir + SEP_STR + "asset_library";
49 }
50
51 void TearDown() override
52 {
54
55 if (!temp_library_path_.empty()) {
56 BLI_delete(temp_library_path_.c_str(), true, true);
58 }
59 }
60
61 /* Register a temporary path, which will be removed at the end of the test.
62 * The returned path ends in a slash. */
64 {
65 BKE_tempdir_init(nullptr);
66 const CatalogFilePath tempdir = BKE_tempdir_session();
67 temp_library_path_ = tempdir + "test-temporary-path" + SEP_STR;
68 return temp_library_path_;
69 }
70
72 {
74 BLI_dir_create_recursive(path.c_str());
75 return path;
76 }
77};
78
80{
83 << "Calling twice without destroying in between should return the same instance.";
84
85 /* This should not crash. */
88
89 /* NOTE: there used to be a test for the opposite here, that after a call to
90 * AssetLibraryService::destroy() the above calls should return freshly allocated objects. This
91 * cannot be reliably tested by just pointer comparison, though. */
92}
93
95{
97
98 AssetLibrary *const lib = service->get_asset_library_on_disk_custom(__func__,
99 asset_library_root_);
100 AssetLibrary *const curfile_lib = service->get_asset_library_current_file();
101
102 EXPECT_EQ(lib, service->get_asset_library_on_disk_custom(__func__, asset_library_root_))
103 << "Calling twice without destroying in between should return the same instance.";
104 EXPECT_EQ(curfile_lib, service->get_asset_library_current_file())
105 << "Calling twice without destroying in between should return the same instance.";
106
107 /* NOTE: there used to be a test for the opposite here, that after a call to
108 * AssetLibraryService::destroy() the above calls should return freshly allocated objects. This
109 * cannot be reliably tested by just pointer comparison, though. */
110}
111
112TEST_F(AssetLibraryServiceTest, library_from_reference)
113{
115
116 AssetLibrary *const curfile_lib = service->get_asset_library_current_file();
117
120 EXPECT_EQ(curfile_lib, service->get_asset_library(nullptr, ref))
121 << "Getting the local (current file) reference without a main saved on disk should return "
122 "the current file library";
123
124 {
125 Main dummy_main{};
126 std::string dummy_filepath = asset_library_root_ + SEP + "dummy.blend";
127 STRNCPY(dummy_main.filepath, dummy_filepath.c_str());
128
129 AssetLibrary *custom_lib = service->get_asset_library_on_disk_custom(__func__,
130 asset_library_root_);
131 AssetLibrary *tmp_curfile_lib = service->get_asset_library(&dummy_main, ref);
132
133 /* Requested a current file library with a (fake) file saved in the same directory as a custom
134 * asset library. The resulting library should never match the custom asset library, even
135 * though the paths match. */
136
137 EXPECT_NE(custom_lib, tmp_curfile_lib)
138 << "Getting an asset library from a local (current file) library reference should never "
139 "match any custom asset library";
140 EXPECT_EQ(custom_lib->root_path(), tmp_curfile_lib->root_path());
141 }
142}
143
144TEST_F(AssetLibraryServiceTest, library_path_trailing_slashes)
145{
147
148 char asset_lib_no_slash[PATH_MAX];
149 char asset_lib_with_slash[PATH_MAX];
150 STRNCPY(asset_lib_no_slash, asset_library_root_.c_str());
151 STRNCPY(asset_lib_with_slash, asset_library_root_.c_str());
152
153 /* Ensure #asset_lib_no_slash has no trailing slash, regardless of what was passed on the CLI to
154 * the unit test. */
155 while (strlen(asset_lib_no_slash) &&
156 ELEM(asset_lib_no_slash[strlen(asset_lib_no_slash) - 1], SEP, ALTSEP))
157 {
158 asset_lib_no_slash[strlen(asset_lib_no_slash) - 1] = '\0';
159 }
160
161 BLI_path_slash_ensure(asset_lib_with_slash, PATH_MAX);
162
163 AssetLibrary *const lib_no_slash = service->get_asset_library_on_disk_custom(__func__,
164 asset_lib_no_slash);
165
166 EXPECT_EQ(lib_no_slash,
167 service->get_asset_library_on_disk_custom(__func__, asset_lib_with_slash))
168 << "With or without trailing slash shouldn't matter.";
169}
170
172{
174 AssetLibrary *const lib = service->get_asset_library_on_disk_custom(__func__,
175 asset_library_root_);
176 AssetCatalogService &cat_service = lib->catalog_service();
177
178 const bUUID UUID_POSES_ELLIE("df60e1f6-2259-475b-93d9-69a1b4a8db78");
179 EXPECT_NE(nullptr, cat_service.find_catalog(UUID_POSES_ELLIE))
180 << "Catalogs should be loaded after getting an asset library from disk.";
181}
182
183TEST_F(AssetLibraryServiceTest, has_any_unsaved_catalogs)
184{
186 EXPECT_FALSE(service->has_any_unsaved_catalogs())
187 << "Empty AssetLibraryService should have no unsaved catalogs";
188
189 AssetLibrary *const lib = service->get_asset_library_on_disk_custom(__func__,
190 asset_library_root_);
191 AssetCatalogService &cat_service = lib->catalog_service();
192 EXPECT_FALSE(service->has_any_unsaved_catalogs())
193 << "Unchanged AssetLibrary should have no unsaved catalogs";
194
195 const bUUID UUID_POSES_ELLIE("df60e1f6-2259-475b-93d9-69a1b4a8db78");
197 EXPECT_FALSE(service->has_any_unsaved_catalogs())
198 << "Deletion of catalogs via AssetCatalogService should not automatically tag as 'unsaved "
199 "changes'.";
200
201 const bUUID UUID_POSES_RUZENA("79a4f887-ab60-4bd4-94da-d572e27d6aed");
202 AssetCatalog *cat = cat_service.find_catalog(UUID_POSES_RUZENA);
203 ASSERT_NE(nullptr, cat) << "Catalog " << UUID_POSES_RUZENA << " should be known";
204
205 cat_service.tag_has_unsaved_changes(cat);
206 EXPECT_TRUE(service->has_any_unsaved_catalogs())
207 << "Tagging as having unsaved changes of a single catalog service should result in unsaved "
208 "changes being reported.";
209 EXPECT_TRUE(cat->flags.has_unsaved_changes);
210}
211
212TEST_F(AssetLibraryServiceTest, has_any_unsaved_catalogs_after_write)
213{
214 const CatalogFilePath writable_dir = create_temp_path(); /* Has trailing slash. */
215 const CatalogFilePath original_cdf_file = asset_library_root_ + SEP_STR +
216 "blender_assets.cats.txt";
217 CatalogFilePath writable_cdf_file = writable_dir + AssetCatalogService::DEFAULT_CATALOG_FILENAME;
218 BLI_path_slash_native(writable_cdf_file.data());
219 ASSERT_EQ(0, BLI_copy(original_cdf_file.c_str(), writable_cdf_file.c_str()));
220
222 AssetLibrary *const lib = service->get_asset_library_on_disk_custom(__func__, writable_dir);
223
224 EXPECT_FALSE(service->has_any_unsaved_catalogs())
225 << "Unchanged AssetLibrary should have no unsaved catalogs";
226
227 AssetCatalogService &cat_service = lib->catalog_service();
228 AssetCatalog *cat = cat_service.find_catalog(UUID_POSES_ELLIE);
229
230 cat_service.tag_has_unsaved_changes(cat);
231
232 EXPECT_TRUE(service->has_any_unsaved_catalogs())
233 << "Tagging as having unsaved changes of a single catalog service should result in unsaved "
234 "changes being reported.";
235 EXPECT_TRUE(cat->flags.has_unsaved_changes);
236
237 cat_service.write_to_disk(writable_dir + "dummy_path.blend");
238 EXPECT_FALSE(service->has_any_unsaved_catalogs())
239 << "Written AssetCatalogService should have no unsaved catalogs";
240 EXPECT_FALSE(cat->flags.has_unsaved_changes);
241}
242
243} // namespace blender::asset_system::tests
void BKE_tempdir_init(const char *userdir)
Definition appdir.cc:1190
void BKE_callback_global_finalize()
Definition callbacks.cc:108
void BKE_callback_global_init()
Definition callbacks.cc:103
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
File and directory operations.
int BLI_copy(const char *path_src, const char *path_dst) ATTR_NONNULL()
bool BLI_dir_create_recursive(const char *dirname) ATTR_NONNULL()
Definition fileops_c.cc:391
int BLI_delete(const char *path, bool dir, bool recursive) ATTR_NONNULL()
#define PATH_MAX
Definition BLI_fileops.h:30
#define ALTSEP
void BLI_path_slash_native(char *path) ATTR_NONNULL(1)
#define SEP
int BLI_path_slash_ensure(char *path, size_t path_maxncpy) ATTR_NONNULL(1)
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define ELEM(...)
void CLG_exit(void)
Definition clog.c:706
void CLG_init(void)
Definition clog.c:699
@ ASSET_LIBRARY_LOCAL
AssetCatalog * find_catalog(CatalogID catalog_id) const
bool write_to_disk(const CatalogFilePath &blend_file_path)
static const CatalogFilePath DEFAULT_CATALOG_FILENAME
struct blender::asset_system::AssetCatalog::Flags flags
AssetLibrary * get_asset_library(const Main *bmain, const AssetLibraryReference &library_reference)
AssetLibrary * get_asset_library_on_disk_custom(StringRef name, StringRefNull root_path)
TEST_F(AssetCatalogTest, load_single_file)
const bUUID UUID_POSES_ELLIE("df60e1f6-2259-475b-93d9-69a1b4a8db78")
const bUUID UUID_POSES_RUZENA("79a4f887-ab60-4bd4-94da-d572e27d6aed")
Universally Unique Identifier according to RFC4122.
void * BKE_tempdir_session
Definition stubs.c:38
#define SEP_STR
Definition unit.cc:39
static DynamicLibrary lib