diff --git a/cicd/stages/test.yml b/cicd/stages/test.yml index 2d1ee04c672461779d77c2e004b44d43f392b3ed..5c9943ab8f28e626a0f01ec7a60487d22111c38e 100644 --- a/cicd/stages/test.yml +++ b/cicd/stages/test.yml @@ -20,8 +20,35 @@ test-x86_64: - cd ${QDS_CI_ARTIFACTS_PATH}/android/x86_64/test || exit 1 - mkdir -p ${QDS_CI_JOB_TEST_RESULTS_PATH} - adb install -r -g android-build-release.apk - - adb shell am start -e applicationArguments "'-o output.txt,txt -o output.xml,xml -o output.junitxml,junitxml'" -n io.qt.qtuiviewer.test/org.qtproject.qt.android.bindings.QtActivity + - 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 + - | + counter=0 + while [ -z "$(adb shell pidof -s io.qt.qtuiviewer.test)" ]; do + echo "Waiting for test to start" + sleep 0.1 + counter=$((counter+1)) + if [ $counter -gt 60 ]; then + echo "Test did not start in time" + exit 1 + fi + done + - PID_OF_TEST=$(adb shell pidof -s io.qt.qtuiviewer.test) + - '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 + counter=$((counter+1)) + if [ $counter -gt 60 ]; then + echo "Test did not finish in time" + exit 1 + fi + done + - adb logcat -d --pid=${PID_OF_TEST} > ${QDS_CI_JOB_TEST_RESULTS_PATH}/logcat.txt - adb shell "run-as io.qt.qtuiviewer.test cat /data/data/io.qt.qtuiviewer.test/files/output.junitxml" > output.junit.xml + - adb uninstall io.qt.qtuiviewer.test - mv output.junit.xml ${QDS_CI_JOB_TEST_RESULTS_PATH}/test.junit.xml artifacts: paths: diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cef94e9fafd108e973ea3b8d482261dccb6c9981..746e970ebbaca3563690d6f9573e39231fc42a4e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -26,6 +26,28 @@ target_link_libraries(${PROJECT_NAME} PRIVATE ZXing::ZXing ) +qt_add_library(qtuiviewerlib OBJECT + EXCLUDE_FROM_ALL + backend/projectmanager.cpp backend/projectmanager.h + backend/serviceconnector.cpp backend/serviceconnector.h + backend/dsconnector.cpp backend/dsconnector.h +) + +target_link_libraries(qtuiviewerlib PRIVATE + Qt6::Core + Qt6::Quick + Qt6::Qml + Qt6::Gui + Qt6::GuiPrivate + Qt6::Multimedia + Qt6::MultimediaWidgets + Qt6::Concurrent +) + +target_include_directories(qtuiviewerlib PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} +) + set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/android ) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0733caf57be2f2a29a9df7c7fa26f24b1e7f34bc..e13567c9280fd89be3dbddbd818a2feb390fca58 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -4,13 +4,23 @@ find_package(Qt6 REQUIRED COMPONENTS Test Core Quick Gui) enable_testing(true) qt_add_executable(${TARGET_NAME} - unit/tst_qtuiviewer.cpp - unit/tst_qtuiviewer.h + tst_qtuiviewer.cpp + tst_qtuiviewer.h ) add_test(NAME ${TARGET_NAME} COMMAND qtuiviewer_test) -target_link_libraries(${TARGET_NAME} PRIVATE Qt::Test Qt::Core Qt::Quick Qt::Gui) +target_link_libraries( + ${TARGET_NAME} + PRIVATE + Qt::Test Qt::Core Qt::Quick Qt::Gui + qtuiviewerlib +) set_property(TARGET ${TARGET_NAME} APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/android ) + +set_property(TARGET ${TARGET_NAME} PROPERTY QT_ANDROID_EXTRA_LIBS + ${ANDROID_OPENSSL_PATH}/libcrypto_3.so + ${ANDROID_OPENSSL_PATH}/libssl_3.so +) diff --git a/tests/scripts/run_test.sh b/tests/scripts/run_test.sh new file mode 100755 index 0000000000000000000000000000000000000000..fd542e5bfc4d1a55db63c6efd8bdddca51f7e845 --- /dev/null +++ b/tests/scripts/run_test.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# This script is used to run the test on the device and collect the logs and the test results. +# 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 + +counter=0 +while [ -z "$(adb shell pidof -s io.qt.qtuiviewer.test)" ]; do + echo "Waiting for test to start" + sleep 0.1 + counter=$((counter + 1)) + if [ $counter -gt 60 ]; then + echo "Test did not start in time" + exit 1 + fi +done + +PID_OF_TEST=$(adb shell pidof -s io.qt.qtuiviewer.test) +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 + counter=$((counter + 1)) + if [ $counter -gt 60 ]; then + echo "Test did not finish in time" + exit 1 + fi +done + +adb logcat -d --pid=${PID_OF_TEST} +adb logcat -d --pid=${PID_OF_TEST} >logcat.txt +adb shell "run-as io.qt.qtuiviewer.test cat /data/data/io.qt.qtuiviewer.test/files/output.junitxml" >output.junit.xml diff --git a/tests/tst_qtuiviewer.cpp b/tests/tst_qtuiviewer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e0c111e0f7a10a5a4fd43661685c0c997df44d25 --- /dev/null +++ b/tests/tst_qtuiviewer.cpp @@ -0,0 +1,224 @@ +/**************************************************************************** +** +** Copyright (C) 2024 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Viewer of the Qt Toolkit. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "tst_qtuiviewer.h" + +#include <QSignalSpy> + +#include "backend/dsconnector.h" +#include "backend/projectmanager.h" +#include "backend/serviceconnector.h" + +#define DEMO_PROJECT_NAME "ClusterTutorial" + +void TestQtUiViewer::initTestCase() +{ + qDebug() << "initTestCase"; + ServiceConnector sc; + m_demoProjectList = sc.fetchDemoList(); + QVERIFY(m_demoProjectList.has_value()); + + m_demoProjectData = sc.fetchDemo(DEMO_PROJECT_NAME); + QVERIFY(m_demoProjectData.has_value()); + + QJsonObject projectInfo; + for (auto project : m_demoProjectList.value()) { + if (DEMO_PROJECT_NAME == project.toObject().value("name").toString().remove(".qmlrc")) { + m_demoInfoCorrect = project.toObject(); + break; + } + } + + m_demoInfoIncorrect = QJsonObject{ + {{"lastUpdate", 1707822220200.017}, {"name", "ClusterTutorial.qmlrc"}}}; + + m_userProjectInfoCorrect = QJsonObject{{{"appName", "Testmcu"}, + {"id", "0sadf8fa9s8df67s8998690a7sdf"}, + {"owner", ""}, + {"passwordHash", ""}, + {"qdsIsEnterprise", true}, + {"qdsVersion", "Qt Design Studio 4.2.0"}, + {"ttlDays", 31}, + {"uploadTime", "2023-10-27T13:57:22"}, + {"userHash", "12038740912873462987"}}}; + + m_userProjectInfoIncorrect = QJsonObject{{{"appName", "Testmcu"}, + {"id", "0sadf8fa9s8df67s8998690a7sdf"}, + {"owner", ""}, + {"passwordHash", ""}, + {"qdsIsEnterprise", true}, + {"qdsVersion", "Qt Design Studio 4.2.0"}, + {"ttlDays", 31}, + {"uploadTime", "2023-10-27T13:58:22"}, + {"userHash", "12038740912873462987"}}}; + qDebug() << "initTestCase done"; +} + +void TestQtUiViewer::fetchDemoProjectList() +{ + QStringList projectNames{"ClusterTutorial.qmlrc", + "CoffeeMachine.qmlrc", + "EBikeDesign.qmlrc", + "MaterialBundle.qmlrc", + "SideMenu.qmlrc", + "WebinarDemo.qmlrc"}; + + QStringList projectNamesFromJson; + for (const auto &project : m_demoProjectList.value()) { + projectNamesFromJson.append(project.toObject().value("name").toString()); + } + + QCOMPARE(projectNamesFromJson, projectNames); +} + +void TestQtUiViewer::fetchDemoProject() +{ + QCOMPARE(m_demoProjectData.has_value(), true); +} + +void TestQtUiViewer::cacheDemoProject() +{ + ProjectManager pm; + + QCOMPARE(pm.cacheDemoProject(m_demoProjectData.value(), m_demoInfoCorrect), true); +} + +void TestQtUiViewer::isDemoProjectCachedTrue() +{ + ProjectManager pm; + + QVERIFY(pm.cacheDemoProject(m_demoProjectData.value(), m_demoInfoCorrect)); + QCOMPARE(pm.isDemoProjectCached(m_demoInfoCorrect), true); +} + +void TestQtUiViewer::isDemoProjectCachedFalse() +{ + ProjectManager pm; + + QVERIFY(pm.cacheDemoProject(m_demoProjectData.value(), m_demoInfoCorrect)); + QCOMPARE(pm.isDemoProjectCached(m_demoInfoIncorrect), false); +} + +void TestQtUiViewer::clearDemoProjectCache() +{ + ProjectManager pm; + QVERIFY(pm.cacheDemoProject(m_demoProjectData.value(), m_demoInfoCorrect)); + + pm.clearDemoCaches(); + QCOMPARE(pm.isDemoProjectCached(m_demoInfoCorrect), false); +} + +void TestQtUiViewer::cacheUserProject() +{ + ProjectManager pm; + QCOMPARE(pm.cacheProject(m_demoProjectData.value(), m_userProjectInfoCorrect), true); +} + +void TestQtUiViewer::isUserProjectCachedTrue() +{ + ProjectManager pm; + pm.cacheProject(m_demoProjectData.value(), m_userProjectInfoCorrect); + QCOMPARE(pm.isProjectCached(m_userProjectInfoCorrect), true); +} + +void TestQtUiViewer::isUserProjectCachedFalse() +{ + ProjectManager pm; + QVERIFY(pm.cacheProject(m_demoProjectData.value(), m_userProjectInfoCorrect)); + QCOMPARE(pm.isProjectCached(m_userProjectInfoIncorrect), false); +} + +void TestQtUiViewer::clearUserProjectCache() +{ + ProjectManager pm; + QVERIFY(pm.cacheProject(m_demoProjectData.value(), m_userProjectInfoCorrect)); + QVERIFY(pm.isProjectCached(m_userProjectInfoCorrect)); + + pm.clearCachedProject(m_userProjectInfoCorrect); + QCOMPARE(pm.isProjectCached(m_userProjectInfoCorrect), false); +} + +void TestQtUiViewer::clearNonExistentUserProjectCache() +{ + ProjectManager pm; + QVERIFY(!pm.isProjectCached(m_userProjectInfoIncorrect)); + pm.clearCachedProject(m_userProjectInfoIncorrect); + QCOMPARE(pm.isProjectCached(m_userProjectInfoIncorrect), false); +} + +void TestQtUiViewer::initDsConnector() +{ + DesignStudioConnector dsc; + + QTcpSocket socket; + socket.connectToHost("localhost", 40000); + + QVERIFY(socket.waitForConnected(1000)); +} + +// void TestQtUiViewer::incomingProjectTrue() +// { +// DesignStudioConnector dsc; + +// QTcpSocket socket; +// socket.connectToHost("localhost", 40000); + +// 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::\n" +// "qmlrc-end::"; +// socket.write(projectData); +// QVERIFY(socket.waitForBytesWritten(1000)); +// QThread::msleep(100); +// QCOMPARE(spy.count(), 1); +// } + +// void TestQtUiViewer::incomingProjectFalse() +// { +// DesignStudioConnector dsc; + +// QTcpSocket socket; +// socket.connectToHost("localhost", 40000); + +// 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, SIGNAL(projectIncoming())); + +// QByteArray projectData = "some arbitrary data"; +// socket.write(projectData); + +// QVERIFY(socket.waitForBytesWritten(1000)); + +// QCOMPARE(spy.count(), 0); +// } + +QTEST_MAIN(TestQtUiViewer); diff --git a/tests/tst_qtuiviewer.h b/tests/tst_qtuiviewer.h new file mode 100644 index 0000000000000000000000000000000000000000..a1dee3f0b420a9b608d8c5c614fe0853f29612f7 --- /dev/null +++ b/tests/tst_qtuiviewer.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2024 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Viewer of the Qt Toolkit. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include <QJsonArray> +#include <QJsonObject> +#include <QtTest/QTest> + +class TestQtUiViewer : public QObject +{ + Q_OBJECT +private: + std::optional<QJsonArray> m_demoProjectList; + std::optional<QByteArray> m_demoProjectData; + QJsonObject m_demoInfoCorrect; + QJsonObject m_demoInfoIncorrect; + QJsonObject m_userProjectInfoCorrect; + QJsonObject m_userProjectInfoIncorrect; + +private slots: + void initTestCase(); + + // service connector tests + void fetchDemoProjectList(); + void fetchDemoProject(); + + // project manager tests - demo project + void cacheDemoProject(); + void isDemoProjectCachedTrue(); + void isDemoProjectCachedFalse(); + void clearDemoProjectCache(); + + // project manager tests - user project + void cacheUserProject(); + void isUserProjectCachedTrue(); + void isUserProjectCachedFalse(); + void clearUserProjectCache(); + void clearNonExistentUserProjectCache(); + + // ds connector tests + void initDsConnector(); + // void incomingProjectTrue(); + // void incomingProjectFalse(); +}; diff --git a/tests/unit/tst_qtuiviewer.cpp b/tests/unit/tst_qtuiviewer.cpp deleted file mode 100644 index bf2aff2dae2ec9418e0ccbcb651177d4f0438cc2..0000000000000000000000000000000000000000 --- a/tests/unit/tst_qtuiviewer.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "tst_qtuiviewer.h" - -void TestQString::toUpper() -{ - qDebug("TestQString::toUpper"); - QString str = "Hello"; - QVERIFY(str.toUpper() == "HELLO"); -} - -void TestQString::toLower() -{ - qDebug("TestQString::toLower"); - QString str = "Hello"; - QCOMPARE(str.toLower(), "hell"); -} - -QTEST_MAIN(TestQString) diff --git a/tests/unit/tst_qtuiviewer.h b/tests/unit/tst_qtuiviewer.h deleted file mode 100644 index cffffcf03f4442c003bf1c86e5ca38b9176fcce7..0000000000000000000000000000000000000000 --- a/tests/unit/tst_qtuiviewer.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include <QtTest/QTest> - -class TestQString : public QObject -{ - Q_OBJECT -private slots: - void toUpper(); - void toLower(); -};