Compare commits
8
Commits
main
..
0d37751d8c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d37751d8c | ||
|
|
ba8479fa8d | ||
|
|
50073e010f | ||
|
|
d79dcac3b3 | ||
|
|
7aadf4212e | ||
|
|
e2e243ad26 | ||
|
|
41d9ef4b7a | ||
|
|
a37fc2255f |
No files matched your search
Vendored
+96
-117
@@ -1,5 +1,10 @@
|
|||||||
pipeline {
|
pipeline {
|
||||||
agent none
|
agent {
|
||||||
|
docker {
|
||||||
|
image 'lifemaps/ci-cpp:latest'
|
||||||
|
reuseNode true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
options {
|
options {
|
||||||
timestamps()
|
timestamps()
|
||||||
@@ -14,133 +19,106 @@ pipeline {
|
|||||||
QT_QPA_PLATFORM = "offscreen"
|
QT_QPA_PLATFORM = "offscreen"
|
||||||
LANG = "C.UTF-8"
|
LANG = "C.UTF-8"
|
||||||
LC_ALL = "C.UTF-8"
|
LC_ALL = "C.UTF-8"
|
||||||
DOCKER_IMAGE = "lifemaps/ci-cpp:latest"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stages {
|
stages {
|
||||||
stage('Docker Image') {
|
stage('Cleanup') {
|
||||||
agent any
|
|
||||||
steps {
|
steps {
|
||||||
script {
|
script {
|
||||||
echo "Checking if Docker image exists locally..."
|
echo "Cleaning workspace to avoid corruption issues..."
|
||||||
def imageExists = sh(script: "docker inspect ${DOCKER_IMAGE} >/dev/null 2>&1", returnStatus: true) == 0
|
// Use shell command with chmod to handle permission issues
|
||||||
if (!imageExists) {
|
sh '''
|
||||||
echo "Docker image not found. Building from ci/Dockerfile.ci..."
|
if [ -d "${WORKSPACE}/${BUILD_DIR}" ]; then
|
||||||
sh 'docker build -t ${DOCKER_IMAGE} -f ci/Dockerfile.ci .'
|
echo "Removing build directory with permission fix..."
|
||||||
} else {
|
chmod -R u+w "${WORKSPACE}/${BUILD_DIR}" 2>/dev/null || true
|
||||||
echo "Docker image ${DOCKER_IMAGE} found locally."
|
rm -rf "${WORKSPACE}/${BUILD_DIR}"
|
||||||
}
|
fi
|
||||||
|
if [ -d "${WORKSPACE}/${COVERAGE_BUILD_DIR}" ]; then
|
||||||
|
echo "Removing coverage build directory..."
|
||||||
|
chmod -R u+w "${WORKSPACE}/${COVERAGE_BUILD_DIR}" 2>/dev/null || true
|
||||||
|
rm -rf "${WORKSPACE}/${COVERAGE_BUILD_DIR}"
|
||||||
|
fi
|
||||||
|
if [ -d "${WORKSPACE}/coverage" ]; then
|
||||||
|
echo "Removing coverage output directory..."
|
||||||
|
chmod -R u+w "${WORKSPACE}/coverage" 2>/dev/null || true
|
||||||
|
rm -rf "${WORKSPACE}/coverage"
|
||||||
|
fi
|
||||||
|
'''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stage('Build and Test') {
|
stage('Checkout') {
|
||||||
agent {
|
steps {
|
||||||
docker {
|
checkout scm
|
||||||
image 'lifemaps/ci-cpp:latest'
|
sh 'git fetch --all --prune'
|
||||||
reuseNode true
|
sh 'git submodule update --init --recursive || true'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Tool Versions') {
|
||||||
|
steps {
|
||||||
|
sh '''
|
||||||
|
python3 --version
|
||||||
|
cmake --version
|
||||||
|
ninja --version
|
||||||
|
g++ --version
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Qt Diagnostics') {
|
||||||
|
steps {
|
||||||
|
sh '''
|
||||||
|
echo "QT_QPA_PLATFORM=$QT_QPA_PLATFORM"
|
||||||
|
echo "LANG=$LANG"
|
||||||
|
echo "LC_ALL=$LC_ALL"
|
||||||
|
dpkg -l | grep -E "qt6-base-dev|qtbase5-dev|qt6-tools" || true
|
||||||
|
pkg-config --list-all | grep -i qt || true
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Policy Checks') {
|
||||||
|
steps {
|
||||||
|
sh 'python3 ci/check_pr_policies.py'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Configure') {
|
||||||
|
steps {
|
||||||
|
sh 'cmake -S ${PROJECT_DIR} -B ${BUILD_DIR} -G Ninja -DCMAKE_BUILD_TYPE=Debug'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Build') {
|
||||||
|
steps {
|
||||||
|
sh 'cmake --build ${BUILD_DIR} --parallel'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Test') {
|
||||||
|
steps {
|
||||||
|
sh 'QT_QPA_PLATFORM=offscreen LANG=C.UTF-8 LC_ALL=C.UTF-8 ctest --test-dir ${BUILD_DIR} --output-on-failure'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Coverage') {
|
||||||
|
when {
|
||||||
|
expression {
|
||||||
|
return env.BRANCH_NAME ==~ /main|master|coverage.*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stages {
|
steps {
|
||||||
stage('Cleanup') {
|
echo "Running coverage collection..."
|
||||||
steps {
|
sh '''
|
||||||
script {
|
${PROJECT_DIR}/scripts/collect-coverage.sh ${WORKSPACE}/${COVERAGE_BUILD_DIR}
|
||||||
echo "Cleaning workspace to avoid corruption issues..."
|
'''
|
||||||
sh '''
|
}
|
||||||
if [ -d "${WORKSPACE}/${BUILD_DIR}" ]; then
|
post {
|
||||||
echo "Removing build directory with permission fix..."
|
always {
|
||||||
chmod -R u+w "${WORKSPACE}/${BUILD_DIR}" 2>/dev/null || true
|
publishCoverage adapters: [lcovAdapter(mergeToOneReport: true, reportFile: 'coverage/lcov.info')],
|
||||||
rm -rf "${WORKSPACE}/${BUILD_DIR}"
|
sourceFileResolver: sourceFiles('STORE_LAST_BUILD')
|
||||||
fi
|
|
||||||
if [ -d "${WORKSPACE}/${COVERAGE_BUILD_DIR}" ]; then
|
|
||||||
echo "Removing coverage build directory..."
|
|
||||||
chmod -R u+w "${WORKSPACE}/${COVERAGE_BUILD_DIR}" 2>/dev/null || true
|
|
||||||
rm -rf "${WORKSPACE}/${COVERAGE_BUILD_DIR}"
|
|
||||||
fi
|
|
||||||
if [ -d "${WORKSPACE}/coverage" ]; then
|
|
||||||
echo "Removing coverage output directory..."
|
|
||||||
chmod -R u+w "${WORKSPACE}/coverage" 2>/dev/null || true
|
|
||||||
rm -rf "${WORKSPACE}/coverage"
|
|
||||||
fi
|
|
||||||
'''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Checkout') {
|
|
||||||
steps {
|
|
||||||
checkout scm
|
|
||||||
sh 'git fetch --all --prune'
|
|
||||||
sh 'git submodule update --init --recursive || true'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Tool Versions') {
|
|
||||||
steps {
|
|
||||||
sh '''
|
|
||||||
python3 --version
|
|
||||||
cmake --version
|
|
||||||
ninja --version
|
|
||||||
g++ --version
|
|
||||||
'''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Qt Diagnostics') {
|
|
||||||
steps {
|
|
||||||
sh '''
|
|
||||||
echo "QT_QPA_PLATFORM=$QT_QPA_PLATFORM"
|
|
||||||
echo "LANG=$LANG"
|
|
||||||
echo "LC_ALL=$LC_ALL"
|
|
||||||
dpkg -l | grep -E "qt6-base-dev|qtbase5-dev|qt6-tools" || true
|
|
||||||
pkg-config --list-all | grep -i qt || true
|
|
||||||
'''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Policy Checks') {
|
|
||||||
steps {
|
|
||||||
sh 'python3 ci/check_pr_policies.py'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Configure') {
|
|
||||||
steps {
|
|
||||||
sh 'cmake -S ${PROJECT_DIR} -B ${BUILD_DIR} -G Ninja -DCMAKE_BUILD_TYPE=Debug'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Build') {
|
|
||||||
steps {
|
|
||||||
sh 'cmake --build ${BUILD_DIR} --parallel'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Test') {
|
|
||||||
steps {
|
|
||||||
sh 'QT_QPA_PLATFORM=offscreen LANG=C.UTF-8 LC_ALL=C.UTF-8 ctest --test-dir ${BUILD_DIR} --output-on-failure'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Coverage') {
|
|
||||||
when {
|
|
||||||
expression {
|
|
||||||
def branch = env.CHANGE_BRANCH ?: env.BRANCH_NAME
|
|
||||||
return branch ==~ /main|master|coverage.*|feature.*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
steps {
|
|
||||||
echo "Running coverage collection..."
|
|
||||||
sh '''
|
|
||||||
${PROJECT_DIR}/scripts/collect-coverage.sh ${WORKSPACE}/${COVERAGE_BUILD_DIR}
|
|
||||||
'''
|
|
||||||
}
|
|
||||||
post {
|
|
||||||
always {
|
|
||||||
recordCoverage tools: [[parser: 'LCOV', pattern: "${PROJECT_DIR}/coverage/lcov.info"]],
|
|
||||||
sourceCodeRetention: 'LAST_BUILD'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,6 +128,7 @@ pipeline {
|
|||||||
always {
|
always {
|
||||||
script {
|
script {
|
||||||
if (getContext(hudson.FilePath)) {
|
if (getContext(hudson.FilePath)) {
|
||||||
|
// Use shell command with chmod to handle permission issues
|
||||||
sh '''
|
sh '''
|
||||||
if [ -d "${WORKSPACE}/${BUILD_DIR}" ]; then
|
if [ -d "${WORKSPACE}/${BUILD_DIR}" ]; then
|
||||||
echo "Final cleanup: Removing build directory..."
|
echo "Final cleanup: Removing build directory..."
|
||||||
|
|||||||
+5
-4
@@ -2,9 +2,9 @@ FROM ubuntu:26.04
|
|||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
# Create jenkins user (UID 1001 to avoid conflicts with existing users)
|
# Create jenkins user with same UID as host jenkins (typically 1000)
|
||||||
RUN groupadd -g 1001 jenkins && \
|
RUN groupadd -g 1000 jenkins && \
|
||||||
useradd -u 1001 -g 1001 -m -s /bin/bash jenkins
|
useradd -u 1000 -g 1000 -m -s /bin/bash jenkins
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y --no-install-recommends \
|
apt-get install -y --no-install-recommends \
|
||||||
@@ -23,7 +23,8 @@ RUN apt-get update && \
|
|||||||
qt6-base-dev-tools \
|
qt6-base-dev-tools \
|
||||||
qt6-tools-dev \
|
qt6-tools-dev \
|
||||||
qt6-tools-dev-tools \
|
qt6-tools-dev-tools \
|
||||||
lcov && \
|
lcov \
|
||||||
|
genhtml && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Set Qt platform for headless testing
|
# Set Qt platform for headless testing
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ enable_testing()
|
|||||||
|
|
||||||
# Add test executable
|
# Add test executable
|
||||||
add_executable(Qt6MigratedBenchmarkTest
|
add_executable(Qt6MigratedBenchmarkTest
|
||||||
|
tests/test_main.cpp
|
||||||
tests/test_mainwindow.cpp
|
tests/test_mainwindow.cpp
|
||||||
MainWindow.h
|
MainWindow.h
|
||||||
MainWindow.cpp
|
MainWindow.cpp
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ lcov --remove "${COVERAGE_DIR}/coverage.info" \
|
|||||||
'*/Qt6/*' \
|
'*/Qt6/*' \
|
||||||
'*/qt6-migrated-benchmark/tests/*' \
|
'*/qt6-migrated-benchmark/tests/*' \
|
||||||
--output-file "${COVERAGE_DIR}/coverage.filtered.info" \
|
--output-file "${COVERAGE_DIR}/coverage.filtered.info" \
|
||||||
--ignore-errors mismatch,unused \
|
--ignore-errors mismatch \
|
||||||
--rc lcov_branch_coverage=1
|
--rc lcov_branch_coverage=1
|
||||||
|
|
||||||
# Generate HTML report
|
# Generate HTML report
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
#include <QtTest/QtTest>
|
||||||
|
|
||||||
|
class TestMainWindow : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void testValidateInputValid();
|
||||||
|
void testValidateInputInvalid();
|
||||||
|
void testValidateInputEmpty();
|
||||||
|
void testValidateInputMixedCase();
|
||||||
|
};
|
||||||
|
|
||||||
|
void TestMainWindow::testValidateInputValid()
|
||||||
|
{
|
||||||
|
// Test valid input patterns
|
||||||
|
QRegularExpression pattern(R"(^[A-Za-z]+\d+$)");
|
||||||
|
|
||||||
|
QVERIFY(pattern.match("Test123").hasMatch());
|
||||||
|
QVERIFY(pattern.match("abc456").hasMatch());
|
||||||
|
QVERIFY(pattern.match("ABC789").hasMatch());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestMainWindow::testValidateInputInvalid()
|
||||||
|
{
|
||||||
|
// Test invalid input patterns
|
||||||
|
QRegularExpression pattern(R"(^[A-Za-z]+\d+$)");
|
||||||
|
|
||||||
|
QVERIFY(!pattern.match("123Test").hasMatch());
|
||||||
|
QVERIFY(!pattern.match("Test").hasMatch());
|
||||||
|
QVERIFY(!pattern.match("123").hasMatch());
|
||||||
|
QVERIFY(!pattern.match("Test123ABC").hasMatch());
|
||||||
|
QVERIFY(!pattern.match("Test-123").hasMatch());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestMainWindow::testValidateInputEmpty()
|
||||||
|
{
|
||||||
|
QRegularExpression pattern(R"(^[A-Za-z]+\d+$)");
|
||||||
|
QVERIFY(!pattern.match("").hasMatch());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestMainWindow::testValidateInputMixedCase()
|
||||||
|
{
|
||||||
|
QRegularExpression pattern(R"(^[A-Za-z]+\d+$)");
|
||||||
|
|
||||||
|
QVERIFY(pattern.match("TeSt123").hasMatch());
|
||||||
|
QVERIFY(pattern.match("aBcDeF999").hasMatch());
|
||||||
|
}
|
||||||
|
|
||||||
|
QTEST_MAIN(TestMainWindow)
|
||||||
|
|
||||||
|
#include "test_main.moc"
|
||||||
@@ -1,88 +1,49 @@
|
|||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
#include <QtTest/QtTest>
|
#include <QtTest/QtTest>
|
||||||
|
|
||||||
class TestMainWindow : public QObject
|
class TestMainWindowWidget : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void testValidateInputValid();
|
|
||||||
void testValidateInputInvalid();
|
|
||||||
void testValidateInputEmpty();
|
|
||||||
void testValidateInputMixedCase();
|
|
||||||
void testMainWindowCreation();
|
void testMainWindowCreation();
|
||||||
void testWindowTitle();
|
void testWindowTitle();
|
||||||
void testValidateInputMethod();
|
void testValidateInputMethod();
|
||||||
void testGetScreenInfo();
|
void testGetScreenInfo();
|
||||||
};
|
};
|
||||||
|
|
||||||
void TestMainWindow::testValidateInputValid()
|
void TestMainWindowWidget::testMainWindowCreation()
|
||||||
{
|
|
||||||
// Test valid input patterns
|
|
||||||
QRegularExpression pattern(R"(^[A-Za-z]+\d+$)");
|
|
||||||
|
|
||||||
QVERIFY(pattern.match("Test123").hasMatch());
|
|
||||||
QVERIFY(pattern.match("abc456").hasMatch());
|
|
||||||
QVERIFY(pattern.match("ABC789").hasMatch());
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestMainWindow::testValidateInputInvalid()
|
|
||||||
{
|
|
||||||
// Test invalid input patterns
|
|
||||||
QRegularExpression pattern(R"(^[A-Za-z]+\d+$)");
|
|
||||||
|
|
||||||
QVERIFY(!pattern.match("123Test").hasMatch());
|
|
||||||
QVERIFY(!pattern.match("Test").hasMatch());
|
|
||||||
QVERIFY(!pattern.match("123").hasMatch());
|
|
||||||
QVERIFY(!pattern.match("Test123ABC").hasMatch());
|
|
||||||
QVERIFY(!pattern.match("Test-123").hasMatch());
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestMainWindow::testValidateInputEmpty()
|
|
||||||
{
|
|
||||||
QRegularExpression pattern(R"(^[A-Za-z]+\d+$)");
|
|
||||||
QVERIFY(!pattern.match("").hasMatch());
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestMainWindow::testValidateInputMixedCase()
|
|
||||||
{
|
|
||||||
QRegularExpression pattern(R"(^[A-Za-z]+\d+$)");
|
|
||||||
|
|
||||||
QVERIFY(pattern.match("TeSt123").hasMatch());
|
|
||||||
QVERIFY(pattern.match("aBcDeF999").hasMatch());
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestMainWindow::testMainWindowCreation()
|
|
||||||
{
|
{
|
||||||
MainWindow window;
|
MainWindow window;
|
||||||
QVERIFY(!window.windowTitle().isEmpty());
|
QVERIFY(!window.windowTitle().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestMainWindow::testWindowTitle()
|
void TestMainWindowWidget::testWindowTitle()
|
||||||
{
|
{
|
||||||
MainWindow window;
|
MainWindow window;
|
||||||
QCOMPARE(window.windowTitle(), QStringLiteral("Qt6 Legacy Migration Benchmark"));
|
QCOMPARE(window.windowTitle(), u"Qt6 Legacy Migration Benchmark"_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestMainWindow::testValidateInputMethod()
|
void TestMainWindowWidget::testValidateInputMethod()
|
||||||
{
|
{
|
||||||
MainWindow window;
|
MainWindow window;
|
||||||
|
|
||||||
QVERIFY(window.validateInput(QStringLiteral("Test123")));
|
QVERIFY(window.validateInput(u"Test123"_s));
|
||||||
QVERIFY(window.validateInput(QStringLiteral("abc456")));
|
QVERIFY(window.validateInput(u"abc456"_s));
|
||||||
QVERIFY(!window.validateInput(QStringLiteral("123Test")));
|
QVERIFY(!window.validateInput(u"123Test"_s));
|
||||||
QVERIFY(!window.validateInput(QStringLiteral("")));
|
QVERIFY(!window.validateInput(u""_s));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestMainWindow::testGetScreenInfo()
|
void TestMainWindowWidget::testGetScreenInfo()
|
||||||
{
|
{
|
||||||
MainWindow window;
|
MainWindow window;
|
||||||
QString info = window.getScreenInfo();
|
QString info = window.getScreenInfo();
|
||||||
QVERIFY(!info.isEmpty());
|
QVERIFY(!info.isEmpty());
|
||||||
QVERIFY(info.contains(QStringLiteral("Screen:")));
|
QVERIFY(info.contains(u"Screen:"_s));
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_MAIN(TestMainWindow)
|
QTEST_MAIN(TestMainWindowWidget)
|
||||||
|
|
||||||
#include "test_mainwindow.moc"
|
#include "test_mainwindow.moc"
|
||||||
Reference in new issue
Block a user