diff --git a/tests/auto/grpc/client/CMakeLists.txt b/tests/auto/grpc/client/CMakeLists.txt index 07dfe0db..2431adea 100644 --- a/tests/auto/grpc/client/CMakeLists.txt +++ b/tests/auto/grpc/client/CMakeLists.txt @@ -4,7 +4,7 @@ add_subdirectory(shared) add_subdirectory(interceptor) add_subdirectory(unattached_channel) -add_subdirectory(no_channel) +add_subdirectory(deadline) add_subdirectory(unarycall) add_subdirectory(serverstream) add_subdirectory(clientstream) diff --git a/tests/auto/grpc/client/no_channel/CMakeLists.txt b/tests/auto/grpc/client/deadline/CMakeLists.txt similarity index 70% rename from tests/auto/grpc/client/no_channel/CMakeLists.txt rename to tests/auto/grpc/client/deadline/CMakeLists.txt index d18d8d53..5ba59c29 100644 --- a/tests/auto/grpc/client/no_channel/CMakeLists.txt +++ b/tests/auto/grpc/client/deadline/CMakeLists.txt @@ -3,19 +3,21 @@ if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) 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) + include("../shared/test_server/CMakeLists.txt") include("../shared/client_service/CMakeLists.txt") + include("../shared/client_test_common/CMakeLists.txt") endif() if(NOT TARGET grpc_testserver) return() endif() -qt_internal_add_test(tst_grpc_client_no_channel +qt_internal_add_test(tst_grpc_client_deadline SOURCES - tst_grpc_client_no_channel.cpp + tst_grpc_client_deadline.cpp INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/../../shared DEFINES @@ -25,6 +27,7 @@ qt_internal_add_test(tst_grpc_client_no_channel Qt::Core Qt::Grpc 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) diff --git a/tests/auto/grpc/client/deadline/tst_grpc_client_deadline.cpp b/tests/auto/grpc/client/deadline/tst_grpc_client_deadline.cpp new file mode 100644 index 00000000..07399403 --- /dev/null +++ b/tests/auto/grpc/client/deadline/tst_grpc_client_deadline.cpp @@ -0,0 +1,70 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#include +#include +#include +#include +#include + +#include + +#include +#include + +#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("minTimeout"); + QTest::addColumn("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(MessageLatency + * minTimeout)); + const auto maxTimeoutDuration = std::chrono::milliseconds(static_cast(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 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(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" diff --git a/tests/auto/grpc/client/no_channel/tst_grpc_client_no_channel.cpp b/tests/auto/grpc/client/no_channel/tst_grpc_client_no_channel.cpp deleted file mode 100644 index 5ab4ae5c..00000000 --- a/tests/auto/grpc/client/no_channel/tst_grpc_client_no_channel.cpp +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only -#include -#if QT_CONFIG(native_grpc) -# include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#if QT_CONFIG(native_grpc) -# include -#endif -#include "testservice_client.grpc.qpb.h" -#include -#include - -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 create(const QGrpcChannelOptions &options) const - { - switch (type) { - case HTTP2: - return std::make_shared(options); -#if QT_CONFIG(native_grpc) - case GRPC_SOCKET: - case GRPC_HTTP: - return std::make_shared(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(); - auto channel = channelFactory->create(channelOptions); - QVERIFY2(channel, "Channel could not been created."); - client->attachChannel(std::move(channel)); - } - - void initTestCase_data() - { - QTest::addColumn>("factory"); - QTest::newRow("Http2Client") << std::make_shared(ChannelFactory::HTTP2); -#if QT_CONFIG(native_grpc) -# ifndef Q_OS_WINDOWS - QTest::newRow("GrpcSocket") - << std::make_shared(ChannelFactory::GRPC_SOCKET); - -# endif - QTest::newRow("GrpcHttp") << std::make_shared(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, factory); - channelFactory = std::move(factory); - } - - void ChannelAndCallDeadlineTest(); - -private: - ServerProcRunner serverProc{ QFINDTESTDATA(TEST_GRPC_SERVER_PATH) }; - std::shared_ptr channelFactory; - std::shared_ptr client; -}; - -void QtGrpcClientNoChannelTest::ChannelAndCallDeadlineTest() -{ - constexpr auto channelTimeout = std::chrono::milliseconds(static_cast(MessageLatency - * 0.25)); - constexpr auto callTimeout = std::chrono::milliseconds(static_cast(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 callOptions = std::nullopt) { - SimpleStringMessage request; - request.setTestFieldString("sleep"); - QSignalSpy clientErrorSpy(client.get(), &TestService::Client::errorOccurred); - QVERIFY(clientErrorSpy.isValid()); - std::shared_ptr 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(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" diff --git a/tests/auto/grpc/client/shared/client_test_common/grpcclienttestbase.cpp b/tests/auto/grpc/client/shared/client_test_common/grpcclienttestbase.cpp index 38fa02b3..bc33d741 100644 --- a/tests/auto/grpc/client/shared/client_test_common/grpcclienttestbase.cpp +++ b/tests/auto/grpc/client/shared/client_test_common/grpcclienttestbase.cpp @@ -5,6 +5,7 @@ #include #include +#include void GrpcClientTestBase::initTestCase_data() { @@ -68,6 +69,17 @@ void GrpcClientTestBase::initTestCase_data() # endif } #endif + + if (m_channels.testFlag(Channel::WithChannelDeadline)) { + constexpr auto + channelTimeout = std::chrono::milliseconds(static_cast(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() diff --git a/tests/auto/grpc/client/shared/client_test_common/grpcclienttestbase.h b/tests/auto/grpc/client/shared/client_test_common/grpcclienttestbase.h index 3280a6f6..d3aad9b6 100644 --- a/tests/auto/grpc/client/shared/client_test_common/grpcclienttestbase.h +++ b/tests/auto/grpc/client/shared/client_test_common/grpcclienttestbase.h @@ -26,7 +26,8 @@ protected: Qt = 0x1, Native = 0x2, Ssl = 0x4, - SslNoCredentials = 0x8 + SslNoCredentials = 0x8, + WithChannelDeadline = 0x10, }; Q_DECLARE_FLAGS(Channels, Channel)