geopro/tests/controller/test_dataset_detail_control...

163 lines
6.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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);
}