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. Signal/Slot problems in QTest
Forum Updated to NodeBB v4.3 + New Features

Signal/Slot problems in QTest

Scheduled Pinned Locked Moved Unsolved General and Desktop
20 Posts 5 Posters 2.8k Views 3 Watching
  • 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.
  • Christian EhrlicherC Christian Ehrlicher

    @HowardHarkness said in Signal/Slot problems in QTest:

    In the unit test, unless I explicitly call it (the explicit call to readPendingDatagrams() shown in my original post works without any explicit wait, indicating that the return packet is coming back very quickly), it never gets called.

    Sorry but re-read this sentence and then tell me again what your problem is.

    Also what for instance does sendCommandButton() do? Please show us the full but simplified code.

    HowardHarknessH Offline
    HowardHarknessH Offline
    HowardHarkness
    wrote on last edited by
    #6

    @Christian-Ehrlicher said in Signal/Slot problems in QTest:

    Sorry but re-read this sentence and then tell me again what your problem is.

    . In the normal application, the slot handler gets called normally.
    . In the unit test, the slot handler never gets called unless I make an explicit call to it.

    Also what for instance does sendCommandButton() do? Please show us the full but simplified code.
    Ok, here's the handler for the send command button, with most of the fluff elided.

    void MainWindow::on_sendCommandButton_clicked()
    {
    	uint commandLineCount(ui->wordCountLineEdit->text().toUInt(nullptr, baseHex));
    	... error condition checks for initial setup
    	else // setup was completed normally
    	{
    		// actual number of lines may differ from the value in wordCountLineEdit
    		QStringList lines(udpPayload.split('\n'));
    		... pad out the payload to 20 bytes for the eval board
    		QString updData(ui->updOutputPlainTextEdit->toPlainText().replace("\n", ""));
    		QByteArray transmitData(QByteArray::fromHex(updData.toUtf8()));
    
    		QNetworkDatagram datagram(transmitData, evalBoardIp, evalBoardPort);
    		quint64 bytesTransmitted = sender->sendPacket(datagram);
    	... compose & display confirmation or failure message in status bar
    	}
    	ui->updInputPlainTextEdit->clear();
    }
    

    The "setup was completed normally" section does get executed, as verified with WireShark, the debugger, and the status bar confirmation message.

    Howard Lee Harkness
    https://howardleeharkness.com/resume
    Current contract ends on March 11th, 2022 -- Looking for C++ Real-time Embedded Systems work

    1 Reply Last reply
    0
    • Pl45m4P Pl45m4

      @Christian-Ehrlicher said in Signal/Slot problems in QTest:

      Also what for instance does sendCommandButton() do?

      I think it's a QPushbutton on which a click() is simulated during the QTest.
      [Edit: You probably know that... :) Misunderstood your question :) ]

      @HowardHarkness
      But @Christian-Ehrlicher is right, nobody can see from your example when, for instance, isPacketReady() becomes true since it's not shown in your header or your code file snippet :)
      Just looked up qWait(int ms)... this, at least is not the problem, since the documentation states:

      While waiting, events will be processed and your test will stay responsive to user interface events or network communication.

      HowardHarknessH Offline
      HowardHarknessH Offline
      HowardHarkness
      wrote on last edited by
      #7

      @Pl45m4 said in Signal/Slot problems in QTest:

      nobody can see from your example when, for instance, isPacketReady() becomes true

      I defined a bool packetReady; in the Sender class, and set it false in the ctor.
      The last line of readPendingDatagrams() is "packetReady = true;" to indicate that it has been called.
      Function isPacketReady() returns the value of packetReady -- which is never true, since the slot handler readPendingDatagrams() is never called.

      Howard Lee Harkness
      https://howardleeharkness.com/resume
      Current contract ends on March 11th, 2022 -- Looking for C++ Real-time Embedded Systems work

      1 Reply Last reply
      0
      • Christian EhrlicherC Online
        Christian EhrlicherC Online
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote on last edited by Christian Ehrlicher
        #8

        This works fine for me

        class tst_Udp : public QObject
        {
          Q_OBJECT
        private Q_SLOTS:
          void testSendReceiveUdp();
        };
        
        void tst_Udp::testSendReceiveUdp()
        {
          QUdpSocket sender;
          QUdpSocket receiver;
          bool packetReceived = false;
          QByteArray buf;
          connect(&receiver, &QUdpSocket::readyRead, [&]() {
            if (receiver.hasPendingDatagrams()) {
              buf.resize(receiver.pendingDatagramSize());
              receiver.readDatagram(buf.data(), buf.size());
              qDebug() << "Received: " << buf;
              packetReceived = true;
            }
          });
          receiver.bind(QHostAddress("127.0.0.1"), 12345);
          QTimer::singleShot(0, this, [&]() {
            sender.writeDatagram(QByteArray("Hello!"), QHostAddress("127.0.0.1"), 12345);
          });
          while (!packetReceived) {
            QTest::qWait(100);
            qDebug() << "Waiting...";
          }
          qDebug() << "Finished";
        }
        
        QTEST_MAIN(tst_Udp)
        

        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
        Visit the Qt Academy at https://academy.qt.io/catalog

        HowardHarknessH 1 Reply Last reply
        1
        • Christian EhrlicherC Christian Ehrlicher

          This works fine for me

          class tst_Udp : public QObject
          {
            Q_OBJECT
          private Q_SLOTS:
            void testSendReceiveUdp();
          };
          
          void tst_Udp::testSendReceiveUdp()
          {
            QUdpSocket sender;
            QUdpSocket receiver;
            bool packetReceived = false;
            QByteArray buf;
            connect(&receiver, &QUdpSocket::readyRead, [&]() {
              if (receiver.hasPendingDatagrams()) {
                buf.resize(receiver.pendingDatagramSize());
                receiver.readDatagram(buf.data(), buf.size());
                qDebug() << "Received: " << buf;
                packetReceived = true;
              }
            });
            receiver.bind(QHostAddress("127.0.0.1"), 12345);
            QTimer::singleShot(0, this, [&]() {
              sender.writeDatagram(QByteArray("Hello!"), QHostAddress("127.0.0.1"), 12345);
            });
            while (!packetReceived) {
              QTest::qWait(100);
              qDebug() << "Waiting...";
            }
            qDebug() << "Finished";
          }
          
          QTEST_MAIN(tst_Udp)
          
          HowardHarknessH Offline
          HowardHarknessH Offline
          HowardHarkness
          wrote on last edited by
          #9

          @Christian-Ehrlicher Does that mean that I have to do the connect() call in the unit test case?

          I'm still a bit confused. The connect() does happen in the unit test setup, as confirmed using the debugger.

          I'll be examining this in more depth after I figure out how to solve my other problem with Ui::MainWindow access...

          Howard Lee Harkness
          https://howardleeharkness.com/resume
          Current contract ends on March 11th, 2022 -- Looking for C++ Real-time Embedded Systems work

          Christian EhrlicherC 1 Reply Last reply
          0
          • HowardHarknessH HowardHarkness

            @Christian-Ehrlicher Does that mean that I have to do the connect() call in the unit test case?

            I'm still a bit confused. The connect() does happen in the unit test setup, as confirmed using the debugger.

            I'll be examining this in more depth after I figure out how to solve my other problem with Ui::MainWindow access...

            Christian EhrlicherC Online
            Christian EhrlicherC Online
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on last edited by
            #10

            @HowardHarkness said in Signal/Slot problems in QTest:

            Does that mean that I have to do the connect() call in the unit test case?

            Somewhere in your code you have to call the connect, yes. How else should the slot be called?

            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
            Visit the Qt Academy at https://academy.qt.io/catalog

            HowardHarknessH 1 Reply Last reply
            0
            • Christian EhrlicherC Christian Ehrlicher

              @HowardHarkness said in Signal/Slot problems in QTest:

              Does that mean that I have to do the connect() call in the unit test case?

              Somewhere in your code you have to call the connect, yes. How else should the slot be called?

              HowardHarknessH Offline
              HowardHarknessH Offline
              HowardHarkness
              wrote on last edited by
              #11

              @Christian-Ehrlicher The problem is that the slot is not called at all in the unit test.

              Howard Lee Harkness
              https://howardleeharkness.com/resume
              Current contract ends on March 11th, 2022 -- Looking for C++ Real-time Embedded Systems work

              Christian EhrlicherC 1 Reply Last reply
              0
              • HowardHarknessH HowardHarkness

                @Christian-Ehrlicher The problem is that the slot is not called at all in the unit test.

                Christian EhrlicherC Online
                Christian EhrlicherC Online
                Christian Ehrlicher
                Lifetime Qt Champion
                wrote on last edited by
                #12

                @HowardHarkness You have a unittest which works - I don't know what you're doing in your code. A slot can only be called when a signal is connected to it.

                Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                Visit the Qt Academy at https://academy.qt.io/catalog

                HowardHarknessH 1 Reply Last reply
                0
                • Christian EhrlicherC Christian Ehrlicher

                  @HowardHarkness You have a unittest which works - I don't know what you're doing in your code. A slot can only be called when a signal is connected to it.

                  HowardHarknessH Offline
                  HowardHarknessH Offline
                  HowardHarkness
                  wrote on last edited by
                  #13

                  @Christian-Ehrlicher said in Signal/Slot problems in QTest:

                  A slot can only be called when a signal is connected to it.

                  The slot is connected, but does not get called unless I insert an explicit call to the read function. I suspect this is a red herring, and the real problem is elsewhere. Inserting the explicit call is the workaround that makes the unit test work. Meanwhile, I'm working on another problem (a poor design decision, which might actually impact this).

                  Howard Lee Harkness
                  https://howardleeharkness.com/resume
                  Current contract ends on March 11th, 2022 -- Looking for C++ Real-time Embedded Systems work

                  1 Reply Last reply
                  0
                  • M Offline
                    M Offline
                    mchinand
                    wrote on last edited by
                    #14

                    You could use a QSignalSpy to check that the signal is actually being emitted during your test. Also, make sure you are connecting the correct instances of your respective classes.

                    HowardHarknessH 1 Reply Last reply
                    0
                    • M mchinand

                      You could use a QSignalSpy to check that the signal is actually being emitted during your test. Also, make sure you are connecting the correct instances of your respective classes.

                      HowardHarknessH Offline
                      HowardHarknessH Offline
                      HowardHarkness
                      wrote on last edited by HowardHarkness
                      #15

                      Well, I'm back from COVID recovery, and still have this problem.
                      I tried the "poor man's" unit test framework -- I created a dialog with an output report and some buttons to run tests on the mainwindow. I was surprised to run into exactly the same problem, in exactly the same place, for what appears to be the same reason.

                      In my test, I click on a button that should send a command to the hardware, which will respond with a reply packet.

                      // send read command
                         btnSendCommand->click();
                      

                      It appears that the signal for the read never gets sent.

                      However, if I actually click on that button with my mouse, it works, and I get the expected input.

                      I have to conclude one of the following:

                      1. The btnSendCommand->click(); does not actually do the same thing as using the mouse to click the button.
                      2. There is some environmental issue I am getting wrong in my test.
                      3. There is a timing issue I don't understand.

                      Howard Lee Harkness
                      https://howardleeharkness.com/resume
                      Current contract ends on March 11th, 2022 -- Looking for C++ Real-time Embedded Systems work

                      Pl45m4P 1 Reply Last reply
                      0
                      • HowardHarknessH HowardHarkness

                        Well, I'm back from COVID recovery, and still have this problem.
                        I tried the "poor man's" unit test framework -- I created a dialog with an output report and some buttons to run tests on the mainwindow. I was surprised to run into exactly the same problem, in exactly the same place, for what appears to be the same reason.

                        In my test, I click on a button that should send a command to the hardware, which will respond with a reply packet.

                        // send read command
                           btnSendCommand->click();
                        

                        It appears that the signal for the read never gets sent.

                        However, if I actually click on that button with my mouse, it works, and I get the expected input.

                        I have to conclude one of the following:

                        1. The btnSendCommand->click(); does not actually do the same thing as using the mouse to click the button.
                        2. There is some environmental issue I am getting wrong in my test.
                        3. There is a timing issue I don't understand.
                        Pl45m4P Offline
                        Pl45m4P Offline
                        Pl45m4
                        wrote on last edited by Pl45m4
                        #16

                        @HowardHarkness said in Signal/Slot problems in QTest:

                        The btnSendCommand->click(); does not actually do the same thing as using the mouse to click the button.

                        What if you "focus" the button first, before you virtually click it? (for example with setFocus).
                        What if you click it twice by code?
                        Just a guess...you could try it.

                        • https://code.woboq.org/qt5/qtbase/src/widgets/widgets/qabstractbutton.cpp.html#_ZN15QAbstractButton5clickEv

                        Have you tried animateClick ()?

                        • https://code.woboq.org/qt5/qtbase/src/widgets/widgets/qabstractbutton.cpp.html#_ZN15QAbstractButton12animateClickEi

                        If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                        ~E. W. Dijkstra

                        HowardHarknessH 1 Reply Last reply
                        0
                        • Pl45m4P Pl45m4

                          @HowardHarkness said in Signal/Slot problems in QTest:

                          The btnSendCommand->click(); does not actually do the same thing as using the mouse to click the button.

                          What if you "focus" the button first, before you virtually click it? (for example with setFocus).
                          What if you click it twice by code?
                          Just a guess...you could try it.

                          • https://code.woboq.org/qt5/qtbase/src/widgets/widgets/qabstractbutton.cpp.html#_ZN15QAbstractButton5clickEv

                          Have you tried animateClick ()?

                          • https://code.woboq.org/qt5/qtbase/src/widgets/widgets/qabstractbutton.cpp.html#_ZN15QAbstractButton12animateClickEi
                          HowardHarknessH Offline
                          HowardHarknessH Offline
                          HowardHarkness
                          wrote on last edited by
                          #17

                          @Pl45m4 Ok, I tried focus(). No difference. I tried multiple calls to click(). No difference. As for animateClick(), I didn't see any difference, but I'm wondering if I need to add some sort of delay to wait for completion.

                          I put some tracing code in the slot handler, and discovered that the first time I invoke the test function, the slot handler is not called. The second time I invoke the test function, the slot IS called, but the results aren't available in time for my checks. So, the THIRD time I invoke the test function, the test results are as expected.

                          So, I think I have narrowed it down to a timing problem. Not sure how to address that yet.

                          Howard Lee Harkness
                          https://howardleeharkness.com/resume
                          Current contract ends on March 11th, 2022 -- Looking for C++ Real-time Embedded Systems work

                          HowardHarknessH 1 Reply Last reply
                          0
                          • HowardHarknessH HowardHarkness

                            @Pl45m4 Ok, I tried focus(). No difference. I tried multiple calls to click(). No difference. As for animateClick(), I didn't see any difference, but I'm wondering if I need to add some sort of delay to wait for completion.

                            I put some tracing code in the slot handler, and discovered that the first time I invoke the test function, the slot handler is not called. The second time I invoke the test function, the slot IS called, but the results aren't available in time for my checks. So, the THIRD time I invoke the test function, the test results are as expected.

                            So, I think I have narrowed it down to a timing problem. Not sure how to address that yet.

                            HowardHarknessH Offline
                            HowardHarknessH Offline
                            HowardHarkness
                            wrote on last edited by
                            #18

                            Ah, I have narrowed it down to some sort of timing or thread conflict. Invoking the test function by hand 3 times has the effect noted above (1. No slot call, 2. Slot call, but updates don't happen in time, 3. Success).
                            However if I just invoke the test function three times in code, the result is no slot call.

                            Howard Lee Harkness
                            https://howardleeharkness.com/resume
                            Current contract ends on March 11th, 2022 -- Looking for C++ Real-time Embedded Systems work

                            1 Reply Last reply
                            0
                            • 6thC6 Offline
                              6thC6 Offline
                              6thC
                              wrote on last edited by
                              #19

                              Did you ever get to the bottom of this?

                              We have the same symptoms with seeing packets in wireshark but readyRead() not triggering, even if I manually check hasPendingDatagrams() after, for immediate replies QUdpSocket just doesn't get the message.

                              HowardHarknessH 1 Reply Last reply
                              0
                              • 6thC6 6thC

                                Did you ever get to the bottom of this?

                                We have the same symptoms with seeing packets in wireshark but readyRead() not triggering, even if I manually check hasPendingDatagrams() after, for immediate replies QUdpSocket just doesn't get the message.

                                HowardHarknessH Offline
                                HowardHarknessH Offline
                                HowardHarkness
                                wrote on last edited by
                                #20

                                @6thC Yes, I did.

                                I'm no longer on that project, but I recall that it was basically a typo. I was not properly setting up the correct slot. Totally my screwup.

                                Howard Lee Harkness
                                https://howardleeharkness.com/resume
                                Current contract ends on March 11th, 2022 -- Looking for C++ Real-time Embedded Systems work

                                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