完善测试
This commit is contained in:
@@ -15,7 +15,8 @@ jobs:
|
|||||||
CMAKE_BUILD_TYPE: Release
|
CMAKE_BUILD_TYPE: Release
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
- name: Install dependencies (Linux)
|
- name: Install dependencies (Linux)
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -306,9 +306,11 @@ void TimelineMarkerList::HandleMarkerTimeChange()
|
|||||||
MarkerAddCommand::MarkerAddCommand(TimelineMarkerList *marker_list,
|
MarkerAddCommand::MarkerAddCommand(TimelineMarkerList *marker_list,
|
||||||
const TimeRange &range, const QString &name,
|
const TimeRange &range, const QString &name,
|
||||||
int color)
|
int color)
|
||||||
: MarkerAddCommand(marker_list,
|
: marker_list_(marker_list)
|
||||||
new TimelineMarker(color, range, name, &memory_manager_))
|
, added_marker_(nullptr)
|
||||||
{
|
{
|
||||||
|
added_marker_ = new TimelineMarker(color, range, name, &memory_manager_);
|
||||||
|
added_marker_->setParent(&memory_manager_);
|
||||||
}
|
}
|
||||||
|
|
||||||
MarkerAddCommand::MarkerAddCommand(TimelineMarkerList *marker_list,
|
MarkerAddCommand::MarkerAddCommand(TimelineMarkerList *marker_list,
|
||||||
|
|||||||
@@ -59,6 +59,13 @@
|
|||||||
- 使用事件循环等待完成。
|
- 使用事件循环等待完成。
|
||||||
- 验证任务确实执行。
|
- 验证任务确实执行。
|
||||||
|
|
||||||
|
## 单元覆盖重点(已扩展)
|
||||||
|
|
||||||
|
- `app/undo`:`undo_stack_test.cpp` 覆盖空栈状态、模型数据、redo 区域颜色、jump 行为、空 MultiUndoCommand 忽略逻辑。
|
||||||
|
- `app/timeline`:`timeline_marker_test.cpp` 覆盖列表排序、最近 marker 查询、含未知元素的保存/加载、marker 增删改命令。
|
||||||
|
- `app/pluginSupport`:`plugin_support_image_test.cpp` 覆盖 OFX 属性映射(bounds/ROD、像素深度、通道、预乘)及分配/清理行为。
|
||||||
|
- `app/render`:`render_videoparams_branch_test.cpp` 覆盖自动 divider、像素宽高比校验、方形像素宽度、Save/Load 回归。
|
||||||
|
|
||||||
## 无 GUI 运行
|
## 无 GUI 运行
|
||||||
|
|
||||||
- 测试避免使用 QWidget。
|
- 测试避免使用 QWidget。
|
||||||
|
|||||||
@@ -59,6 +59,13 @@ If a module has a GUI dependency (e.g., widgets), tests focus on non-visual data
|
|||||||
- Waits for completion using an event loop.
|
- Waits for completion using an event loop.
|
||||||
- Verifies the task ran.
|
- Verifies the task ran.
|
||||||
|
|
||||||
|
## Unit Coverage Highlights (Expanded)
|
||||||
|
|
||||||
|
- `app/undo`: `undo_stack_test.cpp` now covers empty stack state, model data, redo list coloring, jump behavior, and ignored empty multi-commands.
|
||||||
|
- `app/timeline`: `timeline_marker_test.cpp` now covers list ordering, closest-marker lookup, list save/load with unknown elements, and marker add/remove/change commands.
|
||||||
|
- `app/pluginSupport`: `plugin_support_image_test.cpp` now checks OFX property wiring (bounds/ROD, pixel depth, components, premult) and allocation clearing behavior.
|
||||||
|
- `app/render`: `render_videoparams_branch_test.cpp` now covers auto divider selection, pixel aspect validation, square-pixel width, and Save/Load roundtrip.
|
||||||
|
|
||||||
## Headless Execution
|
## Headless Execution
|
||||||
|
|
||||||
- Tests avoid QWidget usage.
|
- Tests avoid QWidget usage.
|
||||||
|
|||||||
@@ -89,3 +89,59 @@ TEST(PluginSupportImage, PropertyFallbacks)
|
|||||||
EXPECT_EQ(image.width(), 32);
|
EXPECT_EQ(image.width(), 32);
|
||||||
EXPECT_EQ(image.height(), 50);
|
EXPECT_EQ(image.height(), 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(PluginSupportImage, AllocateSetsOfxProperties)
|
||||||
|
{
|
||||||
|
OFX::Host::ImageEffect::ClipDescriptor desc(kOfxImageEffectOutputClipName);
|
||||||
|
olive::VideoParams params =
|
||||||
|
MakeParams(8, 6, olive::core::PixelFormat::F16, 4, false);
|
||||||
|
olive::plugin::OliveClipInstance clip(nullptr, desc, params);
|
||||||
|
|
||||||
|
olive::plugin::Image image(clip);
|
||||||
|
OfxRectI bounds = { 2, 3, 10, 9 };
|
||||||
|
OfxRectI rod = { 0, 0, 12, 12 };
|
||||||
|
image.Allocate(8, 6, olive::core::PixelFormat::F16, 4, false, bounds, rod,
|
||||||
|
true);
|
||||||
|
|
||||||
|
EXPECT_NE(image.data(), nullptr);
|
||||||
|
EXPECT_EQ(image.row_bytes(), 8 * 4 * 2);
|
||||||
|
|
||||||
|
int bounds_props[4] = {0};
|
||||||
|
image.getIntPropertyN(kOfxImagePropBounds, bounds_props, 4);
|
||||||
|
EXPECT_EQ(bounds_props[0], bounds.x1);
|
||||||
|
EXPECT_EQ(bounds_props[1], bounds.y1);
|
||||||
|
EXPECT_EQ(bounds_props[2], bounds.x2);
|
||||||
|
EXPECT_EQ(bounds_props[3], bounds.y2);
|
||||||
|
|
||||||
|
int rod_props[4] = {0};
|
||||||
|
image.getIntPropertyN(kOfxImagePropRegionOfDefinition, rod_props, 4);
|
||||||
|
EXPECT_EQ(rod_props[0], rod.x1);
|
||||||
|
EXPECT_EQ(rod_props[1], rod.y1);
|
||||||
|
EXPECT_EQ(rod_props[2], rod.x2);
|
||||||
|
EXPECT_EQ(rod_props[3], rod.y2);
|
||||||
|
|
||||||
|
EXPECT_EQ(image.getStringProperty(kOfxImageEffectPropComponents),
|
||||||
|
std::string(kOfxImageComponentRGBA));
|
||||||
|
EXPECT_EQ(image.getStringProperty(kOfxImageEffectPropPixelDepth),
|
||||||
|
std::string(kOfxBitDepthHalf));
|
||||||
|
EXPECT_EQ(image.getStringProperty(kOfxImageEffectPropPreMultiplication),
|
||||||
|
std::string(kOfxImageUnPreMultiplied));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(PluginSupportImage, EnsureAllocatedPreservesWithoutClear)
|
||||||
|
{
|
||||||
|
OFX::Host::ImageEffect::ClipDescriptor desc(kOfxImageEffectOutputClipName);
|
||||||
|
olive::VideoParams params =
|
||||||
|
MakeParams(4, 4, olive::core::PixelFormat::U8, 3, false);
|
||||||
|
olive::plugin::OliveClipInstance clip(nullptr, desc, params);
|
||||||
|
|
||||||
|
olive::plugin::Image image(clip);
|
||||||
|
OfxRectI bounds = { 0, 0, 4, 4 };
|
||||||
|
OfxRectI rod = bounds;
|
||||||
|
image.AllocateFromParams(params, bounds, rod, true);
|
||||||
|
ASSERT_NE(image.data(), nullptr);
|
||||||
|
image.data()[0] = 0x5A;
|
||||||
|
|
||||||
|
image.EnsureAllocatedFromParams(params, bounds, rod, false);
|
||||||
|
EXPECT_EQ(image.data()[0], 0x5A);
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ extern "C" {
|
|||||||
#include <libavutil/avutil.h>
|
#include <libavutil/avutil.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <QBuffer>
|
||||||
|
#include <QXmlStreamReader>
|
||||||
|
#include <QXmlStreamWriter>
|
||||||
|
|
||||||
#include "render/videoparams.h"
|
#include "render/videoparams.h"
|
||||||
|
|
||||||
TEST(RenderVideoParams, BytesPerChannelAndPixel)
|
TEST(RenderVideoParams, BytesPerChannelAndPixel)
|
||||||
@@ -64,6 +68,21 @@ TEST(RenderVideoParams, FrameRateStringsAndPixelAspect)
|
|||||||
EXPECT_TRUE(names.at(0).contains(QStringLiteral("1.0000")));
|
EXPECT_TRUE(names.at(0).contains(QStringLiteral("1.0000")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(RenderVideoParams, AutoDividerAndPixelAspect)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(olive::VideoParams::generate_auto_divider(640, 480), 1);
|
||||||
|
EXPECT_EQ(olive::VideoParams::generate_auto_divider(7680, 4320), 6);
|
||||||
|
EXPECT_EQ(olive::VideoParams::generate_auto_divider(50000, 50000), 16);
|
||||||
|
|
||||||
|
olive::VideoParams params(100, 50, olive::core::PixelFormat::U8, 4);
|
||||||
|
params.set_pixel_aspect_ratio(olive::core::rational(0, 1));
|
||||||
|
EXPECT_EQ(params.pixel_aspect_ratio(), olive::core::rational(1, 1));
|
||||||
|
EXPECT_EQ(params.square_pixel_width(), 100);
|
||||||
|
|
||||||
|
params.set_pixel_aspect_ratio(olive::core::rational(2, 1));
|
||||||
|
EXPECT_EQ(params.square_pixel_width(), 200);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(RenderVideoParams, ValidityAndTimebase)
|
TEST(RenderVideoParams, ValidityAndTimebase)
|
||||||
{
|
{
|
||||||
olive::VideoParams params;
|
olive::VideoParams params;
|
||||||
@@ -82,3 +101,65 @@ TEST(RenderVideoParams, ValidityAndTimebase)
|
|||||||
EXPECT_EQ(params.get_time_in_timebase_units(olive::core::rational(2, 1)),
|
EXPECT_EQ(params.get_time_in_timebase_units(olive::core::rational(2, 1)),
|
||||||
12);
|
12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(RenderVideoParams, SaveLoadRoundTripExtended)
|
||||||
|
{
|
||||||
|
olive::VideoParams params(1920, 1080, olive::core::rational(1, 24),
|
||||||
|
olive::core::PixelFormat::U16, 4);
|
||||||
|
params.set_depth(2);
|
||||||
|
params.set_pixel_aspect_ratio(olive::core::rational(4, 3));
|
||||||
|
params.set_interlacing(olive::VideoParams::kInterlacedTopFirst);
|
||||||
|
params.set_divider(2);
|
||||||
|
params.set_enabled(false);
|
||||||
|
params.set_x(1.5f);
|
||||||
|
params.set_y(-2.25f);
|
||||||
|
params.set_stream_index(7);
|
||||||
|
params.set_video_type(olive::VideoParams::kVideoTypeImageSequence);
|
||||||
|
params.set_frame_rate(olive::core::rational(30000, 1001));
|
||||||
|
params.set_start_time(123);
|
||||||
|
params.set_duration(456);
|
||||||
|
params.set_premultiplied_alpha(true);
|
||||||
|
params.set_colorspace(QStringLiteral("Rec.709"));
|
||||||
|
params.set_color_range(olive::VideoParams::kColorRangeFull);
|
||||||
|
|
||||||
|
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);
|
||||||
|
ASSERT_TRUE(reader.readNextStartElement());
|
||||||
|
EXPECT_EQ(reader.name().toString(), QStringLiteral("videoparams"));
|
||||||
|
loaded.Load(&reader);
|
||||||
|
|
||||||
|
EXPECT_EQ(loaded.width(), 1920);
|
||||||
|
EXPECT_EQ(loaded.height(), 1080);
|
||||||
|
EXPECT_EQ(loaded.depth(), 2);
|
||||||
|
EXPECT_EQ(loaded.time_base(), olive::core::rational(1, 24));
|
||||||
|
EXPECT_EQ(loaded.format(), olive::core::PixelFormat::U16);
|
||||||
|
EXPECT_EQ(loaded.channel_count(), 4);
|
||||||
|
EXPECT_EQ(loaded.pixel_aspect_ratio(), olive::core::rational(4, 3));
|
||||||
|
EXPECT_EQ(loaded.interlacing(), olive::VideoParams::kInterlacedTopFirst);
|
||||||
|
EXPECT_EQ(loaded.divider(), 2);
|
||||||
|
EXPECT_EQ(loaded.enabled(), false);
|
||||||
|
EXPECT_FLOAT_EQ(loaded.x(), 1.5f);
|
||||||
|
EXPECT_FLOAT_EQ(loaded.y(), -2.25f);
|
||||||
|
EXPECT_EQ(loaded.stream_index(), 7);
|
||||||
|
EXPECT_EQ(loaded.video_type(),
|
||||||
|
olive::VideoParams::kVideoTypeImageSequence);
|
||||||
|
EXPECT_EQ(loaded.frame_rate(), olive::core::rational(30000, 1001));
|
||||||
|
EXPECT_EQ(loaded.start_time(), 123);
|
||||||
|
EXPECT_EQ(loaded.duration(), 456);
|
||||||
|
EXPECT_TRUE(loaded.premultiplied_alpha());
|
||||||
|
EXPECT_EQ(loaded.colorspace(), QStringLiteral("Rec.709"));
|
||||||
|
EXPECT_EQ(loaded.color_range(), olive::VideoParams::kColorRangeFull);
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,3 +36,125 @@ TEST(TimelineMarker, SaveLoadRoundTrip)
|
|||||||
EXPECT_EQ(loaded.name(), QStringLiteral("Marker"));
|
EXPECT_EQ(loaded.name(), QStringLiteral("Marker"));
|
||||||
EXPECT_EQ(loaded.color(), 5);
|
EXPECT_EQ(loaded.color(), 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(TimelineMarkerList, OrderAndLookup)
|
||||||
|
{
|
||||||
|
olive::TimelineMarkerList list;
|
||||||
|
olive::TimelineMarker marker_a(
|
||||||
|
1,
|
||||||
|
olive::core::TimeRange(olive::core::rational(10, 1),
|
||||||
|
olive::core::rational(10, 1)),
|
||||||
|
QStringLiteral("A"),
|
||||||
|
&list);
|
||||||
|
olive::TimelineMarker marker_b(
|
||||||
|
2,
|
||||||
|
olive::core::TimeRange(olive::core::rational(5, 1),
|
||||||
|
olive::core::rational(5, 1)),
|
||||||
|
QStringLiteral("B"),
|
||||||
|
&list);
|
||||||
|
olive::TimelineMarker marker_c(
|
||||||
|
3,
|
||||||
|
olive::core::TimeRange(olive::core::rational(20, 1),
|
||||||
|
olive::core::rational(20, 1)),
|
||||||
|
QStringLiteral("C"),
|
||||||
|
&list);
|
||||||
|
|
||||||
|
ASSERT_EQ(list.size(), 3);
|
||||||
|
auto it = list.cbegin();
|
||||||
|
EXPECT_EQ((*it)->time().in(), olive::core::rational(5, 1));
|
||||||
|
++it;
|
||||||
|
EXPECT_EQ((*it)->time().in(), olive::core::rational(10, 1));
|
||||||
|
++it;
|
||||||
|
EXPECT_EQ((*it)->time().in(), olive::core::rational(20, 1));
|
||||||
|
|
||||||
|
EXPECT_EQ(list.GetMarkerAtTime(olive::core::rational(10, 1)), &marker_a);
|
||||||
|
EXPECT_EQ(list.GetClosestMarkerToTime(olive::core::rational(7, 1)),
|
||||||
|
&marker_b);
|
||||||
|
EXPECT_EQ(list.GetClosestMarkerToTime(olive::core::rational(9, 1)),
|
||||||
|
&marker_a);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TimelineMarkerList, SaveLoadWithUnknownElements)
|
||||||
|
{
|
||||||
|
olive::TimelineMarkerList list;
|
||||||
|
olive::TimelineMarker marker(
|
||||||
|
4,
|
||||||
|
olive::core::TimeRange(olive::core::rational(12, 1),
|
||||||
|
olive::core::rational(15, 1)),
|
||||||
|
QStringLiteral("Span"),
|
||||||
|
&list);
|
||||||
|
|
||||||
|
QByteArray xml;
|
||||||
|
QBuffer buffer(&xml);
|
||||||
|
buffer.open(QIODevice::WriteOnly);
|
||||||
|
QXmlStreamWriter writer(&buffer);
|
||||||
|
writer.writeStartDocument();
|
||||||
|
writer.writeStartElement(QStringLiteral("markers"));
|
||||||
|
writer.writeStartElement(QStringLiteral("unknown"));
|
||||||
|
writer.writeEndElement();
|
||||||
|
list.save(&writer);
|
||||||
|
writer.writeEndElement();
|
||||||
|
writer.writeEndDocument();
|
||||||
|
buffer.close();
|
||||||
|
|
||||||
|
olive::TimelineMarkerList loaded;
|
||||||
|
QBuffer read_buffer(&xml);
|
||||||
|
read_buffer.open(QIODevice::ReadOnly);
|
||||||
|
QXmlStreamReader reader(&read_buffer);
|
||||||
|
EXPECT_TRUE(reader.readNextStartElement());
|
||||||
|
EXPECT_EQ(reader.name().toString(), QStringLiteral("markers"));
|
||||||
|
EXPECT_TRUE(loaded.load(&reader));
|
||||||
|
EXPECT_EQ(loaded.size(), 1);
|
||||||
|
EXPECT_EQ(loaded.front()->name(), QStringLiteral("Span"));
|
||||||
|
EXPECT_EQ(loaded.front()->time().in(), olive::core::rational(12, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TimelineMarkerCommands, AddRemoveAndChange)
|
||||||
|
{
|
||||||
|
olive::TimelineMarkerList list;
|
||||||
|
olive::MarkerAddCommand add(
|
||||||
|
&list,
|
||||||
|
olive::core::TimeRange(olive::core::rational(1, 1),
|
||||||
|
olive::core::rational(2, 1)),
|
||||||
|
QStringLiteral("One"),
|
||||||
|
1);
|
||||||
|
add.redo_now();
|
||||||
|
ASSERT_EQ(list.size(), 1);
|
||||||
|
auto *marker = list.front();
|
||||||
|
EXPECT_EQ(marker->name(), QStringLiteral("One"));
|
||||||
|
|
||||||
|
olive::MarkerChangeNameCommand rename(marker, QStringLiteral("Renamed"));
|
||||||
|
rename.redo_now();
|
||||||
|
EXPECT_EQ(marker->name(), QStringLiteral("Renamed"));
|
||||||
|
rename.undo_now();
|
||||||
|
EXPECT_EQ(marker->name(), QStringLiteral("One"));
|
||||||
|
|
||||||
|
olive::MarkerChangeColorCommand recolor(marker, 9);
|
||||||
|
recolor.redo_now();
|
||||||
|
EXPECT_EQ(marker->color(), 9);
|
||||||
|
recolor.undo_now();
|
||||||
|
EXPECT_EQ(marker->color(), 1);
|
||||||
|
|
||||||
|
olive::MarkerRemoveCommand remove(marker);
|
||||||
|
remove.redo_now();
|
||||||
|
EXPECT_TRUE(list.empty());
|
||||||
|
remove.undo_now();
|
||||||
|
EXPECT_EQ(list.size(), 1);
|
||||||
|
|
||||||
|
olive::TimelineMarker other(
|
||||||
|
2,
|
||||||
|
olive::core::TimeRange(olive::core::rational(5, 1),
|
||||||
|
olive::core::rational(5, 1)),
|
||||||
|
QStringLiteral("Two"),
|
||||||
|
&list);
|
||||||
|
EXPECT_EQ(list.front()->time().in(), olive::core::rational(1, 1));
|
||||||
|
|
||||||
|
olive::MarkerChangeTimeCommand move(
|
||||||
|
marker,
|
||||||
|
olive::core::TimeRange(olive::core::rational(0, 1),
|
||||||
|
olive::core::rational(0, 1)));
|
||||||
|
move.redo_now();
|
||||||
|
EXPECT_EQ(list.front(), marker);
|
||||||
|
move.undo_now();
|
||||||
|
EXPECT_EQ(list.front()->time().in(), olive::core::rational(1, 1));
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <QColor>
|
||||||
|
|
||||||
#include "undo/undostack.h"
|
#include "undo/undostack.h"
|
||||||
#include "undo/undocommand.h"
|
#include "undo/undocommand.h"
|
||||||
|
|
||||||
@@ -47,3 +49,74 @@ TEST(UndoStack, PushUndoRedo)
|
|||||||
stack.redo();
|
stack.redo();
|
||||||
EXPECT_EQ(counter, 1);
|
EXPECT_EQ(counter, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(UndoStack, EmptyStateAndModelData)
|
||||||
|
{
|
||||||
|
olive::UndoStack stack;
|
||||||
|
EXPECT_FALSE(stack.CanUndo());
|
||||||
|
EXPECT_FALSE(stack.CanRedo());
|
||||||
|
EXPECT_EQ(stack.columnCount(), 2);
|
||||||
|
EXPECT_EQ(stack.rowCount(), 1);
|
||||||
|
EXPECT_TRUE(stack.hasChildren(QModelIndex()));
|
||||||
|
|
||||||
|
QModelIndex name_index = stack.index(0, 1);
|
||||||
|
EXPECT_EQ(stack.data(name_index, Qt::DisplayRole).toString(),
|
||||||
|
QStringLiteral("New/Open Project"));
|
||||||
|
EXPECT_EQ(stack.headerData(0, Qt::Horizontal, Qt::DisplayRole).toString(),
|
||||||
|
QStringLiteral("Number"));
|
||||||
|
EXPECT_EQ(stack.headerData(1, Qt::Horizontal, Qt::DisplayRole).toString(),
|
||||||
|
QStringLiteral("Action"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(UndoStack, UndoRedoListsAndColors)
|
||||||
|
{
|
||||||
|
int counter = 0;
|
||||||
|
olive::UndoStack stack;
|
||||||
|
stack.push(new TestCommand(&counter), QStringLiteral("First"));
|
||||||
|
stack.push(new TestCommand(&counter), QStringLiteral("Second"));
|
||||||
|
EXPECT_EQ(counter, 2);
|
||||||
|
EXPECT_EQ(stack.rowCount(), 3);
|
||||||
|
|
||||||
|
stack.undo();
|
||||||
|
EXPECT_EQ(counter, 1);
|
||||||
|
EXPECT_TRUE(stack.CanRedo());
|
||||||
|
|
||||||
|
QModelIndex undone_name = stack.index(2, 1);
|
||||||
|
EXPECT_EQ(stack.data(undone_name, Qt::DisplayRole).toString(),
|
||||||
|
QStringLiteral("Second"));
|
||||||
|
QColor undone_color =
|
||||||
|
stack.data(undone_name, Qt::ForegroundRole).value<QColor>();
|
||||||
|
EXPECT_EQ(undone_color, QColor(Qt::gray));
|
||||||
|
|
||||||
|
stack.redo();
|
||||||
|
EXPECT_EQ(counter, 2);
|
||||||
|
EXPECT_FALSE(stack.CanRedo());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(UndoStack, JumpRestoresState)
|
||||||
|
{
|
||||||
|
int counter = 0;
|
||||||
|
olive::UndoStack stack;
|
||||||
|
stack.push(new TestCommand(&counter), QStringLiteral("A"));
|
||||||
|
stack.push(new TestCommand(&counter), QStringLiteral("B"));
|
||||||
|
stack.push(new TestCommand(&counter), QStringLiteral("C"));
|
||||||
|
EXPECT_EQ(counter, 3);
|
||||||
|
EXPECT_EQ(stack.rowCount(), 4);
|
||||||
|
|
||||||
|
stack.jump(1);
|
||||||
|
EXPECT_EQ(counter, 0);
|
||||||
|
EXPECT_TRUE(stack.CanRedo());
|
||||||
|
|
||||||
|
stack.jump(4);
|
||||||
|
EXPECT_EQ(counter, 3);
|
||||||
|
EXPECT_FALSE(stack.CanRedo());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(UndoStack, EmptyMultiUndoCommandIsIgnored)
|
||||||
|
{
|
||||||
|
olive::UndoStack stack;
|
||||||
|
auto *empty_multi = new olive::MultiUndoCommand();
|
||||||
|
stack.push(empty_multi, QStringLiteral("Empty"));
|
||||||
|
EXPECT_EQ(stack.rowCount(), 1);
|
||||||
|
EXPECT_FALSE(stack.CanUndo());
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user