Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to properly handle asynchronous events with Qt test framework? QSignalSpy::wait() returns false even though signal emitted during given time interval

How to properly handle asynchronous events with Qt test framework? QSignalSpy::wait() returns false even though signal emitted during given time interval

Scheduled Pinned Locked Moved Unsolved General and Desktop
qnetworkreplyqnetworkaccessmqsignalspyqtestqtestlib
3 Posts 2 Posters 3.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    Red Baron
    wrote on last edited by
    #1

    Through a server that runs locally (I use pyftpdlib to make a local directory available through FTP with anonymous login) a class I have written downloads an archive. Triggering the download process (generation of the QNetworkRequest, creating the QNetworkReply and connecting the various signals related to all this) can be seen in the code snippet below:

    // Note that fileName and md5 are for something later on and are not important here
    void Downloader::download(QUrl source, QString fileName, QByteArray md5)
    {
        QNetworkRequest req(source);
        this->reply = this->manager->get(req);
    
        this->md5_download = md5;
        this->fileName = fileName;
    
        connect(this->reply, &QNetworkReply::finished, this, &Downloader::slotDownloadCompleted);
        connect(this->reply, &QIODevice::readyRead, this, &Downloader::slotDownloading);
    
        emit signalDownloading();
    }
    

    Note that I don't connect the QNetworkAccessManager::finished() to the QNetworkReply::deleteLater() since I manually call the slot inside Downloader::slotDownloadComplete().

    My test is rather simple (for now):

    void TestDownloader::testFtpDownload()
    {
        QSignalSpye downloadSpy(this->dw, &Downloader::signalDownloading);
    
        this->dw->download(QUrl("ftp://127.0.0.1:9999/update_0.45.tar.gz"), "update_0.45.tar.gz", QByteArray());
        QVERIFY(downloadSpy.wait());
    }
    

    The downloading of the archive (here update_0.45.tar.gz) does succeed - I can confirm it both in the log of the FTP server and the fact that the archive is in the path of my test binary and valid (can be opened, decompressed etc.).

    However the thing that is bothering me is that no matter what timeout I set (I Tried with up to 40 seconds!) for downloadSpy.wait() it always returns false even though through debugging I can clearly see that emit signalDownloading() is executed plus the fact that the downloaded file has actually been downloaded almost instantly (2KB of data transfer on localhost doesn't take more than 1ms in my experience).

    On several occasions now I am facing such problem of not being able to properly unit-test network functionality in my project because of the asynchronous nature of the network requests and replies. Even though I can clearly verify that things are working (by manually observing the network traffic and filesystem) I would still like to be able to do this properly and in a manner that can be used in a build server or in general an environment when you don't have the ability to manually check things.

    kshegunovK 1 Reply Last reply
    0
    • R Red Baron

      Through a server that runs locally (I use pyftpdlib to make a local directory available through FTP with anonymous login) a class I have written downloads an archive. Triggering the download process (generation of the QNetworkRequest, creating the QNetworkReply and connecting the various signals related to all this) can be seen in the code snippet below:

      // Note that fileName and md5 are for something later on and are not important here
      void Downloader::download(QUrl source, QString fileName, QByteArray md5)
      {
          QNetworkRequest req(source);
          this->reply = this->manager->get(req);
      
          this->md5_download = md5;
          this->fileName = fileName;
      
          connect(this->reply, &QNetworkReply::finished, this, &Downloader::slotDownloadCompleted);
          connect(this->reply, &QIODevice::readyRead, this, &Downloader::slotDownloading);
      
          emit signalDownloading();
      }
      

      Note that I don't connect the QNetworkAccessManager::finished() to the QNetworkReply::deleteLater() since I manually call the slot inside Downloader::slotDownloadComplete().

      My test is rather simple (for now):

      void TestDownloader::testFtpDownload()
      {
          QSignalSpye downloadSpy(this->dw, &Downloader::signalDownloading);
      
          this->dw->download(QUrl("ftp://127.0.0.1:9999/update_0.45.tar.gz"), "update_0.45.tar.gz", QByteArray());
          QVERIFY(downloadSpy.wait());
      }
      

      The downloading of the archive (here update_0.45.tar.gz) does succeed - I can confirm it both in the log of the FTP server and the fact that the archive is in the path of my test binary and valid (can be opened, decompressed etc.).

      However the thing that is bothering me is that no matter what timeout I set (I Tried with up to 40 seconds!) for downloadSpy.wait() it always returns false even though through debugging I can clearly see that emit signalDownloading() is executed plus the fact that the downloaded file has actually been downloaded almost instantly (2KB of data transfer on localhost doesn't take more than 1ms in my experience).

      On several occasions now I am facing such problem of not being able to properly unit-test network functionality in my project because of the asynchronous nature of the network requests and replies. Even though I can clearly verify that things are working (by manually observing the network traffic and filesystem) I would still like to be able to do this properly and in a manner that can be used in a build server or in general an environment when you don't have the ability to manually check things.

      kshegunovK Offline
      kshegunovK Offline
      kshegunov
      Moderators
      wrote on last edited by kshegunov
      #2

      Does this:

      void TestDownloader::testFtpDownload()
      {
          QSignalSpy downloadSpy(this->dw, &Downloader::signalDownloading);
      
          QTimer::singleShot(0, dw, std::bind(&Downloader::download, dw, QUrl("ftp://127.0.0.1:9999/update_0.45.tar.gz"), "update_0.45.tar.gz", QByteArray()));
          QVERIFY(downloadSpy.wait());
      }
      
      

      fix it?

      Read and abide by the Qt Code of Conduct

      1 Reply Last reply
      0
      • R Offline
        R Offline
        Red Baron
        wrote on last edited by
        #3

        Thanks for the reply. Will check it out.

        1 Reply Last reply
        0

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved