Files
oak-editor/tests/gtest/undo_stack_test.cpp
T
Mike-Solar 748c53ac5c 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.
2026-07-13 10:19:30 +08:00

188 lines
4.2 KiB
C++

#include <gtest/gtest.h>
#include <QColor>
#include "undo/undostack.h"
#include "undo/undocommand.h"
namespace {
class TestCommand final : public olive::UndoCommand {
public:
explicit TestCommand(int *value)
: value_(value)
{
}
olive::Project *GetRelevantProject() const override
{
return nullptr;
}
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);
}
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());
}
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);
}