18#include "testing/testing.h"
73 if (catalog_uptr->path == path) {
88 "blender_assets.cats.txt";
100 &
U,
"Test", registered_asset_lib.c_str());
101 ASSERT_NE(
nullptr, asset_lib_pref);
104 if (should_top_level_cdf_exist) {
105 ASSERT_EQ(0,
BLI_copy(original_cdf_file.c_str(), cdf_toplevel.c_str()));
115 const CatalogFilePath blendfilename = asset_lib_subdir +
"some_file.blend";
122 EXPECT_TRUE(
BLI_exists(cdf_toplevel.c_str()));
124 const bool backup_exists =
BLI_exists(backup_filename.c_str());
125 EXPECT_EQ(should_top_level_cdf_exist, backup_exists)
126 <<
"Overwritten CDF should have been backed up.";
130 std::string native_cdf_path = cdf->
file_path;
132 EXPECT_EQ(cdf_toplevel, native_cdf_path);
142 if (should_top_level_cdf_exist) {
143 EXPECT_NE(
nullptr, poses_ellie_catalog);
166 ASSERT_EQ(
nullptr, cat_without_path);
170 ASSERT_NE(
nullptr, poses_ellie);
177 ASSERT_NE(
nullptr, poses_whitespace);
179 EXPECT_EQ(
"character/Ellie/poselib/white space", poses_whitespace->
path.
str());
184 ASSERT_NE(
nullptr, poses_ruzena);
191 ASSERT_NE(
nullptr, another_ruzena);
203 ASSERT_NE(
nullptr, found_by_id);
205 <<
"Backslashes should be normalized when loading from disk.";
210 <<
"Catalog with backslashed path should be findable by the normalized path.";
213 <<
"Nothing should be found when searching for backslashes.";
223 <<
"Adding a catalog at runtime should never mark it as 'first loaded'; "
224 "only loading from disk is allowed to do that.";
228 <<
"Adding a new catalog with an already-loaded path should not mark it as 'first loaded'";
237 <<
"The first-seen definition of a catalog should be returned";
250 EXPECT_NE(
nullptr, catalog);
253 EXPECT_NE(
nullptr, catalog);
258 EXPECT_NE(
nullptr, catalog);
298 const CatalogFilePath save_to_path = use_temp_path() +
"новый.cats.txt";
300 ASSERT_NE(
nullptr, cdf) <<
"unable to load " << load_from_path;
307 const bUUID materials_uuid(
"a2151dff-dead-4f29-b6bc-b2c7d6cccdb4");
309 ASSERT_NE(
nullptr, cat);
323 EXPECT_FALSE(
BLI_exists(default_cdf_path.c_str()));
333 "blender_assets.cats.txt";
337 ASSERT_EQ(0,
BLI_copy(original_cdf_file.c_str(), cdf_filename.c_str()))
338 <<
"Unable to copy " << original_cdf_file <<
" to " << cdf_filename;
351 EXPECT_TRUE(
BLI_exists(cdf_filename.c_str()));
352 EXPECT_TRUE(
BLI_exists(backup_filename.c_str()))
353 <<
"Overwritten CDF should have been backed up.";
359 <<
"Expected to see the newly-created catalog.";
361 <<
"Expected to see the already-existing catalog.";
378 EXPECT_TRUE(
BLI_exists(expected_cdf_path.c_str()));
382 ASSERT_NE(
nullptr, cdf);
396 "blender_assets.cats.txt";
399 ASSERT_EQ(0,
BLI_copy(original_cdf_file.c_str(), writable_cdf_file.c_str()));
411 EXPECT_TRUE(
BLI_exists(writable_cdf_file.c_str()));
412 EXPECT_TRUE(
BLI_exists(backup_filename.c_str()))
413 <<
"Overwritten CDF should have been backed up.";
417 ASSERT_NE(
nullptr, cdf);
431 on_blendfile_save__from_memory_into_existing_asset_lib_without_top_level_cdf)
433 save_from_memory_into_existing_asset_lib(
true);
441 save_from_memory_into_existing_asset_lib(
false);
451 EXPECT_FALSE(
BLI_exists(temp_lib_root.c_str()));
454 ASSERT_NE(
nullptr, cat);
459 EXPECT_FALSE(
BLI_exists(temp_lib_root.c_str()));
463 EXPECT_TRUE(
BLI_is_dir(temp_lib_root.c_str()));
467 EXPECT_TRUE(
BLI_is_file(definition_file_path.c_str()));
474 ASSERT_NE(
nullptr, written_cat);
489 ASSERT_EQ(0,
BLI_copy(default_catalog_path.c_str(), writable_catalog_path.c_str()));
490 EXPECT_TRUE(
BLI_is_dir(temp_lib_root.c_str()));
491 EXPECT_TRUE(
BLI_is_file(writable_catalog_path.c_str()));
508 <<
"expected pre-existing catalogs to be kept in the file";
510 <<
"expecting newly added catalog to not yet be saved to " << temp_lib_root;
517 <<
"expected pre-existing catalogs to be kept in the file";
518 EXPECT_NE(
nullptr, reloaded_service.
find_catalog(new_catalog_id))
519 <<
"expecting newly added catalog to exist in the file";
536 "production/Spite Fright/Characters/Victora/Pose Library/Approved/Body Parts/Hands");
539 EXPECT_EQ(
"production/Spite Fright/Characters/Victora/Pose Library/Approved/Body Parts/Hands",
556 std::vector<AssetCatalogPath> expected_paths{
559 "character/Ellie/backslashes",
560 "character/Ellie/poselib",
561 "character/Ellie/poselib/tailslash",
562 "character/Ellie/poselib/white space",
564 "character/Ružena/poselib",
565 "character/Ružena/poselib/face",
569 "path/without/simplename",
613 std::vector<AssetCatalogPath> expected_paths{
616 "character/Ellie/backslashes",
617 "character/Ellie/poselib",
618 "character/Ellie/poselib/tailslash",
619 "character/Ellie/poselib/white space",
623 "path/without/simplename",
666 <<
"The original (pre-rename) path should not be associated with a catalog any more.";
669 ASSERT_NE(
nullptr, renamed_cat);
670 ASSERT_EQ(orig_cat, renamed_cat) <<
"Changing the path should not reallocate the catalog.";
672 <<
"Changing the path should not change the catalog ID.";
675 <<
"Changing the path should change the path. Surprise.";
678 <<
"Changing the path should update children.";
680 <<
"Changing the path should update children.";
694 <<
"Changing the path should update the simplename.";
696 <<
"Changing the path should update the simplename of children.";
704 const std::string new_path =
705 "this/is/a/very/long/path/that/exceeds/the/simple-name/length/of/assets";
707 <<
"This test case should work with paths longer than AssetMetaData::catalog_simple_name";
713 <<
"The new simple name should fit in the asset metadata.";
714 EXPECT_EQ(
"...very-long-path-that-exceeds-the-simple-name-length-of-assets", new_simple_name)
715 <<
"Changing the path should update the simplename.";
716 EXPECT_EQ(
"...long-path-that-exceeds-the-simple-name-length-of-assets-face",
718 <<
"Changing the path should update the simplename of children.";
735 <<
"The original (pre-rename) path should not be associated with a catalog any more.";
738 ASSERT_NE(
nullptr, renamed_cat);
740 <<
"Changing the path should not change the catalog ID.";
743 <<
"When creating a new catalog by renaming + adding a slash, the renamed catalog should be "
744 "assigned the path passed to update_catalog_path()";
748 ASSERT_NE(
nullptr, new_cat) <<
"Renaming to .../X/Y should cause .../X to exist as well.";
754 EXPECT_EQ(
"character/Ružena/poses/general/hand",
756 <<
"Changing the path should update children.";
757 EXPECT_EQ(
"character/Ružena/poses/general/face",
759 <<
"Changing the path should update children.";
766 "blender_assets.cats.txt";
768 "modified_assets.cats.txt";
769 const CatalogFilePath temp_cdf_file = cdf_dir +
"blender_assets.cats.txt";
770 ASSERT_EQ(0,
BLI_copy(original_cdf_file.c_str(), temp_cdf_file.c_str()));
778 ASSERT_EQ(0,
BLI_copy(modified_cdf_file.c_str(), temp_cdf_file.c_str()));
808 "blender_assets.cats.txt";
810 "catalog_reload_test.cats.txt";
811 const CatalogFilePath temp_cdf_file = cdf_dir +
"blender_assets.cats.txt";
812 ASSERT_EQ(0,
BLI_copy(original_cdf_file.c_str(), temp_cdf_file.c_str()));
828 ASSERT_EQ(0,
BLI_copy(modified_cdf_file.c_str(), temp_cdf_file.c_str()));
850 EXPECT_NE(ellie_whitespace_after_reload, ellie_whitespace_before_reload);
852 EXPECT_EQ(std::string(
"Hah simple name after all"),
873 <<
"The catalogs whose path we changed should now be saved";
875 <<
"Deleted catalogs should not be remembered after saving.";
882 "blender_assets.cats.txt";
884 ASSERT_EQ(0,
BLI_copy(original_cdf_file.c_str(), writable_cdf_file.c_str()));
910 const bUUID cat2_uuid(
"22222222-b847-44d9-bdca-ff04db1c24f5");
911 const bUUID cat4_uuid(
"11111111-b847-44d9-bdca-ff04db1c24f5");
916 cat4_uuid,
"simple/path",
"different ID, same path");
917 const AssetCatalog cat5(cat4_uuid,
"simple/path",
"same ID, same path");
920 by_path.insert(&cat1);
921 by_path.insert(&cat2);
922 by_path.insert(&cat3);
923 by_path.insert(&cat4);
924 by_path.insert(&cat5);
926 AssetCatalogOrderedSet::const_iterator set_iter = by_path.begin();
932 ASSERT_EQ(4, by_path.size()) <<
"Expecting cat5 to not be stored in the set, as it duplicates "
933 "an already-existing path + UUID";
940 if (set_iter != by_path.end()) {
942 FAIL() <<
"Did not expect more items in the set, had at least " << next_cat->
catalog_id <<
":"
952 const bUUID first_seen_uuid(
"3d451c87-27d1-40fd-87fc-f4c9e829c848");
953 const bUUID first_sorted_uuid(
"00000000-0000-0000-0000-000000000001");
954 const bUUID last_sorted_uuid(
"ffffffff-ffff-ffff-ffff-ffffffffffff");
956 AssetCatalog first_seen_cat(first_seen_uuid,
"simple/path/child",
"");
957 const AssetCatalog first_sorted_cat(first_sorted_uuid,
"simple/path/child",
"");
958 const AssetCatalog last_sorted_cat(last_sorted_uuid,
"simple/path/child",
"");
969 by_path.insert(&first_seen_cat);
970 by_path.insert(&first_sorted_cat);
971 by_path.insert(&last_sorted_cat);
973 AssetCatalogOrderedSet::const_iterator set_iter = by_path.begin();
975 EXPECT_EQ(1, by_path.count(&first_seen_cat));
976 EXPECT_EQ(1, by_path.count(&first_sorted_cat));
977 EXPECT_EQ(1, by_path.count(&last_sorted_cat));
978 ASSERT_EQ(3, by_path.size());
980 EXPECT_EQ(first_seen_uuid, (*(set_iter++))->catalog_id);
981 EXPECT_EQ(first_sorted_uuid, (*(set_iter++))->catalog_id);
982 EXPECT_EQ(last_sorted_uuid, (*(set_iter++))->catalog_id);
984 if (set_iter != by_path.end()) {
986 FAIL() <<
"Did not expect more items in the set, had at least " << next_cat->
catalog_id <<
":"
997 <<
"Missing parents should not be immediately created.";
1006 <<
"Empty path should never be valid, even when after missing catalogs";
1017 ASSERT_NE(
nullptr, cat_char) <<
"Missing parents should be created immediately after loading.";
1018 ASSERT_NE(
nullptr, cat_ellie) <<
"Missing parents should be created immediately after loading.";
1019 ASSERT_NE(
nullptr, cat_ruzena) <<
"Missing parents should be created immediately after loading.";
1022 <<
"Missing parents should be marked as having changes.";
1024 <<
"Missing parents should be marked as having changes.";
1026 <<
"Missing parents should be marked as having changes.";
1029 ASSERT_NE(
nullptr, cdf);
1030 EXPECT_TRUE(cdf->
contains(cat_char->
catalog_id)) <<
"Missing parents should be saved to a CDF.";
1031 EXPECT_TRUE(cdf->
contains(cat_ellie->
catalog_id)) <<
"Missing parents should be saved to a CDF.";
1033 <<
"Missing parents should be saved to a CDF.";
1056 <<
"Main catalog should be included in the filter.";
1058 <<
"Sub-catalog should be included in the filter.";
1060 <<
"Sub-catalog should be included in the filter.";
1063 EXPECT_TRUE(filter.contains(alias_ruzena->
catalog_id))
1064 <<
"Alias of main catalog should be included in the filter.";
1065 EXPECT_TRUE(filter.contains(alias_ruzena_hand->
catalog_id))
1066 <<
"Alias of sub-catalog should be included in the filter.";
1069 EXPECT_FALSE(filter.contains(
BLI_uuid_nil())) <<
"Nil catalog should not be included.";
1083 EXPECT_TRUE(filter.contains(unknown_uuid));
1085 EXPECT_FALSE(filter.contains(
BLI_uuid_nil())) <<
"Nil catalog should not be included.";
1102 EXPECT_NE(&empty,
copy.get());
1129 auto cat1 = std::make_unique<AssetCatalog>(
UUID_POSES_RUZENA,
"poses/Henrik",
"");
1132 cat3->flags.is_deleted =
true;
1142 EXPECT_NE(&catcoll,
copy.get());
1157 <<
"AssetCatalogs should be actual copies.";
1161 <<
"AssetCatalogs should be actual copies.";
1175 auto cat1 = std::make_unique<AssetCatalog>(
UUID_POSES_RUZENA,
"poses/Henrik",
"");
1178 cat3->flags.is_deleted =
true;
1189 "path/to/somewhere.cats.txt");
1203 <<
"AssetCatalog pointers should have been remapped to the copy.";
1207 <<
"Deleted AssetCatalog pointers should have been remapped to the copy.";
1220 <<
"Undo steps should be created explicitly, and not after creating any catalog.";
1225 <<
"Undo should be possible after creating an undo snapshot.";
1230 <<
"Undoing the only stored step should make it impossible to undo further.";
1231 EXPECT_TRUE(service.
is_redo_possbile()) <<
"Undoing a step should make redo possible.";
1233 <<
"Undone catalog should not exist after undo.";
1235 <<
"First catalog should still exist after undo.";
1237 <<
"The CDF should also not contain the undone catalog.";
1242 <<
"Undoing and then redoing a step should make it possible to undo again.";
1244 <<
"Undoing and then redoing a step should make redo impossible.";
1246 <<
"Redone catalog should exist after redo.";
1248 <<
"First catalog should still exist after redo.";
1250 <<
"The CDF should contain the redone catalog.";
1271 <<
"After storing an undo snapshot, the redo buffer should be empty.";
1273 <<
"After storing an undo snapshot, undoing should be possible";
1277 "POSES_ELLIE WHITESPACE");
struct bUserAssetLibrary * BKE_preferences_asset_library_add(struct UserDef *userdef, const char *name, const char *dirpath) ATTR_NONNULL(1)
void BKE_preferences_asset_library_remove(struct UserDef *userdef, struct bUserAssetLibrary *library) ATTR_NONNULL()
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
File and directory operations.
bool BLI_file_touch(const char *filepath) ATTR_NONNULL(1)
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
int BLI_copy(const char *path_src, const char *path_dst) ATTR_NONNULL()
bool BLI_dir_create_recursive(const char *dirname) ATTR_NONNULL()
bool BLI_is_file(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
size_t BLI_file_size(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
bool BLI_is_dir(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void BLI_path_slash_native(char *path) ATTR_NONNULL(1)
bool BLI_uuid_is_nil(bUUID uuid)
bUUID BLI_uuid_generate_random(void)
const Value & lookup(const Key &key) const
ValueIterator values() const
void add_new(const Key &key, const Value &value)
bool contains(const Key &key) const
OwningAssetCatalogMap catalogs_
std::unique_ptr< AssetCatalogDefinitionFile > catalog_definition_file_
OwningAssetCatalogMap deleted_catalogs_
std::unique_ptr< AssetCatalogCollection > deep_copy() const
Map< CatalogID, AssetCatalog * > catalogs_
void add_new(AssetCatalog *catalog)
bool contains(CatalogID catalog_id) const
const CatalogFilePath file_path
bool write_to_disk() const
const std::string & str() const
bool is_undo_possbile() const
void delete_catalog_by_id_soft(CatalogID catalog_id)
AssetCatalogFilter create_catalog_filter(CatalogID active_catalog_id) const
AssetCatalog * find_catalog_by_path(const AssetCatalogPath &path) const
AssetCatalog * find_catalog(CatalogID catalog_id) const
void prune_catalogs_by_path(const AssetCatalogPath &path)
bool write_to_disk(const CatalogFilePath &blend_file_path)
void create_missing_catalogs()
AssetCatalog * create_catalog(const AssetCatalogPath &catalog_path)
void update_catalog_path(CatalogID catalog_id, const AssetCatalogPath &new_catalog_path)
void prune_catalogs_by_id(CatalogID catalog_id)
bool is_redo_possbile() const
const OwningAssetCatalogMap & get_deleted_catalogs() const
static const CatalogFilePath DEFAULT_CATALOG_FILENAME
void tag_has_unsaved_changes(AssetCatalog *edited_catalog)
const AssetCatalogDefinitionFile * get_catalog_definition_file() const
const AssetCatalogTree & catalog_tree()
const OwningAssetCatalogMap & get_catalogs() const
const CatalogID catalog_id
struct blender::asset_system::AssetCatalog::Flags flags
void save_from_memory_into_existing_asset_lib(const bool should_top_level_cdf_exist)
static void expect_tree_items(const AssetCatalogTree &tree, const std::vector< AssetCatalogPath > &expected_paths)
std::string asset_library_root_
std::string create_temp_path()
AssetCatalogDefinitionFile * allocate_catalog_definition_file(StringRef file_path)
OwningAssetCatalogMap & get_catalogs()
OwningAssetCatalogMap & get_deleted_catalogs()
AssetCatalogDefinitionFile * get_catalog_definition_file()
Map< CatalogID, AssetCatalog * > get_catalogs()
TestableAssetCatalogService()=default
const OwningAssetCatalogMap & get_deleted_catalogs() const
void create_missing_catalogs()
TestableAssetCatalogService(const CatalogFilePath &asset_library_root)
void delete_catalog_by_id_soft(CatalogID catalog_id)
const AssetCatalogDefinitionFile * get_catalog_definition_file()
int64_t count_catalogs_with_path(const CatalogFilePath &path)
const bUUID UUID_POSES_RUZENA_HAND("81811c31-1a88-4bd7-bb34-c6fc2607a12e")
TEST_F(AssetCatalogTest, load_single_file)
const bUUID UUID_ANOTHER_RUZENA("00000000-d9fa-4b91-b704-e6af1f1339ef")
const bUUID UUID_POSES_RUZENA_FACE("82162c1f-06cc-4d91-a9bf-4f72c104e348")
const bUUID UUID_POSES_ELLIE_TRAILING_SLASH("3376b94b-a28d-4d05-86c1-bf30b937130d")
const bUUID UUID_POSES_ELLIE_BACKSLASHES("a51e17ae-34fc-47d5-ba0f-64c2c9b771f7")
const bUUID UUID_POSES_ELLIE("df60e1f6-2259-475b-93d9-69a1b4a8db78")
const bUUID UUID_WITHOUT_SIMPLENAME("d7916a31-6ca9-4909-955f-182ca2b81fa3")
const bUUID UUID_POSES_RUZENA("79a4f887-ab60-4bd4-94da-d572e27d6aed")
const bUUID UUID_POSES_ELLIE_WHITESPACE("b06132f6-5687-4751-a6dd-392740eb3c46")
const bUUID UUID_ID_WITHOUT_PATH("e34dd2c5-5d2e-4668-9794-1db5de2a4f71")
const bUUID UUID_AGENT_47("c5744ba5-43f5-4f73-8e52-010ad4a61b34")
std::set< const AssetCatalog *, AssetCatalogLessThan > AssetCatalogOrderedSet
std::string CatalogFilePath
static void copy(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node)
Universally Unique Identifier according to RFC4122.