Add tests for loop exit, local/global scope, concurrency, and string escapes

This commit is contained in:
Stone_Red
2026-03-05 01:26:16 +01:00
parent 265f20d4b7
commit ecb6415457
5 changed files with 215 additions and 0 deletions
+18
View File
@@ -200,6 +200,24 @@ public class CodeFlowTests
YesNtAssert.IsLastLineEqual(lines, "ok"); YesNtAssert.IsLastLineEqual(lines, "ok");
} }
[TestMethod]
public void GotoInsideLoopExitsLoopTest()
{
List<string> lines =
[
"var hit = no",
"while 1 == 1:",
"var hit = yes",
"goto done",
"end_while",
"label done:",
"${hit}"
];
YesNtAssert.IsLastLineEqual(lines, "yes");
}
[TestMethod] [TestMethod]
public void LabelWithoutColonFailsTest() public void LabelWithoutColonFailsTest()
{ {
@@ -132,6 +132,25 @@ public class FunctionStatementsTests
YesNtAssert.ContainsTerminationMessage(lines, "Nested functions are not allowed"); YesNtAssert.ContainsTerminationMessage(lines, "Nested functions are not allowed");
} }
[TestMethod]
public void LocalVariableDoesNotLeakToCallerTest()
{
List<string> lines =
[
"goto main",
"func modify:",
"var x = inner",
"return",
"label main:",
"var x = outer",
"call modify",
"${x}"
];
YesNtAssert.IsLastLineEqual(lines, "outer");
}
[TestMethod] [TestMethod]
public void ClearCallStackRunsTest() public void ClearCallStackRunsTest()
{ {
@@ -144,5 +163,66 @@ public class FunctionStatementsTests
YesNtAssert.IsLastLineEqual(lines, "ok"); YesNtAssert.IsLastLineEqual(lines, "ok");
} }
// --- Error path tests ---
[TestMethod]
public void AccessInWithoutArgFailsTest()
{
List<string> lines =
[
"goto main",
"func noin:",
"var x = %in",
"return",
"label main:",
"call noin"
];
YesNtAssert.ContainsTerminationMessage(lines, "No in argument in stack");
}
// --- Nested scope tests ---
[TestMethod]
public void GlobalModifiedInsideFunctionIsVisibleAfterReturnTest()
{
List<string> lines =
[
"goto main",
"func setglobal:",
"global shared = modified",
"return",
"label main:",
"global shared = original",
"call setglobal",
"${shared}"
];
YesNtAssert.IsLastLineEqual(lines, "modified");
}
[TestMethod]
public void NestedFunctionCallsHaveIndependentLocalScopesTest()
{
List<string> lines =
[
"goto main",
"func outer:",
"var x = outer_val",
"call inner",
"push_out ${x}",
"return",
"func inner:",
"var x = inner_val",
"return",
"label main:",
"call outer",
"var result = %out",
"${result}"
];
YesNtAssert.IsLastLineEqual(lines, "outer_val");
}
} }
@@ -63,6 +63,32 @@ public class ProcessingStatementsTests
YesNtAssert.IsLastLineEqual(lines, "hello\nworld"); YesNtAssert.IsLastLineEqual(lines, "hello\nworld");
} }
[TestMethod]
public void CalcRespectsPrecedenceTest()
{
YesNtAssert.IsLineEqual("2 + 3 * 4 calc", "14");
}
[TestMethod]
public void CalcParenthesesOverridePrecedenceTest()
{
YesNtAssert.IsLineEqual("(2 + 3) * 4 calc", "20");
}
[TestMethod]
public void SleepZeroIsValidTest()
{
List<string> lines =
[
"sleep 0",
"var result = ok",
"${result}"
];
YesNtAssert.IsLastLineEqual(lines, "ok");
}
[TestMethod] [TestMethod]
public void SleepInvalidValueFailsTest() public void SleepInvalidValueFailsTest()
{ {
@@ -152,5 +178,26 @@ public class ProcessingStatementsTests
YesNtAssert.IsLastLineEqual(lines, "1", timeout: 3000); YesNtAssert.IsLastLineEqual(lines, "1", timeout: 3000);
} }
[TestMethod]
public void MultipleTasksRunConcurrentlyTest()
{
List<string> lines =
[
"global a = 0",
"global b = 0",
"global a = 1 task",
"global b = 2 task",
"while ${a} == 0:",
"sleep 10",
"end_while",
"while ${b} == 0:",
"sleep 10",
"end_while",
"${b}"
];
YesNtAssert.IsLastLineEqual(lines, "2", timeout: 3000);
}
} }
@@ -58,6 +58,48 @@ public class StringLiteralStatementsTests
YesNtAssert.IsLastLineEqual(lines, "hello world"); YesNtAssert.IsLastLineEqual(lines, "hello world");
} }
[TestMethod]
public void EmptyStringLiteralHasLengthZeroTest()
{
List<string> lines =
[
"var x = \"\"",
"length ${x}",
"var len = %out",
"${len}"
];
YesNtAssert.IsLastLineEqual(lines, "0");
}
[TestMethod]
public void EscapedBackslashProducesLiteralBackslashTest()
{
List<string> lines =
[
"var msg = \"\\\\n\"", // YesNt source: "\\n" → \n (backslash + n, 2 chars)
"length ${msg}",
"var len = %out",
"${len}"
];
YesNtAssert.IsLastLineEqual(lines, "2");
}
[TestMethod]
public void UnknownEscapeSequenceBecomesCharTest()
{
List<string> lines =
[
"var msg = \"\\q\"", // YesNt source: "\q" → q (1 char)
"length ${msg}",
"var len = %out",
"${len}"
];
YesNtAssert.IsLastLineEqual(lines, "1");
}
[TestMethod] [TestMethod]
public void UnterminatedStringLiteralFailsTest() public void UnterminatedStringLiteralFailsTest()
{ {
@@ -91,6 +91,34 @@ public class VariableStatementsTests
YesNtAssert.ContainsTerminationMessage(lines, "Invalid syntax"); YesNtAssert.ContainsTerminationMessage(lines, "Invalid syntax");
} }
[TestMethod]
public void OverwriteVariableTest()
{
List<string> lines =
[
"var x = first",
"var x = second",
"${x}"
];
YesNtAssert.IsLastLineEqual(lines, "second");
}
[TestMethod]
public void EmptyStringVariableHasLengthZeroTest()
{
List<string> lines =
[
"var x = \"\"",
"length ${x}",
"var len = %out",
"${len}"
];
YesNtAssert.IsLastLineEqual(lines, "0");
}
[TestMethod] [TestMethod]
public void MissingVariableReferenceFailsTest() public void MissingVariableReferenceFailsTest()
{ {