浏览代码

Qtfy AsyncReply

- Rename AsyncReply
- Add extra error handling
Alexey Edelev 5 年之前
父节点
当前提交
434c3dd8b3

+ 1 - 1
src/generator/clientgenerator.cpp

@@ -65,7 +65,7 @@ void ClientGenerator::printClientIncludes()
 
     std::unordered_set<std::string> includeSet;
     includeSet.insert("qabstractgrpcclient");
-    includeSet.insert("asyncreply");
+    includeSet.insert("qgrpcasyncreply");
     for (auto type : includeSet) {
         mPrinter.Print({{"include", type}}, Templates::InternalIncludeTemplate);
     }

+ 6 - 6
src/generator/templates.cpp

@@ -183,8 +183,8 @@ const char *Templates::ClassDefinitionTemplate = "\nclass $classname$ : public $
                                                  "{\n";
 const char *Templates::QObjectMacro = "Q_OBJECT";
 const char *Templates::ClientMethodDeclarationSyncTemplate = "Q_INVOKABLE bool $method_name$(const $param_type$ &$param_name$, const QPointer<$return_type$> &$return_name$);\n";
-const char *Templates::ClientMethodDeclarationAsyncTemplate = "Q_INVOKABLE qtprotobuf::AsyncReply *$method_name$(const $param_type$ &$param_name$);\n";
-const char *Templates::ClientMethodDeclarationAsync2Template = "Q_INVOKABLE void $method_name$(const $param_type$ &$param_name$, const QObject *context, const std::function<void(qtprotobuf::AsyncReply *)> &callback);\n";
+const char *Templates::ClientMethodDeclarationAsyncTemplate = "Q_INVOKABLE qtprotobuf::QGrpcAsyncReply *$method_name$(const $param_type$ &$param_name$);\n";
+const char *Templates::ClientMethodDeclarationAsync2Template = "Q_INVOKABLE void $method_name$(const $param_type$ &$param_name$, const QObject *context, const std::function<void(qtprotobuf::QGrpcAsyncReply *)> &callback);\n";
 const char *Templates::ServerMethodDeclarationTemplate = "Q_INVOKABLE virtual $return_type$ $method_name$(const $param_type$ &$param_name$) = 0;\n";
 
 
@@ -195,14 +195,14 @@ const char *Templates::ClientMethodDefinitionSyncTemplate = "\nbool $classname$:
                                                             "{\n"
                                                             "    return call(\"$method_name$\", $param_name$, $return_name$);\n"
                                                             "}\n";
-const char *Templates::ClientMethodDefinitionAsyncTemplate = "\nqtprotobuf::AsyncReply *$classname$::$method_name$(const $param_type$ &$param_name$)\n"
+const char *Templates::ClientMethodDefinitionAsyncTemplate = "\nqtprotobuf::QGrpcAsyncReply *$classname$::$method_name$(const $param_type$ &$param_name$)\n"
                                                              "{\n"
                                                              "    return call(\"$method_name$\", $param_name$);\n"
                                                              "}\n";
-const char *Templates::ClientMethodDefinitionAsync2Template = "\nvoid $classname$::$method_name$(const $param_type$ &$param_name$, const QObject *context, const std::function<void(AsyncReply *)> &callback)\n"
+const char *Templates::ClientMethodDefinitionAsync2Template = "\nvoid $classname$::$method_name$(const $param_type$ &$param_name$, const QObject *context, const std::function<void(QGrpcAsyncReply *)> &callback)\n"
                                                               "{\n"
-                                                              "    qtprotobuf::AsyncReply *reply = call(\"$method_name$\", $param_name$);\n"
-                                                              "    QObject::connect(reply, &qtprotobuf::AsyncReply::finished, context, [reply, callback](){\n"
+                                                              "    qtprotobuf::QGrpcAsyncReply *reply = call(\"$method_name$\", $param_name$);\n"
+                                                              "    QObject::connect(reply, &qtprotobuf::QGrpcAsyncReply::finished, context, [reply, callback](){\n"
                                                               "        callback(reply);\n"
                                                               "    });\n"
                                                               "}\n";

