/*************************************************************************************************** Copyright (C) 2025 The Qt Company Ltd. SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-3.0-only ***************************************************************************************************/ using System; using System.Text; namespace Test_Qt.DotNet.Project.Shared { /// /// Mirror of the native BridgeExitCode enum in QtTestSetupBase.h. Keep numeric values in /// sync with the C++ definition. /// enum ExitCode { Ok = 0, QTestFailure = 1, // QTest will return 1 on test failure LocateAssemblyFailed = 101, WaitForReadyExitedEarly = 102, WaitForReadyTimeout = 103, InitAdapterFailed = 104, FinalizeNotExited = 105, FinalizeFailed = 106 }; internal static class ExitCodeHelper { /// /// Returns a friendly description for bridge-specific exit codes (>= 100). /// public static string ToString(int exitCode) { if (!Enum.IsDefined(typeof(ExitCode), exitCode)) return $"Failed with unknown error, exit({exitCode})"; var code = (ExitCode)exitCode; if (code is ExitCode.Ok or ExitCode.QTestFailure) return ""; // 0 = OK, 1 = QTest failures return code switch { ExitCode.LocateAssemblyFailed => "Failed to locate the generated .NET test assembly", ExitCode.WaitForReadyExitedEarly => "Host process exited before the .NET app signaled readiness", ExitCode.WaitForReadyTimeout => "Timeout while waiting for the .NET app to signal readiness", ExitCode.InitAdapterFailed => "Failed to initialize the Qt/.NET adapter", ExitCode.FinalizeNotExited => "Finalize requested, but the .NET app did not exit in time", ExitCode.FinalizeFailed => "Failed while finalizing the .NET app / adapter", _ => code.ToString() }; } } /// /// Provides shared helpers for building and running temporary Qt/.NET native test projects. /// public abstract class ManagedTestBase { /// /// Creates the temp project, applies the given options, runs a build, saves the log /// and asserts that the build succeeded. /// protected async Task InitializeAndBuildAsync( TempProject temp, CreationOptions options, Action configure = null) { ArgumentNullException.ThrowIfNull(temp); options ??= new(); temp.Create(options); configure?.Invoke(temp); var build = await temp.BuildAsync(); temp.SaveLog(); Assert.IsTrue(build.Ok, build.Output); } /// /// Default options for a QtQuickTest native project (QtQuickTest harness). /// The is the path (relative to the test bin dir) /// where your main.cpp template lives, e.g. QtQuickTest\main.cpp. /// protected static CreationOptions CreateQtQuickTestOptions(string mainCppTarget) { return new CreationOptions { PackageReferences = [Packages.QtBridge], ReplaceGeneratedFiles = [ // main.cpp from test project -> generated native source (@"source\cpp\main.cpp", mainCppTarget), // shared helper headers/sources (@"source\hpp\QtTestSetupBase.h", @"Shared\QtTestSetupBase.h"), (@"source\hpp\QtQuickTestSetup.h", @"Shared\QtQuickTestSetup.h"), (@"source\cpp\QtQuickTestSetup.cpp", @"Shared\QtQuickTestSetup.cpp"), ], // Inject extra sources into CMakeLists.txt AfterSdkTargets = CMake.InjectQtSourcesTargets( "hpp/QtTestSetupBase.h", "hpp/QtQuickTestSetup.h", "cpp/QtQuickTestSetup.cpp") }; } /// /// Default options for a QtTest native project (QtTest harness). /// The is the path (relative to the test bin dir) /// where your main.cpp template lives, e.g. QtTest\main.cpp. /// protected static CreationOptions CreateQtTestOptions(string mainCppTarget) { return new CreationOptions { PackageReferences = [Packages.QtBridge], ReplaceGeneratedFiles = [ (@"source\cpp\main.cpp", mainCppTarget), (@"source\hpp\QtTestSetupBase.h", @"Shared\QtTestSetupBase.h"), ], AfterSdkTargets = CMake.InjectQtSourcesTargets("hpp/QtTestSetupBase.h") }; } } }