Terminal.Gui icon indicating copy to clipboard operation
Terminal.Gui copied to clipboard

Fixes #4102. Add AOT version of Tests

Open BDisp opened this issue 6 months ago • 15 comments

Fixes

  • Fixes #4102

Proposed Changes/Todos

  • [x] Add UnitTests.AOT project
  • [x] Add skip AOT unit tests for Moq packages due to not be AOT compatible. Our concern is only to make Terminal.Gui AOT compatible

Pull Request checklist:

  • [x] I've named my PR in the form of "Fixes #issue. Terse description."
  • [x] My code follows the style guidelines of Terminal.Gui - if you use Visual Studio, hit CTRL-K-D to automatically reformat your files before committing.
  • [x] My code follows the Terminal.Gui library design guidelines
  • [x] I ran dotnet test before commit
  • [ ] I have made corresponding changes to the API documentation (using /// style comments)
  • [x] My changes generate no new warnings
  • [x] I have checked my code and corrected any poor grammar or misspellings
  • [x] I conducted basic QA to assure all features are working

BDisp avatar Jun 07 '25 22:06 BDisp

Impressive work @BDisp!

I'm kinda blown away they pass.

tig avatar Jun 08 '25 14:06 tig

I'm getting errors trying to run UnitTests.AOT via Resharper:

Exit code is 14942208 (14:47:06.704 EROR 1: JetBrains.ReSharper.TestRunner.Application  Autofac.Core.DependencyResolutionException: An exception was thrown while activating ?:JetBrains.ReSharper.TestRunner.Implementation.IRemoteAgentEndpoint -> JetBrains.ReSharper.TestRunner.Implementation.RemoteAgentEndpoint+Connect.
 ---> Autofac.Core.DependencyResolutionException: An exception was thrown while invoking the constructor 'Void .ctor(JetBrains.Lifetimes.Lifetime, Autofac.ILifetimeScope, JetBrains.ReSharper.TestRunner.IConnectOptions, JetBrains.ReSharper.TestRunner.Implementation.Registrations, JetBrains.ReSharper.TestRunner.Abstractions.ILogger)' on type 'Connect'.
 ---> System.PlatformNotSupportedException: Dynamic code generation is not supported on this platform.
...

Test Explorer works fine. 

tig avatar Jun 09 '25 20:06 tig

@BDisp I submitted a PR to this PR:

https://github.com/BDisp/Terminal.Gui/pull/211

tig avatar Jun 09 '25 20:06 tig

Merged. Thanks.

BDisp avatar Jun 09 '25 21:06 BDisp

I'm only having fails on the IntegrationsTests with ReSharper. In Test Explorer and in the CI all passed and some skipped as flagged.

image

BDisp avatar Jun 09 '25 21:06 BDisp

The commit https://github.com/gui-cs/Terminal.Gui/pull/4134/commits/d75456e5da75abd266122b335ede936dc334ef9d allow to link the ExampleWindow.cs file created in the Example project to the NativeAot and SelfContained projects with common code. The launchSettings.json file created in the Example project is copied to all Examples projects but UICatalog which already has his own, at build time. It need to be copied because VS 2022 doesn't support linked this kind of configuration, even you force it. I also added to all Examples a status bar to confirm at runtime which OS and driver version is in use. The Example project use Application.ForceDriver = args.Length > 0 ? args [0] : string.Empty; to start with the passed driver argument and check if it's working well too. All the others projects use Application.Init (null, args.Length > 0 ? args [0] : null); to start with the passed driver argument.

BDisp avatar Jun 11 '25 11:06 BDisp

The commit d75456e allow to link the ExampleWindow.cs file created in the Example project to the NativeAot and SelfContained projects with common code. The launchSettings.json file created in the Example project is copied to all Examples projects but UICatalog which already has his own, at build time. It need to be copied because VS 2022 doesn't support linked this kind of configuration, even you force it. I also added to all Examples a status bar to confirm at runtime which OS and driver version is in use. The Example project use Application.ForceDriver = args.Length > 0 ? args [0] : string.Empty; to start with the passed driver argument and check if it's working well too. All the others projects use Application.Init (null, args.Length > 0 ? args [0] : null); to start with the passed driver argument.

I know I originally suggested that all the Examples be set to compile for AOT as well as the tests. But if we have to add a ton of complexity to the samples for that then I have changed my mind. Just making UI Catalog do it is more than enough.

It's ok for UI Catalog to have extra complexity because it IS a test as well as sample. But the others are primarily SAMPLES and should not be cluttered with things that don't let them illustrate just the bare minimum.

I think this is how we think about each project in ./Examples:

  • UI Catalog - The uber example app that shows EVERYTHING. It ALSO is an app we use for manual/user testing.
  • Example - The simplest example of how to build a TG app.
  • CommunityToolkit - Illustrates how to build a TG app using CommunityToolkit.MVVM.
  • NativeAot - A copy of Example that illustrates how to configure a TG app to build as a native AOT binary.
  • ReactiveExample - A port of Example that illustrates how to use the Reactive extensions to code a TG app.
  • SelfContained - A copy of Example that illiustrates how to build a self-contained, single file app.

I really appreciate you putting the effort in and I feel bad that you did a bunch of work that's not needed. But we need the samples to be as simple as possible to ensure new developers to the project have as simple an experience as possible.

tig avatar Jun 11 '25 12:06 tig

Due this work I found that some things was not working well. The user doesn't not have to do any of this complexity things because the linked and copied files are available as if they are part of each project. I consider important to see how the different examples projects behave in each OS and in each driver, which with only the UICatalog could not be perceptible. Of course I'll also add a UICatalog.AOT project and I think we shouldn't abandon this.

BDisp avatar Jun 11 '25 13:06 BDisp

One think I discover with this PR is the Button.Accepting event being trigger by mouse when I click on a shortcut in the StatusBar. I know that the Button isDefaultView but it wasn't clicked. Only pressing the Key.Enter should trigger the Button.Accepting event. But I'm probably be wrong and it's the behavior you want.

WindowsTerminal_HZtojjxhMm

BDisp avatar Jun 11 '25 13:06 BDisp

One think I discover with this PR is the Button.Accepting event being trigger by mouse when I click on a shortcut in the StatusBar. I know that the Button isDefaultView but it wasn't clicked. Only pressing the Key.Enter should trigger the Button.Accepting event. But I'm probably be wrong and it's the behavior you want.

Seems like a bug for sure!

I totally appreciate that playing with these samples found bugs. However, the right way to deal with those found bugs is to build a unit test that reproduces it. Adding complexity to samples that are intended to be simple is not the right way.

tig avatar Jun 11 '25 13:06 tig

Do you want I close this then?

BDisp avatar Jun 11 '25 14:06 BDisp

Do you want I close this then?

No, why?

I'm just asking you not to complexify the samples as part of this.

tig avatar Jun 11 '25 14:06 tig

The part of the launchSettings.json I agree to remove all the complexity because using the config.json works very well. So I'll remove the Application.ForceDriver and the arguments to the Application.Init method. But with the ExampleWindow.cs which are used in the 3 projects can be linked to the NativeAot and SelfContained projects. About the StatusBar added it's a simple implementation which helps a lot to confirm which OS and driver type is used at the moment. But if you insist to remove it I'll also remove that changes.

BDisp avatar Jun 11 '25 15:06 BDisp

About the StatusBar added it's a simple implementation which helps a lot to confirm which OS and driver type is used at the moment. But if you insist to remove it I'll also remove that changes.

I say remove it before we fully merge this. If it helps temporarily great.

tig avatar Jun 11 '25 17:06 tig

I'm getting errors trying to run UnitTests.AOT via Resharper:

Exit code is 14942208 (14:47:06.704 EROR 1: JetBrains.ReSharper.TestRunner.Application  Autofac.Core.DependencyResolutionException: An exception was thrown while activating ?:JetBrains.ReSharper.TestRunner.Implementation.IRemoteAgentEndpoint -> JetBrains.ReSharper.TestRunner.Implementation.RemoteAgentEndpoint+Connect.
 ---> Autofac.Core.DependencyResolutionException: An exception was thrown while invoking the constructor 'Void .ctor(JetBrains.Lifetimes.Lifetime, Autofac.ILifetimeScope, JetBrains.ReSharper.TestRunner.IConnectOptions, JetBrains.ReSharper.TestRunner.Implementation.Registrations, JetBrains.ReSharper.TestRunner.Abstractions.ILogger)' on type 'Connect'.
 ---> System.PlatformNotSupportedException: Dynamic code generation is not supported on this platform.
...

Test Explorer works fine. 

I'm also getting this error. I think JetBrains.ReSharper.TestRunner.Application Autofac.Core.DependencyResolutionException don't support native AOT. I have to search if this have any workaround.

BDisp avatar Jun 12 '25 21:06 BDisp