| File: Projects\AppHostCodeGenerationDiagnosticWireContractTests.cs | Web Access |
| Project: src\tests\Aspire.Cli.Tests\Aspire.Cli.Tests.csproj (Aspire.Cli.Tests) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Text.Json; using Aspire.Cli.Backchannel; using Aspire.Cli.Projects; namespace Aspire.Cli.Tests.Projects; /// <summary> /// Guards the wire contract between the AppHost server's reflection-based /// <c>SystemTextJsonFormatter</c> (default <see cref="JsonSerializerOptions"/>, no naming policy, /// PascalCase on the wire) and the CLI source-generated /// <see cref="BackchannelJsonSerializerContext"/>. If either side adopts a naming policy or /// renames a property, this test must catch it before the diagnostic silently degrades to /// "all null" on the CLI as in issue #16709. /// </summary> public class AppHostCodeGenerationDiagnosticWireContractTests { [Fact] public void Deserialize_PascalCaseServerPayload_PopulatesAllFields() { const string serverJson = """ { "OriginalExceptionType": "System.TypeLoadException", "TypeName": "Aspire.Hosting.SomeType", "MemberName": "Void Foo()", "RuntimeAspireHostingVersion": "13.4.0-preview.1.26218.1", "RuntimeAspireHostingPath": "C:\\aspire\\Aspire.Hosting.dll", "LoadedAssemblies": [ { "Name": "Aspire.Hosting.CodeGeneration.TypeScript", "InformationalVersion": "13.4.0-preview.1.26227.1", "Location": "C:\\aspire\\Aspire.Hosting.CodeGeneration.TypeScript.dll" } ], "RemediationHint": "Run 'aspire update'." } """; var diagnostic = JsonSerializer.Deserialize( serverJson, BackchannelJsonSerializerContext.Default.AppHostCodeGenerationDiagnostic); Assert.NotNull(diagnostic); Assert.Equal("System.TypeLoadException", diagnostic.OriginalExceptionType); Assert.Equal("Aspire.Hosting.SomeType", diagnostic.TypeName); Assert.Equal("Void Foo()", diagnostic.MemberName); Assert.Equal("13.4.0-preview.1.26218.1", diagnostic.RuntimeAspireHostingVersion); Assert.Equal("C:\\aspire\\Aspire.Hosting.dll", diagnostic.RuntimeAspireHostingPath); Assert.Equal("Run 'aspire update'.", diagnostic.RemediationHint); var loaded = Assert.Single(diagnostic.LoadedAssemblies); Assert.Equal("Aspire.Hosting.CodeGeneration.TypeScript", loaded.Name); Assert.Equal("13.4.0-preview.1.26227.1", loaded.InformationalVersion); Assert.Equal("C:\\aspire\\Aspire.Hosting.CodeGeneration.TypeScript.dll", loaded.Location); } [Fact] public void Roundtrip_UsingRpcFormatterOptions_PreservesAllFields() { // Use the exact same JsonSerializerOptions the StreamJsonRpc formatter uses on the CLI // side. This catches the case where the wire-level deserializer differs from the typed // JsonTypeInfo<T> deserializer used by TryReadDiagnostic. var options = BackchannelJsonSerializerContext.CreateJsonSerializerOptions(); var source = new AppHostCodeGenerationDiagnostic { OriginalExceptionType = "System.TypeLoadException", TypeName = "Aspire.Hosting.SomeType", MemberName = "Void Foo()", RuntimeAspireHostingVersion = "13.4.0-preview.1.26218.1", RuntimeAspireHostingPath = "/aspire/Aspire.Hosting.dll", LoadedAssemblies = [ new AppHostLoadedAssemblyInfo { Name = "Aspire.Hosting.CodeGeneration.TypeScript", InformationalVersion = "13.4.0-preview.1.26227.1", Location = "/aspire/Aspire.Hosting.CodeGeneration.TypeScript.dll" } ], RemediationHint = "Run 'aspire update'." }; var json = JsonSerializer.Serialize(source, typeof(AppHostCodeGenerationDiagnostic), options); var roundtripped = (AppHostCodeGenerationDiagnostic?)JsonSerializer.Deserialize(json, typeof(AppHostCodeGenerationDiagnostic), options); Assert.NotNull(roundtripped); Assert.Equal(source.OriginalExceptionType, roundtripped.OriginalExceptionType); Assert.Equal(source.TypeName, roundtripped.TypeName); Assert.Equal(source.MemberName, roundtripped.MemberName); Assert.Equal(source.RuntimeAspireHostingVersion, roundtripped.RuntimeAspireHostingVersion); Assert.Equal(source.RemediationHint, roundtripped.RemediationHint); var loaded = Assert.Single(roundtripped.LoadedAssemblies); Assert.Equal(source.LoadedAssemblies[0].Name, loaded.Name); Assert.Equal(source.LoadedAssemblies[0].InformationalVersion, loaded.InformationalVersion); } }