test: expand gtest coverage for common/core utilities
Add unit tests for: - CommandLineParser, Debug handler, Decibel, Digit, JobTime, FFmpegUtils - Core StringUtils, Timecode, TimeRange, Bezier, Color - Extend Frame tests to cover pixel access, interlace, conversion Coverage improvements (app + ext/core): - commandlineparser.cpp: 0% -> 93% - debug.cpp: 0% -> 85% - decibel.h: 25% -> 88% - digit.h: 0% -> 100% - ffmpegutils.cpp: 29% -> 90% - frame.cpp: 53% -> 97% - bezier.cpp: 16% -> 98% - color.cpp: 13% -> 71% - Overall line coverage: 17% -> 19%
This commit is contained in:
@@ -5,6 +5,12 @@ add_executable(olive-gtest
|
|||||||
common_range_test.cpp
|
common_range_test.cpp
|
||||||
common_filefunctions_test.cpp
|
common_filefunctions_test.cpp
|
||||||
common_qtutils_test.cpp
|
common_qtutils_test.cpp
|
||||||
|
common_commandlineparser_test.cpp
|
||||||
|
common_debug_test.cpp
|
||||||
|
common_decibel_test.cpp
|
||||||
|
common_digit_test.cpp
|
||||||
|
common_jobtime_test.cpp
|
||||||
|
common_ffmpegutils_test.cpp
|
||||||
config_test.cpp
|
config_test.cpp
|
||||||
audio_level_meter_test.cpp
|
audio_level_meter_test.cpp
|
||||||
audio_synchronizer_test.cpp
|
audio_synchronizer_test.cpp
|
||||||
@@ -16,6 +22,11 @@ add_executable(olive-gtest
|
|||||||
node_globals_test.cpp
|
node_globals_test.cpp
|
||||||
node_project_test.cpp
|
node_project_test.cpp
|
||||||
render_videoparams_test.cpp
|
render_videoparams_test.cpp
|
||||||
|
core_stringutils_test.cpp
|
||||||
|
core_timecode_test.cpp
|
||||||
|
core_timerange_test.cpp
|
||||||
|
core_bezier_test.cpp
|
||||||
|
core_color_test.cpp
|
||||||
render_videoparams_branch_test.cpp
|
render_videoparams_branch_test.cpp
|
||||||
render_audioparams_test.cpp
|
render_audioparams_test.cpp
|
||||||
render_audioparams_branch_test.cpp
|
render_audioparams_branch_test.cpp
|
||||||
|
|||||||
@@ -54,3 +54,133 @@ TEST(CodecFrame, DestroyDeallocatesData)
|
|||||||
EXPECT_FALSE(frame->is_allocated());
|
EXPECT_FALSE(frame->is_allocated());
|
||||||
EXPECT_EQ(frame->data(), nullptr);
|
EXPECT_EQ(frame->data(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(CodecFrame, AllocateInvalidParamsFails)
|
||||||
|
{
|
||||||
|
olive::Frame frame;
|
||||||
|
EXPECT_FALSE(frame.allocate());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CodecFrame, DoubleAllocateReturnsTrue)
|
||||||
|
{
|
||||||
|
olive::VideoParams params(8, 8, olive::core::PixelFormat::U8,
|
||||||
|
olive::VideoParams::kRGBAChannelCount);
|
||||||
|
olive::FramePtr frame = olive::Frame::Create();
|
||||||
|
frame->set_video_params(params);
|
||||||
|
EXPECT_TRUE(frame->allocate());
|
||||||
|
EXPECT_TRUE(frame->allocate());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CodecFrame, ContainsPixel)
|
||||||
|
{
|
||||||
|
olive::VideoParams params(8, 8, olive::core::PixelFormat::U8,
|
||||||
|
olive::VideoParams::kRGBAChannelCount);
|
||||||
|
olive::FramePtr frame = olive::Frame::Create();
|
||||||
|
frame->set_video_params(params);
|
||||||
|
|
||||||
|
EXPECT_FALSE(frame->contains_pixel(0, 0));
|
||||||
|
|
||||||
|
frame->allocate();
|
||||||
|
EXPECT_TRUE(frame->contains_pixel(0, 0));
|
||||||
|
EXPECT_TRUE(frame->contains_pixel(7, 7));
|
||||||
|
EXPECT_FALSE(frame->contains_pixel(8, 0));
|
||||||
|
EXPECT_FALSE(frame->contains_pixel(0, 8));
|
||||||
|
EXPECT_FALSE(frame->contains_pixel(-1, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CodecFrame, GetPixelOutOfBoundsReturnsBlack)
|
||||||
|
{
|
||||||
|
olive::VideoParams params(8, 8, olive::core::PixelFormat::U8,
|
||||||
|
olive::VideoParams::kRGBAChannelCount);
|
||||||
|
olive::FramePtr frame = olive::Frame::Create();
|
||||||
|
frame->set_video_params(params);
|
||||||
|
frame->allocate();
|
||||||
|
|
||||||
|
olive::core::Color c = frame->get_pixel(-1, 0);
|
||||||
|
EXPECT_FLOAT_EQ(c.red(), 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CodecFrame, SetAndGetPixel)
|
||||||
|
{
|
||||||
|
olive::VideoParams params(8, 8, olive::core::PixelFormat::U8,
|
||||||
|
olive::VideoParams::kRGBAChannelCount);
|
||||||
|
olive::FramePtr frame = olive::Frame::Create();
|
||||||
|
frame->set_video_params(params);
|
||||||
|
frame->allocate();
|
||||||
|
|
||||||
|
olive::core::Color red(1.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
frame->set_pixel(3, 3, red);
|
||||||
|
|
||||||
|
olive::core::Color got = frame->get_pixel(3, 3);
|
||||||
|
EXPECT_NEAR(got.red(), 1.0f, 0.01f);
|
||||||
|
EXPECT_NEAR(got.green(), 0.0f, 0.01f);
|
||||||
|
EXPECT_NEAR(got.blue(), 0.0f, 0.01f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CodecFrame, TimestampRoundTrip)
|
||||||
|
{
|
||||||
|
olive::FramePtr frame = olive::Frame::Create();
|
||||||
|
frame->set_timestamp(olive::core::rational(5, 1));
|
||||||
|
EXPECT_EQ(frame->timestamp(), olive::core::rational(5, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CodecFrame, GenerateLineSizeBytes)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(olive::Frame::generate_linesize_bytes(
|
||||||
|
64, olive::core::PixelFormat::U8,
|
||||||
|
olive::VideoParams::kRGBAChannelCount),
|
||||||
|
64 * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CodecFrame, InterlaceFrames)
|
||||||
|
{
|
||||||
|
olive::VideoParams params(4, 4, olive::core::PixelFormat::U8,
|
||||||
|
olive::VideoParams::kRGBAChannelCount);
|
||||||
|
|
||||||
|
olive::FramePtr top = olive::Frame::Create();
|
||||||
|
top->set_video_params(params);
|
||||||
|
top->allocate();
|
||||||
|
memset(top->data(), 0xFF, top->allocated_size());
|
||||||
|
|
||||||
|
olive::FramePtr bottom = olive::Frame::Create();
|
||||||
|
bottom->set_video_params(params);
|
||||||
|
bottom->allocate();
|
||||||
|
memset(bottom->data(), 0x00, bottom->allocated_size());
|
||||||
|
|
||||||
|
olive::FramePtr interlaced = olive::Frame::Interlace(top, bottom);
|
||||||
|
ASSERT_NE(interlaced, nullptr);
|
||||||
|
EXPECT_EQ(interlaced->width(), 4);
|
||||||
|
EXPECT_EQ(interlaced->height(), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CodecFrame, InterlaceIncompatibleReturnsNull)
|
||||||
|
{
|
||||||
|
olive::FramePtr top = olive::Frame::Create();
|
||||||
|
top->set_video_params(olive::VideoParams(
|
||||||
|
4, 4, olive::core::PixelFormat::U8, olive::VideoParams::kRGBAChannelCount));
|
||||||
|
top->allocate();
|
||||||
|
|
||||||
|
olive::FramePtr bottom = olive::Frame::Create();
|
||||||
|
bottom->set_video_params(olive::VideoParams(
|
||||||
|
8, 8, olive::core::PixelFormat::U8, olive::VideoParams::kRGBAChannelCount));
|
||||||
|
bottom->allocate();
|
||||||
|
|
||||||
|
EXPECT_EQ(olive::Frame::Interlace(top, bottom), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CodecFrame, ConvertU8ToU16)
|
||||||
|
{
|
||||||
|
olive::VideoParams params(4, 4, olive::core::PixelFormat::U8,
|
||||||
|
olive::VideoParams::kRGBAChannelCount);
|
||||||
|
olive::FramePtr frame = olive::Frame::Create();
|
||||||
|
frame->set_video_params(params);
|
||||||
|
frame->allocate();
|
||||||
|
|
||||||
|
olive::FramePtr converted =
|
||||||
|
frame->convert(olive::core::PixelFormat::U16);
|
||||||
|
ASSERT_NE(converted, nullptr);
|
||||||
|
EXPECT_EQ(converted->format(), olive::core::PixelFormat::U16);
|
||||||
|
EXPECT_EQ(converted->width(), 4);
|
||||||
|
EXPECT_EQ(converted->height(), 4);
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "common/commandlineparser.h"
|
||||||
|
|
||||||
|
TEST(CommonCommandLineParser, OptionWithoutArgument)
|
||||||
|
{
|
||||||
|
CommandLineParser parser;
|
||||||
|
const CommandLineParser::Option *opt = parser.AddOption(
|
||||||
|
{QStringLiteral("help"), QStringLiteral("h")},
|
||||||
|
QStringLiteral("Show help"), false);
|
||||||
|
|
||||||
|
parser.Process({QStringLiteral("app"), QStringLiteral("-help")});
|
||||||
|
|
||||||
|
EXPECT_TRUE(opt->IsSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonCommandLineParser, ShortOption)
|
||||||
|
{
|
||||||
|
CommandLineParser parser;
|
||||||
|
const CommandLineParser::Option *opt = parser.AddOption(
|
||||||
|
{QStringLiteral("help"), QStringLiteral("h")},
|
||||||
|
QStringLiteral("Show help"), false);
|
||||||
|
|
||||||
|
parser.Process({QStringLiteral("app"), QStringLiteral("-h")});
|
||||||
|
|
||||||
|
EXPECT_TRUE(opt->IsSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonCommandLineParser, OptionWithArgument)
|
||||||
|
{
|
||||||
|
CommandLineParser parser;
|
||||||
|
const CommandLineParser::Option *opt = parser.AddOption(
|
||||||
|
{QStringLiteral("project")}, QStringLiteral("Project file"), true,
|
||||||
|
QStringLiteral("file"));
|
||||||
|
|
||||||
|
parser.Process({QStringLiteral("app"), QStringLiteral("-project"),
|
||||||
|
QStringLiteral("test.ove")});
|
||||||
|
|
||||||
|
EXPECT_TRUE(opt->IsSet());
|
||||||
|
EXPECT_EQ(opt->GetSetting(), QStringLiteral("test.ove"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonCommandLineParser, PositionalArgument)
|
||||||
|
{
|
||||||
|
CommandLineParser parser;
|
||||||
|
const CommandLineParser::PositionalArgument *arg =
|
||||||
|
parser.AddPositionalArgument(QStringLiteral("filename"),
|
||||||
|
QStringLiteral("Project file"), true);
|
||||||
|
|
||||||
|
parser.Process({QStringLiteral("app"), QStringLiteral("test.ove")});
|
||||||
|
|
||||||
|
EXPECT_EQ(arg->GetSetting(), QStringLiteral("test.ove"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonCommandLineParser, UnknownOptionWarning)
|
||||||
|
{
|
||||||
|
CommandLineParser parser;
|
||||||
|
parser.AddOption({QStringLiteral("known")}, QStringLiteral("Known"));
|
||||||
|
|
||||||
|
// Should not crash; unknown option is logged
|
||||||
|
parser.Process({QStringLiteral("app"), QStringLiteral("-unknown")});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonCommandLineParser, UnknownPositionalWarning)
|
||||||
|
{
|
||||||
|
CommandLineParser parser;
|
||||||
|
|
||||||
|
// Should not crash; unknown positional is logged
|
||||||
|
parser.Process({QStringLiteral("app"), QStringLiteral("extra")});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonCommandLineParser, HiddenOptionExcludedFromHelp)
|
||||||
|
{
|
||||||
|
CommandLineParser parser;
|
||||||
|
parser.AddOption({QStringLiteral("visible")}, QStringLiteral("Visible"));
|
||||||
|
parser.AddOption({QStringLiteral("hidden")}, QStringLiteral("Hidden"),
|
||||||
|
false, QString(), true);
|
||||||
|
parser.AddPositionalArgument(QStringLiteral("file"),
|
||||||
|
QStringLiteral("Input file"));
|
||||||
|
|
||||||
|
// Should not crash; hidden option should be skipped during help output
|
||||||
|
parser.PrintHelp("/usr/bin/app");
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "common/debug.h"
|
||||||
|
|
||||||
|
TEST(CommonDebug, DebugHandlerFormatsAllLevels)
|
||||||
|
{
|
||||||
|
// Install handler and restore after test
|
||||||
|
QtMessageHandler old = qInstallMessageHandler(olive::DebugHandler);
|
||||||
|
|
||||||
|
qDebug() << "debug message";
|
||||||
|
qInfo() << "info message";
|
||||||
|
qWarning() << "warning message";
|
||||||
|
qCritical() << "critical message";
|
||||||
|
|
||||||
|
qInstallMessageHandler(old);
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "common/decibel.h"
|
||||||
|
|
||||||
|
TEST(CommonDecibel, FromLinearZeroReturnsMinimum)
|
||||||
|
{
|
||||||
|
EXPECT_DOUBLE_EQ(olive::Decibel::fromLinear(0.0), olive::Decibel::MINIMUM);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonDecibel, FromLinearOneReturnsZero)
|
||||||
|
{
|
||||||
|
EXPECT_DOUBLE_EQ(olive::Decibel::fromLinear(1.0), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonDecibel, FromLinearTenReturnsTwenty)
|
||||||
|
{
|
||||||
|
EXPECT_DOUBLE_EQ(olive::Decibel::fromLinear(10.0), 20.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonDecibel, ToLinearZeroReturnsOne)
|
||||||
|
{
|
||||||
|
EXPECT_DOUBLE_EQ(olive::Decibel::toLinear(0.0), 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonDecibel, ToLinearMinimumReturnsZero)
|
||||||
|
{
|
||||||
|
EXPECT_DOUBLE_EQ(olive::Decibel::toLinear(olive::Decibel::MINIMUM), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonDecibel, ToLinearTwentyReturnsTen)
|
||||||
|
{
|
||||||
|
EXPECT_DOUBLE_EQ(olive::Decibel::toLinear(20.0), 10.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonDecibel, FromLogarithmicAtEdges)
|
||||||
|
{
|
||||||
|
EXPECT_DOUBLE_EQ(olive::Decibel::fromLogarithmic(0.0),
|
||||||
|
olive::Decibel::MINIMUM);
|
||||||
|
EXPECT_DOUBLE_EQ(olive::Decibel::fromLogarithmic(1.0), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonDecibel, ToLogarithmicAtEdges)
|
||||||
|
{
|
||||||
|
EXPECT_DOUBLE_EQ(olive::Decibel::toLogarithmic(0.0), 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonDecibel, LinearLogarithmicRoundTrip)
|
||||||
|
{
|
||||||
|
EXPECT_NEAR(olive::Decibel::LogarithmicToLinear(
|
||||||
|
olive::Decibel::LinearToLogarithmic(0.5)),
|
||||||
|
0.5, 1e-6);
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "common/digit.h"
|
||||||
|
|
||||||
|
TEST(CommonDigit, SingleDigit)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(olive::GetDigitCount(0), 1);
|
||||||
|
EXPECT_EQ(olive::GetDigitCount(5), 1);
|
||||||
|
EXPECT_EQ(olive::GetDigitCount(-5), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonDigit, MultipleDigits)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(olive::GetDigitCount(10), 2);
|
||||||
|
EXPECT_EQ(olive::GetDigitCount(999), 3);
|
||||||
|
EXPECT_EQ(olive::GetDigitCount(1000), 4);
|
||||||
|
EXPECT_EQ(olive::GetDigitCount(-12345), 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonDigit, LargeValue)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(olive::GetDigitCount(123456789012345LL), 15);
|
||||||
|
}
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "common/ffmpegutils.h"
|
||||||
|
|
||||||
|
using namespace olive;
|
||||||
|
|
||||||
|
TEST(CommonFFmpegUtils, GetNativeSampleFormatMapsCorrectly)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_U8),
|
||||||
|
SampleFormat::U8);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_S16),
|
||||||
|
SampleFormat::S16);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_S32),
|
||||||
|
SampleFormat::S32);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_S64),
|
||||||
|
SampleFormat::S64);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_FLT),
|
||||||
|
SampleFormat::F32);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_DBL),
|
||||||
|
SampleFormat::F64);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_U8P),
|
||||||
|
SampleFormat::U8P);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_S16P),
|
||||||
|
SampleFormat::S16P);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_S32P),
|
||||||
|
SampleFormat::S32P);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_S64P),
|
||||||
|
SampleFormat::S64P);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_FLTP),
|
||||||
|
SampleFormat::F32P);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_DBLP),
|
||||||
|
SampleFormat::F64P);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_NONE),
|
||||||
|
SampleFormat::INVALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonFFmpegUtils, GetFFmpegSampleFormatMapsCorrectly)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::U8),
|
||||||
|
AV_SAMPLE_FMT_U8);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::S16),
|
||||||
|
AV_SAMPLE_FMT_S16);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::S32),
|
||||||
|
AV_SAMPLE_FMT_S32);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::S64),
|
||||||
|
AV_SAMPLE_FMT_S64);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::F32),
|
||||||
|
AV_SAMPLE_FMT_FLT);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::F64),
|
||||||
|
AV_SAMPLE_FMT_DBL);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::U8P),
|
||||||
|
AV_SAMPLE_FMT_U8P);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::S16P),
|
||||||
|
AV_SAMPLE_FMT_S16P);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::S32P),
|
||||||
|
AV_SAMPLE_FMT_S32P);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::S64P),
|
||||||
|
AV_SAMPLE_FMT_S64P);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::F32P),
|
||||||
|
AV_SAMPLE_FMT_FLTP);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::F64P),
|
||||||
|
AV_SAMPLE_FMT_DBLP);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::INVALID),
|
||||||
|
AV_SAMPLE_FMT_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonFFmpegUtils, GetSwsColorspaceFromAVColorSpace)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_BT709),
|
||||||
|
SWS_CS_ITU709);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_FCC),
|
||||||
|
SWS_CS_FCC);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_BT470BG),
|
||||||
|
SWS_CS_ITU624);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_SMPTE170M),
|
||||||
|
SWS_CS_SMPTE170M);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_SMPTE240M),
|
||||||
|
SWS_CS_SMPTE240M);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_BT2020_NCL),
|
||||||
|
SWS_CS_BT2020);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_UNSPECIFIED),
|
||||||
|
SWS_CS_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonFFmpegUtils, ConvertJPEGSpaceToRegularSpace)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(FFmpegUtils::ConvertJPEGSpaceToRegularSpace(AV_PIX_FMT_YUVJ420P),
|
||||||
|
AV_PIX_FMT_YUV420P);
|
||||||
|
EXPECT_EQ(FFmpegUtils::ConvertJPEGSpaceToRegularSpace(AV_PIX_FMT_YUVJ422P),
|
||||||
|
AV_PIX_FMT_YUV422P);
|
||||||
|
EXPECT_EQ(FFmpegUtils::ConvertJPEGSpaceToRegularSpace(AV_PIX_FMT_YUVJ444P),
|
||||||
|
AV_PIX_FMT_YUV444P);
|
||||||
|
EXPECT_EQ(FFmpegUtils::ConvertJPEGSpaceToRegularSpace(AV_PIX_FMT_YUVJ440P),
|
||||||
|
AV_PIX_FMT_YUV440P);
|
||||||
|
EXPECT_EQ(FFmpegUtils::ConvertJPEGSpaceToRegularSpace(AV_PIX_FMT_YUVJ411P),
|
||||||
|
AV_PIX_FMT_YUV411P);
|
||||||
|
EXPECT_EQ(FFmpegUtils::ConvertJPEGSpaceToRegularSpace(AV_PIX_FMT_YUV420P),
|
||||||
|
AV_PIX_FMT_YUV420P);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonFFmpegUtils, GetCompatiblePixelFormatNative)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetCompatiblePixelFormat(PixelFormat::U8),
|
||||||
|
PixelFormat::U8);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetCompatiblePixelFormat(PixelFormat::U10),
|
||||||
|
PixelFormat::U8);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetCompatiblePixelFormat(PixelFormat::U16),
|
||||||
|
PixelFormat::U16);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetCompatiblePixelFormat(PixelFormat::F16),
|
||||||
|
PixelFormat::U16);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetCompatiblePixelFormat(PixelFormat::F32),
|
||||||
|
PixelFormat::U16);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetCompatiblePixelFormat(PixelFormat::INVALID),
|
||||||
|
PixelFormat::INVALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonFFmpegUtils, GetFFmpegPixelFormat)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::U8,
|
||||||
|
VideoParams::kRGBChannelCount),
|
||||||
|
AV_PIX_FMT_RGB24);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::U16,
|
||||||
|
VideoParams::kRGBChannelCount),
|
||||||
|
AV_PIX_FMT_RGB48);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::F32,
|
||||||
|
VideoParams::kRGBChannelCount),
|
||||||
|
AV_PIX_FMT_RGBF32);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::U8,
|
||||||
|
VideoParams::kRGBAChannelCount),
|
||||||
|
AV_PIX_FMT_RGBA);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::U16,
|
||||||
|
VideoParams::kRGBAChannelCount),
|
||||||
|
AV_PIX_FMT_RGBA64);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::F32,
|
||||||
|
VideoParams::kRGBAChannelCount),
|
||||||
|
AV_PIX_FMT_RGBAF32);
|
||||||
|
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::INVALID, 0),
|
||||||
|
AV_PIX_FMT_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonFFmpegUtils, GetCompatiblePixelFormatAV)
|
||||||
|
{
|
||||||
|
AVPixelFormat fmt = FFmpegUtils::GetCompatiblePixelFormat(AV_PIX_FMT_YUV420P);
|
||||||
|
EXPECT_NE(fmt, AV_PIX_FMT_NONE);
|
||||||
|
|
||||||
|
fmt = FFmpegUtils::GetCompatiblePixelFormat(AV_PIX_FMT_YUV420P,
|
||||||
|
PixelFormat::U8);
|
||||||
|
EXPECT_EQ(fmt, AV_PIX_FMT_RGBA);
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "common/jobtime.h"
|
||||||
|
|
||||||
|
TEST(CommonJobTime, ConstructorAcquiresValue)
|
||||||
|
{
|
||||||
|
olive::JobTime a;
|
||||||
|
olive::JobTime b;
|
||||||
|
|
||||||
|
EXPECT_NE(a.value(), b.value());
|
||||||
|
EXPECT_LT(a.value(), b.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonJobTime, AcquireUpdatesValue)
|
||||||
|
{
|
||||||
|
olive::JobTime a;
|
||||||
|
uint64_t first = a.value();
|
||||||
|
a.Acquire();
|
||||||
|
uint64_t second = a.value();
|
||||||
|
|
||||||
|
EXPECT_GT(second, first);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonJobTime, ComparisonOperators)
|
||||||
|
{
|
||||||
|
olive::JobTime a;
|
||||||
|
olive::JobTime b;
|
||||||
|
|
||||||
|
EXPECT_LT(a, b);
|
||||||
|
EXPECT_GT(b, a);
|
||||||
|
EXPECT_LE(a, a);
|
||||||
|
EXPECT_GE(b, b);
|
||||||
|
EXPECT_EQ(a, a);
|
||||||
|
EXPECT_NE(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CommonJobTime, DebugStream)
|
||||||
|
{
|
||||||
|
olive::JobTime a;
|
||||||
|
QDebug debug(QtDebugMsg);
|
||||||
|
debug << a;
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "olive/core/util/bezier.h"
|
||||||
|
|
||||||
|
using namespace olive::core;
|
||||||
|
|
||||||
|
TEST(CoreBezier, DefaultConstruction)
|
||||||
|
{
|
||||||
|
Bezier b;
|
||||||
|
EXPECT_DOUBLE_EQ(b.x(), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b.y(), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b.cp1_x(), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b.cp1_y(), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b.cp2_x(), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b.cp2_y(), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreBezier, ValueConstruction)
|
||||||
|
{
|
||||||
|
Bezier b(1.0, 2.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b.x(), 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b.y(), 2.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreBezier, FullConstruction)
|
||||||
|
{
|
||||||
|
Bezier b(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b.x(), 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b.y(), 2.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b.cp1_x(), 3.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b.cp1_y(), 4.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b.cp2_x(), 5.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b.cp2_y(), 6.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreBezier, Setters)
|
||||||
|
{
|
||||||
|
Bezier b;
|
||||||
|
b.set_x(10.0);
|
||||||
|
b.set_y(20.0);
|
||||||
|
b.set_cp1_x(30.0);
|
||||||
|
b.set_cp1_y(40.0);
|
||||||
|
b.set_cp2_x(50.0);
|
||||||
|
b.set_cp2_y(60.0);
|
||||||
|
|
||||||
|
EXPECT_DOUBLE_EQ(b.x(), 10.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b.y(), 20.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b.cp1_x(), 30.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b.cp1_y(), 40.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b.cp2_x(), 50.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b.cp2_y(), 60.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreBezier, QuadraticXtoT)
|
||||||
|
{
|
||||||
|
double t = Bezier::QuadraticXtoT(0.5, 0.0, 0.5, 1.0);
|
||||||
|
EXPECT_NEAR(t, 0.5, 0.00001);
|
||||||
|
|
||||||
|
t = Bezier::QuadraticXtoT(0.0, 0.0, 0.5, 1.0);
|
||||||
|
EXPECT_NEAR(t, 0.0, 0.00001);
|
||||||
|
|
||||||
|
t = Bezier::QuadraticXtoT(1.0, 0.0, 0.5, 1.0);
|
||||||
|
EXPECT_NEAR(t, 1.0, 0.00001);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreBezier, QuadraticTtoY)
|
||||||
|
{
|
||||||
|
EXPECT_NEAR(Bezier::QuadraticTtoY(0.0, 0.5, 1.0, 0.0), 0.0, 0.00001);
|
||||||
|
EXPECT_NEAR(Bezier::QuadraticTtoY(0.0, 0.5, 1.0, 0.5), 0.5, 0.00001);
|
||||||
|
EXPECT_NEAR(Bezier::QuadraticTtoY(0.0, 0.5, 1.0, 1.0), 1.0, 0.00001);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreBezier, QuadraticXtoY)
|
||||||
|
{
|
||||||
|
Imath::V2d a(0.0, 0.0);
|
||||||
|
Imath::V2d b(0.5, 0.5);
|
||||||
|
Imath::V2d c(1.0, 1.0);
|
||||||
|
|
||||||
|
EXPECT_NEAR(Bezier::QuadraticXtoY(0.5, a, b, c), 0.5, 0.00001);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreBezier, CubicXtoT)
|
||||||
|
{
|
||||||
|
double t = Bezier::CubicXtoT(0.5, 0.0, 0.33, 0.66, 1.0);
|
||||||
|
EXPECT_NEAR(t, 0.5, 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreBezier, CubicTtoY)
|
||||||
|
{
|
||||||
|
EXPECT_NEAR(Bezier::CubicTtoY(0.0, 0.33, 0.66, 1.0, 0.0), 0.0, 0.00001);
|
||||||
|
EXPECT_NEAR(Bezier::CubicTtoY(0.0, 0.33, 0.66, 1.0, 1.0), 1.0, 0.00001);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreBezier, CubicXtoY)
|
||||||
|
{
|
||||||
|
Imath::V2d a(0.0, 0.0);
|
||||||
|
Imath::V2d b(0.33, 0.0);
|
||||||
|
Imath::V2d c(0.66, 1.0);
|
||||||
|
Imath::V2d d(1.0, 1.0);
|
||||||
|
|
||||||
|
double y = Bezier::CubicXtoY(0.5, a, b, c, d);
|
||||||
|
EXPECT_GE(y, 0.0);
|
||||||
|
EXPECT_LE(y, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreBezier, VectorConverters)
|
||||||
|
{
|
||||||
|
Bezier b(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
|
||||||
|
Imath::V2d v = b.to_vec();
|
||||||
|
EXPECT_DOUBLE_EQ(v.x, 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(v.y, 2.0);
|
||||||
|
|
||||||
|
Imath::V2d cp1 = b.control_point_1_to_vec();
|
||||||
|
EXPECT_DOUBLE_EQ(cp1.x, 3.0);
|
||||||
|
EXPECT_DOUBLE_EQ(cp1.y, 4.0);
|
||||||
|
|
||||||
|
Imath::V2d cp2 = b.control_point_2_to_vec();
|
||||||
|
EXPECT_DOUBLE_EQ(cp2.x, 5.0);
|
||||||
|
EXPECT_DOUBLE_EQ(cp2.y, 6.0);
|
||||||
|
}
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "olive/core/util/color.h"
|
||||||
|
|
||||||
|
using namespace olive::core;
|
||||||
|
|
||||||
|
TEST(CoreColor, DefaultConstruction)
|
||||||
|
{
|
||||||
|
Color c;
|
||||||
|
EXPECT_FLOAT_EQ(c.red(), 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(c.green(), 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(c.blue(), 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(c.alpha(), 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreColor, ValueConstruction)
|
||||||
|
{
|
||||||
|
Color c(0.1f, 0.2f, 0.3f, 0.4f);
|
||||||
|
EXPECT_FLOAT_EQ(c.red(), 0.1f);
|
||||||
|
EXPECT_FLOAT_EQ(c.green(), 0.2f);
|
||||||
|
EXPECT_FLOAT_EQ(c.blue(), 0.3f);
|
||||||
|
EXPECT_FLOAT_EQ(c.alpha(), 0.4f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreColor, SettersAndDataAccess)
|
||||||
|
{
|
||||||
|
Color c;
|
||||||
|
c.set_red(0.5f);
|
||||||
|
c.set_green(0.6f);
|
||||||
|
c.set_blue(0.7f);
|
||||||
|
c.set_alpha(0.8f);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(c.data()[0], 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(c.data()[1], 0.6f);
|
||||||
|
EXPECT_FLOAT_EQ(c.data()[2], 0.7f);
|
||||||
|
EXPECT_FLOAT_EQ(c.data()[3], 0.8f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreColor, FromHsvRed)
|
||||||
|
{
|
||||||
|
Color c = Color::fromHsv(0.0f, 1.0f, 1.0f);
|
||||||
|
EXPECT_NEAR(c.red(), 1.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(c.green(), 0.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(c.blue(), 0.0f, 0.001f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreColor, FromHsvGreen)
|
||||||
|
{
|
||||||
|
Color c = Color::fromHsv(120.0f, 1.0f, 1.0f);
|
||||||
|
EXPECT_NEAR(c.red(), 0.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(c.green(), 1.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(c.blue(), 0.0f, 0.001f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreColor, FromHsvBlue)
|
||||||
|
{
|
||||||
|
Color c = Color::fromHsv(240.0f, 1.0f, 1.0f);
|
||||||
|
EXPECT_NEAR(c.red(), 0.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(c.green(), 0.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(c.blue(), 1.0f, 0.001f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreColor, HsvRoundTrip)
|
||||||
|
{
|
||||||
|
Color original(0.8f, 0.4f, 0.2f);
|
||||||
|
float h, s, v;
|
||||||
|
original.toHsv(&h, &s, &v);
|
||||||
|
|
||||||
|
EXPECT_NEAR(original.hsv_hue(), h, 0.001f);
|
||||||
|
EXPECT_NEAR(original.hsv_saturation(), s, 0.001f);
|
||||||
|
EXPECT_NEAR(original.value(), v, 0.001f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreColor, HslRoundTrip)
|
||||||
|
{
|
||||||
|
Color original(0.2f, 0.5f, 0.8f);
|
||||||
|
float h, s, l;
|
||||||
|
original.toHsl(&h, &s, &l);
|
||||||
|
|
||||||
|
EXPECT_NEAR(original.hsl_hue(), h, 0.001f);
|
||||||
|
EXPECT_NEAR(original.hsl_saturation(), s, 0.001f);
|
||||||
|
EXPECT_NEAR(original.lightness(), l, 0.001f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreColor, ArithmeticOperators)
|
||||||
|
{
|
||||||
|
Color a(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
Color b(0.5f, 0.5f, 0.5f, 0.5f);
|
||||||
|
|
||||||
|
Color sum = a + b;
|
||||||
|
EXPECT_FLOAT_EQ(sum.red(), 1.5f);
|
||||||
|
|
||||||
|
Color diff = a - b;
|
||||||
|
EXPECT_FLOAT_EQ(diff.red(), 0.5f);
|
||||||
|
|
||||||
|
Color scaled = a * 2.0f;
|
||||||
|
EXPECT_FLOAT_EQ(scaled.red(), 2.0f);
|
||||||
|
|
||||||
|
Color divided = a / 2.0f;
|
||||||
|
EXPECT_FLOAT_EQ(divided.red(), 0.5f);
|
||||||
|
|
||||||
|
Color added_scalar = a + 1.0f;
|
||||||
|
EXPECT_FLOAT_EQ(added_scalar.red(), 2.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreColor, CompoundAssignment)
|
||||||
|
{
|
||||||
|
Color c(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
|
c += Color(0.5f, 0.5f, 0.5f, 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(c.red(), 1.5f);
|
||||||
|
|
||||||
|
c *= 2.0f;
|
||||||
|
EXPECT_FLOAT_EQ(c.red(), 3.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreColor, GetRoughLuminance)
|
||||||
|
{
|
||||||
|
Color white(1.0f, 1.0f, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(white.GetRoughLuminance(), 1.0f);
|
||||||
|
|
||||||
|
Color black(0.0f, 0.0f, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(black.GetRoughLuminance(), 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreColor, ToDataAndFromDataU8)
|
||||||
|
{
|
||||||
|
Color c(1.0f, 0.5f, 0.0f, 1.0f);
|
||||||
|
uint8_t data[4];
|
||||||
|
c.toData(reinterpret_cast<char *>(data), PixelFormat::U8, 4);
|
||||||
|
|
||||||
|
EXPECT_EQ(data[0], 255u);
|
||||||
|
EXPECT_EQ(data[1], 127u);
|
||||||
|
EXPECT_EQ(data[2], 0u);
|
||||||
|
EXPECT_EQ(data[3], 255u);
|
||||||
|
|
||||||
|
Color restored = Color::fromData(reinterpret_cast<const char *>(data),
|
||||||
|
PixelFormat::U8, 4);
|
||||||
|
EXPECT_NEAR(restored.red(), 1.0f, 0.01f);
|
||||||
|
EXPECT_NEAR(restored.green(), 0.5f, 0.01f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreColor, ToDataAndFromDataF32)
|
||||||
|
{
|
||||||
|
Color c(0.25f, 0.5f, 0.75f, 1.0f);
|
||||||
|
float data[4];
|
||||||
|
c.toData(reinterpret_cast<char *>(data), PixelFormat::F32, 4);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(data[0], 0.25f);
|
||||||
|
EXPECT_FLOAT_EQ(data[1], 0.5f);
|
||||||
|
EXPECT_FLOAT_EQ(data[2], 0.75f);
|
||||||
|
EXPECT_FLOAT_EQ(data[3], 1.0f);
|
||||||
|
|
||||||
|
Color restored = Color::fromData(reinterpret_cast<const char *>(data),
|
||||||
|
PixelFormat::F32, 4);
|
||||||
|
EXPECT_FLOAT_EQ(restored.red(), 0.25f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreColor, ToDataAndFromDataU10)
|
||||||
|
{
|
||||||
|
Color c(1.0f, 0.5f, 0.0f, 1.0f);
|
||||||
|
uint32_t data;
|
||||||
|
c.toData(reinterpret_cast<char *>(&data), PixelFormat::U10, 4);
|
||||||
|
|
||||||
|
Color restored = Color::fromData(reinterpret_cast<const char *>(&data),
|
||||||
|
PixelFormat::U10, 4);
|
||||||
|
EXPECT_NEAR(restored.red(), 1.0f, 0.001f);
|
||||||
|
EXPECT_NEAR(restored.green(), 0.5f, 0.001f);
|
||||||
|
EXPECT_NEAR(restored.blue(), 0.0f, 0.001f);
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "olive/core/util/stringutils.h"
|
||||||
|
|
||||||
|
using namespace olive::core;
|
||||||
|
|
||||||
|
TEST(CoreStringUtils, Split)
|
||||||
|
{
|
||||||
|
auto result = StringUtils::split("a,b,c", ',');
|
||||||
|
ASSERT_EQ(result.size(), 3u);
|
||||||
|
EXPECT_EQ(result[0], "a");
|
||||||
|
EXPECT_EQ(result[1], "b");
|
||||||
|
EXPECT_EQ(result[2], "c");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreStringUtils, SplitRegex)
|
||||||
|
{
|
||||||
|
auto result = StringUtils::split_regex("one:two;three", std::regex("(:)|(;)| "));
|
||||||
|
ASSERT_EQ(result.size(), 3u);
|
||||||
|
EXPECT_EQ(result[0], "one");
|
||||||
|
EXPECT_EQ(result[1], "two");
|
||||||
|
EXPECT_EQ(result[2], "three");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreStringUtils, ToInt)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
EXPECT_EQ(StringUtils::to_int("42", &ok), 42);
|
||||||
|
EXPECT_TRUE(ok);
|
||||||
|
|
||||||
|
EXPECT_EQ(StringUtils::to_int("-7", 10, &ok), -7);
|
||||||
|
EXPECT_TRUE(ok);
|
||||||
|
|
||||||
|
EXPECT_EQ(StringUtils::to_int("ff", 16, &ok), 255);
|
||||||
|
EXPECT_TRUE(ok);
|
||||||
|
|
||||||
|
EXPECT_EQ(StringUtils::to_int("abc", &ok), 0);
|
||||||
|
EXPECT_FALSE(ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreStringUtils, ToStringLeftpad)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(StringUtils::to_string_leftpad(5, 3), "005");
|
||||||
|
EXPECT_EQ(StringUtils::to_string_leftpad(123, 2), "123");
|
||||||
|
EXPECT_EQ(StringUtils::to_string_leftpad(7, 4, '*'), "***7");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreStringUtils, Format)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(StringUtils::format("Hello %s %d", "world", 42),
|
||||||
|
"Hello world 42");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreStringUtils, Trim)
|
||||||
|
{
|
||||||
|
std::string s = " hello world ";
|
||||||
|
StringUtils::trim(s);
|
||||||
|
EXPECT_EQ(s, "hello world");
|
||||||
|
|
||||||
|
EXPECT_EQ(StringUtils::trimmed("\t\nvalue\t\n"), "value");
|
||||||
|
EXPECT_EQ(StringUtils::ltrimmed(" left"), "left");
|
||||||
|
EXPECT_EQ(StringUtils::rtrimmed("right "), "right");
|
||||||
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "olive/core/util/timecodefunctions.h"
|
||||||
|
|
||||||
|
using namespace olive::core;
|
||||||
|
|
||||||
|
TEST(CoreTimecode, TimeToTimecodeSeconds)
|
||||||
|
{
|
||||||
|
rational time(5, 1);
|
||||||
|
rational tb(1, 25);
|
||||||
|
std::string tc = Timecode::time_to_timecode(time, tb, Timecode::kTimecodeSeconds);
|
||||||
|
EXPECT_EQ(tc, "00:00:05.000");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimecode, TimeToTimecodeNonDropFrame)
|
||||||
|
{
|
||||||
|
rational time(2, 1);
|
||||||
|
rational tb(1, 25);
|
||||||
|
std::string tc =
|
||||||
|
Timecode::time_to_timecode(time, tb, Timecode::kTimecodeNonDropFrame);
|
||||||
|
EXPECT_EQ(tc, "00:00:02:00");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimecode, TimeToTimecodePlusSign)
|
||||||
|
{
|
||||||
|
rational time(1, 1);
|
||||||
|
rational tb(1, 25);
|
||||||
|
std::string tc = Timecode::time_to_timecode(time, tb,
|
||||||
|
Timecode::kTimecodeSeconds, true);
|
||||||
|
EXPECT_EQ(tc.substr(0, 1), "+");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimecode, TimeToTimecodeInvalidTimebase)
|
||||||
|
{
|
||||||
|
rational time(1, 1);
|
||||||
|
EXPECT_EQ(Timecode::time_to_timecode(time, rational(), Timecode::kFrames),
|
||||||
|
"INVALID TIMEBASE");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimecode, TimecodeToTimeSeconds)
|
||||||
|
{
|
||||||
|
rational tb(1, 25);
|
||||||
|
bool ok = false;
|
||||||
|
rational t = Timecode::timecode_to_time("00:00:05.500", tb,
|
||||||
|
Timecode::kTimecodeSeconds, &ok);
|
||||||
|
EXPECT_TRUE(ok);
|
||||||
|
EXPECT_EQ(t, rational(11, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimecode, TimecodeToTimeNonDropFrame)
|
||||||
|
{
|
||||||
|
rational tb(1, 25);
|
||||||
|
bool ok = false;
|
||||||
|
rational t = Timecode::timecode_to_time("00:00:02:03", tb,
|
||||||
|
Timecode::kTimecodeNonDropFrame, &ok);
|
||||||
|
EXPECT_TRUE(ok);
|
||||||
|
EXPECT_EQ(t, rational(53, 25));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimecode, TimecodeToTimeInvalid)
|
||||||
|
{
|
||||||
|
rational tb(1, 25);
|
||||||
|
bool ok = true;
|
||||||
|
Timecode::timecode_to_time("not a timecode", tb,
|
||||||
|
Timecode::kTimecodeSeconds, &ok);
|
||||||
|
EXPECT_FALSE(ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimecode, TimeToString)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(Timecode::time_to_string(3661000), "01:01:01");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimecode, SnapTimeToTimebase)
|
||||||
|
{
|
||||||
|
rational tb(1, 25);
|
||||||
|
rational snapped = Timecode::snap_time_to_timebase(rational(1, 10), tb);
|
||||||
|
// 0.1s @ 25fps rounds to frame 3 (0.12s)
|
||||||
|
EXPECT_EQ(snapped, rational(3, 25));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimecode, TimeToTimestamp)
|
||||||
|
{
|
||||||
|
rational tb(1, 25);
|
||||||
|
EXPECT_EQ(Timecode::time_to_timestamp(rational(2, 1), tb), 50);
|
||||||
|
EXPECT_EQ(Timecode::time_to_timestamp(0.08, tb, Timecode::kFloor), 2);
|
||||||
|
EXPECT_EQ(Timecode::time_to_timestamp(0.08, tb, Timecode::kCeil), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimecode, TimestampToTime)
|
||||||
|
{
|
||||||
|
rational tb(1, 25);
|
||||||
|
EXPECT_EQ(Timecode::timestamp_to_time(50, tb), rational(2, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimecode, RescaleTimestamp)
|
||||||
|
{
|
||||||
|
rational src(1, 25);
|
||||||
|
rational dst(1, 30);
|
||||||
|
EXPECT_EQ(Timecode::rescale_timestamp(50, src, dst), 60);
|
||||||
|
EXPECT_EQ(Timecode::rescale_timestamp(50, src, src), 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimecode, RescaleTimestampCeil)
|
||||||
|
{
|
||||||
|
rational src(1, 25);
|
||||||
|
rational dst(1, 30);
|
||||||
|
EXPECT_EQ(Timecode::rescale_timestamp_ceil(1, src, dst), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimecode, TimebaseIsDropFrame)
|
||||||
|
{
|
||||||
|
EXPECT_FALSE(Timecode::timebase_is_drop_frame(rational(1, 25)));
|
||||||
|
EXPECT_TRUE(Timecode::timebase_is_drop_frame(rational(1001, 30000)));
|
||||||
|
}
|
||||||
@@ -0,0 +1,184 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "olive/core/util/timerange.h"
|
||||||
|
|
||||||
|
using namespace olive::core;
|
||||||
|
|
||||||
|
TEST(CoreTimeRange, ConstructAndAccess)
|
||||||
|
{
|
||||||
|
TimeRange r(rational(1), rational(5));
|
||||||
|
EXPECT_EQ(r.in(), rational(1));
|
||||||
|
EXPECT_EQ(r.out(), rational(5));
|
||||||
|
EXPECT_EQ(r.length(), rational(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimeRange, NormalizationSwapsReversedBounds)
|
||||||
|
{
|
||||||
|
TimeRange r(rational(5), rational(1));
|
||||||
|
EXPECT_EQ(r.in(), rational(1));
|
||||||
|
EXPECT_EQ(r.out(), rational(5));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimeRange, SettersNormalize)
|
||||||
|
{
|
||||||
|
TimeRange r(rational(0), rational(10));
|
||||||
|
r.set_in(rational(15));
|
||||||
|
EXPECT_EQ(r.in(), rational(10));
|
||||||
|
EXPECT_EQ(r.out(), rational(15));
|
||||||
|
|
||||||
|
r.set_out(rational(2));
|
||||||
|
EXPECT_EQ(r.in(), rational(2));
|
||||||
|
EXPECT_EQ(r.out(), rational(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimeRange, ContainsRational)
|
||||||
|
{
|
||||||
|
TimeRange r(rational(0), rational(10));
|
||||||
|
EXPECT_TRUE(r.Contains(rational(5)));
|
||||||
|
EXPECT_FALSE(r.Contains(rational(10)));
|
||||||
|
EXPECT_FALSE(r.Contains(rational(-1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimeRange, ContainsRange)
|
||||||
|
{
|
||||||
|
TimeRange outer(rational(0), rational(10));
|
||||||
|
TimeRange inner(rational(2), rational(8));
|
||||||
|
TimeRange partial(rational(5), rational(15));
|
||||||
|
|
||||||
|
EXPECT_TRUE(outer.Contains(inner));
|
||||||
|
EXPECT_FALSE(outer.Contains(partial));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimeRange, OverlapsWith)
|
||||||
|
{
|
||||||
|
TimeRange a(rational(0), rational(10));
|
||||||
|
TimeRange b(rational(5), rational(15));
|
||||||
|
TimeRange c(rational(10), rational(20));
|
||||||
|
|
||||||
|
EXPECT_TRUE(a.OverlapsWith(b));
|
||||||
|
// By default bounds are inclusive, so [0,10] and [10,20] touch and overlap
|
||||||
|
EXPECT_TRUE(a.OverlapsWith(c));
|
||||||
|
EXPECT_FALSE(a.OverlapsWith(c, false, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimeRange, CombineAndIntersect)
|
||||||
|
{
|
||||||
|
TimeRange a(rational(0), rational(10));
|
||||||
|
TimeRange b(rational(5), rational(15));
|
||||||
|
|
||||||
|
TimeRange combined = a.Combined(b);
|
||||||
|
EXPECT_EQ(combined.in(), rational(0));
|
||||||
|
EXPECT_EQ(combined.out(), rational(15));
|
||||||
|
|
||||||
|
TimeRange intersect = a.Intersected(b);
|
||||||
|
EXPECT_EQ(intersect.in(), rational(5));
|
||||||
|
EXPECT_EQ(intersect.out(), rational(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimeRange, Arithmetic)
|
||||||
|
{
|
||||||
|
TimeRange r(rational(0), rational(10));
|
||||||
|
TimeRange shifted = r + rational(5);
|
||||||
|
EXPECT_EQ(shifted.in(), rational(5));
|
||||||
|
EXPECT_EQ(shifted.out(), rational(15));
|
||||||
|
|
||||||
|
shifted -= rational(3);
|
||||||
|
EXPECT_EQ(shifted.in(), rational(2));
|
||||||
|
EXPECT_EQ(shifted.out(), rational(12));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimeRange, Split)
|
||||||
|
{
|
||||||
|
TimeRange r(rational(0), rational(10));
|
||||||
|
auto pieces = r.Split(3);
|
||||||
|
ASSERT_EQ(pieces.size(), 4u);
|
||||||
|
EXPECT_EQ(pieces.front().in(), rational(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimeRangeList, InsertMergesOverlapping)
|
||||||
|
{
|
||||||
|
TimeRangeList list;
|
||||||
|
list.insert(TimeRange(rational(0), rational(5)));
|
||||||
|
list.insert(TimeRange(rational(3), rational(8)));
|
||||||
|
list.insert(TimeRange(rational(10), rational(12)));
|
||||||
|
|
||||||
|
EXPECT_EQ(list.size(), 2);
|
||||||
|
EXPECT_EQ(list.first().in(), rational(0));
|
||||||
|
EXPECT_EQ(list.first().out(), rational(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimeRangeList, RemoveSplitsRange)
|
||||||
|
{
|
||||||
|
TimeRangeList list;
|
||||||
|
list.insert(TimeRange(rational(0), rational(10)));
|
||||||
|
list.remove(TimeRange(rational(3), rational(7)));
|
||||||
|
|
||||||
|
EXPECT_EQ(list.size(), 2);
|
||||||
|
EXPECT_EQ(list.first().out(), rational(3));
|
||||||
|
EXPECT_EQ(list.last().in(), rational(7));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimeRangeList, Shift)
|
||||||
|
{
|
||||||
|
TimeRangeList list;
|
||||||
|
list.insert(TimeRange(rational(0), rational(5)));
|
||||||
|
list.shift(rational(10));
|
||||||
|
|
||||||
|
EXPECT_EQ(list.first().in(), rational(10));
|
||||||
|
EXPECT_EQ(list.first().out(), rational(15));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimeRangeList, TrimInAndOut)
|
||||||
|
{
|
||||||
|
TimeRangeList list;
|
||||||
|
list.insert(TimeRange(rational(10), rational(20)));
|
||||||
|
list.trim_in(rational(5));
|
||||||
|
EXPECT_EQ(list.first().in(), rational(15));
|
||||||
|
EXPECT_EQ(list.first().out(), rational(20));
|
||||||
|
|
||||||
|
list.trim_out(rational(-5));
|
||||||
|
// set_out(out + diff) = 20 + (-5) = 15
|
||||||
|
EXPECT_EQ(list.first().out(), rational(15));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimeRangeList, Intersects)
|
||||||
|
{
|
||||||
|
TimeRangeList list;
|
||||||
|
list.insert(TimeRange(rational(0), rational(10)));
|
||||||
|
list.insert(TimeRange(rational(20), rational(30)));
|
||||||
|
|
||||||
|
TimeRangeList result = list.Intersects(TimeRange(rational(5), rational(25)));
|
||||||
|
EXPECT_EQ(result.size(), 2);
|
||||||
|
EXPECT_EQ(result.first().in(), rational(5));
|
||||||
|
EXPECT_EQ(result.first().out(), rational(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimeRangeListFrameIterator, IteratesFrames)
|
||||||
|
{
|
||||||
|
TimeRangeList list;
|
||||||
|
// 5 seconds at 25fps = 125 frames
|
||||||
|
list.insert(TimeRange(rational(0), rational(5)));
|
||||||
|
TimeRangeListFrameIterator it(list, rational(1, 25));
|
||||||
|
|
||||||
|
rational out;
|
||||||
|
int count = 0;
|
||||||
|
while (it.GetNext(&out)) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ(count, 125);
|
||||||
|
EXPECT_EQ(it.size(), 125);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CoreTimeRangeListFrameIterator, HasNext)
|
||||||
|
{
|
||||||
|
TimeRangeList list;
|
||||||
|
list.insert(TimeRange(rational(0), rational(1)));
|
||||||
|
TimeRangeListFrameIterator it(list, rational(1, 25));
|
||||||
|
|
||||||
|
EXPECT_TRUE(it.HasNext());
|
||||||
|
rational out;
|
||||||
|
while (it.GetNext(&out)) {
|
||||||
|
}
|
||||||
|
EXPECT_FALSE(it.HasNext());
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user