+ 2 - 2
src/grpc/CMakeLists.txt

@@ -12,7 +12,7 @@ set(CMAKE_AUTORCC ON)
 
 include(${CMAKE_SOURCE_DIR}/cmake/Coverage.cmake)
 
-file(GLOB SOURCES asyncreply.cpp
+file(GLOB SOURCES qgrpcasyncreply.cpp
     qabstractgrpcchannel.cpp
     qgrpchttp2channel.cpp
     qabstractgrpcclient.cpp
@@ -20,7 +20,7 @@ file(GLOB SOURCES asyncreply.cpp
     sslcredentials.cpp
     insecurecredentials.cpp)
 
-file(GLOB HEADERS asyncreply.h
+file(GLOB HEADERS qgrpcasyncreply.h
     qabstractgrpcchannel.h
     qgrpchttp2channel.h
     qabstractgrpcclient.h

+ 0 - 82
src/grpc/asyncreply.h

@@ -1,82 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2019 Alexey Edelev <semlanik@gmail.com>
- *
- * This file is part of qtprotobuf project https://git.semlanik.org/semlanik/qtprotobuf
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this
- * software and associated documentation files (the "Software"), to deal in the Software
- * without restriction, including without limitation the rights to use, copy, modify,
- * merge, publish, distribute, sublicense, and/or sell copies of the Software, and
- * to permit persons to whom the Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be included in all copies
- * or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
- * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
- * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#pragma once
-
-#include <functional>
-#include <QPointer>
-#include <QMutex>
-#include <memory>
-
-#include "qabstractgrpcchannel.h"
-
-#include "qtgrpcglobal.h"
-
-namespace qtprotobuf {
-/*!
- * \ingroup QtGrpc
- * \brief The AsyncReply class
- */
-class Q_GRPC_EXPORT AsyncReply final : public QObject
-{
-    Q_OBJECT
-public:
-    void abort() {
-        m_channel->abort(this);
-    }
-
-    template <typename T>
-    T read() {
-        QMutexLocker locker(&m_asyncLock);
-        T value;
-        value.deserialize(m_data);
-        return value;
-    }
-
-    void setData(const QByteArray &data) { m_data = data; }
-
-signals:
-    void finished();
-    void error(QAbstractGrpcChannel::StatusCode);
-
-protected:
-    AsyncReply(const std::shared_ptr<QAbstractGrpcChannel> &channel, QObject *parent = nullptr) : QObject(parent)
-    , m_channel(channel){}
-    ~AsyncReply();
-
-private:
-    AsyncReply();
-    Q_DISABLE_COPY(AsyncReply)
-    AsyncReply(AsyncReply &&) = delete;
-    AsyncReply &operator =(AsyncReply &&) = delete;
-
-    friend class QAbstractGrpcClient;
-
-    std::shared_ptr<QAbstractGrpcChannel> m_channel;
-    QByteArray m_data;
-
-    QMutex m_asyncLock;
-};
-}

+ 8 - 8
src/grpc/qabstractgrpcchannel.h

@@ -33,7 +33,7 @@
 
 namespace qtprotobuf {
 
-class AsyncReply;
+class QGrpcAsyncReply;
 class QAbstractGrpcClient;
 /*!
  * \ingroup QtGrpc
@@ -82,16 +82,16 @@ public:
     virtual StatusCode call(const QString &method, const QString &service, const QByteArray &args, QByteArray &ret) = 0;
 
     /*!
-     * \brief Calls \p method asynchronously with given serialized messge \p args. Result of method call is written to AsyncReply.
+     * \brief Calls \p method asynchronously with given serialized messge \p args. Result of method call is written to QGrpcAsyncReply.
      *        \note This method is asynchronous, that means it returns control imediately after it is called.
      * \param[in] method remote method is called
      * \param[in] service service identified in URL path format
      * \param[in] args serialized argument message
-     * \param[out] ret AsyncReply that will be returned to end-point user to read data once call complete.
-     *            AsyncReply lifecycle is managed by QAbstractGrpcClient only.
-     *            \see AsyncReply for details
+     * \param[out] ret QGrpcAsyncReply that will be returned to end-point user to read data once call complete.
+     *            QGrpcAsyncReply lifecycle is managed by QAbstractGrpcClient only.
+     *            \see QGrpcAsyncReply for details
      */
-    virtual void call(const QString &method, const QString &service, const QByteArray &args, qtprotobuf::AsyncReply *ret) = 0;
+    virtual void call(const QString &method, const QString &service, const QByteArray &args, qtprotobuf::QGrpcAsyncReply *ret) = 0;
 
     /*!
      * \brief Subscribes to server-side stream to receive updates for given \p method.
@@ -110,12 +110,12 @@ protected:
      *        \note by default abort is explicitly not supported by QAbstractGrpcChannel and throws assert when called
      * \param[in] reply returned by asynchronous QAbstractGrpcChannel::call() method
      */
-    virtual void abort(AsyncReply *reply) {
+    virtual void abort(QGrpcAsyncReply *reply) {
         Q_UNUSED(reply)
         assert("Abort is not supported by used channel");
     }
 
-    friend class AsyncReply;
+    friend class QGrpcAsyncReply;
 private:
     Q_DISABLE_COPY(QAbstractGrpcChannel)
 };

+ 6 - 6
src/grpc/qabstractgrpcclient.cpp

@@ -66,18 +66,18 @@ QAbstractGrpcChannel::StatusCode QAbstractGrpcClient::call(const QString &method
     return callStatus;
 }
 
-AsyncReply *QAbstractGrpcClient::call(const QString &method, const QByteArray &arg)
+QGrpcAsyncReply *QAbstractGrpcClient::call(const QString &method, const QByteArray &arg)
 {
-    AsyncReply *reply = nullptr;
+    QGrpcAsyncReply *reply = nullptr;
     if (d->channel) {
-        reply = new AsyncReply(d->channel, this);
+        reply = new QGrpcAsyncReply(d->channel, this);
 
-        connect(reply, &AsyncReply::error, this, [this, reply](QAbstractGrpcChannel::StatusCode statusCode) {
-            error(statusCode, QLatin1String("Connection has been aborted."));
+        connect(reply, &QGrpcAsyncReply::error, this, [this, reply](QAbstractGrpcChannel::StatusCode statusCode, const QString &errorMessage) {
+            error(statusCode, errorMessage);
             reply->deleteLater();
         });
 
-        connect(reply, &AsyncReply::finished, this, [reply](){
+        connect(reply, &QGrpcAsyncReply::finished, this, [reply](){
             reply->deleteLater();
         });
 

+ 4 - 4
src/grpc/qabstractgrpcclient.h

@@ -35,7 +35,7 @@
 #include <qtprotobuflogging.h>
 
 #include "qabstractgrpcchannel.h"
-#include "asyncreply.h"
+#include "qgrpcasyncreply.h"
 
 #include "qtgrpcglobal.h"
 
@@ -101,7 +101,7 @@ protected:
      * \param[in] arg Protobuf message argument for \p method
      */
     template<typename A>
-    AsyncReply *call(const QString &method, const A &arg) {
+    QGrpcAsyncReply *call(const QString &method, const A &arg) {
         return call(method, arg.serialize());
     }
 
@@ -163,7 +163,7 @@ private:
     /*!
      * \private
      */
-    AsyncReply *call(const QString &method, const QByteArray &arg);
+    QGrpcAsyncReply *call(const QString &method, const QByteArray &arg);
 
     /*!
      * \private
@@ -189,7 +189,7 @@ private:
             qProtoCritical() << outOfRangeErrorMessage;
             return false;
         } catch (...) {
-            error(QAbstractGrpcChannel::OutOfRange, QLatin1String("Unknown exception caught during deserialization"));
+            error(QAbstractGrpcChannel::Internal, QLatin1String("Unknown exception caught during deserialization"));
             return false;
         }
         return true;

+ 4 - 4
src/grpc/asyncreply.cpp → src/grpc/qgrpcasyncreply.cpp

@@ -23,15 +23,15 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
-#include "asyncreply.h"
+#include "qgrpcasyncreply.h"
 #include <qtprotobuflogging.h>
 
 using namespace qtprotobuf;
 
-AsyncReply::~AsyncReply()
+QGrpcAsyncReply::~QGrpcAsyncReply()
 {
-    qProtoDebug() << "Trying ~AsyncReply" << this;
+    qProtoDebug() << "Trying ~QGrpcAsyncReply" << this;
     QMutexLocker locker(&m_asyncLock);
-    qProtoDebug() << "~AsyncReply" << this;
+    qProtoDebug() << "~QGrpcAsyncReply" << this;
     (void)locker;
 }

+ 123 - 0
src/grpc/qgrpcasyncreply.h

@@ -0,0 +1,123 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 Alexey Edelev <semlanik@gmail.com>
+ *
+ * This file is part of qtprotobuf project https://git.semlanik.org/semlanik/qtprotobuf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ * software and associated documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and
+ * to permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies
+ * or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <functional>
+#include <QPointer>
+#include <QMutex>
+#include <memory>
+
+#include "qabstractgrpcchannel.h"
+
+#include "qtgrpcglobal.h"
+
+namespace qtprotobuf {
+
+/*!
+ * \ingroup QtGrpc
+ * \brief The QGrpcAsyncReply class contains data for asynchronous call of gRPC client API. It's owned by client class, that
+ *        created it. QGrpcAsyncReply coul be used by QAbstractGrpcChannel implementations to control call work flow and
+ *        abort calls if possible in case if QGrpcAsyncReply::abort method called by library user.
+ */
+class Q_GRPC_EXPORT QGrpcAsyncReply final : public QObject
+{
+    Q_OBJECT
+public:
+    /*!
+     * \brief Reads message from raw byte array stored in QGrpcAsyncReply
+     * \return Copy of deserialized message or non-initialized message in case of exceptional situation
+     */
+    template <typename T>
+    T read() {
+        QMutexLocker locker(&m_asyncLock);
+        T value;
+        try {
+            value.deserialize(m_data);
+        } catch (std::invalid_argument &) {
+            static const QLatin1String invalidArgumentErrorMessage("Response deserialization failed invalid field found");
+            error(QAbstractGrpcChannel::InvalidArgument, invalidArgumentErrorMessage);
+        } catch (std::out_of_range &) {
+            static const QLatin1String outOfRangeErrorMessage("Invalid size of received buffer");
+            error(QAbstractGrpcChannel::OutOfRange, outOfRangeErrorMessage);
+        } catch (...) {
+            error(QAbstractGrpcChannel::Internal, QLatin1String("Unknown exception caught during deserialization"));
+        }
+        return value;
+    }
+
+    /*!
+     * \brief Interface for implementation of QAbstractGrpcChannel. Should be used to write raw data from channel to
+     *        reply
+     * \param data Raw data received from channel
+     */
+    void setData(const QByteArray &data)
+    {
+        QMutexLocker locker(&m_asyncLock);
+        m_data = data;
+    }
+
+    /*!
+     * \brief Aborts this reply and try to abort call in channel
+     */
+    void abort() {
+        m_channel->abort(this);
+    }
+
+signals:
+    /*!
+     * \brief The signal is emitted when reply is ready for read. Usualy called by channel when all chunks of data
+     *        recevied
+     */
+    void finished();
+
+    /*!
+     * \brief The signal is emitted when error happend in channel or during serialization
+     * \param code gRPC channel QAbstractGrpcChannel::StatusCode
+     * \param errorMessage Description of error occured
+     */
+    void error(QAbstractGrpcChannel::StatusCode code, const QString &errorMessage);
+
+protected:
+    //! \private
+    QGrpcAsyncReply(const std::shared_ptr<QAbstractGrpcChannel> &channel, QObject *parent = nullptr) : QObject(parent)
+    , m_channel(channel){}
+    //! \private
+    ~QGrpcAsyncReply();
+
+private:
+    QGrpcAsyncReply();
+    Q_DISABLE_COPY(QGrpcAsyncReply)
+    QGrpcAsyncReply(QGrpcAsyncReply &&) = delete;
+    QGrpcAsyncReply &operator =(QGrpcAsyncReply &&) = delete;
+
+    friend class QAbstractGrpcClient;
+
+    std::shared_ptr<QAbstractGrpcChannel> m_channel;
+    QByteArray m_data;
+
+    QMutex m_asyncLock;
+};
+}

+ 7 - 7
src/grpc/qgrpchttp2channel.cpp

@@ -33,7 +33,7 @@
 #include <QTimer>
 #include <QtEndian>
 
-#include "asyncreply.h"
+#include "qgrpcasyncreply.h"
 #include "qabstractgrpcclient.h"
 #include "abstractcredentials.h"
 
@@ -214,7 +214,7 @@ QAbstractGrpcChannel::StatusCode QGrpcHttp2Channel::call(const QString &method,
     return grpcStatus;
 }
 
-void QGrpcHttp2Channel::call(const QString &method, const QString &service, const QByteArray &args, qtprotobuf::AsyncReply *reply)
+void QGrpcHttp2Channel::call(const QString &method, const QString &service, const QByteArray &args, qtprotobuf::QGrpcAsyncReply *reply)
 {
     QNetworkReply *networkReply = d->post(method, service, args);
 
@@ -223,16 +223,16 @@ void QGrpcHttp2Channel::call(const QString &method, const QString &service, cons
         QByteArray data = QGrpcHttp2ChannelPrivate::processReply(networkReply, grpcStatus);
 
         qProtoDebug() << "RECV: " << data;
-        if (StatusCode::Ok == grpcStatus ) {
+        if (StatusCode::Ok == grpcStatus) {
             reply->setData(data);
             reply->finished();
         } else {
             reply->setData({});
-            reply->error(grpcStatus);
+            reply->error(grpcStatus, QString()); //TODO: read error message from reply
         }
     });
 
-    QObject::connect(reply, &AsyncReply::error, networkReply, [networkReply, connection](QAbstractGrpcChannel::StatusCode code) {
+    QObject::connect(reply, &QGrpcAsyncReply::error, networkReply, [networkReply, connection]() {
         QObject::disconnect(connection);
         QGrpcHttp2ChannelPrivate::abortNetworkReply(networkReply);
     });
@@ -289,9 +289,9 @@ void QGrpcHttp2Channel::subscribe(const QString &method, const QString &service,
     });
 }
 
-void QGrpcHttp2Channel::abort(AsyncReply *reply)
+void QGrpcHttp2Channel::abort(QGrpcAsyncReply *reply)
 {
     assert(reply != nullptr);
     reply->setData({});
-    reply->error(StatusCode::Aborted);
+    reply->error(StatusCode::Aborted, QLatin1String("Call aborted by user or timeout"));
 }

+ 2 - 2
src/grpc/qgrpchttp2channel.h

@@ -44,11 +44,11 @@ public:
     ~QGrpcHttp2Channel();
 
     StatusCode call(const QString &method, const QString &service, const QByteArray &args, QByteArray &ret) override;
-    void call(const QString &method, const QString &service, const QByteArray &args, qtprotobuf::AsyncReply *reply) override;
+    void call(const QString &method, const QString &service, const QByteArray &args, qtprotobuf::QGrpcAsyncReply *reply) override;
     void subscribe(const QString &method, const QString &service, const QByteArray &args, QAbstractGrpcClient *client, const std::function<void (const QByteArray &)> &handler) override;
 
 protected:
-    void abort(AsyncReply *reply) override;
+    void abort(QGrpcAsyncReply *reply) override;
 
 private:
     Q_DISABLE_COPY(QGrpcHttp2Channel)

+ 11 - 11
tests/test_grpc/clienttest.cpp

@@ -62,7 +62,7 @@ TEST_F(ClientTest, CheckMethodsGeneration)
     QPointer<SimpleStringMessage> result(new SimpleStringMessage);
     testClient.testMethod(request, result);
     testClient.testMethod(request);
-    testClient.testMethod(request, &testClient, [](AsyncReply *){});
+    testClient.testMethod(request, &testClient, [](QGrpcAsyncReply *){});
     delete result;
 }
 
@@ -87,8 +87,8 @@ TEST_F(ClientTest, StringEchoAsyncTest)
     request.setTestFieldString("Hello beach!");
     QEventLoop waiter;
 
-    AsyncReply *reply = testClient.testMethod(request);
-    QObject::connect(reply, &AsyncReply::finished, &m_app, [reply, &result, &waiter]() {
+    QGrpcAsyncReply *reply = testClient.testMethod(request);
+    QObject::connect(reply, &QGrpcAsyncReply::finished, &m_app, [reply, &result, &waiter]() {
         result = reply->read<SimpleStringMessage>();
         waiter.quit();
     });
@@ -105,7 +105,7 @@ TEST_F(ClientTest, StringEchoAsync2Test)
     SimpleStringMessage request;
     request.setTestFieldString("Hello beach!");
     QEventLoop waiter;
-    testClient.testMethod(request, &m_app, [&result, &waiter](AsyncReply *reply) {
+    testClient.testMethod(request, &m_app, [&result, &waiter](QGrpcAsyncReply *reply) {
         result = reply->read<SimpleStringMessage>();
         waiter.quit();
     });
@@ -122,16 +122,16 @@ TEST_F(ClientTest, StringEchoImmediateAsyncAbortTest)
     SimpleStringMessage request;
     request.setTestFieldString("sleep");
     QEventLoop waiter;
-    AsyncReply *reply = testClient.testMethod(request);
+    QGrpcAsyncReply *reply = testClient.testMethod(request);
 
     result.setTestFieldString("Result not changed by echo");
-    QObject::connect(reply, &AsyncReply::finished, &m_app, [&waiter, &result, reply]() {
+    QObject::connect(reply, &QGrpcAsyncReply::finished, &m_app, [&waiter, &result, reply]() {
         result = reply->read<SimpleStringMessage>();
         waiter.quit();
     });
 
     QAbstractGrpcChannel::StatusCode asyncStatus = QAbstractGrpcChannel::StatusCode::Ok;
-    QObject::connect(reply, &AsyncReply::error, reply, [&asyncStatus](QAbstractGrpcChannel::StatusCode code){
+    QObject::connect(reply, &QGrpcAsyncReply::error, reply, [&asyncStatus](QAbstractGrpcChannel::StatusCode code){
         asyncStatus = code;
     });
 
@@ -158,20 +158,20 @@ TEST_F(ClientTest, StringEchoDeferredAsyncAbortTest)
     SimpleStringMessage request;
     request.setTestFieldString("sleep");
     QEventLoop waiter;
-    AsyncReply *reply = testClient.testMethod(request);
+    QGrpcAsyncReply *reply = testClient.testMethod(request);
 
     result.setTestFieldString("Result not changed by echo");
     bool errorCalled = false;
     reply = testClient.testMethod(request);
-    QObject::connect(reply, &AsyncReply::finished, &m_app, [reply, &result, &waiter]() {
+    QObject::connect(reply, &QGrpcAsyncReply::finished, &m_app, [reply, &result, &waiter]() {
         result = reply->read<SimpleStringMessage>();
         waiter.quit();
     });
-    QObject::connect(reply, &AsyncReply::error, reply, [&errorCalled](QAbstractGrpcChannel::StatusCode){
+    QObject::connect(reply, &QGrpcAsyncReply::error, reply, [&errorCalled](QAbstractGrpcChannel::StatusCode){
         errorCalled = true;
     });
 
-    QTimer::singleShot(2000, reply, &AsyncReply::abort);
+    QTimer::singleShot(2000, reply, &QGrpcAsyncReply::abort);
     QTimer::singleShot(5000, &waiter, &QEventLoop::quit);
 
     waiter.exec();