geopro/tests/net/test_api_chain.cpp

71 lines
3.0 KiB
C++

#include <gtest/gtest.h>
#include <stdexcept>
#include <QSignalSpy>
#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<ApiChain::StepFactory> steps{
[&](const QList<ApiResponse>&) -> IApiCall* { return s1; },
[&](const QList<ApiResponse>& 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<QList<ApiResponse>>();
EXPECT_EQ(resps.size(), 2);
}
TEST(ApiChain, FailFastShortCircuitsRemainingSteps) {
auto* s1 = new FakeApiCall;
bool secondBuilt = false;
QList<ApiChain::StepFactory> steps{
[&](const QList<ApiResponse>&) -> IApiCall* { return s1; },
[&](const QList<ApiResponse>&) -> 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<ApiChain::StepFactory> steps{[&](const QList<ApiResponse>&) -> 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<ApiChain::StepFactory> steps{
[&](const QList<ApiResponse>&) -> IApiCall* { return s1; },
[&](const QList<ApiResponse>&) -> 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);
}