From b2fdd9c8419b0275356fdbf4cd5c41fc7bfe3a9d Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Wed, 4 Mar 2026 19:41:14 +0100 Subject: [PATCH] Remove Initialize calls and add AddStatement tests --- YesNt.CodeEditor/Editor.cs | 1 - YesNt.Interpreter.App/Program.cs | 1 - YesNt.Interpreter.Tests/AddStatementTests.cs | 220 ++++++++++++++++++ .../ConsoleStatementsTests.cs | 3 +- YesNt.Interpreter.Tests/YesNtAssert.cs | 23 +- YesNt.Interpreter/Program.cs | 1 - YesNt.Interpreter/Runtime/YesNtInterpreter.cs | 14 +- .../Statements/ProcessingStatements.cs | 3 +- 8 files changed, 250 insertions(+), 16 deletions(-) create mode 100644 YesNt.Interpreter.Tests/AddStatementTests.cs diff --git a/YesNt.CodeEditor/Editor.cs b/YesNt.CodeEditor/Editor.cs index f2b2973..6bd5b21 100644 --- a/YesNt.CodeEditor/Editor.cs +++ b/YesNt.CodeEditor/Editor.cs @@ -32,7 +32,6 @@ internal class TextEditor public TextEditor() { - YesNtInterpreter.Initialize(); YesNtInterpreter.OnDebugOutput += YesNtInterpreter_OnDebugOutput; YesNtInterpreter.OnLineExecuted += YesNtInterpreter_OnLineExecuted; syntaxHighlighter = new(YesNtInterpreter.StatementInformation); diff --git a/YesNt.Interpreter.App/Program.cs b/YesNt.Interpreter.App/Program.cs index 61311f7..ccd2ec9 100644 --- a/YesNt.Interpreter.App/Program.cs +++ b/YesNt.Interpreter.App/Program.cs @@ -5,7 +5,6 @@ using YesNt.Interpreter.Runtime; if (args.Length == 1) { YesNtInterpreter interpreter = new YesNtInterpreter(); - interpreter.Initialize(); interpreter.Execute(args[0]); } else diff --git a/YesNt.Interpreter.Tests/AddStatementTests.cs b/YesNt.Interpreter.Tests/AddStatementTests.cs new file mode 100644 index 0000000..6b4f6cd --- /dev/null +++ b/YesNt.Interpreter.Tests/AddStatementTests.cs @@ -0,0 +1,220 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +using System.Collections.Generic; + +using YesNt.Interpreter.Attributes; +using YesNt.Interpreter.Enums; +using YesNt.Interpreter.Runtime; + +namespace YesNt.Interpreter.Tests; + +[TestClass] +public class AddStatementTests +{ + [TestMethod] + public void AddStatementStartOfLineExecutesHandlerTest() + { + List lines = + [ + "my_command hello" + ]; + + string? capturedArgs = null; + + YesNtAssert.GetLastLineWithSetup(lines, interpreter => + { + interpreter.AddStatement("my_command", SearchMode.StartOfLine, SpaceAround.End, args => + { + capturedArgs = args; + }); + }); + + Assert.AreEqual("hello", capturedArgs); + } + + [TestMethod] + public void AddStatementConvenienceOverloadHandlerIsCalledTest() + { + List lines = + [ + "custom_cmd world" + ]; + + bool handlerCalled = false; + + YesNtAssert.GetLastLineWithSetup(lines, interpreter => + { + interpreter.AddStatement("custom_cmd", SearchMode.StartOfLine, SpaceAround.End, _ => + { + handlerCalled = true; + }); + }); + + Assert.IsTrue(handlerCalled); + } + + [TestMethod] + public void AddStatementAttributeOverloadHandlerIsCalledTest() + { + List lines = + [ + "attr_cmd test" + ]; + + bool handlerCalled = false; + + YesNtAssert.GetLastLineWithSetup(lines, interpreter => + { + var attr = new StatementAttribute("attr_cmd", SearchMode.StartOfLine, SpaceAround.End); + interpreter.AddStatement(attr, _ => + { + handlerCalled = true; + }); + }); + + Assert.IsTrue(handlerCalled); + } + + [TestMethod] + public void AddStatementExactSearchModeTest() + { + List lines = + [ + "exact_cmd" + ]; + + bool handlerCalled = false; + + YesNtAssert.GetLastLineWithSetup(lines, interpreter => + { + interpreter.AddStatement("exact_cmd", SearchMode.Exact, SpaceAround.None, _ => + { + handlerCalled = true; + }); + }); + + Assert.IsTrue(handlerCalled); + } + + [TestMethod] + public void AddStatementContainsSearchModeTest() + { + List lines = + [ + "prefix ~mark~ suffix" + ]; + + bool handlerCalled = false; + + YesNtAssert.GetLastLineWithSetup(lines, interpreter => + { + interpreter.AddStatement(" ~mark~ ", SearchMode.Contains, SpaceAround.None, _ => + { + handlerCalled = true; + }); + }); + + Assert.IsTrue(handlerCalled); + } + + [TestMethod] + public void AddStatementEndOfLineSearchModeTest() + { + List lines = + [ + "some text !end" + ]; + + bool handlerCalled = false; + + YesNtAssert.GetLastLineWithSetup(lines, interpreter => + { + interpreter.AddStatement(" !end", SearchMode.EndOfLine, SpaceAround.None, _ => + { + handlerCalled = true; + }); + }); + + Assert.IsTrue(handlerCalled); + } + + [TestMethod] + public void AddStatementReceivesCorrectArgsTest() + { + List lines = + [ + "capture_cmd the quick brown fox" + ]; + + string? capturedArgs = null; + + YesNtAssert.GetLastLineWithSetup(lines, interpreter => + { + interpreter.AddStatement("capture_cmd", SearchMode.StartOfLine, SpaceAround.End, args => + { + capturedArgs = args; + }); + }); + + Assert.AreEqual("the quick brown fox", capturedArgs); + } + + [TestMethod] + public void AddStatementWorksAlongsideBuiltinStatementsTest() + { + List lines = + [ + "custom_log first", + "print_line second" + ]; + + bool customCalled = false; + + YesNtAssert.ContainsDebugOutputWithSetup(lines, "second", interpreter => + { + interpreter.AddStatement("custom_log", SearchMode.StartOfLine, SpaceAround.End, _ => + { + customCalled = true; + }); + }); + + Assert.IsTrue(customCalled); + } + + [TestMethod] + public void AddStatementUnknownStatementFailsTest() + { + List lines = + [ + "unknown_command foo" + ]; + + YesNtAssert.ContainsTerminationMessage(lines, "Invalid statement"); + } + + [TestMethod] + public void AddStatementWithHighPriorityRunsBeforeNormalTest() + { + List lines = + [ + "priority_cmd arg" + ]; + + int callOrder = 0; + int highPriorityOrder = -1; + int normalPriorityOrder = -1; + + YesNtAssert.GetLastLineWithSetup(lines, interpreter => + { + interpreter.AddStatement( + new StatementAttribute("priority_cmd", SearchMode.StartOfLine, SpaceAround.End) { Priority = Priority.High }, + _ => highPriorityOrder = callOrder++); + + interpreter.AddStatement( + new StatementAttribute("priority_cmd", SearchMode.StartOfLine, SpaceAround.End) { Priority = Priority.Normal }, + _ => normalPriorityOrder = callOrder++); + }); + + Assert.IsTrue(highPriorityOrder < normalPriorityOrder, "High priority statement should execute before Normal priority"); + } +} diff --git a/YesNt.Interpreter.Tests/ConsoleStatementsTests.cs b/YesNt.Interpreter.Tests/ConsoleStatementsTests.cs index fc076b7..1f9d6cd 100644 --- a/YesNt.Interpreter.Tests/ConsoleStatementsTests.cs +++ b/YesNt.Interpreter.Tests/ConsoleStatementsTests.cs @@ -79,9 +79,8 @@ public class ConsoleStatementsTests public void ReadKeyCanBeInterruptedByStopTest() { YesNtInterpreter interpreter = new YesNtInterpreter(); - interpreter.Initialize(); - AutoResetEvent onDone = new AutoResetEvent(false); + AutoResetEvent onDone= new AutoResetEvent(false); StringBuilder output = new StringBuilder(); interpreter.OnDebugOutput += (s) => _ = output.Append(s); diff --git a/YesNt.Interpreter.Tests/YesNtAssert.cs b/YesNt.Interpreter.Tests/YesNtAssert.cs index 75380e7..09e53a5 100644 --- a/YesNt.Interpreter.Tests/YesNtAssert.cs +++ b/YesNt.Interpreter.Tests/YesNtAssert.cs @@ -67,10 +67,31 @@ internal static class YesNtAssert StringAssert.Matches(value, new Regex(pattern)); } + public static void IsLastLineEqualWithSetup(List lines, string expected, Action setup, int timeout = 1000) + { + (DebugEventArgs? debugEventArgs, _) = ExecuteAndCapture(lines, timeout, setup); + Assert.AreEqual(expected, debugEventArgs?.CurrentLine); + } + + public static void ContainsDebugOutputWithSetup(List lines, string expectedFragment, Action setup, int timeout = 1000) + { + (_, string debugOutput) = ExecuteAndCapture(lines, timeout, setup); + StringAssert.Contains(debugOutput, expectedFragment); + } + + public static string? GetLastLineWithSetup(List lines, Action setup, int timeout = 1000) + { + (DebugEventArgs? debugEventArgs, _) = ExecuteAndCapture(lines, timeout, setup); + return debugEventArgs?.CurrentLine; + } + private static (DebugEventArgs? LastDebugEvent, string DebugOutput) ExecuteAndCapture(List lines, int timeout) + => ExecuteAndCapture(lines, timeout, setup: null); + + private static (DebugEventArgs? LastDebugEvent, string DebugOutput) ExecuteAndCapture(List lines, int timeout, Action? setup) { YesNtInterpreter yesNtInterpreter = new YesNtInterpreter(); - yesNtInterpreter.Initialize(); + setup?.Invoke(yesNtInterpreter); AutoResetEvent onDone = new AutoResetEvent(false); DebugEventArgs? debugEventArgs = null; diff --git a/YesNt.Interpreter/Program.cs b/YesNt.Interpreter/Program.cs index 1582b6b..330c6f7 100644 --- a/YesNt.Interpreter/Program.cs +++ b/YesNt.Interpreter/Program.cs @@ -11,7 +11,6 @@ internal static class Program if (args.Length == 1) { YesNtInterpreter interpreter = new YesNtInterpreter(); - interpreter.Initialize(); interpreter.Execute(args[0]); } else diff --git a/YesNt.Interpreter/Runtime/YesNtInterpreter.cs b/YesNt.Interpreter/Runtime/YesNtInterpreter.cs index 65b5c47..c9ec6d3 100644 --- a/YesNt.Interpreter/Runtime/YesNtInterpreter.cs +++ b/YesNt.Interpreter/Runtime/YesNtInterpreter.cs @@ -60,21 +60,19 @@ public class YesNtInterpreter AddStatement(new StatementAttribute(name, searchMode, spaceAround, consoleColor), handler); } - public void Stop() + public YesNtInterpreter() { - runtimeInfo.Exit("Terminated by external process", true); - } - - public void Initialize() - { - statements.Clear(); - staticStatements.Clear(); GeneratedStatementRegistry.Register(runtimeInfo, out statements, out staticStatements); runtimeInfo.OnDebugOutput += (s) => OnDebugOutput?.Invoke(s); runtimeInfo.OnLineExecuted += (DebugEventArgs e) => OnLineExecuted?.Invoke(e); } + public void Stop() + { + runtimeInfo.Exit("Terminated by external process", true); + } + public void Execute(string path, bool isDebugMode = false) { runtimeInfo.Reset(); diff --git a/YesNt.Interpreter/Statements/ProcessingStatements.cs b/YesNt.Interpreter/Statements/ProcessingStatements.cs index bd363f5..31c524c 100644 --- a/YesNt.Interpreter/Statements/ProcessingStatements.cs +++ b/YesNt.Interpreter/Statements/ProcessingStatements.cs @@ -50,8 +50,7 @@ internal partial class ProcessingStatements : StatementRuntimeInformation _ = Task.Run(() => { YesNtInterpreter interpreter = new YesNtInterpreter(); - interpreter.Initialize(); - interpreter.Execute(lines, RuntimeInfo.GlobalVariables, lineNumber, RuntimeInfo); + interpreter.Execute(lines, RuntimeInfo.GlobalVariables, lineNumber, RuntimeInfo); }); RuntimeInfo.CurrentLine = string.Empty;