b211911f98
v2-ci / unit-tests (push) Failing after 13m22s
Akka.TestKit.Xunit2 -> Akka.TestKit.Xunit 1.5.62 (xunit.v3 TestKit; needs xunit.v3 3.2.2, set via VersionOverride on the four projects). Removes the xunit 2.9.3 pin. IAsyncLifetime returns ValueTask, SqlServerFactAttribute gains the source-info ctor, and xUnit1051 call sites pass TestContext.Current.CancellationToken. Test counts unchanged. Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
59 lines
2.8 KiB
C#
59 lines
2.8 KiB
C#
using Microsoft.CodeAnalysis;
|
|
using Shouldly;
|
|
using Xunit;
|
|
using ZB.MOM.WW.OtOpcUa.AdminUI.ScriptAnalysis;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.ScriptAnalysis;
|
|
|
|
/// <summary>
|
|
/// R04:P2 — the editor used to build a brand-new <c>CSharpCompilation</c> (and re-bind the whole sandbox
|
|
/// reference set) on every completion / hover / signature-help / diagnostics request. Each analysis now
|
|
/// derives from ONE process-wide base compilation via <c>ReplaceSyntaxTree</c>, so the referenced-assembly
|
|
/// binding is done once and shared.
|
|
/// </summary>
|
|
public sealed class AnalysisCompilationReuseTests
|
|
{
|
|
[Fact]
|
|
public void Two_services_share_the_bound_reference_set()
|
|
{
|
|
// Two separate scopes (two HTTP requests) analysing different sources.
|
|
var c1 = new ScriptAnalysisService().CompilationFor("return 1;");
|
|
var c2 = new ScriptAnalysisService().CompilationFor("return 2;");
|
|
|
|
// Positive control: the two compilations really carry different user sources.
|
|
c1.SyntaxTrees.Single().ToString().ShouldContain("return 1;");
|
|
c2.SyntaxTrees.Single().ToString().ShouldContain("return 2;");
|
|
c1.ShouldNotBeSameAs(c2);
|
|
|
|
// Derived from one bound base: the corlib symbol is the SAME instance, not a re-bound copy.
|
|
c1.GetSpecialType(SpecialType.System_Object)
|
|
.ShouldBeSameAs(c2.GetSpecialType(SpecialType.System_Object));
|
|
c1.GetSpecialType(SpecialType.System_Object)
|
|
.ShouldBeSameAs(ScriptAnalysisService.BaseCompilation.GetSpecialType(SpecialType.System_Object));
|
|
}
|
|
|
|
[Fact]
|
|
public void Repeated_analysis_in_one_scope_replaces_the_tree_rather_than_adding_one()
|
|
{
|
|
var svc = new ScriptAnalysisService();
|
|
svc.CompilationFor("return 1;");
|
|
var second = svc.CompilationFor("return 2;");
|
|
|
|
second.SyntaxTrees.Count().ShouldBe(1);
|
|
second.SyntaxTrees.Single().ToString().ShouldContain("return 2;");
|
|
second.SyntaxTrees.Single().ToString().ShouldNotContain("return 1;");
|
|
}
|
|
|
|
[Fact]
|
|
public void Diagnostics_are_unchanged_by_reuse()
|
|
{
|
|
// A clean script stays clean and an error stays an error across interleaved analyses on one service
|
|
// — a stale tree leaking from the previous call would surface here.
|
|
var svc = new ScriptAnalysisService();
|
|
svc.Diagnose(new DiagnoseRequest("return ctx.Nope();"), TestContext.Current.CancellationToken).Markers.ShouldContain(m => m.Severity == 8);
|
|
svc.Diagnose(new DiagnoseRequest("""return (double)ctx.GetTag("A").Value * 2.0;"""), TestContext.Current.CancellationToken).Markers.ShouldBeEmpty();
|
|
svc.Diagnose(new DiagnoseRequest("var a = 1;\nreturn ctx.Nope();"), TestContext.Current.CancellationToken).Markers
|
|
.ShouldContain(m => m.Severity == 8 && m.StartLineNumber == 2);
|
|
}
|
|
}
|