#include #include #include #include "ApiChain.hpp" #include "net/FakeApiCall.hpp" using namespace geopro::net; using geopro::net::test::FakeApiCall; namespace { ApiResponse ok(int v = 0) { ApiResponse r; r.code = 200; r.httpStatus = 200; r.data = QJsonObject{{"v", v}}; return r; } ApiResponse bad() { ApiResponse r; r.code = 500; r.httpStatus = 200; r.msg = QStringLiteral("boom"); return r; } auto isFailure = [](const ApiResponse& r) { return r.code != 200 || !r.rawError.isEmpty(); }; } // namespace TEST(ApiChain, RunsStepsInOrderAndPassesPriorResponses) { auto* s1 = new FakeApiCall; auto* s2 = new FakeApiCall; int seenPrior = -1; QList steps{ [&](const QList&) -> IApiCall* { return s1; }, [&](const QList& prior) -> IApiCall* { seenPrior = prior.size(); // 第二步能看到第一步响应 return s2; }}; auto* chain = new ApiChain(steps, isFailure); QSignalSpy okSpy(chain, &ApiChain::succeeded); s1->fire(ok(11)); // 第一步完成 → 触发第二步工厂 EXPECT_EQ(seenPrior, 1); EXPECT_EQ(okSpy.count(), 0); // 还差第二步 s2->fire(ok(22)); EXPECT_EQ(okSpy.count(), 1); const auto resps = okSpy.takeFirst().at(0).value>(); EXPECT_EQ(resps.size(), 2); } TEST(ApiChain, FailFastShortCircuitsRemainingSteps) { auto* s1 = new FakeApiCall; bool secondBuilt = false; QList steps{ [&](const QList&) -> IApiCall* { return s1; }, [&](const QList&) -> IApiCall* { secondBuilt = true; return new FakeApiCall; }}; auto* chain = new ApiChain(steps, isFailure); QSignalSpy failSpy(chain, &ApiChain::failed); s1->fire(bad()); // 第一步失败 EXPECT_EQ(failSpy.count(), 1); EXPECT_FALSE(secondBuilt); // 后续步骤不再构造 } TEST(ApiChain, AbortGateSuppressesLateSignals) { auto* s1 = new FakeApiCall; QList steps{[&](const QList&) -> IApiCall* { return s1; }}; auto* chain = new ApiChain(steps, isFailure); QSignalSpy okSpy(chain, &ApiChain::succeeded); chain->abort(); EXPECT_TRUE(s1->aborted); // 在飞步骤被 abort s1->fire(ok()); // 迟到 EXPECT_EQ(okSpy.count(), 0); // aborted_ 闸门 } TEST(ApiChain, StepFactoryThrowBecomesFailed) { auto* s1 = new FakeApiCall; QList steps{ [&](const QList&) -> IApiCall* { return s1; }, [&](const QList&) -> IApiCall* { throw std::runtime_error("rsa fail"); }}; auto* chain = new ApiChain(steps, isFailure); QSignalSpy failSpy(chain, &ApiChain::failed); s1->fire(ok()); // 触发第二步工厂 → 抛 → failed EXPECT_EQ(failSpy.count(), 1); }