Blender  V3.3
asset_library_service_test.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2020 Blender Foundation. All rights reserved. */
3 
5 
6 #include "BLI_fileops.h" /* For PATH_MAX (at least on Windows). */
7 #include "BLI_path_util.h"
8 
9 #include "BKE_appdir.h"
10 #include "BKE_callbacks.h"
11 
12 #include "CLG_log.h"
13 
14 #include "testing/testing.h"
15 
16 namespace blender::bke::tests {
17 
18 const bUUID UUID_POSES_ELLIE("df60e1f6-2259-475b-93d9-69a1b4a8db78");
19 
20 class AssetLibraryServiceTest : public testing::Test {
21  public:
24 
25  static void SetUpTestSuite()
26  {
27  CLG_init();
29  }
30  static void TearDownTestSuite()
31  {
32  CLG_exit();
34  }
35 
36  void SetUp() override
37  {
38  const std::string test_files_dir = blender::tests::flags_test_asset_dir();
39  if (test_files_dir.empty()) {
40  FAIL();
41  }
42  asset_library_root_ = test_files_dir + "/" + "asset_library";
43  temp_library_path_ = "";
44  }
45 
46  void TearDown() override
47  {
49 
50  if (!temp_library_path_.empty()) {
51  BLI_delete(temp_library_path_.c_str(), true, true);
52  temp_library_path_ = "";
53  }
54  }
55 
56  /* Register a temporary path, which will be removed at the end of the test.
57  * The returned path ends in a slash. */
59  {
60  BKE_tempdir_init("");
61  const CatalogFilePath tempdir = BKE_tempdir_session();
62  temp_library_path_ = tempdir + "test-temporary-path/";
63  return temp_library_path_;
64  }
65 
67  {
69  BLI_dir_create_recursive(path.c_str());
70  return path;
71  }
72 };
73 
75 {
78  << "Calling twice without destroying in between should return the same instance.";
79 
80  /* This should not crash. */
83 
84  /* NOTE: there used to be a test for the opposite here, that after a call to
85  * AssetLibraryService::destroy() the above calls should return freshly allocated objects. This
86  * cannot be reliably tested by just pointer comparison, though. */
87 }
88 
89 TEST_F(AssetLibraryServiceTest, library_pointers)
90 {
92  AssetLibrary *const lib = service->get_asset_library_on_disk(asset_library_root_);
93  AssetLibrary *const curfile_lib = service->get_asset_library_current_file();
94 
95  EXPECT_EQ(lib, service->get_asset_library_on_disk(asset_library_root_))
96  << "Calling twice without destroying in between should return the same instance.";
97  EXPECT_EQ(curfile_lib, service->get_asset_library_current_file())
98  << "Calling twice without destroying in between should return the same instance.";
99 
100  /* NOTE: there used to be a test for the opposite here, that after a call to
101  * AssetLibraryService::destroy() the above calls should return freshly allocated objects. This
102  * cannot be reliably tested by just pointer comparison, though. */
103 }
104 
105 TEST_F(AssetLibraryServiceTest, library_path_trailing_slashes)
106 {
108 
109  char asset_lib_no_slash[PATH_MAX];
110  char asset_lib_with_slash[PATH_MAX];
111  STRNCPY(asset_lib_no_slash, asset_library_root_.c_str());
112  STRNCPY(asset_lib_with_slash, asset_library_root_.c_str());
113 
114  /* Ensure #asset_lib_no_slash has no trailing slash, regardless of what was passed on the CLI to
115  * the unit test. */
116  while (strlen(asset_lib_no_slash) &&
117  ELEM(asset_lib_no_slash[strlen(asset_lib_no_slash) - 1], SEP, ALTSEP)) {
118  asset_lib_no_slash[strlen(asset_lib_no_slash) - 1] = '\0';
119  }
120 
121  BLI_path_slash_ensure(asset_lib_with_slash);
122 
123  AssetLibrary *const lib_no_slash = service->get_asset_library_on_disk(asset_lib_no_slash);
124 
125  EXPECT_EQ(lib_no_slash, service->get_asset_library_on_disk(asset_lib_with_slash))
126  << "With or without trailing slash shouldn't matter.";
127 }
128 
130 {
132  AssetLibrary *const lib = service->get_asset_library_on_disk(asset_library_root_);
133  AssetCatalogService *const cat_service = lib->catalog_service.get();
134 
135  const bUUID UUID_POSES_ELLIE("df60e1f6-2259-475b-93d9-69a1b4a8db78");
136  EXPECT_NE(nullptr, cat_service->find_catalog(UUID_POSES_ELLIE))
137  << "Catalogs should be loaded after getting an asset library from disk.";
138 }
139 
140 TEST_F(AssetLibraryServiceTest, has_any_unsaved_catalogs)
141 {
143  EXPECT_FALSE(service->has_any_unsaved_catalogs())
144  << "Empty AssetLibraryService should have no unsaved catalogs";
145 
146  AssetLibrary *const lib = service->get_asset_library_on_disk(asset_library_root_);
147  AssetCatalogService *const cat_service = lib->catalog_service.get();
148  EXPECT_FALSE(service->has_any_unsaved_catalogs())
149  << "Unchanged AssetLibrary should have no unsaved catalogs";
150 
151  const bUUID UUID_POSES_ELLIE("df60e1f6-2259-475b-93d9-69a1b4a8db78");
153  EXPECT_FALSE(service->has_any_unsaved_catalogs())
154  << "Deletion of catalogs via AssetCatalogService should not automatically tag as 'unsaved "
155  "changes'.";
156 
157  const bUUID UUID_POSES_RUZENA("79a4f887-ab60-4bd4-94da-d572e27d6aed");
158  AssetCatalog *cat = cat_service->find_catalog(UUID_POSES_RUZENA);
159  ASSERT_NE(nullptr, cat) << "Catalog " << UUID_POSES_RUZENA << " should be known";
160 
161  cat_service->tag_has_unsaved_changes(cat);
162  EXPECT_TRUE(service->has_any_unsaved_catalogs())
163  << "Tagging as having unsaved changes of a single catalog service should result in unsaved "
164  "changes being reported.";
165  EXPECT_TRUE(cat->flags.has_unsaved_changes);
166 }
167 
168 TEST_F(AssetLibraryServiceTest, has_any_unsaved_catalogs_after_write)
169 {
170  const CatalogFilePath writable_dir = create_temp_path(); /* Has trailing slash. */
171  const CatalogFilePath original_cdf_file = asset_library_root_ + "/blender_assets.cats.txt";
172  CatalogFilePath writable_cdf_file = writable_dir + AssetCatalogService::DEFAULT_CATALOG_FILENAME;
173  BLI_path_slash_native(writable_cdf_file.data());
174  ASSERT_EQ(0, BLI_copy(original_cdf_file.c_str(), writable_cdf_file.c_str()));
175 
177  AssetLibrary *const lib = service->get_asset_library_on_disk(writable_dir);
178 
179  EXPECT_FALSE(service->has_any_unsaved_catalogs())
180  << "Unchanged AssetLibrary should have no unsaved catalogs";
181 
182  AssetCatalogService *const cat_service = lib->catalog_service.get();
183  AssetCatalog *cat = cat_service->find_catalog(UUID_POSES_ELLIE);
184 
185  cat_service->tag_has_unsaved_changes(cat);
186 
187  EXPECT_TRUE(service->has_any_unsaved_catalogs())
188  << "Tagging as having unsaved changes of a single catalog service should result in unsaved "
189  "changes being reported.";
190  EXPECT_TRUE(cat->flags.has_unsaved_changes);
191 
192  cat_service->write_to_disk(writable_dir + "dummy_path.blend");
193  EXPECT_FALSE(service->has_any_unsaved_catalogs())
194  << "Written AssetCatalogService should have no unsaved catalogs";
195  EXPECT_FALSE(cat->flags.has_unsaved_changes);
196 }
197 
198 } // namespace blender::bke::tests
void BKE_tempdir_init(const char *userdir)
Definition: appdir.c:1133
void BKE_callback_global_finalize(void)
Definition: callbacks.c:105
void BKE_callback_global_init(void)
Definition: callbacks.c:100
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
File and directory operations.
int BLI_delete(const char *file, bool dir, bool recursive) ATTR_NONNULL()
Definition: fileops.c:934
bool BLI_dir_create_recursive(const char *dir) ATTR_NONNULL()
Definition: fileops.c:1219
int BLI_copy(const char *file, const char *to) ATTR_NONNULL()
Definition: fileops.c:1198
#define PATH_MAX
Definition: BLI_fileops.h:29
#define ALTSEP
#define SEP
int BLI_path_slash_ensure(char *string) ATTR_NONNULL()
Definition: path_util.c:1780
void BLI_path_slash_native(char *path) ATTR_NONNULL()
Definition: path_util.c:1805
#define STRNCPY(dst, src)
Definition: BLI_string.h:483
#define ELEM(...)
void CLG_exit(void)
Definition: clog.c:703
void CLG_init(void)
Definition: clog.c:696
bool write_to_disk(const CatalogFilePath &blend_file_path)
void tag_has_unsaved_changes(AssetCatalog *edited_catalog)
AssetCatalog * find_catalog(CatalogID catalog_id) const
static const CatalogFilePath DEFAULT_CATALOG_FILENAME
struct blender::bke::AssetCatalog::Flags flags
static AssetLibraryService * get()
AssetLibrary * get_asset_library_on_disk(StringRefNull top_level_directory)
DRWShaderLibrary * lib
void * BKE_tempdir_session
const bUUID UUID_POSES_ELLIE("df60e1f6-2259-475b-93d9-69a1b4a8db78")
TEST_F(BKE_armature_find_selected_bones_test, some_bones_selected)
const bUUID UUID_POSES_RUZENA("79a4f887-ab60-4bd4-94da-d572e27d6aed")
std::string CatalogFilePath
Universally Unique Identifier according to RFC4122.