QtGrpcClientUnaryCallTest: improve test logic for metadata()

Extend the testcase to cover both, initial and trailing metadata. This
also shows the current problems with having a QHash metadata and also
the missing separation between initial and trailing metadata.

Pick-to: 6.10 6.9 6.8
Change-Id: I880846ae06e8db338cdb3629dafdff430cab3edb
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
This commit is contained in:
Dennis Oberst 2025-07-07 18:32:31 +02:00
parent 2816a2203f
commit 542efe69ec
2 changed files with 62 additions and 39 deletions

View File

@ -13,6 +13,7 @@
#include <grpc++/grpc++.h>
#include <memory>
#include <charconv>
namespace {
@ -226,21 +227,45 @@ Status TestServiceServiceImpl::testMethodNonCompatibleArgRet(grpc::ServerContext
Status TestServiceServiceImpl::testMetadata(grpc::ServerContext *ctx, const Empty *,
qtgrpc::tests::Empty *)
{
std::string client_return_header;
for (const auto &header : ctx->client_metadata()) {
if (header.first == "client_header") {
ctx->AddTrailingMetadata("server_header",
std::string(header.second.data(), header.second.size()));
} else if (header.first == "client_return_header") {
if (client_return_header.empty())
client_return_header = std::string(header.second.data(), header.second.size());
else
client_return_header = "invalid_value";
}
const auto &md = ctx->client_metadata();
auto initial = md.find("request_initial");
uint initialCount = 0;
if (initial != md.end()) {
std::string v (initial->second.begin(), initial->second.end());
auto result = std::from_chars(v.data(), v.data() + v.size(), initialCount);
if (result.ec != std::errc())
return { grpc::StatusCode::ABORTED, "conversion failed initial" };
}
ctx->AddTrailingMetadata("client_return_header", client_return_header);
return Status();
auto trailing = md.find("request_trailing");
uint trailingCount = 0;
if (trailing != md.end()) {
std::string v (trailing->second.begin(), trailing->second.end());
auto result = std::from_chars(v.data(), v.data() + v.size(), trailingCount);
if (result.ec != std::errc())
return { grpc::StatusCode::ABORTED, "conversion failed trailing" };
}
auto sum = md.equal_range("request_sum");
uint sumCount = 0;
while (sum.first != sum.second) {
uint temp = 0;
std::string v (sum.first->second.begin(), sum.first->second.end());
auto result = std::from_chars(v.data(), v.data() + v.size(), temp);
if (result.ec != std::errc())
return { grpc::StatusCode::ABORTED, "conversion failed sum" };
sumCount += temp;
++sum.first;
}
for (auto i = 0u; i < initialCount; ++i)
ctx->AddInitialMetadata("response_initial", std::to_string(i));
for (auto i = 0u; i < trailingCount; ++i)
ctx->AddTrailingMetadata("response_trailing", std::to_string(i));
if (sumCount > 0)
ctx->AddTrailingMetadata("response_sum", std::to_string(sumCount));
return Status::OK;
}
grpc::Status TestServiceServiceImpl::testMethodClientStream(

View File

@ -142,37 +142,35 @@ void QtGrpcClientUnaryCallTest::asyncStatusMessage()
void QtGrpcClientUnaryCallTest::metadata()
{
QGrpcCallOptions opt;
opt.setMetadata({
{ "client_header", "1" },
{ "client_return_header", "valid_value" }
});
QHash<QByteArray, QByteArray> clientMd{
{ "request_initial", "3" },
{ "request_trailing", "2" },
{ "request_sum", "20" },
{ "request_sum", "10" }
};
QT_IGNORE_DEPRECATIONS(opt.setMetadata(clientMd);)
auto reply = client()->testMetadata({}, opt);
QSignalSpy replyFinishedSpy(reply.get(), &QGrpcCallReply::finished);
QVERIFY(replyFinishedSpy.isValid());
QHash<QByteArray, QByteArray> metadata;
QEventLoop waiter;
QTRY_COMPARE_EQ_WITH_TIMEOUT(replyFinishedSpy.count(), 1, FailTimeout);
const auto &args = replyFinishedSpy.first();
QCOMPARE_EQ(args.count(), 1);
QVERIFY(args.first().value<QGrpcStatus>().isOk());
connect(
reply.get(), &QGrpcOperation::finished, this,
[&reply, &metadata, &waiter](const QGrpcStatus &) {
metadata = reply->metadata();
waiter.quit();
},
Qt::SingleShotConnection);
const auto &md = reply->metadata();
auto initialIt = md.equal_range("response_initial");
QCOMPARE_EQ(std::distance(initialIt.first, initialIt.second), 1);
QCOMPARE_EQ(initialIt.first.value(), "2");
waiter.exec();
auto trailingIt = md.equal_range("response_trailing");
QCOMPARE_EQ(std::distance(trailingIt.first, trailingIt.second), 1);
QCOMPARE_EQ(trailingIt.first.value(), "1");
int serverHeaderCount = 0;
QByteArray clientReturnHeader;
for (const auto &[key, value] : reply->metadata().asKeyValueRange()) {
if (key == "server_header") {
QCOMPARE_EQ(QString::fromLatin1(value), QString::number(++serverHeaderCount));
} else if (key == "client_return_header") {
clientReturnHeader = value;
}
}
QCOMPARE_EQ(serverHeaderCount, 1);
QCOMPARE_EQ(clientReturnHeader, "valid_value"_ba);
auto sumIt = md.equal_range("response_sum");
QCOMPARE_EQ(std::distance(sumIt.first, sumIt.second), 1);
auto sum = sumIt.first.value();
QVERIFY(sum == "20"_ba || sum == "10"_ba);
}
QTEST_MAIN(QtGrpcClientUnaryCallTest)