163 lines
6.3 KiB
C++
163 lines
6.3 KiB
C++
#include <gtest/gtest.h>
|
||
#include <QSignalSpy>
|
||
#include "DatasetDetailController.hpp"
|
||
#include "IDatasetChartStrategy.hpp"
|
||
#include "repo/IAsyncDatasetRepository.hpp"
|
||
#include "api/DatasetLoadHandles.hpp"
|
||
using namespace geopro;
|
||
|
||
namespace {
|
||
// 反演策略桩:散点 + 网格两阶段。
|
||
struct InversionStrategy : controller::IDatasetChartStrategy {
|
||
std::string ddCode() const override { return "dd_inversion_data"; }
|
||
bool hasGridPhase() const override { return true; }
|
||
};
|
||
// 无网格阶段策略桩:仅散点(如纯散点类型)。
|
||
struct NoGridStrategy : controller::IDatasetChartStrategy {
|
||
std::string ddCode() const override { return "dd_scatter_only"; }
|
||
bool hasGridPhase() const override { return false; }
|
||
};
|
||
// 注册了反演策略的注册表(多数用例复用)。
|
||
controller::ChartStrategyRegistry makeInversionRegistry() {
|
||
controller::ChartStrategyRegistry reg;
|
||
reg.add(std::make_unique<InversionStrategy>());
|
||
return reg;
|
||
}
|
||
|
||
// 桩句柄:不声明 Q_OBJECT —— 发射继承自 data::ChartLoad/GridLoad 的信号、override abort。
|
||
struct StubChartLoad : data::ChartLoad {
|
||
bool aborted = false;
|
||
void abort() override { aborted = true; }
|
||
void fireDone() { emit done(data::ChartParts{}); }
|
||
void fireFailed() { emit failed(QStringLiteral("x")); }
|
||
};
|
||
struct StubGridLoad : data::GridLoad {
|
||
bool aborted = false;
|
||
void abort() override { aborted = true; }
|
||
void fireDone() { emit done(data::GridParts{}); }
|
||
void fireFailed() { emit failed(QStringLiteral("x")); }
|
||
};
|
||
struct StubAsyncRepo : data::IAsyncDatasetRepository {
|
||
StubChartLoad* lastChart = nullptr;
|
||
StubGridLoad* lastGrid = nullptr;
|
||
data::ChartLoad* loadChartAsync(const std::string&) override {
|
||
lastChart = new StubChartLoad; return lastChart;
|
||
}
|
||
data::GridLoad* loadGridAsync(const std::string&) override {
|
||
lastGrid = new StubGridLoad; return lastGrid;
|
||
}
|
||
};
|
||
}
|
||
|
||
TEST(DatasetDetailController, EmitsChartReadyOnDone) {
|
||
StubAsyncRepo repo;
|
||
auto reg = makeInversionRegistry();
|
||
controller::DatasetDetailController c(repo, reg);
|
||
QSignalSpy spy(&c, &controller::DatasetDetailController::chartReady);
|
||
c.openDataset("ds1", "dd_inversion_data");
|
||
repo.lastChart->fireDone();
|
||
EXPECT_EQ(spy.count(), 1);
|
||
}
|
||
|
||
TEST(DatasetDetailController, EmitsLoadFailedOnFailed) {
|
||
StubAsyncRepo repo;
|
||
auto reg = makeInversionRegistry();
|
||
controller::DatasetDetailController c(repo, reg);
|
||
QSignalSpy spy(&c, &controller::DatasetDetailController::loadFailed);
|
||
c.openDataset("ds1", "dd_inversion_data");
|
||
repo.lastChart->fireFailed();
|
||
EXPECT_EQ(spy.count(), 1);
|
||
}
|
||
|
||
TEST(DatasetDetailController, UnsupportedTypeFailsImmediately) {
|
||
StubAsyncRepo repo;
|
||
auto reg = makeInversionRegistry(); // 注册了反演,但未注册 dd_other
|
||
controller::DatasetDetailController c(repo, reg);
|
||
QSignalSpy spy(&c, &controller::DatasetDetailController::loadFailed);
|
||
c.openDataset("ds1", "dd_other");
|
||
EXPECT_EQ(spy.count(), 1);
|
||
EXPECT_EQ(repo.lastChart, nullptr); // 未发起加载
|
||
}
|
||
|
||
// 空注册表 → 任意 ddCode 都不支持 → loadFailed,不发起加载。
|
||
TEST(DatasetDetailController, EmptyRegistryFailsAnyType) {
|
||
StubAsyncRepo repo;
|
||
controller::ChartStrategyRegistry reg; // 空
|
||
controller::DatasetDetailController c(repo, reg);
|
||
QSignalSpy spy(&c, &controller::DatasetDetailController::loadFailed);
|
||
c.openDataset("ds1", "dd_inversion_data");
|
||
EXPECT_EQ(spy.count(), 1);
|
||
EXPECT_EQ(repo.lastChart, nullptr);
|
||
}
|
||
|
||
// 无网格阶段的策略 → loadGridData 不发起网格加载。
|
||
TEST(DatasetDetailController, NoGridPhaseStrategySkipsGridLoad) {
|
||
StubAsyncRepo repo;
|
||
controller::ChartStrategyRegistry reg;
|
||
reg.add(std::make_unique<NoGridStrategy>());
|
||
controller::DatasetDetailController c(repo, reg);
|
||
c.loadGridData("ds1", "dd_scatter_only");
|
||
EXPECT_EQ(repo.lastGrid, nullptr); // hasGridPhase()==false → 未发起
|
||
}
|
||
|
||
TEST(DatasetDetailController, AbortsPreviousOnReopen) {
|
||
StubAsyncRepo repo;
|
||
auto reg = makeInversionRegistry();
|
||
controller::DatasetDetailController c(repo, reg);
|
||
c.openDataset("dsA", "dd_inversion_data");
|
||
StubChartLoad* a = repo.lastChart;
|
||
c.openDataset("dsB", "dd_inversion_data"); // 替换
|
||
EXPECT_TRUE(a->aborted); // 旧句柄被 abort
|
||
}
|
||
|
||
TEST(DatasetDetailController, DropsLateSignalFromAbortedLoad) {
|
||
StubAsyncRepo repo;
|
||
auto reg = makeInversionRegistry();
|
||
controller::DatasetDetailController c(repo, reg);
|
||
QSignalSpy spy(&c, &controller::DatasetDetailController::chartReady);
|
||
c.openDataset("dsA", "dd_inversion_data");
|
||
StubChartLoad* a = repo.lastChart;
|
||
c.openDataset("dsB", "dd_inversion_data");
|
||
StubChartLoad* b = repo.lastChart;
|
||
a->fireDone(); // 旧句柄迟到 → 身份比对丢弃
|
||
EXPECT_EQ(spy.count(), 0);
|
||
b->fireDone(); // 当前句柄 → 正常
|
||
EXPECT_EQ(spy.count(), 1);
|
||
}
|
||
|
||
TEST(DatasetDetailController, EmitsGridReadyOnDone) {
|
||
StubAsyncRepo repo;
|
||
auto reg = makeInversionRegistry();
|
||
controller::DatasetDetailController c(repo, reg);
|
||
QSignalSpy spy(&c, &controller::DatasetDetailController::gridReady);
|
||
c.loadGridData("ds1", "dd_inversion_data");
|
||
repo.lastGrid->fireDone();
|
||
EXPECT_EQ(spy.count(), 1);
|
||
}
|
||
|
||
TEST(DatasetDetailController, EmitsLoadFailedOnGridFailed) {
|
||
StubAsyncRepo repo;
|
||
auto reg = makeInversionRegistry();
|
||
controller::DatasetDetailController c(repo, reg);
|
||
QSignalSpy spy(&c, &controller::DatasetDetailController::loadFailed);
|
||
c.loadGridData("ds1", "dd_inversion_data");
|
||
repo.lastGrid->fireFailed();
|
||
EXPECT_EQ(spy.count(), 1);
|
||
}
|
||
|
||
TEST(DatasetDetailController, DropsLateGridSignalFromAbortedLoad) {
|
||
StubAsyncRepo repo;
|
||
auto reg = makeInversionRegistry();
|
||
controller::DatasetDetailController c(repo, reg);
|
||
QSignalSpy spy(&c, &controller::DatasetDetailController::gridReady);
|
||
c.loadGridData("dsA", "dd_inversion_data");
|
||
StubGridLoad* a = repo.lastGrid;
|
||
c.loadGridData("dsB", "dd_inversion_data"); // 替换 → 旧句柄被 abort
|
||
StubGridLoad* b = repo.lastGrid;
|
||
EXPECT_TRUE(a->aborted);
|
||
a->fireDone(); // 旧句柄迟到 → 身份比对丢弃
|
||
EXPECT_EQ(spy.count(), 0);
|
||
b->fireDone(); // 当前句柄 → 正常
|
||
EXPECT_EQ(spy.count(), 1);
|
||
}
|