添加测试
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build-test:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-22.04, macos-13, windows-2022]
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: Release
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
ninja-build pkg-config \
|
||||
qt6-base-dev qt6-base-dev-tools qt6-tools-dev qt6-tools-dev-tools \
|
||||
libavcodec-dev libavformat-dev libavfilter-dev libavutil-dev libswscale-dev libswresample-dev \
|
||||
libopencolorio-dev libopenimageio-dev libopenexr-dev libexpat1-dev \
|
||||
portaudio19-dev libgl1-mesa-dev
|
||||
|
||||
- name: Install dependencies (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
brew update
|
||||
brew install ninja pkg-config qt@6 ffmpeg openimageio opencolorio openexr portaudio expat opentimelineio
|
||||
echo "$(brew --prefix qt@6)/bin" >> "$GITHUB_PATH"
|
||||
echo "CMAKE_PREFIX_PATH=$(brew --prefix qt@6)" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Install Qt (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
uses: jurplel/install-qt-action@v4
|
||||
with:
|
||||
version: 6.5.3
|
||||
cache: true
|
||||
tools: 'tools_ninja'
|
||||
|
||||
- name: Install dependencies (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
choco install -y ninja
|
||||
$env:VCPKG_ROOT = "C:\vcpkg"
|
||||
& "$env:VCPKG_ROOT\vcpkg.exe" install ffmpeg openimageio opencolorio openexr expat portaudio --triplet x64-windows
|
||||
echo "VCPKG_ROOT=$env:VCPKG_ROOT" | Out-File -FilePath $env:GITHUB_ENV -Append
|
||||
echo "CMAKE_TOOLCHAIN_FILE=$env:VCPKG_ROOT\scripts\buildsystems\vcpkg.cmake" | Out-File -FilePath $env:GITHUB_ENV -Append
|
||||
|
||||
- name: Configure (Linux/macOS)
|
||||
if: runner.os != 'Windows'
|
||||
run: |
|
||||
cmake -S . -B build -G Ninja \
|
||||
-DBUILD_TESTS=ON \
|
||||
-DBUILD_QT6=ON \
|
||||
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
|
||||
|
||||
- name: Configure (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
cmake -S . -B build -G Ninja `
|
||||
-DBUILD_TESTS=ON `
|
||||
-DBUILD_QT6=ON `
|
||||
-DCMAKE_BUILD_TYPE=$env:CMAKE_BUILD_TYPE `
|
||||
-DCMAKE_TOOLCHAIN_FILE=$env:CMAKE_TOOLCHAIN_FILE `
|
||||
-DCMAKE_PREFIX_PATH=$env:Qt6_DIR
|
||||
|
||||
- name: Build
|
||||
run: cmake --build build --config ${{ env.CMAKE_BUILD_TYPE }}
|
||||
|
||||
- name: Test (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
env:
|
||||
QT_QPA_PLATFORM: offscreen
|
||||
run: ctest --test-dir build --output-on-failure -C ${{ env.CMAKE_BUILD_TYPE }}
|
||||
|
||||
- name: Test (macOS/Windows)
|
||||
if: runner.os != 'Linux'
|
||||
run: ctest --test-dir build --output-on-failure -C ${{ env.CMAKE_BUILD_TYPE }}
|
||||
@@ -0,0 +1,86 @@
|
||||
# Olive Testing Strategy and Plan
|
||||
|
||||
This document describes the automated testing strategy for Olive, including unit tests, integration tests, and CI execution.
|
||||
|
||||
## Goals
|
||||
|
||||
- Maximize automation and reduce manual testing.
|
||||
- Cover all modules with at least one automated test.
|
||||
- Keep integration tests headless (no GUI interaction).
|
||||
- Make failures reproducible on Windows/macOS/Linux CI.
|
||||
|
||||
## Test Layers
|
||||
|
||||
### 1) Unit Tests (GoogleTest)
|
||||
- Focus: small units, deterministic behavior, no GUI.
|
||||
- Location: `tests/gtest/`.
|
||||
- Execution: `ctest` target `olive-gtest`.
|
||||
|
||||
### 1.5) Module Smoke Tests (GoogleTest)
|
||||
- Focus: compile-time and link-time coverage for GUI-heavy modules without instantiating widgets.
|
||||
- Location: `tests/gtest/module_smoke_test.cpp`.
|
||||
- Execution: `ctest` target `olive-gtest`.
|
||||
|
||||
### 2) Integration Tests (GoogleTest)
|
||||
- Focus: cross-module flows without GUI (e.g., serialize → deserialize → resolve).
|
||||
- Location: `tests/gtest/` (prefixed with `ProjectSerializer`, `TaskManager`, etc.).
|
||||
|
||||
### 3) Legacy Tests (Olive macro tests)
|
||||
- Existing tests in `tests/general`, `tests/timeline`, `tests/compositing` remain.
|
||||
|
||||
## Module Coverage Map
|
||||
|
||||
Each top-level module has at least one test that exercises its core API or serialization path.
|
||||
|
||||
- `app/common`: `common_current_test.cpp`, `common_xmlutils_test.cpp`
|
||||
- `app/config`: `config_test.cpp`
|
||||
- `app/node`: `node_value_test.cpp`, `node_keyframe_test.cpp`, `node_serialization_test.cpp`
|
||||
- `app/node/project/serializer`: `project_serializer_test.cpp`
|
||||
- `app/render`: `render_videoparams_test.cpp`, `render_audioparams_test.cpp`
|
||||
- `app/timeline`: `timeline_marker_test.cpp`
|
||||
- `app/undo`: `undo_stack_test.cpp`
|
||||
- `app/task`: `task_taskmanager_test.cpp`
|
||||
- `app/codec`: `codec_frame_test.cpp`
|
||||
- `app/pluginSupport`: `plugin_support_test.cpp`
|
||||
- `app/audio`, `app/cli`, `app/dialog`, `app/panel`, `app/tool`, `app/ui`, `app/widget`, `app/window`: `module_smoke_test.cpp`
|
||||
|
||||
If a module has a GUI dependency (e.g., widgets), tests focus on non-visual data/model components.
|
||||
|
||||
## Integration Test Details
|
||||
|
||||
### Project Serializer Roundtrip
|
||||
- Creates a minimal project with a built-in node.
|
||||
- Saves to XML via `ProjectSerializer::Save`.
|
||||
- Loads with `ProjectSerializer::Load`.
|
||||
- Verifies that nodes are restored.
|
||||
|
||||
### Task Manager Execution
|
||||
- Adds a dummy task to `TaskManager`.
|
||||
- Waits for completion using an event loop.
|
||||
- Verifies the task ran.
|
||||
|
||||
## Headless Execution
|
||||
|
||||
- Tests avoid QWidget usage.
|
||||
- CI sets `QT_QPA_PLATFORM=offscreen` to prevent GUI initialization issues.
|
||||
|
||||
## Continuous Integration
|
||||
|
||||
CI runs on Windows, macOS, and Linux:
|
||||
|
||||
1. Install system dependencies (Qt, FFmpeg, OpenImageIO, OpenColorIO, OpenEXR, PortAudio, Expat).
|
||||
2. Configure with `-DBUILD_TESTS=ON`.
|
||||
3. Build with CMake + Ninja.
|
||||
4. Run `ctest` with output on failure.
|
||||
|
||||
### Dependency Installation Notes
|
||||
- Linux: use distro packages (`apt` on Ubuntu) for Qt6, FFmpeg, OpenImageIO, OpenColorIO, OpenEXR, PortAudio, Expat, OpenGL headers.
|
||||
- macOS: use Homebrew for Qt6 and media/color/image libraries.
|
||||
- Windows: use system installers where available (Qt via `install-qt-action`), and vcpkg for the remaining C/C++ libraries.
|
||||
|
||||
## Adding New Tests
|
||||
|
||||
- Place new unit tests in `tests/gtest`.
|
||||
- Use GoogleTest conventions.
|
||||
- Prefer deterministic fixtures and local-only resources.
|
||||
- When adding a new module, add at least one unit test and one integration scenario if applicable.
|
||||
@@ -69,6 +69,18 @@ function(olive_add_test GROUP NAME SOURCE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
include(FetchContent)
|
||||
find_package(GTest QUIET)
|
||||
if (NOT GTest_FOUND)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
URL https://github.com/google/googletest/archive/refs/tags/v1.15.2.zip
|
||||
)
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
endif()
|
||||
|
||||
add_subdirectory(compositing)
|
||||
add_subdirectory(general)
|
||||
add_subdirectory(timeline)
|
||||
add_subdirectory(gtest)
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
add_executable(olive-gtest
|
||||
main.cpp
|
||||
common_current_test.cpp
|
||||
common_xmlutils_test.cpp
|
||||
config_test.cpp
|
||||
node_value_test.cpp
|
||||
node_keyframe_test.cpp
|
||||
node_serialization_test.cpp
|
||||
render_videoparams_test.cpp
|
||||
render_audioparams_test.cpp
|
||||
project_serializer_test.cpp
|
||||
timeline_marker_test.cpp
|
||||
undo_stack_test.cpp
|
||||
plugin_support_test.cpp
|
||||
codec_frame_test.cpp
|
||||
task_taskmanager_test.cpp
|
||||
module_smoke_test.cpp
|
||||
)
|
||||
|
||||
target_sources(olive-gtest PRIVATE $<TARGET_OBJECTS:libolive-editor>)
|
||||
|
||||
target_include_directories(
|
||||
olive-gtest
|
||||
PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/app
|
||||
${CMAKE_SOURCE_DIR}/tests
|
||||
${OLIVE_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
olive-gtest
|
||||
PRIVATE
|
||||
${OLIVE_LIBRARIES}
|
||||
GTest::gtest
|
||||
)
|
||||
|
||||
target_compile_definitions(
|
||||
olive-gtest
|
||||
PRIVATE
|
||||
${OLIVE_DEFINITIONS}
|
||||
)
|
||||
|
||||
target_compile_options(
|
||||
olive-gtest
|
||||
PRIVATE
|
||||
${OLIVE_COMPILE_OPTIONS}
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
add_test("Olive.gtest" olive-gtest)
|
||||
else()
|
||||
add_test(olive-gtest olive-gtest)
|
||||
endif()
|
||||
@@ -0,0 +1,11 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "codec/frame.h"
|
||||
|
||||
TEST(CodecFrame, DefaultState)
|
||||
{
|
||||
olive::Frame frame;
|
||||
EXPECT_EQ(frame.width(), 0);
|
||||
EXPECT_EQ(frame.height(), 0);
|
||||
EXPECT_EQ(frame.pixel_format(), olive::core::PixelFormat::Format::kFormatNone);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "common/Current.h"
|
||||
#include "render/videoparams.h"
|
||||
#include "render/audioparams.h"
|
||||
|
||||
TEST(CommonCurrent, SetAndGetVideoParams)
|
||||
{
|
||||
olive::VideoParams params;
|
||||
params.set_width(1920);
|
||||
params.set_height(1080);
|
||||
Current::getInstance().setCurrentVideoParams(params);
|
||||
|
||||
const olive::VideoParams &stored = Current::getInstance().currentVideoParams();
|
||||
EXPECT_EQ(stored.width(), 1920);
|
||||
EXPECT_EQ(stored.height(), 1080);
|
||||
}
|
||||
|
||||
TEST(CommonCurrent, SetAndGetAudioParams)
|
||||
{
|
||||
olive::AudioParams params;
|
||||
params.set_sample_rate(48000);
|
||||
Current::getInstance().setCurrentAudioParams(params);
|
||||
|
||||
const olive::AudioParams &stored = Current::getInstance().currentAudioParams();
|
||||
EXPECT_EQ(stored.sample_rate(), 48000);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
#include "common/xmlutils.h"
|
||||
|
||||
TEST(CommonXmlUtils, ReadNextStartElement)
|
||||
{
|
||||
QByteArray xml = "<root><child>value</child></root>";
|
||||
QBuffer buffer(&xml);
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
QXmlStreamReader reader(&buffer);
|
||||
|
||||
EXPECT_TRUE(XMLReadNextStartElement(&reader));
|
||||
EXPECT_EQ(reader.name().toString(), QStringLiteral("root"));
|
||||
EXPECT_TRUE(XMLReadNextStartElement(&reader));
|
||||
EXPECT_EQ(reader.name().toString(), QStringLiteral("child"));
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "config/config.h"
|
||||
|
||||
TEST(Config, DefaultsPresent)
|
||||
{
|
||||
olive::Config &cfg = olive::Config::Current();
|
||||
cfg.SetDefaults();
|
||||
|
||||
EXPECT_TRUE(cfg[QStringLiteral("Style")].isValid());
|
||||
EXPECT_TRUE(cfg[QStringLiteral("TimecodeDisplay")].isValid());
|
||||
EXPECT_TRUE(cfg[QStringLiteral("DefaultStillLength")].isValid());
|
||||
}
|
||||
|
||||
TEST(Config, SetAndGetValues)
|
||||
{
|
||||
olive::Config &cfg = olive::Config::Current();
|
||||
cfg[QStringLiteral("UnitTestValue")] = 42;
|
||||
EXPECT_EQ(cfg[QStringLiteral("UnitTestValue")].toInt(), 42);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#include <QCoreApplication>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#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)
|
||||
{
|
||||
SUCCEED();
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
#include "node/keyframe.h"
|
||||
#include "node/value.h"
|
||||
|
||||
TEST(NodeKeyframe, SaveLoadRoundTrip)
|
||||
{
|
||||
olive::NodeKeyframe key;
|
||||
key.set_input(QStringLiteral("Value"));
|
||||
key.set_time(olive::core::rational(1, 24));
|
||||
key.set_type(olive::NodeKeyframe::kLinear);
|
||||
key.set_value(42.0);
|
||||
key.set_bezier_control_in(QPointF(0.1, 0.2));
|
||||
key.set_bezier_control_out(QPointF(0.3, 0.4));
|
||||
|
||||
QByteArray xml;
|
||||
QBuffer buffer(&xml);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
QXmlStreamWriter writer(&buffer);
|
||||
writer.writeStartDocument();
|
||||
writer.writeStartElement(QStringLiteral("key"));
|
||||
key.save(&writer, olive::NodeValue::kFloat);
|
||||
writer.writeEndElement();
|
||||
writer.writeEndDocument();
|
||||
buffer.close();
|
||||
|
||||
QBuffer read_buffer(&xml);
|
||||
read_buffer.open(QIODevice::ReadOnly);
|
||||
QXmlStreamReader reader(&read_buffer);
|
||||
EXPECT_TRUE(reader.readNextStartElement());
|
||||
EXPECT_EQ(reader.name().toString(), QStringLiteral("key"));
|
||||
|
||||
olive::NodeKeyframe loaded;
|
||||
EXPECT_TRUE(loaded.load(&reader, olive::NodeValue::kFloat));
|
||||
EXPECT_EQ(loaded.input(), QStringLiteral("Value"));
|
||||
EXPECT_EQ(loaded.time(), olive::core::rational(1, 24));
|
||||
EXPECT_EQ(loaded.type(), olive::NodeKeyframe::kLinear);
|
||||
EXPECT_DOUBLE_EQ(loaded.value().toDouble(), 42.0);
|
||||
EXPECT_DOUBLE_EQ(loaded.bezier_control_in().x(), 0.1);
|
||||
EXPECT_DOUBLE_EQ(loaded.bezier_control_in().y(), 0.2);
|
||||
EXPECT_DOUBLE_EQ(loaded.bezier_control_out().x(), 0.3);
|
||||
EXPECT_DOUBLE_EQ(loaded.bezier_control_out().y(), 0.4);
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
#include "node/node.h"
|
||||
#include "node/serializeddata.h"
|
||||
#include "node/value.h"
|
||||
|
||||
namespace {
|
||||
class TestNode final : public olive::Node {
|
||||
public:
|
||||
TestNode()
|
||||
{
|
||||
AddInput(QStringLiteral("Value"), olive::NodeValue::kFloat);
|
||||
SetSplitStandardValue(QStringLiteral("Value"), 3.5, -1);
|
||||
}
|
||||
|
||||
TestNode *copy() const override
|
||||
{
|
||||
return new TestNode();
|
||||
}
|
||||
|
||||
QString Name() const override
|
||||
{
|
||||
return QStringLiteral("TestNode");
|
||||
}
|
||||
|
||||
QString id() const override
|
||||
{
|
||||
return QStringLiteral("org.olivevideoeditor.TestNode");
|
||||
}
|
||||
|
||||
QVector<CategoryID> Category() const override
|
||||
{
|
||||
return { kCategoryUnknown };
|
||||
}
|
||||
|
||||
QString Description() const override
|
||||
{
|
||||
return QStringLiteral("Test node for serialization");
|
||||
}
|
||||
|
||||
void Value(const NodeValueRow &, const NodeGlobals &, NodeValueTable *) const override
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST(NodeSerialization, SaveAndLoadInput)
|
||||
{
|
||||
TestNode node;
|
||||
node.SetLabel(QStringLiteral("MyNode"));
|
||||
node.SetOverrideColor(2);
|
||||
|
||||
QByteArray xml;
|
||||
QBuffer buffer(&xml);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
QXmlStreamWriter writer(&buffer);
|
||||
writer.writeStartDocument();
|
||||
writer.writeStartElement(QStringLiteral("node"));
|
||||
node.Save(&writer);
|
||||
writer.writeEndElement();
|
||||
writer.writeEndDocument();
|
||||
buffer.close();
|
||||
|
||||
TestNode loaded;
|
||||
olive::SerializedData data;
|
||||
QBuffer read_buffer(&xml);
|
||||
read_buffer.open(QIODevice::ReadOnly);
|
||||
QXmlStreamReader reader(&read_buffer);
|
||||
EXPECT_TRUE(reader.readNextStartElement());
|
||||
EXPECT_EQ(reader.name().toString(), QStringLiteral("node"));
|
||||
EXPECT_TRUE(loaded.Load(&reader, &data));
|
||||
|
||||
EXPECT_EQ(loaded.GetLabel(), QStringLiteral("MyNode"));
|
||||
EXPECT_EQ(loaded.GetOverrideColor(), 2);
|
||||
EXPECT_DOUBLE_EQ(loaded.GetSplitStandardValue(QStringLiteral("Value"), -1)
|
||||
.first().toDouble(), 3.5);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <QVector2D>
|
||||
#include <QVector3D>
|
||||
#include <QVector4D>
|
||||
|
||||
#include "node/value.h"
|
||||
|
||||
TEST(NodeValue, VectorRoundTrip)
|
||||
{
|
||||
QVector2D v2(1.5f, -2.0f);
|
||||
QString encoded = olive::NodeValue::ValueToString(
|
||||
olive::NodeValue::kVec2, QVariant::fromValue(v2), false);
|
||||
QVariant decoded = olive::NodeValue::StringToValue(
|
||||
olive::NodeValue::kVec2, encoded, false);
|
||||
QVector2D v2_out = decoded.value<QVector2D>();
|
||||
EXPECT_FLOAT_EQ(v2_out.x(), v2.x());
|
||||
EXPECT_FLOAT_EQ(v2_out.y(), v2.y());
|
||||
|
||||
QVector3D v3(1.0f, 2.0f, 3.0f);
|
||||
encoded = olive::NodeValue::ValueToString(
|
||||
olive::NodeValue::kVec3, QVariant::fromValue(v3), false);
|
||||
decoded = olive::NodeValue::StringToValue(
|
||||
olive::NodeValue::kVec3, encoded, false);
|
||||
QVector3D v3_out = decoded.value<QVector3D>();
|
||||
EXPECT_FLOAT_EQ(v3_out.x(), v3.x());
|
||||
EXPECT_FLOAT_EQ(v3_out.y(), v3.y());
|
||||
EXPECT_FLOAT_EQ(v3_out.z(), v3.z());
|
||||
|
||||
QVector4D v4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
encoded = olive::NodeValue::ValueToString(
|
||||
olive::NodeValue::kVec4, QVariant::fromValue(v4), false);
|
||||
decoded = olive::NodeValue::StringToValue(
|
||||
olive::NodeValue::kVec4, encoded, false);
|
||||
QVector4D v4_out = decoded.value<QVector4D>();
|
||||
EXPECT_FLOAT_EQ(v4_out.x(), v4.x());
|
||||
EXPECT_FLOAT_EQ(v4_out.y(), v4.y());
|
||||
EXPECT_FLOAT_EQ(v4_out.z(), v4.z());
|
||||
EXPECT_FLOAT_EQ(v4_out.w(), v4.w());
|
||||
}
|
||||
|
||||
TEST(NodeValue, BinaryRoundTrip)
|
||||
{
|
||||
QByteArray data("OliveTest");
|
||||
QString encoded = olive::NodeValue::ValueToString(
|
||||
olive::NodeValue::kBinary, data, false);
|
||||
QVariant decoded = olive::NodeValue::StringToValue(
|
||||
olive::NodeValue::kBinary, encoded, false);
|
||||
EXPECT_EQ(decoded.toByteArray(), data);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "pluginSupport/OliveHost.h"
|
||||
|
||||
TEST(PluginSupport, LoadPluginsEmptyPath)
|
||||
{
|
||||
EXPECT_NO_THROW({
|
||||
olive::plugin::loadPlugins(QString());
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
#include "node/factory.h"
|
||||
#include "node/project.h"
|
||||
#include "node/input/time/timeinput.h"
|
||||
#include "node/project/serializer/serializer.h"
|
||||
|
||||
TEST(ProjectSerializer, SaveLoadProjectRoundTrip)
|
||||
{
|
||||
olive::NodeFactory::Initialize();
|
||||
|
||||
olive::Project project;
|
||||
project.Initialize();
|
||||
|
||||
auto *node = new olive::TimeInput();
|
||||
node->SetLabel(QStringLiteral("TimeInput"));
|
||||
node->setParent(&project);
|
||||
|
||||
olive::ProjectSerializer::SaveData save_data(
|
||||
olive::ProjectSerializer::kProject, &project, QString());
|
||||
|
||||
QByteArray xml;
|
||||
QBuffer buffer(&xml);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
QXmlStreamWriter writer(&buffer);
|
||||
EXPECT_EQ(olive::ProjectSerializer::Save(&writer, save_data),
|
||||
olive::ProjectSerializer::kSuccess);
|
||||
buffer.close();
|
||||
|
||||
olive::Project loaded_project;
|
||||
QBuffer read_buffer(&xml);
|
||||
read_buffer.open(QIODevice::ReadOnly);
|
||||
QXmlStreamReader reader(&read_buffer);
|
||||
olive::ProjectSerializer::Result result =
|
||||
olive::ProjectSerializer::Load(&loaded_project, &reader,
|
||||
olive::ProjectSerializer::kProject);
|
||||
EXPECT_EQ(result.code(), olive::ProjectSerializer::kSuccess);
|
||||
EXPECT_FALSE(loaded_project.nodes().isEmpty());
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
#include "node/project/serializer/typeserializer.h"
|
||||
#include "render/audioparams.h"
|
||||
|
||||
TEST(RenderAudioParams, SaveLoadRoundTrip)
|
||||
{
|
||||
olive::AudioParams params;
|
||||
params.set_sample_rate(48000);
|
||||
params.set_enabled(true);
|
||||
params.set_time_base(olive::core::rational(1, 48000));
|
||||
|
||||
QByteArray xml;
|
||||
QBuffer buffer(&xml);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
QXmlStreamWriter writer(&buffer);
|
||||
writer.writeStartDocument();
|
||||
writer.writeStartElement(QStringLiteral("audioparams"));
|
||||
olive::TypeSerializer::SaveAudioParams(&writer, params);
|
||||
writer.writeEndElement();
|
||||
writer.writeEndDocument();
|
||||
buffer.close();
|
||||
|
||||
QBuffer read_buffer(&xml);
|
||||
read_buffer.open(QIODevice::ReadOnly);
|
||||
QXmlStreamReader reader(&read_buffer);
|
||||
EXPECT_TRUE(reader.readNextStartElement());
|
||||
EXPECT_EQ(reader.name().toString(), QStringLiteral("audioparams"));
|
||||
olive::AudioParams loaded = olive::TypeSerializer::LoadAudioParams(&reader);
|
||||
|
||||
EXPECT_EQ(loaded.sample_rate(), 48000);
|
||||
EXPECT_TRUE(loaded.enabled());
|
||||
EXPECT_EQ(loaded.time_base(), olive::core::rational(1, 48000));
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
#include "render/videoparams.h"
|
||||
|
||||
TEST(RenderVideoParams, SaveLoadRoundTrip)
|
||||
{
|
||||
olive::VideoParams params;
|
||||
params.set_width(1280);
|
||||
params.set_height(720);
|
||||
params.set_frame_rate(olive::core::rational(24, 1));
|
||||
params.set_pixel_aspect_ratio(olive::core::rational(1, 1));
|
||||
params.set_colorspace(QStringLiteral("test"));
|
||||
|
||||
QByteArray xml;
|
||||
QBuffer buffer(&xml);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
QXmlStreamWriter writer(&buffer);
|
||||
writer.writeStartDocument();
|
||||
writer.writeStartElement(QStringLiteral("videoparams"));
|
||||
params.Save(&writer);
|
||||
writer.writeEndElement();
|
||||
writer.writeEndDocument();
|
||||
buffer.close();
|
||||
|
||||
olive::VideoParams loaded;
|
||||
QBuffer read_buffer(&xml);
|
||||
read_buffer.open(QIODevice::ReadOnly);
|
||||
QXmlStreamReader reader(&read_buffer);
|
||||
EXPECT_TRUE(reader.readNextStartElement());
|
||||
EXPECT_EQ(reader.name().toString(), QStringLiteral("videoparams"));
|
||||
loaded.Load(&reader);
|
||||
|
||||
EXPECT_EQ(loaded.width(), 1280);
|
||||
EXPECT_EQ(loaded.height(), 720);
|
||||
EXPECT_EQ(loaded.frame_rate(), olive::core::rational(24, 1));
|
||||
EXPECT_EQ(loaded.pixel_aspect_ratio(), olive::core::rational(1, 1));
|
||||
EXPECT_EQ(loaded.colorspace(), QStringLiteral("test"));
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <QEventLoop>
|
||||
#include <QTimer>
|
||||
|
||||
#include "task/taskmanager.h"
|
||||
|
||||
namespace {
|
||||
class DummyTask final : public olive::Task {
|
||||
public:
|
||||
explicit DummyTask(bool *ran)
|
||||
: ran_(ran)
|
||||
{
|
||||
SetTitle(QStringLiteral("DummyTask"));
|
||||
}
|
||||
|
||||
protected:
|
||||
bool Run() override
|
||||
{
|
||||
if (ran_) {
|
||||
*ran_ = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool *ran_ = nullptr;
|
||||
};
|
||||
}
|
||||
|
||||
TEST(TaskManager, AddAndRunTask)
|
||||
{
|
||||
olive::TaskManager::CreateInstance();
|
||||
olive::TaskManager *mgr = olive::TaskManager::instance();
|
||||
ASSERT_NE(mgr, nullptr);
|
||||
|
||||
bool ran = false;
|
||||
DummyTask *task = new DummyTask(&ran);
|
||||
|
||||
QEventLoop loop;
|
||||
QObject::connect(task, &olive::Task::Finished, &loop, [&loop](olive::Task *, bool) {
|
||||
loop.quit();
|
||||
});
|
||||
|
||||
mgr->AddTask(task);
|
||||
|
||||
QTimer::singleShot(5000, &loop, &QEventLoop::quit);
|
||||
loop.exec();
|
||||
|
||||
EXPECT_TRUE(ran);
|
||||
olive::TaskManager::DestroyInstance();
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
#include "timeline/timelinemarker.h"
|
||||
|
||||
TEST(TimelineMarker, SaveLoadRoundTrip)
|
||||
{
|
||||
olive::TimelineMarker marker;
|
||||
marker.set_time(olive::core::rational(10, 1));
|
||||
marker.set_name(QStringLiteral("Marker"));
|
||||
marker.set_color(5);
|
||||
|
||||
QByteArray xml;
|
||||
QBuffer buffer(&xml);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
QXmlStreamWriter writer(&buffer);
|
||||
writer.writeStartDocument();
|
||||
writer.writeStartElement(QStringLiteral("marker"));
|
||||
marker.save(&writer);
|
||||
writer.writeEndElement();
|
||||
writer.writeEndDocument();
|
||||
buffer.close();
|
||||
|
||||
olive::TimelineMarker loaded;
|
||||
QBuffer read_buffer(&xml);
|
||||
read_buffer.open(QIODevice::ReadOnly);
|
||||
QXmlStreamReader reader(&read_buffer);
|
||||
EXPECT_TRUE(reader.readNextStartElement());
|
||||
EXPECT_EQ(reader.name().toString(), QStringLiteral("marker"));
|
||||
loaded.load(&reader);
|
||||
|
||||
EXPECT_EQ(loaded.time(), olive::core::rational(10, 1));
|
||||
EXPECT_EQ(loaded.name(), QStringLiteral("Marker"));
|
||||
EXPECT_EQ(loaded.color(), 5);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "undo/undostack.h"
|
||||
#include "undo/undocommand.h"
|
||||
|
||||
namespace {
|
||||
class TestCommand final : public olive::UndoCommand {
|
||||
public:
|
||||
explicit TestCommand(int *value)
|
||||
: value_(value)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void redo() override
|
||||
{
|
||||
if (value_) {
|
||||
(*value_)++;
|
||||
}
|
||||
}
|
||||
|
||||
void undo() override
|
||||
{
|
||||
if (value_) {
|
||||
(*value_)--;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int *value_ = nullptr;
|
||||
};
|
||||
}
|
||||
|
||||
TEST(UndoStack, PushUndoRedo)
|
||||
{
|
||||
int counter = 0;
|
||||
olive::UndoStack stack;
|
||||
stack.push(new TestCommand(&counter), QStringLiteral("Test"));
|
||||
EXPECT_EQ(counter, 1);
|
||||
stack.undo();
|
||||
EXPECT_EQ(counter, 0);
|
||||
stack.redo();
|
||||
EXPECT_EQ(counter, 1);
|
||||
}
|
||||
Reference in New Issue
Block a user