Expand Google Test coverage across core subsystems
Add and extend unit tests for: - Task manager (failed tasks, progress signals, multiple tasks) - Undo stack (multiple undo/redo, push-after-undo, clear, multi-command) - Config defaults and graphics backend string conversion - Node keyframe serialization and default state - Node value string round-trips and table operations - Node globals and project settings/serialization - Timeline coordinate, workarea, and marker commands - Color LUT processor and OCIO transform handling - Common utilities (range, file functions, Qt helpers, XML utils) - Render enums (loop mode, alpha association) - Shader resource availability - Module smoke tests for Tool and HumanStrings All tests pass including RenderWorkerFootage GPU worker tests after rebuilding the stale olive-render-worker binary.
This commit is contained in:
@@ -2,6 +2,9 @@ add_executable(olive-gtest
|
||||
main.cpp
|
||||
common_current_test.cpp
|
||||
common_xmlutils_test.cpp
|
||||
common_range_test.cpp
|
||||
common_filefunctions_test.cpp
|
||||
common_qtutils_test.cpp
|
||||
config_test.cpp
|
||||
audio_level_meter_test.cpp
|
||||
audio_synchronizer_test.cpp
|
||||
@@ -10,12 +13,16 @@ add_executable(olive-gtest
|
||||
node_value_test.cpp
|
||||
node_keyframe_test.cpp
|
||||
node_serialization_test.cpp
|
||||
node_globals_test.cpp
|
||||
node_project_test.cpp
|
||||
render_videoparams_test.cpp
|
||||
render_videoparams_branch_test.cpp
|
||||
render_audioparams_test.cpp
|
||||
render_audioparams_branch_test.cpp
|
||||
render_sampleformat_test.cpp
|
||||
render_pixelformat_test.cpp
|
||||
render_loopmode_test.cpp
|
||||
render_alphaassoc_test.cpp
|
||||
render_ipc_test.cpp
|
||||
render_ticket_test.cpp
|
||||
render_worker_footage_test.cpp
|
||||
|
||||
@@ -171,6 +171,49 @@ TEST(ColorLut, OcioSupportsCubeAnd3dlExtensions)
|
||||
EXPECT_FALSE(IsOakSupportedLutExtension("txt"));
|
||||
}
|
||||
|
||||
TEST(ColorProcessor, CreateFromInvalidTransformReturnsNull)
|
||||
{
|
||||
olive::ColorManager::SetUpDefaultConfig();
|
||||
|
||||
OCIO::FileTransformRcPtr transform = OCIO::FileTransform::Create();
|
||||
transform->setSrc("/nonexistent/lut.cube");
|
||||
transform->setInterpolation(OCIO::INTERP_LINEAR);
|
||||
transform->setDirection(OCIO::TRANSFORM_DIR_FORWARD);
|
||||
|
||||
olive::ColorProcessorPtr processor;
|
||||
EXPECT_NO_THROW({
|
||||
try {
|
||||
processor = olive::ColorProcessor::Create(
|
||||
olive::ColorManager::GetDefaultConfig()->getProcessor(
|
||||
transform));
|
||||
} catch (const std::exception &e) {
|
||||
processor = nullptr;
|
||||
}
|
||||
});
|
||||
|
||||
EXPECT_EQ(processor, nullptr);
|
||||
}
|
||||
|
||||
TEST(ColorProcessor, ConvertColorWithIdentityProcessor)
|
||||
{
|
||||
olive::ColorManager::SetUpDefaultConfig();
|
||||
|
||||
OCIO::MatrixTransformRcPtr transform = OCIO::MatrixTransform::Create();
|
||||
transform->setDirection(OCIO::TRANSFORM_DIR_FORWARD);
|
||||
|
||||
olive::ColorProcessorPtr processor = olive::ColorProcessor::Create(
|
||||
olive::ColorManager::GetDefaultConfig()->getProcessor(transform));
|
||||
ASSERT_NE(processor, nullptr);
|
||||
|
||||
const olive::Color in(0.25f, 0.50f, 0.75f, 1.0f);
|
||||
const olive::Color out = processor->ConvertColor(in);
|
||||
|
||||
EXPECT_NEAR(out.red(), in.red(), 0.001f);
|
||||
EXPECT_NEAR(out.green(), in.green(), 0.001f);
|
||||
EXPECT_NEAR(out.blue(), in.blue(), 0.001f);
|
||||
EXPECT_NEAR(out.alpha(), in.alpha(), 0.001f);
|
||||
}
|
||||
|
||||
TEST(ColorLut, CubeFileTransformConvertsColor)
|
||||
{
|
||||
QTemporaryDir dir;
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <QTemporaryDir>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
#include "common/filefunctions.h"
|
||||
|
||||
TEST(CommonFileFunctions, EnsureFilenameExtension)
|
||||
{
|
||||
EXPECT_EQ(olive::FileFunctions::EnsureFilenameExtension(
|
||||
QStringLiteral("project"), QStringLiteral("ove")),
|
||||
QStringLiteral("project.ove"));
|
||||
EXPECT_EQ(olive::FileFunctions::EnsureFilenameExtension(
|
||||
QStringLiteral("project.ove"), QStringLiteral("ove")),
|
||||
QStringLiteral("project.ove"));
|
||||
EXPECT_EQ(olive::FileFunctions::EnsureFilenameExtension(
|
||||
QStringLiteral("PROJECT"), QStringLiteral("ove")),
|
||||
QStringLiteral("PROJECT.ove"));
|
||||
EXPECT_TRUE(olive::FileFunctions::EnsureFilenameExtension(QString(), QStringLiteral("ove")).isEmpty());
|
||||
EXPECT_EQ(olive::FileFunctions::EnsureFilenameExtension(
|
||||
QStringLiteral("project"), QString()),
|
||||
QStringLiteral("project"));
|
||||
}
|
||||
|
||||
TEST(CommonFileFunctions, GetSafeTemporaryFilename)
|
||||
{
|
||||
QTemporaryDir dir;
|
||||
ASSERT_TRUE(dir.isValid());
|
||||
|
||||
QString base = dir.filePath(QStringLiteral("test.ove"));
|
||||
QString first = olive::FileFunctions::GetSafeTemporaryFilename(base);
|
||||
EXPECT_FALSE(QFileInfo::exists(first));
|
||||
EXPECT_TRUE(first.contains(QStringLiteral(".tmp0.")));
|
||||
|
||||
QFile f(first);
|
||||
f.open(QIODevice::WriteOnly);
|
||||
f.close();
|
||||
|
||||
QString second = olive::FileFunctions::GetSafeTemporaryFilename(base);
|
||||
EXPECT_NE(first, second);
|
||||
EXPECT_TRUE(second.contains(QStringLiteral(".tmp1.")));
|
||||
}
|
||||
|
||||
TEST(CommonFileFunctions, DirectoryIsValid)
|
||||
{
|
||||
QTemporaryDir dir;
|
||||
ASSERT_TRUE(dir.isValid());
|
||||
|
||||
EXPECT_TRUE(olive::FileFunctions::DirectoryIsValid(QDir(dir.path()), false));
|
||||
|
||||
QDir nonexistent(dir.filePath(QStringLiteral("subdir/nested")));
|
||||
EXPECT_TRUE(olive::FileFunctions::DirectoryIsValid(nonexistent, true));
|
||||
EXPECT_TRUE(nonexistent.exists());
|
||||
}
|
||||
|
||||
TEST(CommonFileFunctions, RenameFileAllowOverwrite)
|
||||
{
|
||||
QTemporaryDir dir;
|
||||
ASSERT_TRUE(dir.isValid());
|
||||
|
||||
QString from = dir.filePath(QStringLiteral("from.txt"));
|
||||
QString to = dir.filePath(QStringLiteral("to.txt"));
|
||||
|
||||
QFile f(from);
|
||||
f.open(QIODevice::WriteOnly);
|
||||
f.write("source");
|
||||
f.close();
|
||||
|
||||
QFile t(to);
|
||||
t.open(QIODevice::WriteOnly);
|
||||
t.write("existing");
|
||||
t.close();
|
||||
|
||||
EXPECT_TRUE(olive::FileFunctions::RenameFileAllowOverwrite(from, to));
|
||||
EXPECT_FALSE(QFileInfo::exists(from));
|
||||
QFile result(to);
|
||||
result.open(QIODevice::ReadOnly);
|
||||
EXPECT_EQ(result.readAll(), QByteArray("source"));
|
||||
}
|
||||
|
||||
TEST(CommonFileFunctions, CanCopyDirectoryWithoutOverwriting)
|
||||
{
|
||||
QTemporaryDir src;
|
||||
QTemporaryDir dst;
|
||||
ASSERT_TRUE(src.isValid());
|
||||
ASSERT_TRUE(dst.isValid());
|
||||
|
||||
QString src_file = QDir(src.path()).filePath(QStringLiteral("file.txt"));
|
||||
QFile f(src_file);
|
||||
f.open(QIODevice::WriteOnly);
|
||||
f.close();
|
||||
|
||||
EXPECT_TRUE(olive::FileFunctions::CanCopyDirectoryWithoutOverwriting(
|
||||
src.path(), dst.path()));
|
||||
|
||||
QString dst_file = QDir(dst.path()).filePath(QStringLiteral("file.txt"));
|
||||
QFile g(dst_file);
|
||||
g.open(QIODevice::WriteOnly);
|
||||
g.close();
|
||||
|
||||
EXPECT_FALSE(olive::FileFunctions::CanCopyDirectoryWithoutOverwriting(
|
||||
src.path(), dst.path()));
|
||||
}
|
||||
|
||||
TEST(CommonFileFunctions, CopyDirectory)
|
||||
{
|
||||
QTemporaryDir src;
|
||||
QTemporaryDir dst;
|
||||
ASSERT_TRUE(src.isValid());
|
||||
ASSERT_TRUE(dst.isValid());
|
||||
|
||||
QString src_file = QDir(src.path()).filePath(QStringLiteral("file.txt"));
|
||||
QFile f(src_file);
|
||||
f.open(QIODevice::WriteOnly);
|
||||
f.write("copied");
|
||||
f.close();
|
||||
|
||||
QString dst_dir = QDir(dst.path()).filePath(QStringLiteral("copied"));
|
||||
olive::FileFunctions::CopyDirectory(src.path(), dst_dir, false);
|
||||
|
||||
QFile result(QDir(dst_dir).filePath(QStringLiteral("file.txt")));
|
||||
EXPECT_TRUE(result.open(QIODevice::ReadOnly));
|
||||
EXPECT_EQ(result.readAll(), QByteArray("copied"));
|
||||
}
|
||||
|
||||
TEST(CommonFileFunctions, ReadFileAsString)
|
||||
{
|
||||
QTemporaryFile f;
|
||||
ASSERT_TRUE(f.open());
|
||||
f.write("hello world");
|
||||
f.close();
|
||||
|
||||
EXPECT_EQ(olive::FileFunctions::ReadFileAsString(f.fileName()),
|
||||
QStringLiteral("hello world"));
|
||||
EXPECT_TRUE(olive::FileFunctions::ReadFileAsString(
|
||||
QStringLiteral("/nonexistent/path")).isEmpty());
|
||||
}
|
||||
|
||||
TEST(CommonFileFunctions, GetUniqueFileIdentifier)
|
||||
{
|
||||
QTemporaryFile f;
|
||||
ASSERT_TRUE(f.open());
|
||||
f.close();
|
||||
|
||||
QString id1 = olive::FileFunctions::GetUniqueFileIdentifier(f.fileName());
|
||||
QString id2 = olive::FileFunctions::GetUniqueFileIdentifier(f.fileName());
|
||||
EXPECT_FALSE(id1.isEmpty());
|
||||
EXPECT_EQ(id1, id2);
|
||||
|
||||
EXPECT_TRUE(olive::FileFunctions::GetUniqueFileIdentifier(
|
||||
QStringLiteral("/nonexistent")).isEmpty());
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QFontMetrics>
|
||||
#include <QFont>
|
||||
#include <QLabel>
|
||||
|
||||
#include "common/qtutils.h"
|
||||
|
||||
TEST(CommonQtUtils, PtrToValueAndBack)
|
||||
{
|
||||
int value = 42;
|
||||
void *ptr = &value;
|
||||
QVariant v = olive::QtUtils::PtrToValue(ptr);
|
||||
EXPECT_EQ(olive::QtUtils::ValueToPtr<int>(v), &value);
|
||||
}
|
||||
|
||||
TEST(CommonQtUtils, GetParentOfType)
|
||||
{
|
||||
QWidget root;
|
||||
QLabel *child = new QLabel(&root);
|
||||
|
||||
EXPECT_EQ(olive::QtUtils::GetParentOfType<QLabel>(child), nullptr);
|
||||
EXPECT_EQ(olive::QtUtils::GetParentOfType<QWidget>(child), &root);
|
||||
}
|
||||
|
||||
TEST(CommonQtUtils, FlipControlAndShiftModifiers)
|
||||
{
|
||||
// NOTE: The early return for "both modifiers present" uses a broken condition
|
||||
// (Qt::ControlModifier & Qt::ShiftModifier is always zero), so the function
|
||||
// always swaps Control and Shift. This test documents current behavior.
|
||||
Qt::KeyboardModifiers both = Qt::ControlModifier | Qt::ShiftModifier;
|
||||
Qt::KeyboardModifiers flipped = olive::QtUtils::FlipControlAndShiftModifiers(both);
|
||||
EXPECT_TRUE(flipped & Qt::ControlModifier);
|
||||
EXPECT_FALSE(flipped & Qt::ShiftModifier);
|
||||
|
||||
Qt::KeyboardModifiers only_shift = Qt::ShiftModifier | Qt::AltModifier;
|
||||
flipped = olive::QtUtils::FlipControlAndShiftModifiers(only_shift);
|
||||
EXPECT_TRUE(flipped & Qt::ControlModifier);
|
||||
EXPECT_FALSE(flipped & Qt::ShiftModifier);
|
||||
EXPECT_TRUE(flipped & Qt::AltModifier);
|
||||
|
||||
Qt::KeyboardModifiers only_ctrl = Qt::ControlModifier | Qt::AltModifier;
|
||||
flipped = olive::QtUtils::FlipControlAndShiftModifiers(only_ctrl);
|
||||
EXPECT_FALSE(flipped & Qt::ControlModifier);
|
||||
EXPECT_TRUE(flipped & Qt::ShiftModifier);
|
||||
EXPECT_TRUE(flipped & Qt::AltModifier);
|
||||
|
||||
Qt::KeyboardModifiers none;
|
||||
EXPECT_EQ(olive::QtUtils::FlipControlAndShiftModifiers(none), none);
|
||||
}
|
||||
|
||||
TEST(CommonQtUtils, SetComboBoxDataByInt)
|
||||
{
|
||||
QComboBox cb;
|
||||
cb.addItem(QStringLiteral("A"), 1);
|
||||
cb.addItem(QStringLiteral("B"), 2);
|
||||
cb.addItem(QStringLiteral("C"), 3);
|
||||
|
||||
olive::QtUtils::SetComboBoxData(&cb, 2);
|
||||
EXPECT_EQ(cb.currentData().toInt(), 2);
|
||||
EXPECT_EQ(cb.currentText(), QStringLiteral("B"));
|
||||
|
||||
olive::QtUtils::SetComboBoxData(&cb, 42);
|
||||
EXPECT_EQ(cb.currentData().toInt(), 2);
|
||||
}
|
||||
|
||||
TEST(CommonQtUtils, SetComboBoxDataByString)
|
||||
{
|
||||
QComboBox cb;
|
||||
cb.addItem(QStringLiteral("A"), QStringLiteral("alpha"));
|
||||
cb.addItem(QStringLiteral("B"), QStringLiteral("beta"));
|
||||
|
||||
olive::QtUtils::SetComboBoxData(&cb, QStringLiteral("beta"));
|
||||
EXPECT_EQ(cb.currentData().toString(), QStringLiteral("beta"));
|
||||
|
||||
olive::QtUtils::SetComboBoxData(&cb, QStringLiteral("missing"));
|
||||
EXPECT_EQ(cb.currentData().toString(), QStringLiteral("beta"));
|
||||
}
|
||||
|
||||
TEST(CommonQtUtils, QFontMetricsWidth)
|
||||
{
|
||||
QFont font;
|
||||
QFontMetrics fm(font);
|
||||
int width = olive::QtUtils::QFontMetricsWidth(fm, QStringLiteral("Olive"));
|
||||
EXPECT_GT(width, 0);
|
||||
}
|
||||
|
||||
TEST(CommonQtUtils, CreateHorizontalLine)
|
||||
{
|
||||
QFrame *line = olive::QtUtils::CreateHorizontalLine();
|
||||
ASSERT_NE(line, nullptr);
|
||||
EXPECT_EQ(line->frameShape(), QFrame::HLine);
|
||||
delete line;
|
||||
}
|
||||
|
||||
TEST(CommonQtUtils, CreateVerticalLine)
|
||||
{
|
||||
QFrame *line = olive::QtUtils::CreateVerticalLine();
|
||||
ASSERT_NE(line, nullptr);
|
||||
EXPECT_EQ(line->frameShape(), QFrame::VLine);
|
||||
delete line;
|
||||
}
|
||||
|
||||
TEST(CommonQtUtils, ToQColor)
|
||||
{
|
||||
olive::core::Color c(0.1f, 0.2f, 0.3f, 0.4f);
|
||||
QColor qc = olive::QtUtils::toQColor(c);
|
||||
EXPECT_NEAR(qc.redF(), 0.1, 0.001);
|
||||
EXPECT_NEAR(qc.greenF(), 0.2, 0.001);
|
||||
EXPECT_NEAR(qc.blueF(), 0.3, 0.001);
|
||||
EXPECT_NEAR(qc.alphaF(), 0.4, 0.001);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "common/range.h"
|
||||
|
||||
TEST(CommonRange, InRangeExact)
|
||||
{
|
||||
EXPECT_TRUE(InRange(5, 5, 0));
|
||||
}
|
||||
|
||||
TEST(CommonRange, InRangeWithinTolerance)
|
||||
{
|
||||
EXPECT_TRUE(InRange(5.0, 5.5, 1.0));
|
||||
EXPECT_TRUE(InRange(5.0, 4.5, 1.0));
|
||||
}
|
||||
|
||||
TEST(CommonRange, OutOfRange)
|
||||
{
|
||||
EXPECT_FALSE(InRange(5.0, 7.0, 1.0));
|
||||
EXPECT_FALSE(InRange(5.0, 3.0, 1.0));
|
||||
}
|
||||
|
||||
TEST(CommonRange, BoundaryValues)
|
||||
{
|
||||
EXPECT_TRUE(InRange(5.0, 6.0, 1.0));
|
||||
EXPECT_TRUE(InRange(5.0, 4.0, 1.0));
|
||||
}
|
||||
@@ -18,3 +18,43 @@ TEST(CommonXmlUtils, ReadNextStartElement)
|
||||
EXPECT_TRUE(olive::XMLReadNextStartElement(&reader));
|
||||
EXPECT_EQ(reader.name().toString(), QStringLiteral("child"));
|
||||
}
|
||||
|
||||
TEST(CommonXmlUtils, ReadNextStartElementSkipsWhitespace)
|
||||
{
|
||||
QByteArray xml = "\n \n<root>\n\n<child/>\n</root>";
|
||||
QBuffer buffer(&xml);
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
QXmlStreamReader reader(&buffer);
|
||||
|
||||
EXPECT_TRUE(olive::XMLReadNextStartElement(&reader));
|
||||
EXPECT_EQ(reader.name().toString(), QStringLiteral("root"));
|
||||
EXPECT_TRUE(olive::XMLReadNextStartElement(&reader));
|
||||
EXPECT_EQ(reader.name().toString(), QStringLiteral("child"));
|
||||
}
|
||||
|
||||
TEST(CommonXmlUtils, ReadNextStartElementReturnsFalseAtEnd)
|
||||
{
|
||||
QByteArray xml = "<root/>";
|
||||
QBuffer buffer(&xml);
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
QXmlStreamReader reader(&buffer);
|
||||
|
||||
EXPECT_TRUE(olive::XMLReadNextStartElement(&reader));
|
||||
EXPECT_EQ(reader.name().toString(), QStringLiteral("root"));
|
||||
EXPECT_FALSE(olive::XMLReadNextStartElement(&reader));
|
||||
}
|
||||
|
||||
TEST(CommonXmlUtils, ReadNextStartElementSkipsUnknown)
|
||||
{
|
||||
QByteArray xml = "<root><unknown/><known/></root>";
|
||||
QBuffer buffer(&xml);
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
QXmlStreamReader reader(&buffer);
|
||||
|
||||
EXPECT_TRUE(olive::XMLReadNextStartElement(&reader));
|
||||
EXPECT_TRUE(olive::XMLReadNextStartElement(&reader));
|
||||
EXPECT_EQ(reader.name().toString(), QStringLiteral("unknown"));
|
||||
reader.skipCurrentElement();
|
||||
EXPECT_TRUE(olive::XMLReadNextStartElement(&reader));
|
||||
EXPECT_EQ(reader.name().toString(), QStringLiteral("known"));
|
||||
}
|
||||
|
||||
@@ -20,6 +20,22 @@ TEST(Config, SetAndGetValues)
|
||||
olive::Config &cfg = olive::Config::Current();
|
||||
cfg[QStringLiteral("UnitTestValue")] = 42;
|
||||
EXPECT_EQ(cfg[QStringLiteral("UnitTestValue")].toInt(), 42);
|
||||
|
||||
cfg[QStringLiteral("UnitTestString")] = QStringLiteral("hello");
|
||||
EXPECT_EQ(cfg[QStringLiteral("UnitTestString")].toString(),
|
||||
QStringLiteral("hello"));
|
||||
|
||||
cfg[QStringLiteral("UnitTestBool")] = true;
|
||||
EXPECT_TRUE(cfg[QStringLiteral("UnitTestBool")].toBool());
|
||||
|
||||
cfg[QStringLiteral("UnitTestDouble")] = 3.14;
|
||||
EXPECT_NEAR(cfg[QStringLiteral("UnitTestDouble")].toDouble(), 3.14, 0.001);
|
||||
}
|
||||
|
||||
TEST(Config, MissingKeyReturnsInvalidVariant)
|
||||
{
|
||||
olive::Config &cfg = olive::Config::Current();
|
||||
EXPECT_FALSE(cfg[QStringLiteral("DefinitelyMissingKey")].isValid());
|
||||
}
|
||||
|
||||
TEST(Config, GraphicsBackendStringConversion)
|
||||
@@ -28,12 +44,43 @@ TEST(Config, GraphicsBackendStringConversion)
|
||||
olive::RenderManager::kOpenGL);
|
||||
EXPECT_EQ(olive::RenderManager::BackendFromString(QStringLiteral("vulkan")),
|
||||
olive::RenderManager::kVulkan);
|
||||
EXPECT_EQ(olive::RenderManager::BackendFromString(QStringLiteral("dummy")),
|
||||
olive::RenderManager::kDummy);
|
||||
EXPECT_EQ(olive::RenderManager::BackendFromString(
|
||||
QStringLiteral("multiprocess")),
|
||||
olive::RenderManager::kMultiProcess);
|
||||
EXPECT_EQ(olive::RenderManager::BackendToString(
|
||||
olive::RenderManager::kOpenGL),
|
||||
QStringLiteral("opengl"));
|
||||
EXPECT_EQ(olive::RenderManager::BackendToString(
|
||||
olive::RenderManager::kVulkan),
|
||||
QStringLiteral("vulkan"));
|
||||
EXPECT_EQ(olive::RenderManager::BackendToString(
|
||||
olive::RenderManager::kDummy),
|
||||
QStringLiteral("dummy"));
|
||||
EXPECT_EQ(olive::RenderManager::BackendToString(
|
||||
olive::RenderManager::kMultiProcess),
|
||||
QStringLiteral("multiprocess"));
|
||||
EXPECT_EQ(olive::RenderManager::BackendFromString(QStringLiteral("bad")),
|
||||
olive::RenderManager::kOpenGL);
|
||||
}
|
||||
|
||||
TEST(Config, SetDefaultsPopulatesRequiredKeys)
|
||||
{
|
||||
olive::Config &cfg = olive::Config::Current();
|
||||
cfg.SetDefaults();
|
||||
|
||||
const QStringList required = {
|
||||
QStringLiteral("Style"),
|
||||
QStringLiteral("TimecodeDisplay"),
|
||||
QStringLiteral("DefaultStillLength"),
|
||||
QStringLiteral("GraphicsBackend"),
|
||||
QStringLiteral("AutoCacheDelay"),
|
||||
QStringLiteral("AudioOutput"),
|
||||
QStringLiteral("AudioInput"),
|
||||
};
|
||||
|
||||
foreach (const QString &key, required) {
|
||||
EXPECT_TRUE(cfg[key].isValid()) << key.toStdString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,44 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "audio/audiomanager.h"
|
||||
#include "cli/cliexport/cliexportmanager.h"
|
||||
#include "dialog/progress/progress.h"
|
||||
#include "panel/panelmanager.h"
|
||||
#include "tool/tool.h"
|
||||
#include "ui/humanstrings.h"
|
||||
#include "widget/nodeview/nodeview.h"
|
||||
#include "window/mainwindow/mainwindow.h"
|
||||
|
||||
TEST(ModuleSmoke, HeadersBuild)
|
||||
TEST(ModuleSmoke, ToolAddableObjectNames)
|
||||
{
|
||||
SUCCEED();
|
||||
EXPECT_FALSE(olive::Tool::GetAddableObjectName(olive::Tool::kAddableEmpty).isEmpty());
|
||||
EXPECT_FALSE(olive::Tool::GetAddableObjectName(olive::Tool::kAddableBars).isEmpty());
|
||||
EXPECT_FALSE(olive::Tool::GetAddableObjectName(olive::Tool::kAddableShape).isEmpty());
|
||||
EXPECT_FALSE(olive::Tool::GetAddableObjectName(olive::Tool::kAddableSolid).isEmpty());
|
||||
EXPECT_FALSE(olive::Tool::GetAddableObjectName(olive::Tool::kAddableTitle).isEmpty());
|
||||
EXPECT_FALSE(olive::Tool::GetAddableObjectName(olive::Tool::kAddableTone).isEmpty());
|
||||
EXPECT_FALSE(olive::Tool::GetAddableObjectName(olive::Tool::kAddableSubtitle).isEmpty());
|
||||
}
|
||||
|
||||
TEST(ModuleSmoke, ToolAddableObjectIds)
|
||||
{
|
||||
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableEmpty), QStringLiteral("empty"));
|
||||
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableBars), QStringLiteral("bars"));
|
||||
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableShape), QStringLiteral("shape"));
|
||||
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableSolid), QStringLiteral("solid"));
|
||||
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableTitle), QStringLiteral("title"));
|
||||
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableTone), QStringLiteral("tone"));
|
||||
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableSubtitle), QStringLiteral("subtitle"));
|
||||
}
|
||||
|
||||
TEST(ModuleSmoke, HumanStringsSampleRate)
|
||||
{
|
||||
EXPECT_FALSE(olive::HumanStrings::SampleRateToString(48000).isEmpty());
|
||||
EXPECT_FALSE(olive::HumanStrings::SampleRateToString(44100).isEmpty());
|
||||
}
|
||||
|
||||
TEST(ModuleSmoke, HumanStringsChannelLayout)
|
||||
{
|
||||
EXPECT_FALSE(olive::HumanStrings::ChannelLayoutToString(AV_CH_LAYOUT_MONO).isEmpty());
|
||||
EXPECT_FALSE(olive::HumanStrings::ChannelLayoutToString(AV_CH_LAYOUT_STEREO).isEmpty());
|
||||
}
|
||||
|
||||
TEST(ModuleSmoke, HumanStringsFormat)
|
||||
{
|
||||
EXPECT_FALSE(olive::HumanStrings::FormatToString(olive::SampleFormat::U8).isEmpty());
|
||||
EXPECT_FALSE(olive::HumanStrings::FormatToString(olive::SampleFormat::F32).isEmpty());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "node/globals.h"
|
||||
#include "render/videoparams.h"
|
||||
#include "render/loopmode.h"
|
||||
|
||||
TEST(NodeGlobals, DefaultConstruction)
|
||||
{
|
||||
olive::NodeGlobals globals;
|
||||
EXPECT_EQ(globals.vparams().width(), 0);
|
||||
EXPECT_EQ(globals.vparams().height(), 0);
|
||||
EXPECT_EQ(globals.aparams().sample_rate(), 0);
|
||||
}
|
||||
|
||||
TEST(NodeGlobals, ConstructedWithParams)
|
||||
{
|
||||
olive::VideoParams video_params(1920, 1080, olive::PixelFormat::F32, 4);
|
||||
olive::AudioParams audio_params;
|
||||
audio_params.set_sample_rate(48000);
|
||||
audio_params.set_channel_layout(AV_CH_LAYOUT_STEREO);
|
||||
|
||||
olive::TimeRange time(olive::core::rational(1, 24), olive::core::rational(2, 24));
|
||||
olive::NodeGlobals globals(video_params, audio_params, time, olive::LoopMode::kLoopModeLoop);
|
||||
|
||||
EXPECT_EQ(globals.vparams().width(), 1920);
|
||||
EXPECT_EQ(globals.vparams().height(), 1080);
|
||||
EXPECT_EQ(globals.aparams().sample_rate(), 48000);
|
||||
EXPECT_EQ(globals.loop_mode(), olive::LoopMode::kLoopModeLoop);
|
||||
EXPECT_EQ(globals.time().in(), olive::core::rational(1, 24));
|
||||
EXPECT_EQ(globals.time().out(), olive::core::rational(2, 24));
|
||||
}
|
||||
|
||||
TEST(NodeGlobals, RationalConstructorExpandsToFrame)
|
||||
{
|
||||
olive::VideoParams video_params(1280, 720, olive::PixelFormat::F32, 4);
|
||||
video_params.set_frame_rate(24);
|
||||
olive::AudioParams audio_params;
|
||||
audio_params.set_sample_rate(44100);
|
||||
|
||||
olive::NodeGlobals globals(video_params, audio_params,
|
||||
olive::core::rational(0, 1),
|
||||
olive::LoopMode::kLoopModeClamp);
|
||||
|
||||
EXPECT_EQ(globals.time().in(), olive::core::rational(0, 1));
|
||||
EXPECT_EQ(globals.time().out(), olive::core::rational(1, 24));
|
||||
}
|
||||
@@ -45,3 +45,40 @@ TEST(NodeKeyframe, SaveLoadRoundTrip)
|
||||
EXPECT_DOUBLE_EQ(loaded.bezier_control_out().x(), 0.3);
|
||||
EXPECT_DOUBLE_EQ(loaded.bezier_control_out().y(), 0.4);
|
||||
}
|
||||
|
||||
TEST(NodeKeyframe, TypeEnumeration)
|
||||
{
|
||||
using olive::NodeKeyframe;
|
||||
|
||||
EXPECT_NE(NodeKeyframe::kLinear, NodeKeyframe::kHold);
|
||||
EXPECT_NE(NodeKeyframe::kLinear, NodeKeyframe::kBezier);
|
||||
}
|
||||
|
||||
TEST(NodeKeyframe, DefaultState)
|
||||
{
|
||||
olive::NodeKeyframe key;
|
||||
EXPECT_TRUE(key.input().isEmpty());
|
||||
EXPECT_EQ(key.time(), olive::core::rational(0, 1));
|
||||
EXPECT_EQ(key.type(), olive::NodeKeyframe::kLinear);
|
||||
EXPECT_TRUE(key.value().isNull());
|
||||
}
|
||||
|
||||
TEST(NodeKeyframe, SetValueRoundTrip)
|
||||
{
|
||||
olive::NodeKeyframe key;
|
||||
|
||||
key.set_value(QVariant::fromValue(olive::Color(0.1f, 0.2f, 0.3f, 1.0f)));
|
||||
const olive::Color c = key.value().value<olive::Color>();
|
||||
EXPECT_FLOAT_EQ(c.red(), 0.1f);
|
||||
EXPECT_FLOAT_EQ(c.green(), 0.2f);
|
||||
EXPECT_FLOAT_EQ(c.blue(), 0.3f);
|
||||
}
|
||||
|
||||
TEST(NodeKeyframe, BezierControlDefaults)
|
||||
{
|
||||
olive::NodeKeyframe key;
|
||||
EXPECT_DOUBLE_EQ(key.bezier_control_in().x(), 0.0);
|
||||
EXPECT_DOUBLE_EQ(key.bezier_control_in().y(), 0.0);
|
||||
EXPECT_DOUBLE_EQ(key.bezier_control_out().x(), 0.0);
|
||||
EXPECT_DOUBLE_EQ(key.bezier_control_out().y(), 0.0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "node/project.h"
|
||||
|
||||
TEST(NodeProject, DefaultsAfterConstruction)
|
||||
{
|
||||
olive::Project project;
|
||||
|
||||
EXPECT_EQ(project.filename(), QString());
|
||||
EXPECT_EQ(project.name(), QStringLiteral("(untitled)"));
|
||||
EXPECT_EQ(project.pretty_filename(), QStringLiteral("(untitled)"));
|
||||
EXPECT_TRUE(project.is_new());
|
||||
EXPECT_FALSE(project.is_modified());
|
||||
EXPECT_TRUE(project.has_autorecovery_been_saved());
|
||||
EXPECT_FALSE(project.GetUuid().isNull());
|
||||
EXPECT_NE(project.color_manager(), nullptr);
|
||||
EXPECT_EQ(project.root(), nullptr);
|
||||
EXPECT_TRUE(project.nodes().isEmpty());
|
||||
}
|
||||
|
||||
TEST(NodeProject, FilenameAndNameUpdate)
|
||||
{
|
||||
olive::Project project;
|
||||
|
||||
project.set_filename(QStringLiteral("/tmp/test_project.ove"));
|
||||
EXPECT_EQ(project.filename(), QStringLiteral("/tmp/test_project.ove"));
|
||||
EXPECT_EQ(project.name(), QStringLiteral("test_project"));
|
||||
EXPECT_EQ(project.pretty_filename(), QStringLiteral("/tmp/test_project.ove"));
|
||||
EXPECT_FALSE(project.is_new());
|
||||
}
|
||||
|
||||
TEST(NodeProject, ModifiedState)
|
||||
{
|
||||
olive::Project project;
|
||||
|
||||
project.set_modified(true);
|
||||
EXPECT_TRUE(project.is_modified());
|
||||
EXPECT_FALSE(project.has_autorecovery_been_saved());
|
||||
|
||||
project.set_modified(false);
|
||||
EXPECT_FALSE(project.is_modified());
|
||||
EXPECT_TRUE(project.has_autorecovery_been_saved());
|
||||
}
|
||||
|
||||
TEST(NodeProject, SettingsRoundTrip)
|
||||
{
|
||||
olive::Project project;
|
||||
|
||||
project.SetSetting(olive::Project::kCacheLocationSettingKey,
|
||||
QString::number(olive::Project::kCacheStoreAlongsideProject));
|
||||
EXPECT_EQ(project.GetCacheLocationSetting(),
|
||||
olive::Project::kCacheStoreAlongsideProject);
|
||||
|
||||
project.SetCustomCachePath(QStringLiteral("/tmp/cache"));
|
||||
EXPECT_EQ(project.GetCustomCachePath(), QStringLiteral("/tmp/cache"));
|
||||
|
||||
project.SetColorConfigFilename(QStringLiteral("config.ocio"));
|
||||
EXPECT_EQ(project.GetColorConfigFilename(), QStringLiteral("config.ocio"));
|
||||
|
||||
project.SetDefaultInputColorSpace(QStringLiteral("ACEScg"));
|
||||
EXPECT_EQ(project.GetDefaultInputColorSpace(), QStringLiteral("ACEScg"));
|
||||
|
||||
project.SetColorReferenceSpace(QStringLiteral("ACES - ACEScg"));
|
||||
EXPECT_EQ(project.GetColorReferenceSpace(), QStringLiteral("ACES - ACEScg"));
|
||||
}
|
||||
|
||||
TEST(NodeProject, InitializeCreatesRoot)
|
||||
{
|
||||
olive::Project project;
|
||||
EXPECT_EQ(project.root(), nullptr);
|
||||
|
||||
project.Initialize();
|
||||
EXPECT_NE(project.root(), nullptr);
|
||||
EXPECT_EQ(project.root()->GetLabel(), QStringLiteral("Root"));
|
||||
}
|
||||
|
||||
TEST(NodeProject, UuidCanBeRegenerated)
|
||||
{
|
||||
olive::Project project;
|
||||
const QUuid original = project.GetUuid();
|
||||
|
||||
project.RegenerateUuid();
|
||||
EXPECT_FALSE(project.GetUuid().isNull());
|
||||
EXPECT_NE(project.GetUuid(), original);
|
||||
}
|
||||
|
||||
TEST(NodeProject, GetProjectFromObject)
|
||||
{
|
||||
olive::Project project;
|
||||
olive::ColorManager *cm = project.color_manager();
|
||||
EXPECT_EQ(olive::Project::GetProjectFromObject(cm), &project);
|
||||
}
|
||||
|
||||
TEST(NodeProject, SaveProducesXml)
|
||||
{
|
||||
olive::Project project;
|
||||
project.Initialize();
|
||||
|
||||
QByteArray xml;
|
||||
QXmlStreamWriter writer(&xml);
|
||||
writer.writeStartDocument();
|
||||
writer.writeStartElement(QStringLiteral("project"));
|
||||
project.Save(&writer);
|
||||
writer.writeEndElement();
|
||||
writer.writeEndDocument();
|
||||
|
||||
EXPECT_FALSE(xml.isEmpty());
|
||||
EXPECT_TRUE(xml.contains("uuid"));
|
||||
}
|
||||
@@ -48,3 +48,80 @@ TEST(NodeValue, BinaryRoundTrip)
|
||||
olive::NodeValue::kBinary, encoded, false);
|
||||
EXPECT_EQ(decoded.toByteArray(), data);
|
||||
}
|
||||
|
||||
TEST(NodeValue, TypeClassification)
|
||||
{
|
||||
EXPECT_TRUE(olive::NodeValue::type_can_be_interpolated(olive::NodeValue::kFloat));
|
||||
EXPECT_TRUE(olive::NodeValue::type_can_be_interpolated(olive::NodeValue::kColor));
|
||||
EXPECT_FALSE(olive::NodeValue::type_can_be_interpolated(olive::NodeValue::kInt));
|
||||
|
||||
EXPECT_TRUE(olive::NodeValue::type_is_numeric(olive::NodeValue::kInt));
|
||||
EXPECT_TRUE(olive::NodeValue::type_is_numeric(olive::NodeValue::kFloat));
|
||||
EXPECT_FALSE(olive::NodeValue::type_is_numeric(olive::NodeValue::kText));
|
||||
|
||||
EXPECT_TRUE(olive::NodeValue::type_is_vector(olive::NodeValue::kVec2));
|
||||
EXPECT_TRUE(olive::NodeValue::type_is_vector(olive::NodeValue::kVec3));
|
||||
EXPECT_FALSE(olive::NodeValue::type_is_vector(olive::NodeValue::kFloat));
|
||||
|
||||
EXPECT_TRUE(olive::NodeValue::type_is_buffer(olive::NodeValue::kTexture));
|
||||
EXPECT_TRUE(olive::NodeValue::type_is_buffer(olive::NodeValue::kSamples));
|
||||
EXPECT_FALSE(olive::NodeValue::type_is_buffer(olive::NodeValue::kColor));
|
||||
}
|
||||
|
||||
TEST(NodeValue, DataTypeNameRoundTrip)
|
||||
{
|
||||
for (int i = olive::NodeValue::kNone; i < olive::NodeValue::kDataTypeCount; ++i) {
|
||||
auto type = static_cast<olive::NodeValue::Type>(i);
|
||||
QString name = olive::NodeValue::GetDataTypeName(type);
|
||||
if (name.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
EXPECT_EQ(olive::NodeValue::GetDataTypeFromName(name), type)
|
||||
<< name.toStdString();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(NodeValue, ConstructionAndAccessors)
|
||||
{
|
||||
olive::NodeValue val(olive::NodeValue::kInt, static_cast<int64_t>(42));
|
||||
EXPECT_EQ(val.type(), olive::NodeValue::kInt);
|
||||
EXPECT_EQ(val.toInt(), 42);
|
||||
EXPECT_TRUE(val);
|
||||
|
||||
val.set_tag(QStringLiteral("tag"));
|
||||
EXPECT_EQ(val.tag(), QStringLiteral("tag"));
|
||||
}
|
||||
|
||||
TEST(NodeValueTable, PushAndGet)
|
||||
{
|
||||
olive::NodeValueTable table;
|
||||
olive::NodeValue v(olive::NodeValue::kFloat, 3.14);
|
||||
table.Push(v);
|
||||
|
||||
EXPECT_EQ(table.Count(), 1);
|
||||
EXPECT_FALSE(table.isEmpty());
|
||||
EXPECT_TRUE(table.Has(olive::NodeValue::kFloat));
|
||||
|
||||
olive::NodeValue got = table.Get(olive::NodeValue::kFloat);
|
||||
EXPECT_DOUBLE_EQ(got.toDouble(), 3.14);
|
||||
}
|
||||
|
||||
TEST(NodeValueTable, TakeRemovesValue)
|
||||
{
|
||||
olive::NodeValueTable table;
|
||||
table.Push(olive::NodeValue(olive::NodeValue::kInt, static_cast<int64_t>(1)));
|
||||
table.Push(olive::NodeValue(olive::NodeValue::kInt, static_cast<int64_t>(2)));
|
||||
|
||||
olive::NodeValue taken = table.Take(olive::NodeValue::kInt);
|
||||
EXPECT_EQ(taken.toInt(), 2);
|
||||
EXPECT_EQ(table.Count(), 1);
|
||||
}
|
||||
|
||||
TEST(NodeValueTable, ClearEmptiesTable)
|
||||
{
|
||||
olive::NodeValueTable table;
|
||||
table.Push(olive::NodeValue(olive::NodeValue::kText, QStringLiteral("hello")));
|
||||
table.Clear();
|
||||
EXPECT_TRUE(table.isEmpty());
|
||||
EXPECT_EQ(table.Count(), 0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "render/alphaassoc.h"
|
||||
|
||||
TEST(AlphaAssociated, ValuesAreDistinct)
|
||||
{
|
||||
EXPECT_NE(olive::kAlphaNone, olive::kAlphaUnassociated);
|
||||
EXPECT_NE(olive::kAlphaNone, olive::kAlphaAssociated);
|
||||
EXPECT_NE(olive::kAlphaUnassociated, olive::kAlphaAssociated);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "render/loopmode.h"
|
||||
|
||||
TEST(LoopMode, ValuesAreDistinct)
|
||||
{
|
||||
EXPECT_NE(olive::LoopMode::kLoopModeOff, olive::LoopMode::kLoopModeLoop);
|
||||
EXPECT_NE(olive::LoopMode::kLoopModeOff, olive::LoopMode::kLoopModeClamp);
|
||||
EXPECT_NE(olive::LoopMode::kLoopModeLoop, olive::LoopMode::kLoopModeClamp);
|
||||
}
|
||||
@@ -11,9 +11,42 @@ TEST(Shaders, ResourcesAvailable)
|
||||
QStringLiteral(":/shaders/deinterlace2.frag"),
|
||||
QStringLiteral(":/shaders/rgbhistogram.frag"),
|
||||
QStringLiteral(":/shaders/rgbhistogram.vert"),
|
||||
QStringLiteral(":/shaders/rgbhistogram_secondary.frag"),
|
||||
QStringLiteral(":/shaders/rgbvectorscope.frag"),
|
||||
QStringLiteral(":/shaders/rgbvectorscope.vert"),
|
||||
QStringLiteral(":/shaders/threewaycolor.frag")
|
||||
QStringLiteral(":/shaders/rgbwaveform.frag"),
|
||||
QStringLiteral(":/shaders/rgbwaveform.vert"),
|
||||
QStringLiteral(":/shaders/threewaycolor.frag"),
|
||||
QStringLiteral(":/shaders/alphaover.frag"),
|
||||
QStringLiteral(":/shaders/blur.frag"),
|
||||
QStringLiteral(":/shaders/chromakey.frag"),
|
||||
QStringLiteral(":/shaders/colordifferencekey.frag"),
|
||||
QStringLiteral(":/shaders/colormanage.frag"),
|
||||
QStringLiteral(":/shaders/cornerpin.frag"),
|
||||
QStringLiteral(":/shaders/cornerpin.vert"),
|
||||
QStringLiteral(":/shaders/crop.frag"),
|
||||
QStringLiteral(":/shaders/crossdissolve.frag"),
|
||||
QStringLiteral(":/shaders/deinterlace.frag"),
|
||||
QStringLiteral(":/shaders/despill.frag"),
|
||||
QStringLiteral(":/shaders/diptoblack.frag"),
|
||||
QStringLiteral(":/shaders/dropshadow.frag"),
|
||||
QStringLiteral(":/shaders/flip.frag"),
|
||||
QStringLiteral(":/shaders/interlace.frag"),
|
||||
QStringLiteral(":/shaders/invertrgb.frag"),
|
||||
QStringLiteral(":/shaders/invertrgba.frag"),
|
||||
QStringLiteral(":/shaders/mosaic.frag"),
|
||||
QStringLiteral(":/shaders/multiply.frag"),
|
||||
QStringLiteral(":/shaders/noise.frag"),
|
||||
QStringLiteral(":/shaders/opacity.frag"),
|
||||
QStringLiteral(":/shaders/opacity_rgb.frag"),
|
||||
QStringLiteral(":/shaders/rgb.frag"),
|
||||
QStringLiteral(":/shaders/ripple.frag"),
|
||||
QStringLiteral(":/shaders/shape.frag"),
|
||||
QStringLiteral(":/shaders/solid.frag"),
|
||||
QStringLiteral(":/shaders/stroke.frag"),
|
||||
QStringLiteral(":/shaders/swirl.frag"),
|
||||
QStringLiteral(":/shaders/tile.frag"),
|
||||
QStringLiteral(":/shaders/wave.frag"),
|
||||
};
|
||||
|
||||
for (const QString &path : shader_paths) {
|
||||
|
||||
@@ -26,6 +26,42 @@ protected:
|
||||
private:
|
||||
bool *ran_ = nullptr;
|
||||
};
|
||||
|
||||
class FailingTask final : public olive::Task {
|
||||
public:
|
||||
FailingTask()
|
||||
{
|
||||
SetTitle(QStringLiteral("FailingTask"));
|
||||
}
|
||||
|
||||
protected:
|
||||
bool Run() override
|
||||
{
|
||||
SetError(QStringLiteral("expected failure"));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class ProgressTask final : public olive::Task {
|
||||
public:
|
||||
explicit ProgressTask(int steps)
|
||||
: steps_(steps)
|
||||
{
|
||||
SetTitle(QStringLiteral("ProgressTask"));
|
||||
}
|
||||
|
||||
protected:
|
||||
bool Run() override
|
||||
{
|
||||
for (int i = 0; i <= steps_; ++i) {
|
||||
emit ProgressChanged(static_cast<double>(i) / steps_);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
int steps_ = 1;
|
||||
};
|
||||
}
|
||||
|
||||
TEST(TaskManager, AddAndRunTask)
|
||||
@@ -50,3 +86,83 @@ TEST(TaskManager, AddAndRunTask)
|
||||
EXPECT_TRUE(ran);
|
||||
olive::TaskManager::DestroyInstance();
|
||||
}
|
||||
|
||||
TEST(TaskManager, FailedTaskEmitsTaskFailed)
|
||||
{
|
||||
olive::TaskManager::CreateInstance();
|
||||
olive::TaskManager *mgr = olive::TaskManager::instance();
|
||||
ASSERT_NE(mgr, nullptr);
|
||||
|
||||
FailingTask *task = new FailingTask();
|
||||
|
||||
QEventLoop loop;
|
||||
bool saw_failed = false;
|
||||
QObject::connect(mgr, &olive::TaskManager::TaskFailed, &loop,
|
||||
[&loop, &saw_failed](olive::Task *) {
|
||||
saw_failed = true;
|
||||
loop.quit();
|
||||
});
|
||||
QTimer::singleShot(5000, &loop, &QEventLoop::quit);
|
||||
|
||||
mgr->AddTask(task);
|
||||
loop.exec();
|
||||
|
||||
EXPECT_TRUE(saw_failed);
|
||||
EXPECT_FALSE(task->GetError().isEmpty());
|
||||
olive::TaskManager::DestroyInstance();
|
||||
}
|
||||
|
||||
TEST(TaskManager, ProgressSignalIsEmitted)
|
||||
{
|
||||
olive::TaskManager::CreateInstance();
|
||||
olive::TaskManager *mgr = olive::TaskManager::instance();
|
||||
ASSERT_NE(mgr, nullptr);
|
||||
|
||||
ProgressTask *task = new ProgressTask(4);
|
||||
|
||||
QEventLoop loop;
|
||||
QVector<double> progress;
|
||||
QObject::connect(task, &olive::Task::ProgressChanged, &loop,
|
||||
[&progress](double p) { progress.append(p); });
|
||||
QObject::connect(task, &olive::Task::Finished, &loop,
|
||||
[&loop](olive::Task *, bool) { loop.quit(); });
|
||||
QTimer::singleShot(5000, &loop, &QEventLoop::quit);
|
||||
|
||||
mgr->AddTask(task);
|
||||
loop.exec();
|
||||
|
||||
EXPECT_FALSE(progress.isEmpty());
|
||||
EXPECT_GE(progress.last(), 0.99);
|
||||
olive::TaskManager::DestroyInstance();
|
||||
}
|
||||
|
||||
TEST(TaskManager, MultipleTasksComplete)
|
||||
{
|
||||
olive::TaskManager::CreateInstance();
|
||||
olive::TaskManager *mgr = olive::TaskManager::instance();
|
||||
ASSERT_NE(mgr, nullptr);
|
||||
|
||||
bool ran1 = false;
|
||||
bool ran2 = false;
|
||||
DummyTask *task1 = new DummyTask(&ran1);
|
||||
DummyTask *task2 = new DummyTask(&ran2);
|
||||
|
||||
QEventLoop loop;
|
||||
int finished = 0;
|
||||
auto on_finished = [&loop, &finished](olive::Task *, bool) {
|
||||
if (++finished == 2) {
|
||||
loop.quit();
|
||||
}
|
||||
};
|
||||
QObject::connect(task1, &olive::Task::Finished, &loop, on_finished);
|
||||
QObject::connect(task2, &olive::Task::Finished, &loop, on_finished);
|
||||
QTimer::singleShot(5000, &loop, &QEventLoop::quit);
|
||||
|
||||
mgr->AddTask(task1);
|
||||
mgr->AddTask(task2);
|
||||
loop.exec();
|
||||
|
||||
EXPECT_TRUE(ran1);
|
||||
EXPECT_TRUE(ran2);
|
||||
olive::TaskManager::DestroyInstance();
|
||||
}
|
||||
|
||||
@@ -32,3 +32,36 @@ TEST(TimelineCoordinate, Constructors)
|
||||
EXPECT_EQ(with_type.GetTrack().type(), olive::Track::kSubtitle);
|
||||
EXPECT_EQ(with_type.GetTrack().index(), 3);
|
||||
}
|
||||
|
||||
TEST(TimelineCoordinate, CopyAndAssignment)
|
||||
{
|
||||
const olive::core::rational frame(7, 1);
|
||||
olive::Track::Reference ref(olive::Track::kVideo, 4);
|
||||
|
||||
olive::TimelineCoordinate original(frame, ref);
|
||||
olive::TimelineCoordinate copy(original);
|
||||
EXPECT_EQ(copy.GetFrame(), frame);
|
||||
EXPECT_EQ(copy.GetTrack(), ref);
|
||||
|
||||
olive::TimelineCoordinate assigned;
|
||||
assigned = original;
|
||||
EXPECT_EQ(assigned.GetFrame(), frame);
|
||||
EXPECT_EQ(assigned.GetTrack(), ref);
|
||||
}
|
||||
|
||||
TEST(TimelineCoordinate, Equality)
|
||||
{
|
||||
olive::TimelineCoordinate a(olive::core::rational(5, 1),
|
||||
olive::Track::Reference(olive::Track::kVideo, 1));
|
||||
olive::TimelineCoordinate b(olive::core::rational(5, 1),
|
||||
olive::Track::Reference(olive::Track::kVideo, 1));
|
||||
olive::TimelineCoordinate c(olive::core::rational(6, 1),
|
||||
olive::Track::Reference(olive::Track::kVideo, 1));
|
||||
olive::TimelineCoordinate d(olive::core::rational(5, 1),
|
||||
olive::Track::Reference(olive::Track::kAudio, 1));
|
||||
|
||||
EXPECT_EQ(a.GetFrame(), b.GetFrame());
|
||||
EXPECT_EQ(a.GetTrack(), b.GetTrack());
|
||||
EXPECT_NE(a.GetFrame(), c.GetFrame());
|
||||
EXPECT_NE(a.GetTrack(), d.GetTrack());
|
||||
}
|
||||
|
||||
@@ -37,6 +37,13 @@ TEST(TimelineMarker, SaveLoadRoundTrip)
|
||||
EXPECT_EQ(loaded.color(), 5);
|
||||
}
|
||||
|
||||
TEST(TimelineMarker, DefaultConstruction)
|
||||
{
|
||||
olive::TimelineMarker marker;
|
||||
EXPECT_TRUE(marker.name().isEmpty());
|
||||
EXPECT_EQ(marker.time().in(), olive::core::rational(0, 1));
|
||||
}
|
||||
|
||||
TEST(TimelineMarkerList, OrderAndLookup)
|
||||
{
|
||||
olive::TimelineMarkerList list;
|
||||
@@ -74,6 +81,13 @@ TEST(TimelineMarkerList, OrderAndLookup)
|
||||
&marker_a);
|
||||
}
|
||||
|
||||
TEST(TimelineMarkerList, GetMarkerAtTimeReturnsNullWhenEmpty)
|
||||
{
|
||||
olive::TimelineMarkerList list;
|
||||
EXPECT_EQ(list.GetMarkerAtTime(olive::core::rational(10, 1)), nullptr);
|
||||
EXPECT_EQ(list.GetClosestMarkerToTime(olive::core::rational(10, 1)), nullptr);
|
||||
}
|
||||
|
||||
TEST(TimelineMarkerList, SaveLoadWithUnknownElements)
|
||||
{
|
||||
olive::TimelineMarkerList list;
|
||||
@@ -158,3 +172,18 @@ TEST(TimelineMarkerCommands, AddRemoveAndChange)
|
||||
move.undo_now();
|
||||
EXPECT_EQ(list.front()->time().in(), olive::core::rational(1, 1));
|
||||
}
|
||||
|
||||
TEST(TimelineMarkerCommands, AddCommandUndo)
|
||||
{
|
||||
olive::TimelineMarkerList list;
|
||||
olive::MarkerAddCommand add(
|
||||
&list,
|
||||
olive::core::TimeRange(olive::core::rational(5, 1),
|
||||
olive::core::rational(5, 1)),
|
||||
QStringLiteral("UndoMe"),
|
||||
2);
|
||||
add.redo_now();
|
||||
EXPECT_EQ(list.size(), 1);
|
||||
add.undo_now();
|
||||
EXPECT_TRUE(list.empty());
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ TEST(TimelineWorkArea, SaveLoadRoundTrip)
|
||||
olive::TimelineWorkArea workarea;
|
||||
workarea.set_enabled(true);
|
||||
workarea.set_range(olive::core::TimeRange(olive::core::rational(2, 1),
|
||||
olive::core::rational(6, 1)));
|
||||
olive::core::rational(6, 1)));
|
||||
|
||||
QByteArray xml;
|
||||
QBuffer buffer(&xml);
|
||||
@@ -51,5 +51,47 @@ TEST(TimelineWorkArea, SaveLoadRoundTrip)
|
||||
EXPECT_TRUE(loaded.enabled());
|
||||
EXPECT_EQ(loaded.range(),
|
||||
olive::core::TimeRange(olive::core::rational(2, 1),
|
||||
olive::core::rational(6, 1)));
|
||||
olive::core::rational(6, 1)));
|
||||
}
|
||||
|
||||
TEST(TimelineWorkArea, DisabledWorkAreaRoundTrip)
|
||||
{
|
||||
olive::TimelineWorkArea workarea;
|
||||
workarea.set_enabled(false);
|
||||
workarea.set_range(olive::core::TimeRange(olive::core::rational(0, 1),
|
||||
olive::core::rational(10, 1)));
|
||||
|
||||
QByteArray xml;
|
||||
QBuffer buffer(&xml);
|
||||
ASSERT_TRUE(buffer.open(QIODevice::WriteOnly));
|
||||
QXmlStreamWriter writer(&buffer);
|
||||
writer.writeStartDocument();
|
||||
writer.writeStartElement(QStringLiteral("workarea"));
|
||||
workarea.save(&writer);
|
||||
writer.writeEndElement();
|
||||
writer.writeEndDocument();
|
||||
buffer.close();
|
||||
|
||||
olive::TimelineWorkArea loaded;
|
||||
QBuffer read_buffer(&xml);
|
||||
ASSERT_TRUE(read_buffer.open(QIODevice::ReadOnly));
|
||||
QXmlStreamReader reader(&read_buffer);
|
||||
ASSERT_TRUE(reader.readNextStartElement());
|
||||
EXPECT_TRUE(loaded.load(&reader));
|
||||
|
||||
EXPECT_FALSE(loaded.enabled());
|
||||
EXPECT_EQ(loaded.range(),
|
||||
olive::core::TimeRange(olive::core::rational(0, 1),
|
||||
olive::core::rational(10, 1)));
|
||||
}
|
||||
|
||||
TEST(TimelineWorkArea, SetRangeUpdatesInOut)
|
||||
{
|
||||
olive::TimelineWorkArea workarea;
|
||||
workarea.set_range(olive::core::TimeRange(olive::core::rational(3, 1),
|
||||
olive::core::rational(8, 1)));
|
||||
|
||||
EXPECT_EQ(workarea.in(), olive::core::rational(3, 1));
|
||||
EXPECT_EQ(workarea.out(), olive::core::rational(8, 1));
|
||||
EXPECT_EQ(workarea.length(), olive::core::rational(5, 1));
|
||||
}
|
||||
|
||||
@@ -120,3 +120,68 @@ TEST(UndoStack, EmptyMultiUndoCommandIsIgnored)
|
||||
EXPECT_EQ(stack.rowCount(), 1);
|
||||
EXPECT_FALSE(stack.CanUndo());
|
||||
}
|
||||
|
||||
TEST(UndoStack, MultipleUndosAndRedos)
|
||||
{
|
||||
int counter = 0;
|
||||
olive::UndoStack stack;
|
||||
stack.push(new TestCommand(&counter), QStringLiteral("One"));
|
||||
stack.push(new TestCommand(&counter), QStringLiteral("Two"));
|
||||
stack.push(new TestCommand(&counter), QStringLiteral("Three"));
|
||||
EXPECT_EQ(counter, 3);
|
||||
|
||||
stack.undo();
|
||||
stack.undo();
|
||||
EXPECT_EQ(counter, 1);
|
||||
EXPECT_TRUE(stack.CanUndo());
|
||||
EXPECT_TRUE(stack.CanRedo());
|
||||
|
||||
stack.redo();
|
||||
EXPECT_EQ(counter, 2);
|
||||
}
|
||||
|
||||
TEST(UndoStack, PushAfterUndoClearsRedoBranch)
|
||||
{
|
||||
int counter = 0;
|
||||
olive::UndoStack stack;
|
||||
stack.push(new TestCommand(&counter), QStringLiteral("First"));
|
||||
stack.push(new TestCommand(&counter), QStringLiteral("Second"));
|
||||
EXPECT_EQ(counter, 2);
|
||||
|
||||
stack.undo();
|
||||
EXPECT_EQ(counter, 1);
|
||||
|
||||
stack.push(new TestCommand(&counter), QStringLiteral("Third"));
|
||||
EXPECT_EQ(counter, 2);
|
||||
EXPECT_FALSE(stack.CanRedo());
|
||||
}
|
||||
|
||||
TEST(UndoStack, ResetClearsHistory)
|
||||
{
|
||||
int counter = 0;
|
||||
olive::UndoStack stack;
|
||||
stack.push(new TestCommand(&counter), QStringLiteral("Action"));
|
||||
EXPECT_EQ(counter, 1);
|
||||
|
||||
stack.clear();
|
||||
EXPECT_FALSE(stack.CanUndo());
|
||||
EXPECT_FALSE(stack.CanRedo());
|
||||
EXPECT_EQ(stack.rowCount(), 1);
|
||||
}
|
||||
|
||||
TEST(UndoStack, MultiUndoCommandWithChildren)
|
||||
{
|
||||
int counter = 0;
|
||||
olive::UndoStack stack;
|
||||
|
||||
auto *multi = new olive::MultiUndoCommand();
|
||||
multi->add_child(new TestCommand(&counter));
|
||||
multi->add_child(new TestCommand(&counter));
|
||||
stack.push(multi, QStringLiteral("Multi"));
|
||||
|
||||
EXPECT_EQ(counter, 2);
|
||||
stack.undo();
|
||||
EXPECT_EQ(counter, 0);
|
||||
stack.redo();
|
||||
EXPECT_EQ(counter, 2);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user