mirror of https://github.com/qt/qtgrpc.git
Refactor tst_grpc_client_no_channel test
Rename the test to tst_grpc_client_deadline. Use GrpcClientTestBase as the test base. Add WithChannelDeadline channel to GrpcClientTestBase. Pick-to: 6.6 6.7 Change-Id: I6125f68f40b26ba645a97721641123d01a5387b2 Reviewed-by: Tatiana Borisova <tatiana.borisova@qt.io>
This commit is contained in:
parent
5189fddaed
commit
bc424839f1
|
|
@ -4,7 +4,7 @@ add_subdirectory(shared)
|
||||||
|
|
||||||
add_subdirectory(interceptor)
|
add_subdirectory(interceptor)
|
||||||
add_subdirectory(unattached_channel)
|
add_subdirectory(unattached_channel)
|
||||||
add_subdirectory(no_channel)
|
add_subdirectory(deadline)
|
||||||
add_subdirectory(unarycall)
|
add_subdirectory(unarycall)
|
||||||
add_subdirectory(serverstream)
|
add_subdirectory(serverstream)
|
||||||
add_subdirectory(clientstream)
|
add_subdirectory(clientstream)
|
||||||
|
|
|
||||||
|
|
@ -3,19 +3,21 @@
|
||||||
|
|
||||||
if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
|
if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
|
||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
project(tst_grpc_client_no_channel LANGUAGES CXX)
|
project(tst_grpc_client_deadline LANGUAGES CXX)
|
||||||
find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
|
find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
|
||||||
|
|
||||||
include("../shared/test_server/CMakeLists.txt")
|
include("../shared/test_server/CMakeLists.txt")
|
||||||
include("../shared/client_service/CMakeLists.txt")
|
include("../shared/client_service/CMakeLists.txt")
|
||||||
|
include("../shared/client_test_common/CMakeLists.txt")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT TARGET grpc_testserver)
|
if(NOT TARGET grpc_testserver)
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
qt_internal_add_test(tst_grpc_client_no_channel
|
qt_internal_add_test(tst_grpc_client_deadline
|
||||||
SOURCES
|
SOURCES
|
||||||
tst_grpc_client_no_channel.cpp
|
tst_grpc_client_deadline.cpp
|
||||||
INCLUDE_DIRECTORIES
|
INCLUDE_DIRECTORIES
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/../../shared
|
${CMAKE_CURRENT_SOURCE_DIR}/../../shared
|
||||||
DEFINES
|
DEFINES
|
||||||
|
|
@ -25,6 +27,7 @@ qt_internal_add_test(tst_grpc_client_no_channel
|
||||||
Qt::Core
|
Qt::Core
|
||||||
Qt::Grpc
|
Qt::Grpc
|
||||||
tst_grpc_client_qtgrpc_gen
|
tst_grpc_client_qtgrpc_gen
|
||||||
|
tst_grpc_client_test_common
|
||||||
)
|
)
|
||||||
|
|
||||||
add_dependencies(tst_grpc_client_no_channel grpc_testserver)
|
add_dependencies(tst_grpc_client_deadline grpc_testserver)
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||||
|
#include <QSignalSpy>
|
||||||
|
#include <QTest>
|
||||||
|
#include <QtGrpc/QGrpcCallOptions>
|
||||||
|
#include <QtGrpc/QGrpcCallReply>
|
||||||
|
#include <QtGrpc/QGrpcChannelOptions>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
#include <grpcclienttestbase.h>
|
||||||
|
#include <message_latency_defs.h>
|
||||||
|
|
||||||
|
#include "testservice_client.grpc.qpb.h"
|
||||||
|
|
||||||
|
using namespace Qt::Literals::StringLiterals;
|
||||||
|
using namespace qtgrpc::tests;
|
||||||
|
|
||||||
|
class QtGrpcClientDeadlineTest : public GrpcClientTestBase
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
QtGrpcClientDeadlineTest() : GrpcClientTestBase(Channels(Channel::WithChannelDeadline)) { }
|
||||||
|
private slots:
|
||||||
|
void ChannelAndCallDeadlineTest_data();
|
||||||
|
void ChannelAndCallDeadlineTest();
|
||||||
|
};
|
||||||
|
|
||||||
|
void QtGrpcClientDeadlineTest::ChannelAndCallDeadlineTest_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<double>("minTimeout");
|
||||||
|
QTest::addColumn<double>("maxTimeout");
|
||||||
|
|
||||||
|
QTest::addRow("0.0") << double(0) << double(0.6);
|
||||||
|
QTest::addRow("0.25") << double(0.25) << double(0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtGrpcClientDeadlineTest::ChannelAndCallDeadlineTest()
|
||||||
|
{
|
||||||
|
QFETCH(double, minTimeout);
|
||||||
|
QFETCH(double, maxTimeout);
|
||||||
|
const auto minTimeoutDuration = std::chrono::milliseconds(static_cast<int64_t>(MessageLatency
|
||||||
|
* minTimeout));
|
||||||
|
const auto maxTimeoutDuration = std::chrono::milliseconds(static_cast<int64_t>(MessageLatency
|
||||||
|
* maxTimeout));
|
||||||
|
QGrpcCallOptions callOpts;
|
||||||
|
callOpts.withDeadline(minTimeoutDuration);
|
||||||
|
|
||||||
|
SimpleStringMessage request;
|
||||||
|
request.setTestFieldString("sleep");
|
||||||
|
QSignalSpy clientErrorSpy(client().get(), &TestService::Client::errorOccurred);
|
||||||
|
QVERIFY(clientErrorSpy.isValid());
|
||||||
|
std::shared_ptr<QGrpcCallReply> reply;
|
||||||
|
reply = client()->testMethod(request, callOpts);
|
||||||
|
QSignalSpy callFinishedSpy(reply.get(), &QGrpcCallReply::finished);
|
||||||
|
QVERIFY(callFinishedSpy.isValid());
|
||||||
|
// Still waiting for a timeout
|
||||||
|
QTRY_COMPARE_EQ_WITH_TIMEOUT(clientErrorSpy.count(), 0, minTimeoutDuration.count());
|
||||||
|
// Time window to receive the timout
|
||||||
|
QTRY_COMPARE_EQ_WITH_TIMEOUT(clientErrorSpy.count(), 1,
|
||||||
|
maxTimeoutDuration.count() + MessageLatencyThreshold);
|
||||||
|
|
||||||
|
const auto code = qvariant_cast<QGrpcStatus>(clientErrorSpy.at(0).first()).code();
|
||||||
|
// Really low timeout can trigger before service becomes available
|
||||||
|
QVERIFY(code == QGrpcStatus::StatusCode::Cancelled
|
||||||
|
|| code == QGrpcStatus::StatusCode::Unavailable);
|
||||||
|
}
|
||||||
|
|
||||||
|
QTEST_MAIN(QtGrpcClientDeadlineTest)
|
||||||
|
#include "tst_grpc_client_deadline.moc"
|
||||||
|
|
@ -1,162 +0,0 @@
|
||||||
// Copyright (C) 2023 The Qt Company Ltd.
|
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
|
||||||
#include <QGrpcCallReply>
|
|
||||||
#if QT_CONFIG(native_grpc)
|
|
||||||
# include <QGrpcChannel>
|
|
||||||
#endif
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QCryptographicHash>
|
|
||||||
#include <QGrpcHttp2Channel>
|
|
||||||
#include <QSignalSpy>
|
|
||||||
#include <QTest>
|
|
||||||
#include <QtGrpc/QGrpcCallOptions>
|
|
||||||
#include <QtGrpc/QGrpcChannelOptions>
|
|
||||||
#include <memory>
|
|
||||||
#if QT_CONFIG(native_grpc)
|
|
||||||
# include <grpcpp/security/credentials.h>
|
|
||||||
#endif
|
|
||||||
#include "testservice_client.grpc.qpb.h"
|
|
||||||
#include <message_latency_defs.h>
|
|
||||||
#include <server_proc_runner.h>
|
|
||||||
|
|
||||||
using namespace Qt::Literals::StringLiterals;
|
|
||||||
using namespace qtgrpc::tests;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class ChannelFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum ChannelType {
|
|
||||||
HTTP2,
|
|
||||||
GRPC_SOCKET,
|
|
||||||
GRPC_HTTP,
|
|
||||||
};
|
|
||||||
|
|
||||||
ChannelFactory(ChannelType type) : type(type) { }
|
|
||||||
|
|
||||||
std::shared_ptr<QAbstractGrpcChannel> create(const QGrpcChannelOptions &options) const
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case HTTP2:
|
|
||||||
return std::make_shared<QGrpcHttp2Channel>(options);
|
|
||||||
#if QT_CONFIG(native_grpc)
|
|
||||||
case GRPC_SOCKET:
|
|
||||||
case GRPC_HTTP:
|
|
||||||
return std::make_shared<QGrpcChannel>(options,
|
|
||||||
QGrpcChannel::InsecureChannelCredentials);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
QUrl getUrl() const
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case HTTP2:
|
|
||||||
return QUrl("http://localhost:50051", QUrl::StrictMode);
|
|
||||||
#if QT_CONFIG(native_grpc)
|
|
||||||
case GRPC_SOCKET:
|
|
||||||
return QUrl("unix:///tmp/qtgrpc_test.sock");
|
|
||||||
case GRPC_HTTP:
|
|
||||||
return QUrl("localhost:50051");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return QUrl();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
ChannelType type;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
class QtGrpcClientNoChannelTest : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
private slots:
|
|
||||||
void createClient(const QGrpcChannelOptions &channelOptions)
|
|
||||||
{
|
|
||||||
client = std::make_shared<TestService::Client>();
|
|
||||||
auto channel = channelFactory->create(channelOptions);
|
|
||||||
QVERIFY2(channel, "Channel could not been created.");
|
|
||||||
client->attachChannel(std::move(channel));
|
|
||||||
}
|
|
||||||
|
|
||||||
void initTestCase_data()
|
|
||||||
{
|
|
||||||
QTest::addColumn<std::shared_ptr<ChannelFactory>>("factory");
|
|
||||||
QTest::newRow("Http2Client") << std::make_shared<ChannelFactory>(ChannelFactory::HTTP2);
|
|
||||||
#if QT_CONFIG(native_grpc)
|
|
||||||
# ifndef Q_OS_WINDOWS
|
|
||||||
QTest::newRow("GrpcSocket")
|
|
||||||
<< std::make_shared<ChannelFactory>(ChannelFactory::GRPC_SOCKET);
|
|
||||||
|
|
||||||
# endif
|
|
||||||
QTest::newRow("GrpcHttp") << std::make_shared<ChannelFactory>(ChannelFactory::GRPC_HTTP);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void initTestCase() { qRegisterProtobufTypes(); }
|
|
||||||
|
|
||||||
void init()
|
|
||||||
{
|
|
||||||
if (serverProc.state() != QProcess::ProcessState::Running) {
|
|
||||||
qInfo() << "Restarting server";
|
|
||||||
serverProc.restart();
|
|
||||||
QVERIFY2(serverProc.state() == QProcess::ProcessState::Running,
|
|
||||||
"Precondition failed - Server cannot be started.");
|
|
||||||
}
|
|
||||||
|
|
||||||
QFETCH_GLOBAL(std::shared_ptr<ChannelFactory>, factory);
|
|
||||||
channelFactory = std::move(factory);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelAndCallDeadlineTest();
|
|
||||||
|
|
||||||
private:
|
|
||||||
ServerProcRunner serverProc{ QFINDTESTDATA(TEST_GRPC_SERVER_PATH) };
|
|
||||||
std::shared_ptr<ChannelFactory> channelFactory;
|
|
||||||
std::shared_ptr<TestService::Client> client;
|
|
||||||
};
|
|
||||||
|
|
||||||
void QtGrpcClientNoChannelTest::ChannelAndCallDeadlineTest()
|
|
||||||
{
|
|
||||||
constexpr auto channelTimeout = std::chrono::milliseconds(static_cast<int64_t>(MessageLatency
|
|
||||||
* 0.25));
|
|
||||||
constexpr auto callTimeout = std::chrono::milliseconds(static_cast<int64_t>(MessageLatency
|
|
||||||
* 0.6));
|
|
||||||
QGrpcChannelOptions channelOpts(channelFactory->getUrl());
|
|
||||||
channelOpts.withDeadline(channelTimeout);
|
|
||||||
createClient(channelOpts);
|
|
||||||
QGrpcCallOptions callOpts;
|
|
||||||
callOpts.withDeadline(callTimeout);
|
|
||||||
auto executeTest = [this](uint64_t minTimeout, uint64_t maxTimeout,
|
|
||||||
std::optional<QGrpcCallOptions> callOptions = std::nullopt) {
|
|
||||||
SimpleStringMessage request;
|
|
||||||
request.setTestFieldString("sleep");
|
|
||||||
QSignalSpy clientErrorSpy(client.get(), &TestService::Client::errorOccurred);
|
|
||||||
QVERIFY(clientErrorSpy.isValid());
|
|
||||||
std::shared_ptr<QGrpcCallReply> reply;
|
|
||||||
if (callOptions)
|
|
||||||
reply = client->testMethod(request, *callOptions);
|
|
||||||
else
|
|
||||||
reply = client->testMethod(request);
|
|
||||||
QSignalSpy callFinishedSpy(reply.get(), &QGrpcCallReply::finished);
|
|
||||||
QVERIFY(callFinishedSpy.isValid());
|
|
||||||
// Still waiting for a timeout
|
|
||||||
QTRY_COMPARE_EQ_WITH_TIMEOUT(clientErrorSpy.count(), 0, minTimeout);
|
|
||||||
// Time window to receive the timout
|
|
||||||
QTRY_COMPARE_EQ_WITH_TIMEOUT(clientErrorSpy.count(), 1, maxTimeout);
|
|
||||||
const auto code = qvariant_cast<QGrpcStatus>(clientErrorSpy.at(0).first()).code();
|
|
||||||
// Really low timeout can trigger before service becomes available
|
|
||||||
QVERIFY(code == QGrpcStatus::StatusCode::Cancelled
|
|
||||||
|| code == QGrpcStatus::StatusCode::Unavailable);
|
|
||||||
};
|
|
||||||
executeTest(0, channelTimeout.count() + MessageLatencyThreshold);
|
|
||||||
executeTest(channelTimeout.count(), callTimeout.count() + MessageLatencyThreshold, callOpts);
|
|
||||||
}
|
|
||||||
|
|
||||||
QTEST_MAIN(QtGrpcClientNoChannelTest)
|
|
||||||
#include "tst_grpc_client_no_channel.moc"
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include <QtGrpc/QGrpcChannelOptions>
|
#include <QtGrpc/QGrpcChannelOptions>
|
||||||
#include <QtNetwork/qtnetwork-config.h>
|
#include <QtNetwork/qtnetwork-config.h>
|
||||||
|
#include <message_latency_defs.h>
|
||||||
|
|
||||||
void GrpcClientTestBase::initTestCase_data()
|
void GrpcClientTestBase::initTestCase_data()
|
||||||
{
|
{
|
||||||
|
|
@ -68,6 +69,17 @@ void GrpcClientTestBase::initTestCase_data()
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (m_channels.testFlag(Channel::WithChannelDeadline)) {
|
||||||
|
constexpr auto
|
||||||
|
channelTimeout = std::chrono::milliseconds(static_cast<int64_t>(MessageLatency * 0.25));
|
||||||
|
QTest::newRow("Http2ClientDeadline")
|
||||||
|
<< QFlags{ Channel::Qt, Channel::WithChannelDeadline }
|
||||||
|
<< std::shared_ptr<
|
||||||
|
QAbstractGrpcChannel>(new QGrpcHttp2Channel(QGrpcChannelOptions{
|
||||||
|
QUrl("http://localhost:50051", QUrl::StrictMode) }
|
||||||
|
.withDeadline(channelTimeout)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrpcClientTestBase::init()
|
void GrpcClientTestBase::init()
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@ protected:
|
||||||
Qt = 0x1,
|
Qt = 0x1,
|
||||||
Native = 0x2,
|
Native = 0x2,
|
||||||
Ssl = 0x4,
|
Ssl = 0x4,
|
||||||
SslNoCredentials = 0x8
|
SslNoCredentials = 0x8,
|
||||||
|
WithChannelDeadline = 0x10,
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(Channels, Channel)
|
Q_DECLARE_FLAGS(Channels, Channel)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue