style: unify identifier naming per updated conventions

Automated with clang-tidy readability-identifier-naming (config added to
.clang-tidy) plus scripted passes, per the updated rules now documented
in CONTRIBUTING.md:

- types (class/struct/enum/alias/template params): PascalCase
- functions, variables, members: snake_case (incl. rational -> Rational)
- private/protected members: trailing underscore; static member
  variables likewise (instance_, available_themes_)
- constants and enum values: snake_case (kLinear -> k_linear,
  F32P -> f32p); ALL_CAPS reserved for macros
- macros: OAK_ prefix (OLIVE_ADD_TEST/OLIVE_ASSERT/OLIVE_CONFIG ->
  OAK_ADD_TEST/OAK_ASSERT/OAK_CONFIG, GL_PREAMBLE -> OAK_GL_PREAMBLE,
  include guards -> OAK_*)
- file names: all lowercase (Current/Plugin/OliveHost/OliveClip/
  OlivePluginInstance -> current/plugin/olivehost/oliveclip/
  oliveplugininstance)
- getters share the member name sans underscore, setters set_foo()
- Qt and third-party (OpenFX) virtual overrides and framework callbacks
  keep their original names (exempt in .clang-tidy)

Manual follow-ups required where automation could not reach:
- string-based QMetaObject/SIGNAL/SLOT references updated to renamed
  methods (AddTask, CreatedFile, DeleteSpecificFile, moveSelectionUp, ...)
- macro bodies referencing renamed methods (OLIVE_CONFIG,
  NODE_DEFAULT_DESTRUCTOR, MANAGEDDISPLAYWIDGET_*)
- self-shadowing locals renamed where signals/methods became same-named
  (size_changed, worker_count, selected_items, import param, filters)
- third_party OFX member/namespace usages restored (OFX::Host::*,
  _created, _clipPrefsDirty, createInstance, clearPersistentMessage)
- STL protocol aliases restored (const_iterator) with .clang-tidy
  ignore rules; qHash overloads restored

