harden(controller): 析构 abort 在飞句柄(退出契约 spec §7) + Grid 路径回灌/失败用例对称覆盖(评审 I-1/M-3/M-4)
This commit is contained in:
parent
e57985c057
commit
350f46060d
|
|
@ -6,6 +6,11 @@ namespace geopro::controller {
|
||||||
DatasetDetailController::DatasetDetailController(data::IAsyncDatasetRepository& repo, QObject* parent)
|
DatasetDetailController::DatasetDetailController(data::IAsyncDatasetRepository& repo, QObject* parent)
|
||||||
: QObject(parent), repo_(repo) {}
|
: QObject(parent), repo_(repo) {}
|
||||||
|
|
||||||
|
DatasetDetailController::~DatasetDetailController() {
|
||||||
|
if (chartLoad_) chartLoad_->abort(); // 退出契约:abort 在飞句柄,不依赖外部析构顺序兜底
|
||||||
|
if (gridLoad_) gridLoad_->abort();
|
||||||
|
}
|
||||||
|
|
||||||
void DatasetDetailController::openDataset(const QString& dsId, const QString& ddCode) {
|
void DatasetDetailController::openDataset(const QString& dsId, const QString& ddCode) {
|
||||||
if (ddCode != QLatin1String("dd_inversion_data")) { // 首版仅支持 ERT 反演
|
if (ddCode != QLatin1String("dd_inversion_data")) { // 首版仅支持 ERT 反演
|
||||||
emit loadFailed(dsId, QStringLiteral("暂不支持该数据类型的预览"));
|
emit loadFailed(dsId, QStringLiteral("暂不支持该数据类型的预览"));
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit DatasetDetailController(data::IAsyncDatasetRepository& repo, QObject* parent = nullptr);
|
explicit DatasetDetailController(data::IAsyncDatasetRepository& repo, QObject* parent = nullptr);
|
||||||
|
~DatasetDetailController() override; // 退出契约(spec §7):abort 在飞句柄,避免迟到信号打到已析构 this
|
||||||
public slots:
|
public slots:
|
||||||
void openDataset(const QString& dsId, const QString& ddCode);
|
void openDataset(const QString& dsId, const QString& ddCode);
|
||||||
void focusDataset(const QString& dsId);
|
void focusDataset(const QString& dsId);
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ struct StubGridLoad : data::GridLoad {
|
||||||
bool aborted = false;
|
bool aborted = false;
|
||||||
void abort() override { aborted = true; }
|
void abort() override { aborted = true; }
|
||||||
void fireDone() { emit done(data::GridParts{}); }
|
void fireDone() { emit done(data::GridParts{}); }
|
||||||
|
void fireFailed() { emit failed(QStringLiteral("x")); }
|
||||||
};
|
};
|
||||||
struct StubAsyncRepo : data::IAsyncDatasetRepository {
|
struct StubAsyncRepo : data::IAsyncDatasetRepository {
|
||||||
StubChartLoad* lastChart = nullptr;
|
StubChartLoad* lastChart = nullptr;
|
||||||
|
|
@ -79,3 +80,36 @@ TEST(DatasetDetailController, DropsLateSignalFromAbortedLoad) {
|
||||||
b->fireDone(); // 当前句柄 → 正常
|
b->fireDone(); // 当前句柄 → 正常
|
||||||
EXPECT_EQ(spy.count(), 1);
|
EXPECT_EQ(spy.count(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(DatasetDetailController, EmitsGridReadyOnDone) {
|
||||||
|
StubAsyncRepo repo;
|
||||||
|
controller::DatasetDetailController c(repo);
|
||||||
|
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;
|
||||||
|
controller::DatasetDetailController c(repo);
|
||||||
|
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;
|
||||||
|
controller::DatasetDetailController c(repo);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue