diff --git a/3rdparty/qtquickdesigner-components b/3rdparty/qtquickdesigner-components index 5f115ed120adb58972ac3a0a2b80ec42cf3769a1..8be09977abbdb638bf483ea417b36091b409c54f 160000 --- a/3rdparty/qtquickdesigner-components +++ b/3rdparty/qtquickdesigner-components @@ -1 +1 @@ -Subproject commit 5f115ed120adb58972ac3a0a2b80ec42cf3769a1 +Subproject commit 8be09977abbdb638bf483ea417b36091b409c54f diff --git a/README.md b/README.md index 94c64199d13e3573c097a705341ddeac81f0768a..0aa72b4bd0791d893d8075016d7d733e149b6c0d 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,19 @@ cmake --build build Upload the final APK file to your Android device and run. Then follow the instructions within the app. +## Testing + +To run the tests a running emulator or a connected device is required. There's a helper script to run the tests under `tests/scripts/run-tests.sh`. To run the tests first copy the APK file to the device and then run the script. It'll extract the test results as `output.junit.xml` file. + +Test results can be viewed with any JUnit compatible viewer. For example, you can use `xunit-viewer` to view the results: + +```bash +npm i -g xunit-viewer +xunit-viewer -r output.junit.xml +``` + +It'll create a `report.html` file that can be opened in a web browser. For more information about `xunit-viewer` please visit the [GitHub repo](https://github.com/lukejpreston/xunit-viewer). + ## 3rd Party Libraries/Components * [zxing-cpp](https://github.com/zxing-cpp/zxing-cpp.git) diff --git a/src/backend/dsconnector.cpp b/src/backend/dsconnector.cpp index a608535595d8f23866ee6275cf3f8b742e69a8cf..928c608a5e6b3c171edebfc9c3c4d96d68a5255e 100644 --- a/src/backend/dsconnector.cpp +++ b/src/backend/dsconnector.cpp @@ -27,8 +27,9 @@ #include <QNetworkInterface> -DesignStudioConnector::DesignStudioConnector(QObject *parent) +DesignStudioConnector::DesignStudioConnector(const quint16 port, QObject *parent) : QObject(parent) + , m_tcpPort(port) { initTcpServer(); } @@ -71,31 +72,33 @@ void DesignStudioConnector::initTcpServer() } qDebug() << "Listening on port " << m_tcpPort; - connect(&m_tcpServer, &QTcpServer::newConnection, this, [this]() { - qDebug() << "New connection from Design Studio"; - emit networkStatusUpdated("Qt Design Studio is connected.\n Waiting for project..."); - m_tcpSocket.reset(m_tcpServer.nextPendingConnection()); - m_ipUpdateTimer.stop(); - - connect(m_tcpSocket.data(), &QTcpSocket::disconnected, this, [this]() { - qDebug() << "Disconnected from Design Studio"; - emit networkStatusUpdated("\nLocal IP: " + m_ipv4Addr - + "\nWaiting for Qt Design Studio to connect..."); - m_projectData.clear(); - m_ipUpdateTimer.start(); - }); - - connect(m_tcpSocket.data(), - &QTcpSocket::readyRead, - this, - &DesignStudioConnector::receiveProject); - }); + connect(&m_tcpServer, &QTcpServer::newConnection, this, &DesignStudioConnector::clientConnected); m_ipUpdateTimer.setInterval(5000); connect(&m_ipUpdateTimer, &QTimer::timeout, this, &DesignStudioConnector::updateIpv4Addr); m_ipUpdateTimer.start(); } +void DesignStudioConnector::clientConnected() +{ + qDebug() << "New connection from Design Studio"; + emit networkStatusUpdated("Qt Design Studio is connected.\n Waiting for project..."); + m_tcpSocket.reset(m_tcpServer.nextPendingConnection()); + m_projectData.clear(); + m_ipUpdateTimer.stop(); + + connect(m_tcpSocket.data(), &QTcpSocket::disconnected, this, [&]() { + qDebug() << "Disconnected from Design Studio"; + emit networkStatusUpdated("\nLocal IP: " + m_ipv4Addr + + "\nWaiting for Qt Design Studio to connect..."); + }); + + connect(m_tcpSocket.data(), + &QTcpSocket::readyRead, + this, + &DesignStudioConnector::receiveProject); +} + void DesignStudioConnector::updateIpv4Addr() { const QList<QHostAddress> list = QNetworkInterface::allAddresses(); diff --git a/src/backend/dsconnector.h b/src/backend/dsconnector.h index 66e1ec5cf81be42c11752f6b8a211fa96b536e61..1068224b5932a7c93d6f0c949fb25c5f651a9141 100644 --- a/src/backend/dsconnector.h +++ b/src/backend/dsconnector.h @@ -36,7 +36,7 @@ class DesignStudioConnector : public QObject { Q_OBJECT public: - explicit DesignStudioConnector(QObject *parent = nullptr); + explicit DesignStudioConnector(const quint16 port = 40000, QObject *parent = nullptr); public slots: void sendProjectReceived(); @@ -45,7 +45,7 @@ private: // Tcp connection members QTcpServer m_tcpServer; QScopedPointer<QTcpSocket> m_tcpSocket; - const quint32 m_tcpPort = 40000; + const quint32 m_tcpPort; // Udp connection members QTimer m_ipUpdateTimer; @@ -59,6 +59,7 @@ private: void initTcpServer(); void receiveProject(); void updateIpv4Addr(); + void clientConnected(); signals: void networkStatusUpdated(QString); diff --git a/src/backend/projectmanager.cpp b/src/backend/projectmanager.cpp index 629536f518307fb3192788b46995106aa40f12bf..ed795814da3dada736e4bd375b0f88cfadaa240d 100644 --- a/src/backend/projectmanager.cpp +++ b/src/backend/projectmanager.cpp @@ -534,9 +534,9 @@ void ProjectManager::orientateWindow(Qt::ScreenOrientation orientation) QQuickItem *childItem{contentItem->childItems().at(0)}; const QRect screenGeometry = QGuiApplication::primaryScreen()->geometry(); - const QString orientationString = (orientation == Qt::LandscapeOrientation ? "landscape" - : "portrait"); - qDebug() << "Adapting orientation to " << orientationString << " mode" + const QString orientationString = (orientation == Qt::PortraitOrientation ? "portrait" + : "landscape"); + qDebug() << "Adapting orientation to" << orientationString << "mode. enum_val:" << orientation << ". Initial sizing:" << Qt::endl << "-- Screen size: " << screenGeometry.height() << " x " << screenGeometry.width() << Qt::endl diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e13567c9280fd89be3dbddbd818a2feb390fca58..e290b1706a39bf5ddd04c4bec43ffece7df45ecb 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME ${PROJECT_NAME}_test) -find_package(Qt6 REQUIRED COMPONENTS Test Core Quick Gui) +find_package(Qt6 REQUIRED COMPONENTS Test Core Quick Gui Multimedia) enable_testing(true) qt_add_executable(${TARGET_NAME} @@ -12,7 +12,7 @@ add_test(NAME ${TARGET_NAME} COMMAND qtuiviewer_test) target_link_libraries( ${TARGET_NAME} PRIVATE - Qt::Test Qt::Core Qt::Quick Qt::Gui + Qt::Test Qt::Core Qt::Quick Qt::Gui Qt::Multimedia qtuiviewerlib ) diff --git a/tests/scripts/run_test.sh b/tests/scripts/run_test.sh index fd542e5bfc4d1a55db63c6efd8bdddca51f7e845..6015ffa87add2b82a7626001d5f3cf22df9f0171 100755 --- a/tests/scripts/run_test.sh +++ b/tests/scripts/run_test.sh @@ -3,7 +3,7 @@ # Precondition: The device/emulator is connected/running and the test application is installed on it. adb shell "run-as io.qt.qtuiviewer.test rm -rf /data/data/io.qt.qtuiviewer.test/files/output.junitxml" -adb shell am start -e applicationArguments "'-o output.junitxml,junitxml'" -n io.qt.qtuiviewer.test/org.qtproject.qt.android.bindings.QtActivity +adb shell am start -e applicationArguments "'-o output.junitxml,junitxml -v2'" -n io.qt.qtuiviewer.test/org.qtproject.qt.android.bindings.QtActivity counter=0 while [ -z "$(adb shell pidof -s io.qt.qtuiviewer.test)" ]; do @@ -21,10 +21,10 @@ echo "PID of test: ${PID_OF_TEST}" counter=0 while [ -n "$(adb shell pidof -s io.qt.qtuiviewer.test)" ]; do - echo "Waiting for test to finish" - sleep 0.1 + echo "Waiting for test to finish. Elapsed time: $counter seconds" + sleep 1 counter=$((counter + 1)) - if [ $counter -gt 60 ]; then + if [ $counter -gt 300 ]; then echo "Test did not finish in time" exit 1 fi diff --git a/tests/tst_qtuiviewer.cpp b/tests/tst_qtuiviewer.cpp index e0c111e0f7a10a5a4fd43661685c0c997df44d25..08499d8c8876a997c4b77181a206e2578280efac 100644 --- a/tests/tst_qtuiviewer.cpp +++ b/tests/tst_qtuiviewer.cpp @@ -170,7 +170,7 @@ void TestQtUiViewer::clearNonExistentUserProjectCache() void TestQtUiViewer::initDsConnector() { - DesignStudioConnector dsc; + DesignStudioConnector dsc(40000); QTcpSocket socket; socket.connectToHost("localhost", 40000); @@ -178,47 +178,95 @@ void TestQtUiViewer::initDsConnector() QVERIFY(socket.waitForConnected(1000)); } -// void TestQtUiViewer::incomingProjectTrue() -// { -// DesignStudioConnector dsc; +void TestQtUiViewer::incomingProjectTrue() +{ + DesignStudioConnector dsc(40001); + + QTcpSocket socket; + socket.connectToHost("localhost", 40001); + + QVERIFY(socket.waitForConnected(1000)); + + // we'll write a sample project over the tcp connection + // and expect the DesignStudioConnector to emit the projectIncoming signal + QSignalSpy spy(&dsc, &DesignStudioConnector::projectIncoming); + QVERIFY(spy.isValid()); + + QByteArray projectData = "qres::qmlrc-start::"; + socket.write(projectData); + QVERIFY(socket.waitForBytesWritten(1000)); + + QTRY_COMPARE(spy.count(), 1); +} -// QTcpSocket socket; -// socket.connectToHost("localhost", 40000); +void TestQtUiViewer::incomingProjectFalse() +{ + DesignStudioConnector dsc(40002); -// QVERIFY(socket.waitForConnected(1000)); + QTcpSocket socket; + socket.connectToHost("localhost", 40002); -// // we'll write a sample project over the tcp connection -// // and expect the DesignStudioConnector to emit the projectIncoming signal -// QSignalSpy spy(&dsc, &DesignStudioConnector::projectIncoming); -// QVERIFY(spy.isValid()); + QVERIFY(socket.waitForConnected(1000)); -// QByteArray projectData = "qres::qmlrc-start::\n" -// "qmlrc-end::"; -// socket.write(projectData); -// QVERIFY(socket.waitForBytesWritten(1000)); -// QThread::msleep(100); -// QCOMPARE(spy.count(), 1); -// } + // we'll write a arbitrary data over the tcp connection + // and don't expect the DesignStudioConnector to emit the projectIncoming signal + QSignalSpy spy(&dsc, SIGNAL(projectIncoming())); -// void TestQtUiViewer::incomingProjectFalse() -// { -// DesignStudioConnector dsc; + QByteArray projectData = "some arbitrary data"; + socket.write(projectData); + QVERIFY(socket.waitForBytesWritten(1000)); -// QTcpSocket socket; -// socket.connectToHost("localhost", 40000); + QTRY_COMPARE(spy.count(), 0); +} -// QVERIFY(socket.waitForConnected(1000)); +void TestQtUiViewer::receiveProject() +{ + DesignStudioConnector dsc(40003); -// // we'll write a sample project over the tcp connection -// // and expect the DesignStudioConnector to emit the projectIncoming signal -// QSignalSpy spy(&dsc, SIGNAL(projectIncoming())); + QTcpSocket socket; + socket.connectToHost("localhost", 40003); -// QByteArray projectData = "some arbitrary data"; -// socket.write(projectData); + QVERIFY(socket.waitForConnected(1000)); -// QVERIFY(socket.waitForBytesWritten(1000)); + // we'll write a sample project over the tcp connection + // and expect the DesignStudioConnector to emit the projectReceived signal + QSignalSpy spy(&dsc, &DesignStudioConnector::projectReceived); + QVERIFY(spy.isValid()); -// QCOMPARE(spy.count(), 0); -// } + QByteArray projectData = "qres::qmlrc-start::"; + socket.write(projectData); + QVERIFY(socket.waitForBytesWritten(1000)); + + spy.wait(1000); + + projectData = "Hello World::qmlrc-end::"; + socket.write(projectData); + QVERIFY(socket.waitForBytesWritten(1000)); + + QTRY_COMPARE(spy.count(), 1); +} + +void TestQtUiViewer::networkStatusUpdated() +{ + DesignStudioConnector dsc(40004); + + QTcpSocket socket; + + QSignalSpy spy(&dsc, &DesignStudioConnector::networkStatusUpdated); + QVERIFY(spy.isValid()); + + socket.connectToHost("localhost", 40004); + QVERIFY(socket.waitForConnected(1000)); + + spy.wait(500); + QTRY_COMPARE(spy.count(), 1); + + socket.disconnectFromHost(); + socket.waitForDisconnected(1000); + QVERIFY(socket.state() == QAbstractSocket::UnconnectedState); + + spy.wait(500); + QTRY_COMPARE(spy.count(), 2); +} QTEST_MAIN(TestQtUiViewer); diff --git a/tests/tst_qtuiviewer.h b/tests/tst_qtuiviewer.h index a1dee3f0b420a9b608d8c5c614fe0853f29612f7..c158d378053baccfec8b52b34bb965ce015414a2 100644 --- a/tests/tst_qtuiviewer.h +++ b/tests/tst_qtuiviewer.h @@ -60,6 +60,8 @@ private slots: // ds connector tests void initDsConnector(); - // void incomingProjectTrue(); - // void incomingProjectFalse(); + void incomingProjectTrue(); + void incomingProjectFalse(); + void receiveProject(); + void networkStatusUpdated(); };