/*************************************************************************************************** Copyright (C) 2025 The Qt Company Ltd. SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only ***************************************************************************************************/ using System; namespace Test_Qt.DotNet.Project { [TestClass] public class Test_IncrementalBuild { private const string ProgramCs = $@" using Qt.Quick; namespace Test_IncrementalBuild {{ //REMOVE_CLASS// /* public class MyClassA {{ //PRIVATE_FUNC// private int MyPrivateFunc() => 42; //PUBLIC_FUNC// public int MyPublicFunc() => 42; }} //REMOVE_CLASS// */ //PRIVATE_CLASS// internal class MyOtherClass {{ }} //PUBLIC_CLASS// public class MyClassB {{ }} internal class Program {{ static int Main(string[] args) => 0; }} }} "; private const string MainQml = $@" import QtQuick ApplicationWindow {{ id: window; width: 220; height: 240; visible: true; title: ""Test_IncrementalBuild"" }} "; [Flags] public enum Cpp { None = 0, Cast = 1 << 0, Convert = 1 << 1, Dispatch = 1 << 2, Main = 1 << 3, MyClassA = 1 << 4, MyClassB = 1 << 5 } [TestMethod , DataRow("CleanBuild", null , Cpp.Cast | Cpp.Convert | Cpp.Dispatch | Cpp.Main | Cpp.MyClassA) , DataRow("NoChanges", "", Cpp.None) , DataRow("QmlChanged", "QML", Cpp.None) , DataRow("PrivateFunc", "PRIVATE_FUNC", Cpp.None) , DataRow("PublicFunc", "PUBLIC_FUNC", Cpp.MyClassA) , DataRow("PrivateClass", "PRIVATE_CLASS", Cpp.None) , DataRow("PublicClass", "PUBLIC_CLASS", Cpp.Cast | Cpp.Dispatch | Cpp.MyClassB) , DataRow("RemoveClass", "REMOVE_CLASS", Cpp.Cast | Cpp.Dispatch) ] public async Task IncrementalBuild(string context, string action, Cpp cppFiles) { string[] targets = [ "FindReferenceAssembliesForReferences", "CoreCompile", "QtDotNetGenerate" ]; using var temp = new TempProject(); temp.Create(new() { PackageReferences = [Packages.QtBridge] }); temp.AddFile("Program.cs", ProgramCs); temp.AddFile("Main.qml", MainQml); await temp.BuildAsync(new() { Targets = targets }); if (action != null) { switch (action) { case "": break; case "QML": temp.AddFile("Main.qml", MainQml); break; default: temp.AddFile("Program.cs", ProgramCs.Replace($"//{action}//", "")); break; } await temp.BuildAsync(new() { Targets = targets }); } temp.SaveLog(context); Assert.IsTrue(temp.Log.TryFindTarget("QtDotNetGenerate", out var target)); Action check = cppFiles.HasFlag(Cpp.Main) ? Assert.IsTrue : Assert.IsFalse; check(target.HasMessage(new(@"\bmain.cpp\b"))); check = cppFiles.HasFlag(Cpp.Convert) ? Assert.IsTrue : Assert.IsFalse; check(target.HasMessage(new(@"\bconvert.cpp\b"))); check = cppFiles.HasFlag(Cpp.Dispatch) ? Assert.IsTrue : Assert.IsFalse; check(target.HasMessage(new(@"\bobject_dispatch.cpp\b"))); check = cppFiles.HasFlag(Cpp.Cast) ? Assert.IsTrue : Assert.IsFalse; check(target.HasMessage(new(@"\btypecast.cpp\b"))); check = cppFiles.HasFlag(Cpp.MyClassA) ? Assert.IsTrue : Assert.IsFalse; check(target.HasMessage(new(@"\bmyclassa.cpp\b"))); check = cppFiles.HasFlag(Cpp.MyClassB) ? Assert.IsTrue : Assert.IsFalse; check(target.HasMessage(new(@"\bmyclassb.cpp\b"))); } } }