Files
archived-Reclass/tests/test_command_row.cpp
IChooseYou 5b46065403 feat: enum/bitfield editing, MCP guard rails, PDB anonymous type inlining
- Enum inline editing: name/value commit handling, auto-sort by value
- Bitfield support in PDB import with proper container nodes
- Per-member hover/selection highlighting (kMemberBit encoding)
- Context menu fixes for enum/bitfield member lines
- MCP pagination (limit/offset), includeMembers param, tree.search tool
- MCP status bar activity indicator for tool calls
- PDB anonymous type inlining: inline <unnamed-tag> types as children
- Skip anonymous pointer targets to prevent root orphans
- Enum import diagnostics for debugging missing enums
2026-02-24 10:37:42 -07:00

140 lines
5.0 KiB
C++

#include <QTest>
#include <QString>
#include <memory>
#include "providers/provider.h"
#include "providers/buffer_provider.h"
#include "providers/null_provider.h"
using namespace rcx;
// -- Replicate the label-building logic from updateCommandRow so we can test it
// without needing a full RcxController/RcxDocument/RcxEditor stack.
static QString buildSourceLabel(const Provider& prov) {
QString provName = prov.name();
if (provName.isEmpty())
return QStringLiteral("source\u25BE");
return QStringLiteral("'%1'\u25BE").arg(provName);
}
static QString buildCommandRow(const Provider& prov, uint64_t baseAddress) {
QString src = buildSourceLabel(prov);
QString addr = QStringLiteral("0x") +
QString::number(baseAddress, 16).toUpper();
return QStringLiteral(" %1 %2").arg(src, addr);
}
// -- Replicate commandRowSrcSpan for testing
struct TestColumnSpan {
int start = 0;
int end = 0;
bool valid = false;
};
static TestColumnSpan commandRowSrcSpan(const QString& lineText) {
int arrow = lineText.indexOf(QChar(0x25BE));
if (arrow < 0) return {};
int start = 0;
while (start < arrow && !lineText[start].isLetterOrNumber()
&& lineText[start] != '<' && lineText[start] != '\'') start++;
if (start >= arrow) return {};
return {start, arrow, true};
}
class TestCommandRow : public QObject {
Q_OBJECT
private slots:
// ---------------------------------------------------------------
// Source label text
// ---------------------------------------------------------------
void label_nullProvider_showsSelectSource() {
NullProvider p;
QCOMPARE(buildSourceLabel(p), QStringLiteral("source\u25BE"));
}
void label_bufferNoName_showsSelectSource() {
// BufferProvider with empty name also triggers source▾
BufferProvider p(QByteArray(4, '\0'));
QCOMPARE(buildSourceLabel(p), QStringLiteral("source\u25BE"));
}
void label_bufferWithName_showsFileAndName() {
BufferProvider p(QByteArray(4, '\0'), "dump.bin");
QCOMPARE(buildSourceLabel(p), QStringLiteral("'dump.bin'\u25BE"));
}
// ---------------------------------------------------------------
// Full command row text
// ---------------------------------------------------------------
void row_nullProvider() {
NullProvider p;
QString row = buildCommandRow(p, 0);
QCOMPARE(row, QStringLiteral(" source\u25BE 0x0"));
}
void row_fileProvider() {
BufferProvider p(QByteArray(4, '\0'), "test.bin");
QString row = buildCommandRow(p, 0x140000000ULL);
QCOMPARE(row, QStringLiteral(" 'test.bin'\u25BE 0x140000000"));
}
// ---------------------------------------------------------------
// Source span parsing
// ---------------------------------------------------------------
void span_selectSource() {
QString row = buildCommandRow(NullProvider{}, 0);
auto span = commandRowSrcSpan(row);
QVERIFY(span.valid);
QString extracted = row.mid(span.start, span.end - span.start);
QCOMPARE(extracted, QStringLiteral("source"));
}
void span_fileProvider() {
BufferProvider p(QByteArray(4, '\0'), "dump.bin");
QString row = buildCommandRow(p, 0x140000000ULL);
auto span = commandRowSrcSpan(row);
QVERIFY(span.valid);
QString extracted = row.mid(span.start, span.end - span.start);
QCOMPARE(extracted, QStringLiteral("'dump.bin'"));
}
void span_processProvider_simulated() {
// Simulate a process provider without needing Windows APIs
// by building the string directly
QString row = QStringLiteral(" 'notepad.exe'\u25BE 0x7FF600000000");
auto span = commandRowSrcSpan(row);
QVERIFY(span.valid);
QString extracted = row.mid(span.start, span.end - span.start);
QCOMPARE(extracted, QStringLiteral("'notepad.exe'"));
}
// ---------------------------------------------------------------
// Provider switching simulation
// ---------------------------------------------------------------
void switching_nullToFileToProcess() {
// Start with NullProvider
std::unique_ptr<Provider> prov = std::make_unique<NullProvider>();
QCOMPARE(buildSourceLabel(*prov), QStringLiteral("source\u25BE"));
// User loads a file
prov = std::make_unique<BufferProvider>(QByteArray(64, '\0'), "game.exe");
QCOMPARE(buildSourceLabel(*prov), QStringLiteral("'game.exe'\u25BE"));
// User switches to a "process" -- simulate with a named BufferProvider
// (ProcessProvider needs Windows, but the label logic is the same)
prov = std::make_unique<BufferProvider>(QByteArray(64, '\0'), "notepad.exe");
// BufferProvider kind is "File", but the switching mechanism works the same
QCOMPARE(prov->kind(), QStringLiteral("File"));
QCOMPARE(prov->name(), QStringLiteral("notepad.exe"));
}
};
QTEST_MAIN(TestCommandRow)
#include "test_command_row.moc"