diff --git a/test/PatternKit.Generators.Tests/InterpreterGeneratorTests.cs b/test/PatternKit.Generators.Tests/InterpreterGeneratorTests.cs index 64e55000..ab1ce50a 100644 --- a/test/PatternKit.Generators.Tests/InterpreterGeneratorTests.cs +++ b/test/PatternKit.Generators.Tests/InterpreterGeneratorTests.cs @@ -114,6 +114,48 @@ public static partial class PricingRules ScenarioExpect.Equal("PKINT003", diagnostic.Id); } + [Scenario("Reports diagnostics for invalid interpreter rule shapes")] + [Fact] + public void ReportsDiagnosticsForInvalidInterpreterRuleShapes() + { + var source = """ + using PatternKit.Generators.Interpreter; + + namespace Demo; + + public sealed class PricingContext; + + [GenerateInterpreter(typeof(PricingContext), typeof(decimal))] + public static partial class PricingRules + { + [InterpreterTerminal(" ")] + private static decimal BlankName(string token) => 0m; + + [InterpreterTerminal("void")] + private static void VoidTerminal(string token) { } + + [InterpreterTerminal("generic")] + private static decimal GenericTerminal(string token) => 0m; + + [InterpreterTerminal("missing-parameter")] + private static decimal MissingParameter() => 0m; + + [InterpreterNonTerminal("wrong-first")] + private static decimal WrongFirst(string token) => 0m; + + [InterpreterTerminal("wrong-context")] + private static decimal WrongContext(string token, object context) => 0m; + } + """; + + var comp = CreateCompilation(source, nameof(ReportsDiagnosticsForInvalidInterpreterRuleShapes)); + var gen = new InterpreterGenerator(); + _ = RoslynTestHelpers.Run(comp, gen, out var run, out _); + + var diagnostics = run.Results.SelectMany(result => result.Diagnostics).ToArray(); + ScenarioExpect.Equal(6, diagnostics.Count(diagnostic => diagnostic.Id == "PKINT003")); + } + [Scenario("Reports diagnostic for duplicate interpreter rules")] [Fact] public void ReportsDiagnosticForDuplicateInterpreterRules() diff --git a/test/PatternKit.Generators.Tests/ObserverGeneratorTests.cs b/test/PatternKit.Generators.Tests/ObserverGeneratorTests.cs index c7788d3c..fde50b4f 100644 --- a/test/PatternKit.Generators.Tests/ObserverGeneratorTests.cs +++ b/test/PatternKit.Generators.Tests/ObserverGeneratorTests.cs @@ -1070,4 +1070,50 @@ internal partial record class DomainEvent var emit = updated.Emit(Stream.Null); ScenarioExpect.True(emit.Success, string.Join("\n", emit.Diagnostics)); } + + [Scenario("Invalid enum configuration falls back to observer defaults")] + [Fact] + public void Invalid_Enum_Configuration_Falls_Back_To_Observer_Defaults() + { + const string code = """ + using PatternKit.Generators.Observer; + + namespace Test; + + public record Payload(int Value); + + [Observer( + typeof(Payload), + Threading = (ObserverThreadingPolicy)99, + Exceptions = (ObserverExceptionPolicy)99, + Order = (ObserverOrderPolicy)99)] + internal partial class DomainEvent + { + } + """; + + var comp = RoslynTestHelpers.CreateCompilation( + code, + assemblyName: nameof(Invalid_Enum_Configuration_Falls_Back_To_Observer_Defaults)); + + var gen = new Observer.ObserverGenerator(); + _ = RoslynTestHelpers.Run(comp, gen, out var run, out var updated); + + ScenarioExpect.All(run.Results, r => ScenarioExpect.Empty(r.Diagnostics)); + + var generated = run.Results + .SelectMany(r => r.GeneratedSources) + .Single() + .SourceText.ToString(); + + ScenarioExpect.Contains("namespace Test;", generated); + ScenarioExpect.Contains("internal partial class DomainEvent", generated); + ScenarioExpect.Contains("public readonly object Lock = new();", generated); + ScenarioExpect.Contains("lock (_state.Lock)", generated); + ScenarioExpect.Contains("OnSubscriberError(ex);", generated); + ScenarioExpect.DoesNotContain("System.AggregateException", generated); + + var emit = updated.Emit(Stream.Null); + ScenarioExpect.True(emit.Success, string.Join("\n", emit.Diagnostics)); + } }