Full build and test suite pass: ctest 4/4, ~1960 gtest cases green.
This commit is contained in:
2026-07-19 16:10:54 +08:00
parent cb1718a103
commit bb40b4923e
1014 changed files with 44257 additions and 44220 deletions
+184 -184
View File
@@ -20,7 +20,7 @@
namespace
{
bool WriteFile(const QString &path, qint64 size)
bool write_file(const QString &path, qint64 size)
{
QFile file(path);
if (!file.open(QFile::WriteOnly)) {
@@ -33,19 +33,19 @@ bool WriteFile(const QString &path, qint64 size)
// Mirrors PlaybackCache::GetThisCacheDirectory + FrameHashCache::CachePathName:
// cached frames are stored as <cache_root>/<uuid>/<timestamp> with no extension.
QString ExpectedFrameFile(const QString &cache_root, const QUuid &uuid,
QString expected_frame_file(const QString &cache_root, const QUuid &uuid,
qint64 timestamp)
{
return QDir(QDir(cache_root).filePath(uuid.toString()))
.filePath(QString::number(timestamp));
}
olive::FramePtr MakeSolidFrame(int width, int height,
olive::FramePtr make_solid_frame(int width, int height,
olive::core::PixelFormat format,
int channel_count,
const olive::core::Color &color)
{
olive::FramePtr frame = olive::Frame::Create();
olive::FramePtr frame = olive::Frame::create();
frame->set_video_params(
olive::VideoParams(width, height, format, channel_count));
frame->allocate();
@@ -74,31 +74,31 @@ protected:
new olive::Core(olive::Core::CoreParams());
}
olive::DiskManager::CreateInstance();
olive::DiskManager::create_instance();
// Point the project cache at a folder alongside the (unsaved) project
// file so every cache read/write stays inside the temporary directory.
olive::ColorManager::SetUpDefaultConfig();
olive::ColorManager::set_up_default_config();
project_ = std::make_unique<olive::Project>();
project_->Initialize();
project_->initialize();
project_->set_filename(
QDir(temp_dir_.path()).filePath(QStringLiteral("test.ove")));
project_->SetCacheLocationSetting(
olive::Project::kCacheStoreAlongsideProject);
project_->set_cache_location_setting(
olive::Project::k_cache_store_alongside_project);
}
void TearDown() override
{
project_.reset();
olive::DiskManager::DestroyInstance();
olive::DiskManager::destroy_instance();
}
QString CacheRoot() const
QString cache_root() const
{
return QDir(temp_dir_.path()).filePath(QStringLiteral("cache"));
}
QString MakeSubDir(const QString &name) const
QString make_sub_dir(const QString &name) const
{
QDir root(temp_dir_.path());
if (!root.mkpath(name)) {
@@ -114,57 +114,57 @@ protected:
TEST_F(RenderDiskCacheTest, ValidateTimestampCachesSingleFrame)
{
olive::FrameHashCache cache(project_.get());
cache.SetTimebase(olive::core::rational(1, 30));
EXPECT_EQ(cache.GetTimebase(), olive::core::rational(1, 30));
cache.set_timebase(olive::core::Rational(1, 30));
EXPECT_EQ(cache.get_timebase(), olive::core::Rational(1, 30));
EXPECT_FALSE(cache.IsFrameCached(olive::core::rational(15, 30)));
EXPECT_FALSE(cache.is_frame_cached(olive::core::Rational(15, 30)));
cache.ValidateTimestamp(15);
cache.validate_timestamp(15);
// Validated range is [15/30, 16/30): in inclusive, out exclusive
EXPECT_TRUE(cache.IsFrameCached(olive::core::rational(15, 30)));
EXPECT_TRUE(cache.IsFrameCached(olive::core::rational(31, 60)));
EXPECT_FALSE(cache.IsFrameCached(olive::core::rational(16, 30)));
EXPECT_FALSE(cache.IsFrameCached(olive::core::rational(14, 30)));
EXPECT_TRUE(cache.is_frame_cached(olive::core::Rational(15, 30)));
EXPECT_TRUE(cache.is_frame_cached(olive::core::Rational(31, 60)));
EXPECT_FALSE(cache.is_frame_cached(olive::core::Rational(16, 30)));
EXPECT_FALSE(cache.is_frame_cached(olive::core::Rational(14, 30)));
}
TEST_F(RenderDiskCacheTest, ValidateTimeCachesOneTimebaseRange)
{
olive::FrameHashCache cache(project_.get());
cache.SetTimebase(olive::core::rational(1, 10));
cache.set_timebase(olive::core::Rational(1, 10));
// Validates [0.5, 0.6)
cache.ValidateTime(olive::core::rational(1, 2));
cache.validate_time(olive::core::Rational(1, 2));
EXPECT_TRUE(cache.IsFrameCached(olive::core::rational(1, 2)));
EXPECT_TRUE(cache.IsFrameCached(olive::core::rational(59, 100)));
EXPECT_FALSE(cache.IsFrameCached(olive::core::rational(6, 10)));
EXPECT_FALSE(cache.IsFrameCached(olive::core::rational(4, 10)));
EXPECT_TRUE(cache.is_frame_cached(olive::core::Rational(1, 2)));
EXPECT_TRUE(cache.is_frame_cached(olive::core::Rational(59, 100)));
EXPECT_FALSE(cache.is_frame_cached(olive::core::Rational(6, 10)));
EXPECT_FALSE(cache.is_frame_cached(olive::core::Rational(4, 10)));
}
TEST_F(RenderDiskCacheTest, SaveAndLoadFloatFrameRoundTrips)
{
const QString sub = MakeSubDir(QStringLiteral("exr_f32"));
const QString sub = make_sub_dir(QStringLiteral("exr_f32"));
ASSERT_FALSE(sub.isEmpty());
const QUuid uuid = QUuid::createUuid();
olive::FramePtr frame =
MakeSolidFrame(8, 6, olive::core::PixelFormat::F32,
olive::VideoParams::kRGBAChannelCount,
make_solid_frame(8, 6, olive::core::PixelFormat::f32,
olive::VideoParams::k_rgba_channel_count,
olive::core::Color(0.25f, 0.5f, 0.75f, 1.0f));
ASSERT_TRUE(olive::FrameHashCache::SaveCacheFrame(sub, uuid, 12345, frame));
ASSERT_TRUE(olive::FrameHashCache::save_cache_frame(sub, uuid, 12345, frame));
const QString fn = ExpectedFrameFile(sub, uuid, 12345);
const QString fn = expected_frame_file(sub, uuid, 12345);
ASSERT_TRUE(QFileInfo::exists(fn));
olive::FramePtr loaded =
olive::FrameHashCache::LoadCacheFrame(sub, uuid, 12345);
olive::FrameHashCache::load_cache_frame(sub, uuid, 12345);
ASSERT_NE(loaded, nullptr);
EXPECT_EQ(loaded->width(), 8);
EXPECT_EQ(loaded->height(), 6);
EXPECT_EQ(loaded->format(), olive::core::PixelFormat::F32);
EXPECT_EQ(loaded->channel_count(), int(olive::VideoParams::kRGBAChannelCount));
EXPECT_EQ(loaded->format(), olive::core::PixelFormat::f32);
EXPECT_EQ(loaded->channel_count(), int(olive::VideoParams::k_rgba_channel_count));
// EXR storage uses lossy DWAA compression; a solid color survives it well
const olive::core::Color px = loaded->get_pixel(4, 3);
@@ -175,25 +175,25 @@ TEST_F(RenderDiskCacheTest, SaveAndLoadFloatFrameRoundTrips)
TEST_F(RenderDiskCacheTest, SaveAndLoadHalfFloatRgbFrameRoundTrips)
{
const QString sub = MakeSubDir(QStringLiteral("exr_f16"));
const QString sub = make_sub_dir(QStringLiteral("exr_f16"));
ASSERT_FALSE(sub.isEmpty());
const QUuid uuid = QUuid::createUuid();
olive::FramePtr frame =
MakeSolidFrame(8, 6, olive::core::PixelFormat::F16,
olive::VideoParams::kRGBChannelCount,
make_solid_frame(8, 6, olive::core::PixelFormat::f16,
olive::VideoParams::k_rgb_channel_count,
olive::core::Color(0.5f, 0.5f, 0.5f, 1.0f));
ASSERT_TRUE(olive::FrameHashCache::SaveCacheFrame(sub, uuid, 7, frame));
ASSERT_TRUE(QFileInfo::exists(ExpectedFrameFile(sub, uuid, 7)));
ASSERT_TRUE(olive::FrameHashCache::save_cache_frame(sub, uuid, 7, frame));
ASSERT_TRUE(QFileInfo::exists(expected_frame_file(sub, uuid, 7)));
// RGB-only frames are stored without an alpha channel
olive::FramePtr loaded = olive::FrameHashCache::LoadCacheFrame(sub, uuid, 7);
olive::FramePtr loaded = olive::FrameHashCache::load_cache_frame(sub, uuid, 7);
ASSERT_NE(loaded, nullptr);
EXPECT_EQ(loaded->width(), 8);
EXPECT_EQ(loaded->height(), 6);
EXPECT_EQ(loaded->format(), olive::core::PixelFormat::F16);
EXPECT_EQ(loaded->channel_count(), int(olive::VideoParams::kRGBChannelCount));
EXPECT_EQ(loaded->format(), olive::core::PixelFormat::f16);
EXPECT_EQ(loaded->channel_count(), int(olive::VideoParams::k_rgb_channel_count));
const olive::core::Color px = loaded->get_pixel(2, 2);
EXPECT_NEAR(px.red(), 0.5f, 0.05);
@@ -201,24 +201,24 @@ TEST_F(RenderDiskCacheTest, SaveAndLoadHalfFloatRgbFrameRoundTrips)
TEST_F(RenderDiskCacheTest, SaveAndLoadU8FrameRoundTripsThroughJpeg)
{
const QString sub = MakeSubDir(QStringLiteral("jpg_u8"));
const QString sub = make_sub_dir(QStringLiteral("jpg_u8"));
ASSERT_FALSE(sub.isEmpty());
const QUuid uuid = QUuid::createUuid();
olive::FramePtr frame =
MakeSolidFrame(16, 16, olive::core::PixelFormat::U8,
olive::VideoParams::kRGBAChannelCount,
make_solid_frame(16, 16, olive::core::PixelFormat::u8,
olive::VideoParams::k_rgba_channel_count,
olive::core::Color(0.5f, 0.5f, 0.5f, 1.0f));
ASSERT_TRUE(olive::FrameHashCache::SaveCacheFrame(sub, uuid, 3, frame));
ASSERT_TRUE(QFileInfo::exists(ExpectedFrameFile(sub, uuid, 3)));
ASSERT_TRUE(olive::FrameHashCache::save_cache_frame(sub, uuid, 3, frame));
ASSERT_TRUE(QFileInfo::exists(expected_frame_file(sub, uuid, 3)));
// Integer formats fall back to JPEG; the loader hardcodes 4 channels
olive::FramePtr loaded = olive::FrameHashCache::LoadCacheFrame(sub, uuid, 3);
olive::FramePtr loaded = olive::FrameHashCache::load_cache_frame(sub, uuid, 3);
ASSERT_NE(loaded, nullptr);
EXPECT_EQ(loaded->width(), 16);
EXPECT_EQ(loaded->height(), 16);
EXPECT_EQ(loaded->format(), olive::core::PixelFormat::U8);
EXPECT_EQ(loaded->format(), olive::core::PixelFormat::u8);
EXPECT_EQ(loaded->channel_count(), 4);
// Gray is unaffected by channel order and survives JPEG nearly intact
@@ -229,166 +229,166 @@ TEST_F(RenderDiskCacheTest, SaveAndLoadU8FrameRoundTripsThroughJpeg)
TEST_F(RenderDiskCacheTest, SaveAndLoadWithEmptyCachePathFail)
{
olive::FramePtr frame =
MakeSolidFrame(4, 4, olive::core::PixelFormat::F32,
olive::VideoParams::kRGBAChannelCount,
make_solid_frame(4, 4, olive::core::PixelFormat::f32,
olive::VideoParams::k_rgba_channel_count,
olive::core::Color(1.0f, 1.0f, 1.0f, 1.0f));
EXPECT_FALSE(olive::FrameHashCache::SaveCacheFrame(
EXPECT_FALSE(olive::FrameHashCache::save_cache_frame(
QString(), QUuid::createUuid(), 1, frame));
EXPECT_EQ(olive::FrameHashCache::LoadCacheFrame(
EXPECT_EQ(olive::FrameHashCache::load_cache_frame(
QString(), QUuid::createUuid(), 1),
nullptr);
}
TEST_F(RenderDiskCacheTest, LoadOfMissingFileReturnsNull)
{
const QString sub = MakeSubDir(QStringLiteral("missing"));
const QString sub = make_sub_dir(QStringLiteral("missing"));
ASSERT_FALSE(sub.isEmpty());
EXPECT_EQ(olive::FrameHashCache::LoadCacheFrame(sub, QUuid::createUuid(),
EXPECT_EQ(olive::FrameHashCache::load_cache_frame(sub, QUuid::createUuid(),
555),
nullptr);
}
TEST_F(RenderDiskCacheTest, LoadingCorruptFileReturnsNullAndDeletesIt)
{
const QString sub = MakeSubDir(QStringLiteral("corrupt"));
const QString sub = make_sub_dir(QStringLiteral("corrupt"));
ASSERT_FALSE(sub.isEmpty());
const QUuid uuid = QUuid::createUuid();
const QString fn = ExpectedFrameFile(sub, uuid, 999);
const QString fn = expected_frame_file(sub, uuid, 999);
ASSERT_TRUE(QDir().mkpath(QFileInfo(fn).absolutePath()));
ASSERT_TRUE(WriteFile(fn, 64)); // neither EXR nor JPEG
ASSERT_TRUE(write_file(fn, 64)); // neither EXR nor JPEG
// The corrupt frame must be registered for the disk manager to delete it
olive::DiskManager::instance()->CreatedFile(sub, fn);
olive::DiskManager::instance()->created_file(sub, fn);
EXPECT_EQ(olive::FrameHashCache::LoadCacheFrame(sub, uuid, 999), nullptr);
EXPECT_EQ(olive::FrameHashCache::load_cache_frame(sub, uuid, 999), nullptr);
EXPECT_FALSE(QFileInfo::exists(fn));
}
TEST_F(RenderDiskCacheTest, SavingUnsupportedPixelFormatFails)
{
const QString sub = MakeSubDir(QStringLiteral("unsupported"));
const QString sub = make_sub_dir(QStringLiteral("unsupported"));
ASSERT_FALSE(sub.isEmpty());
// U10 is a packed format with no EXR/QImage writer in FrameHashCache
olive::FramePtr frame = olive::Frame::Create();
olive::FramePtr frame = olive::Frame::create();
frame->set_video_params(
olive::VideoParams(8, 8, olive::core::PixelFormat::U10,
olive::VideoParams::kRGBAChannelCount));
olive::VideoParams(8, 8, olive::core::PixelFormat::u10,
olive::VideoParams::k_rgba_channel_count));
frame->allocate();
const QString fn = QDir(sub).filePath(QStringLiteral("u10_frame"));
EXPECT_FALSE(olive::FrameHashCache::SaveCacheFrame(fn, frame));
EXPECT_FALSE(olive::FrameHashCache::save_cache_frame(fn, frame));
EXPECT_FALSE(QFileInfo::exists(fn));
}
TEST_F(RenderDiskCacheTest, SaveCacheFrameRegistersFolderWithDiskManager)
{
const QString sub = MakeSubDir(QStringLiteral("registered"));
const QString sub = make_sub_dir(QStringLiteral("registered"));
ASSERT_FALSE(sub.isEmpty());
const QUuid uuid = QUuid::createUuid();
olive::FramePtr frame =
MakeSolidFrame(4, 4, olive::core::PixelFormat::F32,
olive::VideoParams::kRGBAChannelCount,
make_solid_frame(4, 4, olive::core::PixelFormat::f32,
olive::VideoParams::k_rgba_channel_count,
olive::core::Color(0.0f, 0.0f, 0.0f, 1.0f));
olive::DiskManager *dm = olive::DiskManager::instance();
const int folder_count_before = dm->GetOpenFolders().size();
const int folder_count_before = dm->get_open_folders().size();
ASSERT_TRUE(olive::FrameHashCache::SaveCacheFrame(sub, uuid, 42, frame));
ASSERT_TRUE(olive::FrameHashCache::save_cache_frame(sub, uuid, 42, frame));
EXPECT_EQ(dm->GetOpenFolders().size(), folder_count_before + 1);
EXPECT_EQ(dm->get_open_folders().size(), folder_count_before + 1);
// Registration means the folder now tracks the file for deletion
olive::DiskCacheFolder *folder = dm->GetOpenFolder(sub);
olive::DiskCacheFolder *folder = dm->get_open_folder(sub);
ASSERT_NE(folder, nullptr);
EXPECT_TRUE(folder->DeleteSpecificFile(ExpectedFrameFile(sub, uuid, 42)));
EXPECT_TRUE(folder->delete_specific_file(expected_frame_file(sub, uuid, 42)));
}
TEST_F(RenderDiskCacheTest, GetValidCacheFilenameRequiresValidatedFrame)
{
olive::FrameHashCache cache(project_.get());
cache.SetTimebase(olive::core::rational(1, 30));
cache.set_timebase(olive::core::Rational(1, 30));
const olive::core::rational t(15, 30);
EXPECT_TRUE(cache.GetValidCacheFilename(t).isEmpty());
const olive::core::Rational t(15, 30);
EXPECT_TRUE(cache.get_valid_cache_filename(t).isEmpty());
cache.ValidateTimestamp(15);
cache.validate_timestamp(15);
const QString fn = cache.GetValidCacheFilename(t);
EXPECT_EQ(fn, ExpectedFrameFile(CacheRoot(), cache.GetUuid(), 15));
const QString fn = cache.get_valid_cache_filename(t);
EXPECT_EQ(fn, expected_frame_file(cache_root(), cache.get_uuid(), 15));
}
TEST_F(RenderDiskCacheTest, DeletingFrameThroughDiskManagerInvalidatesRange)
{
olive::FrameHashCache cache(project_.get());
cache.SetTimebase(olive::core::rational(1, 30));
cache.set_timebase(olive::core::Rational(1, 30));
olive::FramePtr frame =
MakeSolidFrame(4, 4, olive::core::PixelFormat::F32,
olive::VideoParams::kRGBAChannelCount,
make_solid_frame(4, 4, olive::core::PixelFormat::f32,
olive::VideoParams::k_rgba_channel_count,
olive::core::Color(1.0f, 0.0f, 0.0f, 1.0f));
// Instance overloads resolve the cache dir/uuid from the parent project
ASSERT_TRUE(cache.SaveCacheFrame(15, frame));
ASSERT_TRUE(cache.save_cache_frame(15, frame));
const QString fn = ExpectedFrameFile(CacheRoot(), cache.GetUuid(), 15);
const QString fn = expected_frame_file(cache_root(), cache.get_uuid(), 15);
ASSERT_TRUE(QFileInfo::exists(fn));
ASSERT_NE(cache.LoadCacheFrame(15), nullptr);
ASSERT_NE(cache.load_cache_frame(15), nullptr);
const olive::core::rational t(15, 30);
cache.ValidateTimestamp(15);
ASSERT_TRUE(cache.IsFrameCached(t));
const olive::core::Rational t(15, 30);
cache.validate_timestamp(15);
ASSERT_TRUE(cache.is_frame_cached(t));
// Deletion must propagate through DiskManager::DeletedFrame into HashDeleted
olive::DiskManager::instance()->DeleteSpecificFile(fn);
olive::DiskManager::instance()->delete_specific_file(fn);
EXPECT_FALSE(QFileInfo::exists(fn));
EXPECT_FALSE(cache.IsFrameCached(t));
EXPECT_FALSE(cache.is_frame_cached(t));
}
TEST_F(RenderDiskCacheTest, DiskDeletedSignalFromForeignCacheDoesNotInvalidate)
{
olive::FrameHashCache cache(project_.get());
cache.SetTimebase(olive::core::rational(1, 30));
cache.ValidateTimestamp(15);
cache.set_timebase(olive::core::Rational(1, 30));
cache.validate_timestamp(15);
const olive::core::rational t(15, 30);
ASSERT_TRUE(cache.IsFrameCached(t));
const olive::core::Rational t(15, 30);
ASSERT_TRUE(cache.is_frame_cached(t));
// Different cache directory: must be ignored
emit olive::DiskManager::instance()
->DeletedFrame(QStringLiteral("/some/other/cache"),
->deleted_frame(QStringLiteral("/some/other/cache"),
QStringLiteral("/some/other/cache/15"));
EXPECT_TRUE(cache.IsFrameCached(t));
EXPECT_TRUE(cache.is_frame_cached(t));
// Same directory but a different cache UUID: must be ignored
emit olive::DiskManager::instance()
->DeletedFrame(CacheRoot(),
ExpectedFrameFile(CacheRoot(), QUuid::createUuid(), 15));
EXPECT_TRUE(cache.IsFrameCached(t));
->deleted_frame(cache_root(),
expected_frame_file(cache_root(), QUuid::createUuid(), 15));
EXPECT_TRUE(cache.is_frame_cached(t));
}
TEST_F(RenderDiskCacheTest, InvalidateProjectSignalClearsValidatedRanges)
{
olive::FrameHashCache cache(project_.get());
cache.SetTimebase(olive::core::rational(1, 30));
cache.set_timebase(olive::core::Rational(1, 30));
const olive::core::rational t(15, 30);
cache.ValidateTimestamp(15);
ASSERT_TRUE(cache.IsFrameCached(t));
const olive::core::Rational t(15, 30);
cache.validate_timestamp(15);
ASSERT_TRUE(cache.is_frame_cached(t));
// An unrelated project must not invalidate this cache
olive::ColorManager::SetUpDefaultConfig();
olive::ColorManager::set_up_default_config();
olive::Project other;
emit olive::DiskManager::instance()->InvalidateProject(&other);
EXPECT_TRUE(cache.IsFrameCached(t));
emit olive::DiskManager::instance()->invalidate_project(&other);
EXPECT_TRUE(cache.is_frame_cached(t));
emit olive::DiskManager::instance()->InvalidateProject(project_.get());
EXPECT_FALSE(cache.IsFrameCached(t));
emit olive::DiskManager::instance()->invalidate_project(project_.get());
EXPECT_FALSE(cache.is_frame_cached(t));
}
TEST_F(RenderDiskCacheTest, ValidatedStatePersistsAcrossCaches)
@@ -397,77 +397,77 @@ TEST_F(RenderDiskCacheTest, ValidatedStatePersistsAcrossCaches)
{
olive::FrameHashCache cache(project_.get());
cache.SetUuid(uuid);
cache.SetTimebase(olive::core::rational(1, 30));
cache.ValidateTimestamp(15);
cache.set_uuid(uuid);
cache.set_timebase(olive::core::Rational(1, 30));
cache.validate_timestamp(15);
}
const QString state_file =
QDir(QDir(CacheRoot()).filePath(uuid.toString()))
QDir(QDir(cache_root()).filePath(uuid.toString()))
.filePath(QStringLiteral("state"));
ASSERT_TRUE(QFileInfo::exists(state_file));
// SetUuid triggers LoadState, restoring timebase and validated ranges
olive::FrameHashCache restored(project_.get());
restored.SetUuid(uuid);
restored.set_uuid(uuid);
EXPECT_EQ(restored.GetTimebase(), olive::core::rational(1, 30));
EXPECT_TRUE(restored.IsFrameCached(olive::core::rational(15, 30)));
EXPECT_FALSE(restored.IsFrameCached(olive::core::rational(16, 30)));
EXPECT_EQ(restored.get_timebase(), olive::core::Rational(1, 30));
EXPECT_TRUE(restored.is_frame_cached(olive::core::Rational(15, 30)));
EXPECT_FALSE(restored.is_frame_cached(olive::core::Rational(16, 30)));
}
TEST_F(RenderDiskCacheTest, PassthroughProvidesFilenameForUnvalidatedFrame)
{
const olive::core::rational tb(1, 30);
const olive::core::Rational tb(1, 30);
olive::FrameHashCache source(project_.get());
source.SetTimebase(tb);
source.ValidateTimestamp(15);
source.set_timebase(tb);
source.validate_timestamp(15);
olive::FrameHashCache dest(project_.get());
dest.SetPassthrough(&source);
dest.set_passthrough(&source);
// SetPassthrough adopts the source cache's timebase
EXPECT_EQ(dest.GetTimebase(), tb);
EXPECT_EQ(dest.get_timebase(), tb);
// The frame is not validated locally but the passthrough covers it
const olive::core::rational t(15, 30);
EXPECT_FALSE(dest.IsFrameCached(t));
EXPECT_EQ(dest.GetValidCacheFilename(t),
ExpectedFrameFile(CacheRoot(), source.GetUuid(), 15));
const olive::core::Rational t(15, 30);
EXPECT_FALSE(dest.is_frame_cached(t));
EXPECT_EQ(dest.get_valid_cache_filename(t),
expected_frame_file(cache_root(), source.get_uuid(), 15));
}
TEST_F(RenderDiskCacheTest, ThumbnailCacheUsesFixedTimebase)
{
olive::ThumbnailCache cache(project_.get());
EXPECT_EQ(cache.GetTimebase(), olive::core::rational(1, 10));
EXPECT_EQ(cache.get_timebase(), olive::core::Rational(1, 10));
}
TEST_F(RenderDiskCacheTest, FolderDefaultsToTwentyGbLimit)
{
const QString sub = MakeSubDir(QStringLiteral("folder_defaults"));
const QString sub = make_sub_dir(QStringLiteral("folder_defaults"));
ASSERT_FALSE(sub.isEmpty());
olive::DiskCacheFolder folder(sub);
EXPECT_EQ(folder.GetPath(), sub);
EXPECT_EQ(folder.GetLimit(), 21474836480LL); // 20 GB
EXPECT_FALSE(folder.GetClearOnClose());
EXPECT_EQ(folder.get_path(), sub);
EXPECT_EQ(folder.get_limit(), 21474836480LL); // 20 GB
EXPECT_FALSE(folder.get_clear_on_close());
}
TEST_F(RenderDiskCacheTest, CreatedFileCanBeDeletedSpecifically)
{
const QString sub = MakeSubDir(QStringLiteral("delete_specific"));
const QString sub = make_sub_dir(QStringLiteral("delete_specific"));
ASSERT_FALSE(sub.isEmpty());
olive::DiskCacheFolder folder(sub);
const QString fn = QDir(sub).filePath(QStringLiteral("frame1"));
ASSERT_TRUE(WriteFile(fn, 128));
folder.CreatedFile(fn);
ASSERT_TRUE(write_file(fn, 128));
folder.created_file(fn);
QSignalSpy spy(&folder, &olive::DiskCacheFolder::DeletedFrame);
QSignalSpy spy(&folder, &olive::DiskCacheFolder::deleted_frame);
EXPECT_TRUE(folder.DeleteSpecificFile(fn));
EXPECT_TRUE(folder.delete_specific_file(fn));
EXPECT_FALSE(QFileInfo::exists(fn));
ASSERT_EQ(spy.count(), 1);
@@ -476,28 +476,28 @@ TEST_F(RenderDiskCacheTest, CreatedFileCanBeDeletedSpecifically)
EXPECT_EQ(args.at(1).toString(), fn);
// A second deletion attempt fails, as does deleting an unknown file
EXPECT_FALSE(folder.DeleteSpecificFile(fn));
EXPECT_FALSE(folder.DeleteSpecificFile(
EXPECT_FALSE(folder.delete_specific_file(fn));
EXPECT_FALSE(folder.delete_specific_file(
QDir(sub).filePath(QStringLiteral("never_registered"))));
}
TEST_F(RenderDiskCacheTest, ClearCacheRemovesAllRegisteredFiles)
{
const QString sub = MakeSubDir(QStringLiteral("clear_cache"));
const QString sub = make_sub_dir(QStringLiteral("clear_cache"));
ASSERT_FALSE(sub.isEmpty());
olive::DiskCacheFolder folder(sub);
const QString f1 = QDir(sub).filePath(QStringLiteral("a"));
const QString f2 = QDir(sub).filePath(QStringLiteral("b"));
ASSERT_TRUE(WriteFile(f1, 32));
ASSERT_TRUE(WriteFile(f2, 32));
folder.CreatedFile(f1);
folder.CreatedFile(f2);
ASSERT_TRUE(write_file(f1, 32));
ASSERT_TRUE(write_file(f2, 32));
folder.created_file(f1);
folder.created_file(f2);
QSignalSpy spy(&folder, &olive::DiskCacheFolder::DeletedFrame);
QSignalSpy spy(&folder, &olive::DiskCacheFolder::deleted_frame);
EXPECT_TRUE(folder.ClearCache());
EXPECT_TRUE(folder.clear_cache());
EXPECT_FALSE(QFileInfo::exists(f1));
EXPECT_FALSE(QFileInfo::exists(f2));
EXPECT_EQ(spy.count(), 2);
@@ -505,85 +505,85 @@ TEST_F(RenderDiskCacheTest, ClearCacheRemovesAllRegisteredFiles)
TEST_F(RenderDiskCacheTest, ClearCacheToleratesExternallyRemovedFiles)
{
const QString sub = MakeSubDir(QStringLiteral("clear_missing"));
const QString sub = make_sub_dir(QStringLiteral("clear_missing"));
ASSERT_FALSE(sub.isEmpty());
olive::DiskCacheFolder folder(sub);
const QString fn = QDir(sub).filePath(QStringLiteral("gone"));
ASSERT_TRUE(WriteFile(fn, 32));
folder.CreatedFile(fn);
ASSERT_TRUE(write_file(fn, 32));
folder.created_file(fn);
ASSERT_TRUE(QFile::remove(fn));
// Already-missing files count as successfully cleared
EXPECT_TRUE(folder.ClearCache());
EXPECT_TRUE(folder.clear_cache());
}
TEST_F(RenderDiskCacheTest, FolderStatePersistsAcrossInstances)
{
const QString sub = MakeSubDir(QStringLiteral("persist"));
const QString sub = make_sub_dir(QStringLiteral("persist"));
ASSERT_FALSE(sub.isEmpty());
const QString fn = QDir(sub).filePath(QStringLiteral("persisted_frame"));
ASSERT_TRUE(WriteFile(fn, 64));
ASSERT_TRUE(write_file(fn, 64));
{
olive::DiskCacheFolder folder(sub);
folder.SetLimit(12345);
folder.CreatedFile(fn);
folder.set_limit(12345);
folder.created_file(fn);
// Destruction writes the index file into the cache folder
}
{
olive::DiskCacheFolder reopened(sub);
EXPECT_EQ(reopened.GetLimit(), 12345);
EXPECT_FALSE(reopened.GetClearOnClose());
EXPECT_EQ(reopened.get_limit(), 12345);
EXPECT_FALSE(reopened.get_clear_on_close());
// The persisted entry is only known if the index was reloaded
EXPECT_TRUE(reopened.DeleteSpecificFile(fn));
EXPECT_TRUE(reopened.delete_specific_file(fn));
EXPECT_FALSE(QFileInfo::exists(fn));
}
}
TEST_F(RenderDiskCacheTest, ExceedingLimitEvictsLeastRecentlyUsedFile)
{
const QString sub = MakeSubDir(QStringLiteral("eviction"));
const QString sub = make_sub_dir(QStringLiteral("eviction"));
ASSERT_FALSE(sub.isEmpty());
olive::DiskCacheFolder folder(sub);
folder.SetLimit(250);
EXPECT_EQ(folder.GetLimit(), 250);
folder.set_limit(250);
EXPECT_EQ(folder.get_limit(), 250);
// Names are ordered so that even identical timestamps evict "aaa_evict"
const QString keep = QDir(sub).filePath(QStringLiteral("zzz_keep"));
const QString evict = QDir(sub).filePath(QStringLiteral("aaa_evict"));
const QString newest = QDir(sub).filePath(QStringLiteral("bbb_newest"));
ASSERT_TRUE(WriteFile(keep, 100));
folder.CreatedFile(keep);
ASSERT_TRUE(write_file(keep, 100));
folder.created_file(keep);
QThread::msleep(20);
ASSERT_TRUE(WriteFile(evict, 100));
folder.CreatedFile(evict);
ASSERT_TRUE(write_file(evict, 100));
folder.created_file(evict);
// Both files fit within the limit
ASSERT_TRUE(QFileInfo::exists(keep));
ASSERT_TRUE(QFileInfo::exists(evict));
// Unknown filenames are ignored by Accessed
folder.Accessed(QDir(sub).filePath(QStringLiteral("unknown")));
folder.accessed(QDir(sub).filePath(QStringLiteral("unknown")));
QThread::msleep(20);
// "keep" becomes the most recently used file
folder.Accessed(keep);
folder.accessed(keep);
QSignalSpy spy(&folder, &olive::DiskCacheFolder::DeletedFrame);
QSignalSpy spy(&folder, &olive::DiskCacheFolder::deleted_frame);
ASSERT_TRUE(WriteFile(newest, 100));
folder.CreatedFile(newest); // 300 > 250, one eviction required
ASSERT_TRUE(write_file(newest, 100));
folder.created_file(newest); // 300 > 250, one eviction required
EXPECT_TRUE(QFileInfo::exists(keep));
EXPECT_FALSE(QFileInfo::exists(evict));
@@ -595,17 +595,17 @@ TEST_F(RenderDiskCacheTest, ExceedingLimitEvictsLeastRecentlyUsedFile)
TEST_F(RenderDiskCacheTest, ClearOnCloseDeletesFilesWhenFolderCloses)
{
const QString sub = MakeSubDir(QStringLiteral("clear_on_close"));
const QString sub = make_sub_dir(QStringLiteral("clear_on_close"));
ASSERT_FALSE(sub.isEmpty());
const QString fn = QDir(sub).filePath(QStringLiteral("closing_frame"));
ASSERT_TRUE(WriteFile(fn, 32));
ASSERT_TRUE(write_file(fn, 32));
{
olive::DiskCacheFolder folder(sub);
folder.SetClearOnClose(true);
EXPECT_TRUE(folder.GetClearOnClose());
folder.CreatedFile(fn);
folder.set_clear_on_close(true);
EXPECT_TRUE(folder.get_clear_on_close());
folder.created_file(fn);
}
EXPECT_FALSE(QFileInfo::exists(fn));
@@ -616,22 +616,22 @@ TEST_F(RenderDiskCacheTest, DiskManagerOpenFolderDeduplicates)
olive::DiskManager *dm = olive::DiskManager::instance();
ASSERT_NE(dm, nullptr);
const QString sub = MakeSubDir(QStringLiteral("dedupe"));
const QString sub = make_sub_dir(QStringLiteral("dedupe"));
ASSERT_FALSE(sub.isEmpty());
const int folder_count_before = dm->GetOpenFolders().size();
const int folder_count_before = dm->get_open_folders().size();
olive::DiskCacheFolder *first = dm->GetOpenFolder(sub);
olive::DiskCacheFolder *second = dm->GetOpenFolder(sub);
olive::DiskCacheFolder *first = dm->get_open_folder(sub);
olive::DiskCacheFolder *second = dm->get_open_folder(sub);
ASSERT_NE(first, nullptr);
EXPECT_EQ(first, second);
EXPECT_EQ(first->GetPath(), sub);
EXPECT_EQ(dm->GetOpenFolders().size(), folder_count_before + 1);
EXPECT_EQ(first->get_path(), sub);
EXPECT_EQ(dm->get_open_folders().size(), folder_count_before + 1);
// An empty path resolves to the default cache folder
EXPECT_EQ(dm->GetOpenFolder(QString()), dm->GetDefaultCacheFolder());
EXPECT_FALSE(dm->GetDefaultCachePath().isEmpty());
EXPECT_EQ(dm->get_open_folder(QString()), dm->get_default_cache_folder());
EXPECT_FALSE(dm->get_default_cache_path().isEmpty());
}
TEST_F(RenderDiskCacheTest, DiskManagerClearDiskCacheRemovesFiles)
@@ -639,14 +639,14 @@ TEST_F(RenderDiskCacheTest, DiskManagerClearDiskCacheRemovesFiles)
olive::DiskManager *dm = olive::DiskManager::instance();
ASSERT_NE(dm, nullptr);
const QString sub = MakeSubDir(QStringLiteral("managed_clear"));
const QString sub = make_sub_dir(QStringLiteral("managed_clear"));
ASSERT_FALSE(sub.isEmpty());
const QString fn = QDir(sub).filePath(QStringLiteral("managed_frame"));
ASSERT_TRUE(WriteFile(fn, 32));
dm->CreatedFile(sub, fn);
ASSERT_TRUE(write_file(fn, 32));
dm->created_file(sub, fn);
ASSERT_TRUE(QFileInfo::exists(fn));
EXPECT_TRUE(dm->ClearDiskCache(sub));
EXPECT_TRUE(dm->clear_disk_cache(sub));
EXPECT_FALSE(QFileInfo::exists(fn));
}