tornavis/source/blender/asset_system/tests/asset_library_service_test.cc

244 lines
9.1 KiB
C++

/* SPDX-FileCopyrightText: 2020 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "asset_library_service.hh"
#include "BLI_fileops.h" /* For PATH_MAX (at least on Windows). */
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BKE_appdir.hh"
#include "BKE_callbacks.hh"
#include "BKE_main.hh"
#include "DNA_asset_types.h"
#include "CLG_log.h"
#include "testing/testing.h"
namespace blender::asset_system::tests {
const bUUID UUID_POSES_ELLIE("df60e1f6-2259-475b-93d9-69a1b4a8db78");
class AssetLibraryServiceTest : public testing::Test {
public:
CatalogFilePath asset_library_root_;
CatalogFilePath temp_library_path_;
static void SetUpTestSuite()
{
CLG_init();
BKE_callback_global_init();
}
static void TearDownTestSuite()
{
CLG_exit();
BKE_callback_global_finalize();
}
void SetUp() override
{
const std::string test_files_dir = blender::tests::flags_test_asset_dir();
if (test_files_dir.empty()) {
FAIL();
}
asset_library_root_ = test_files_dir + SEP_STR + "asset_library";
temp_library_path_ = "";
}
void TearDown() override
{
AssetLibraryService::destroy();
if (!temp_library_path_.empty()) {
BLI_delete(temp_library_path_.c_str(), true, true);
temp_library_path_ = "";
}
}
/* Register a temporary path, which will be removed at the end of the test.
* The returned path ends in a slash. */
CatalogFilePath use_temp_path()
{
BKE_tempdir_init(nullptr);
const CatalogFilePath tempdir = BKE_tempdir_session();
temp_library_path_ = tempdir + "test-temporary-path" + SEP_STR;
return temp_library_path_;
}
CatalogFilePath create_temp_path()
{
CatalogFilePath path = use_temp_path();
BLI_dir_create_recursive(path.c_str());
return path;
}
};
TEST_F(AssetLibraryServiceTest, get_destroy)
{
AssetLibraryService *const service = AssetLibraryService::get();
EXPECT_EQ(service, AssetLibraryService::get())
<< "Calling twice without destroying in between should return the same instance.";
/* This should not crash. */
AssetLibraryService::destroy();
AssetLibraryService::destroy();
/* NOTE: there used to be a test for the opposite here, that after a call to
* AssetLibraryService::destroy() the above calls should return freshly allocated objects. This
* cannot be reliably tested by just pointer comparison, though. */
}
TEST_F(AssetLibraryServiceTest, library_pointers)
{
AssetLibraryService *service = AssetLibraryService::get();
AssetLibrary *const lib = service->get_asset_library_on_disk_custom(__func__,
asset_library_root_);
AssetLibrary *const curfile_lib = service->get_asset_library_current_file();
EXPECT_EQ(lib, service->get_asset_library_on_disk_custom(__func__, asset_library_root_))
<< "Calling twice without destroying in between should return the same instance.";
EXPECT_EQ(curfile_lib, service->get_asset_library_current_file())
<< "Calling twice without destroying in between should return the same instance.";
/* NOTE: there used to be a test for the opposite here, that after a call to
* AssetLibraryService::destroy() the above calls should return freshly allocated objects. This
* cannot be reliably tested by just pointer comparison, though. */
}
TEST_F(AssetLibraryServiceTest, library_from_reference)
{
AssetLibraryService *service = AssetLibraryService::get();
AssetLibrary *const curfile_lib = service->get_asset_library_current_file();
AssetLibraryReference ref{};
ref.type = ASSET_LIBRARY_LOCAL;
EXPECT_EQ(curfile_lib, service->get_asset_library(nullptr, ref))
<< "Getting the local (current file) reference without a main saved on disk should return "
"the current file library";
{
Main dummy_main{};
std::string dummy_filepath = asset_library_root_ + SEP + "dummy.blend";
STRNCPY(dummy_main.filepath, dummy_filepath.c_str());
AssetLibrary *custom_lib = service->get_asset_library_on_disk_custom(__func__,
asset_library_root_);
AssetLibrary *tmp_curfile_lib = service->get_asset_library(&dummy_main, ref);
/* Requested a current file library with a (fake) file saved in the same directory as a custom
* asset library. The resulting library should never match the custom asset library, even
* though the paths match. */
EXPECT_NE(custom_lib, tmp_curfile_lib)
<< "Getting an asset library from a local (current file) library reference should never "
"match any custom asset library";
EXPECT_EQ(custom_lib->root_path(), tmp_curfile_lib->root_path());
}
}
TEST_F(AssetLibraryServiceTest, library_path_trailing_slashes)
{
AssetLibraryService *service = AssetLibraryService::get();
char asset_lib_no_slash[PATH_MAX];
char asset_lib_with_slash[PATH_MAX];
STRNCPY(asset_lib_no_slash, asset_library_root_.c_str());
STRNCPY(asset_lib_with_slash, asset_library_root_.c_str());
/* Ensure #asset_lib_no_slash has no trailing slash, regardless of what was passed on the CLI to
* the unit test. */
while (strlen(asset_lib_no_slash) &&
ELEM(asset_lib_no_slash[strlen(asset_lib_no_slash) - 1], SEP, ALTSEP))
{
asset_lib_no_slash[strlen(asset_lib_no_slash) - 1] = '\0';
}
BLI_path_slash_ensure(asset_lib_with_slash, PATH_MAX);
AssetLibrary *const lib_no_slash = service->get_asset_library_on_disk_custom(__func__,
asset_lib_no_slash);
EXPECT_EQ(lib_no_slash,
service->get_asset_library_on_disk_custom(__func__, asset_lib_with_slash))
<< "With or without trailing slash shouldn't matter.";
}
TEST_F(AssetLibraryServiceTest, catalogs_loaded)
{
AssetLibraryService *const service = AssetLibraryService::get();
AssetLibrary *const lib = service->get_asset_library_on_disk_custom(__func__,
asset_library_root_);
AssetCatalogService &cat_service = lib->catalog_service();
const bUUID UUID_POSES_ELLIE("df60e1f6-2259-475b-93d9-69a1b4a8db78");
EXPECT_NE(nullptr, cat_service.find_catalog(UUID_POSES_ELLIE))
<< "Catalogs should be loaded after getting an asset library from disk.";
}
TEST_F(AssetLibraryServiceTest, has_any_unsaved_catalogs)
{
AssetLibraryService *const service = AssetLibraryService::get();
EXPECT_FALSE(service->has_any_unsaved_catalogs())
<< "Empty AssetLibraryService should have no unsaved catalogs";
AssetLibrary *const lib = service->get_asset_library_on_disk_custom(__func__,
asset_library_root_);
AssetCatalogService &cat_service = lib->catalog_service();
EXPECT_FALSE(service->has_any_unsaved_catalogs())
<< "Unchanged AssetLibrary should have no unsaved catalogs";
const bUUID UUID_POSES_ELLIE("df60e1f6-2259-475b-93d9-69a1b4a8db78");
cat_service.prune_catalogs_by_id(UUID_POSES_ELLIE);
EXPECT_FALSE(service->has_any_unsaved_catalogs())
<< "Deletion of catalogs via AssetCatalogService should not automatically tag as 'unsaved "
"changes'.";
const bUUID UUID_POSES_RUZENA("79a4f887-ab60-4bd4-94da-d572e27d6aed");
AssetCatalog *cat = cat_service.find_catalog(UUID_POSES_RUZENA);
ASSERT_NE(nullptr, cat) << "Catalog " << UUID_POSES_RUZENA << " should be known";
cat_service.tag_has_unsaved_changes(cat);
EXPECT_TRUE(service->has_any_unsaved_catalogs())
<< "Tagging as having unsaved changes of a single catalog service should result in unsaved "
"changes being reported.";
EXPECT_TRUE(cat->flags.has_unsaved_changes);
}
TEST_F(AssetLibraryServiceTest, has_any_unsaved_catalogs_after_write)
{
const CatalogFilePath writable_dir = create_temp_path(); /* Has trailing slash. */
const CatalogFilePath original_cdf_file = asset_library_root_ + SEP_STR +
"blender_assets.cats.txt";
CatalogFilePath writable_cdf_file = writable_dir + AssetCatalogService::DEFAULT_CATALOG_FILENAME;
BLI_path_slash_native(writable_cdf_file.data());
ASSERT_EQ(0, BLI_copy(original_cdf_file.c_str(), writable_cdf_file.c_str()));
AssetLibraryService *const service = AssetLibraryService::get();
AssetLibrary *const lib = service->get_asset_library_on_disk_custom(__func__, writable_dir);
EXPECT_FALSE(service->has_any_unsaved_catalogs())
<< "Unchanged AssetLibrary should have no unsaved catalogs";
AssetCatalogService &cat_service = lib->catalog_service();
AssetCatalog *cat = cat_service.find_catalog(UUID_POSES_ELLIE);
cat_service.tag_has_unsaved_changes(cat);
EXPECT_TRUE(service->has_any_unsaved_catalogs())
<< "Tagging as having unsaved changes of a single catalog service should result in unsaved "
"changes being reported.";
EXPECT_TRUE(cat->flags.has_unsaved_changes);
cat_service.write_to_disk(writable_dir + "dummy_path.blend");
EXPECT_FALSE(service->has_any_unsaved_catalogs())
<< "Written AssetCatalogService should have no unsaved catalogs";
EXPECT_FALSE(cat->flags.has_unsaved_changes);
}
} // namespace blender::asset_system::tests