Files
EetCpp/tests/eetca_integration_test.cpp
T

151 lines
6.3 KiB
C++

#include "eetca.h"
#include <QFile>
#include <QProcess>
#include <QRegularExpression>
#include <QSslCertificate>
#include <QSslKey>
#include <QSslServer>
#include <QTemporaryDir>
#include <QtTest>
namespace
{
class MockCaServer : public QSslServer
{
public:
explicit MockCaServer(const QByteArray &pkcs12)
: m_pkcs12(pkcs12)
{
connect(this, &QSslServer::pendingConnectionAvailable, this, [this] {
QSslSocket *socket = qobject_cast<QSslSocket *>(nextPendingConnection());
if (socket == nullptr)
{
return;
}
connect(socket, &QSslSocket::readyRead, this, [this, socket] {
const QByteArray request = socket->readAll();
const QByteArray firstLine = request.left(request.indexOf("\r\n"));
const QList<QByteArray> parts = firstLine.split(' ');
if (parts.size() < 2 || !request.contains("Authorization: Bearer "))
{
socket->disconnectFromHost();
return;
}
QByteArray body;
int status = 200;
if (parts.at(1) == "/api/request/renew")
{
body = "{\"reqId\":\"123e4567-e89b-42d3-a456-426614174000\"}";
status = 201;
}
else if (parts.at(1) == "/api/request/123e4567-e89b-42d3-a456-426614174000/status")
{
body = "{\"reqId\":\"123e4567-e89b-42d3-a456-426614174000\","
"\"state\":\"ISSUED\"}";
}
else if (parts.at(1) == "/api/request/not-finished")
{
body = "{\"count\":1,\"data\":[\"123e4567-e89b-42d3-a456-426614174000\"]}";
}
else if (parts.at(1) == "/api/request/123e4567-e89b-42d3-a456-426614174000/claim-download")
{
body = "{\"pkcs12\":\"" + m_pkcs12.toBase64() +
"\",\"password\":\"ABcd1234\",\"certificate\":{"
"\"sn\":\"12345\",\"validFrom\":\"2026-01-01T00:00:00+00:00\","
"\"validTo\":\"2027-01-01T00:00:00+00:00\",\"state\":\"VALID\"}}";
}
else if (parts.at(1) == "/api/request/123e4567-e89b-42d3-a456-426614174000/ack-download")
{
status = 204;
}
else
{
status = 404;
body = "{\"code\":4,\"message\":\"Unknown object.\"}";
}
const QByteArray response =
"HTTP/1.1 " + QByteArray::number(status) + " OK\r\n"
"Content-Type: application/json\r\nContent-Length: " +
QByteArray::number(body.size()) + "\r\nConnection: close\r\n\r\n" + body;
socket->write(response);
socket->disconnectFromHost();
});
});
}
private:
QByteArray m_pkcs12;
};
}
class EetCaIntegrationTest : public QObject
{
Q_OBJECT
private slots:
void runsCertificateWorkflow();
};
void EetCaIntegrationTest::runsCertificateWorkflow()
{
QTemporaryDir directory;
QVERIFY(directory.isValid());
const QString keyPath = directory.filePath(QStringLiteral("key.pem"));
const QString certPath = directory.filePath(QStringLiteral("certificate.pem"));
const QString p12Path = directory.filePath(QStringLiteral("certificate.p12"));
auto runOpenSsl = [](const QStringList &arguments) {
QProcess process;
process.start(QStringLiteral("openssl"), arguments);
QVERIFY2(process.waitForFinished(30000), qPrintable(process.errorString()));
QVERIFY2(process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0,
process.readAllStandardError().constData());
};
runOpenSsl({QStringLiteral("req"), QStringLiteral("-x509"), QStringLiteral("-newkey"),
QStringLiteral("rsa:2048"), QStringLiteral("-nodes"), QStringLiteral("-subj"),
QStringLiteral("/CN=localhost"), QStringLiteral("-keyout"), keyPath,
QStringLiteral("-out"), certPath, QStringLiteral("-days"), QStringLiteral("1")});
runOpenSsl({QStringLiteral("pkcs12"), QStringLiteral("-export"), QStringLiteral("-out"),
p12Path, QStringLiteral("-inkey"), keyPath, QStringLiteral("-in"), certPath,
QStringLiteral("-passout"), QStringLiteral("pass:test")});
QFile p12File(p12Path);
QVERIFY(p12File.open(QIODevice::ReadOnly));
const QByteArray p12 = p12File.readAll();
MockCaServer server(p12);
QSslConfiguration ssl = QSslConfiguration::defaultConfiguration();
QFile keyFile(keyPath);
QFile certificateFile(certPath);
QVERIFY(keyFile.open(QIODevice::ReadOnly));
QVERIFY(certificateFile.open(QIODevice::ReadOnly));
ssl.setPrivateKey(QSslKey(keyFile.readAll(), QSsl::Rsa, QSsl::Pem));
ssl.setLocalCertificate(QSslCertificate(certificateFile.readAll(), QSsl::Pem));
server.setSslConfiguration(ssl);
QVERIFY(server.listen(QHostAddress::LocalHost));
QSslConfiguration clientSsl = QSslConfiguration::defaultConfiguration();
clientSsl.setCaCertificates({ssl.localCertificate()});
EetCaClient client({
QUrl(QStringLiteral("https://localhost:%1/api").arg(server.serverPort())),
p12Path, QByteArrayLiteral("test"), 5000, clientSsl
});
QString error;
QUuid requestId;
QVERIFY2(client.requestRenewal(&requestId, &error), qPrintable(error));
QCOMPARE(requestId, QUuid(QStringLiteral("123e4567-e89b-42d3-a456-426614174000")));
EetCaRequestStatus status;
QVERIFY2(client.requestStatus(requestId, &status, &error), qPrintable(error));
QCOMPARE(status.state, QStringLiteral("ISSUED"));
QList<QUuid> unfinished;
QVERIFY2(client.listUnfinished(&unfinished, &error), qPrintable(error));
QCOMPARE(unfinished, QList<QUuid>{requestId});
EetCaPkcs12 package;
QVERIFY2(client.claimDownload(requestId, &package, &error), qPrintable(error));
QCOMPARE(package.pkcs12, p12);
QCOMPARE(package.password, QByteArrayLiteral("ABcd1234"));
QVERIFY2(client.acknowledgeDownload(requestId, &error), qPrintable(error));
}
QTEST_MAIN(EetCaIntegrationTest)
#include "eetca_integration_test.moc"