71 lines
3.0 KiB
C++
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);
|
|
}
|