chore: initial git load of code space
This commit is contained in:
@@ -0,0 +1,405 @@
|
||||
using Strata.SqlTools.Rules.Rule.Expression;
|
||||
|
||||
namespace Strata.SqlTools.Rules.Tests;
|
||||
|
||||
[TestFixture]
|
||||
public class MarkdownParserTests
|
||||
{
|
||||
#region Basic Literals
|
||||
|
||||
[Test]
|
||||
public void Parse_IntegerLiteral_ReturnsNumberLiteral()
|
||||
{
|
||||
var result = Markdown.Parse("42");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<NumberLiteral>());
|
||||
Assert.That(((NumberLiteral)result).Value, Is.EqualTo(42m));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_DecimalLiteral_ReturnsNumberLiteral()
|
||||
{
|
||||
var result = Markdown.Parse("3.14");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<NumberLiteral>());
|
||||
Assert.That(((NumberLiteral)result).Value, Is.EqualTo(3.14m));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_StringLiteral_DoubleQuotes_ReturnsStringLiteral()
|
||||
{
|
||||
var result = Markdown.Parse("\"hello world\"");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<StringLiteral>());
|
||||
Assert.That(((StringLiteral)result).Value, Is.EqualTo("hello world"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_StringLiteral_SingleQuotes_ReturnsStringLiteral()
|
||||
{
|
||||
var result = Markdown.Parse("'test string'");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<StringLiteral>());
|
||||
Assert.That(((StringLiteral)result).Value, Is.EqualTo("test string"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_BooleanLiteral_True_ReturnsLiteral()
|
||||
{
|
||||
var result = Markdown.Parse("true");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<Literal>());
|
||||
Assert.That(((Literal)result).Value, Is.EqualTo(true));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_BooleanLiteral_False_ReturnsLiteral()
|
||||
{
|
||||
var result = Markdown.Parse("false");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<Literal>());
|
||||
Assert.That(((Literal)result).Value, Is.EqualTo(false));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Property Access
|
||||
|
||||
[Test]
|
||||
public void Parse_SimpleProperty_ReturnsProperty()
|
||||
{
|
||||
var result = Markdown.Parse("PropertyName");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<Property>());
|
||||
var prop = (Property)result;
|
||||
Assert.That(prop.PropertyName, Is.EqualTo("PropertyName"));
|
||||
Assert.That(prop.Expression, Is.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_PropertyWithParameter_ReturnsProperty()
|
||||
{
|
||||
var result = Markdown.Parse("x.Age");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<Property>());
|
||||
var prop = (Property)result;
|
||||
Assert.That(prop.PropertyName, Is.EqualTo("Age"));
|
||||
Assert.That(prop.Expression, Is.InstanceOf<Parameter>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_LatexTextProperty_ReturnsProperty()
|
||||
{
|
||||
var result = Markdown.Parse("\\text{input.Department}");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<Property>());
|
||||
var prop = (Property)result;
|
||||
Assert.That(prop.PropertyName, Is.EqualTo("Department"));
|
||||
Assert.That(prop.Expression, Is.InstanceOf<Parameter>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_LatexTextString_ReturnsStringLiteral()
|
||||
{
|
||||
var result = Markdown.Parse("\\text{some text}");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<StringLiteral>());
|
||||
Assert.That(((StringLiteral)result).Value, Is.EqualTo("some text"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Comparisons
|
||||
|
||||
[Test]
|
||||
public void Parse_Equality_ReturnsEqual()
|
||||
{
|
||||
var result = Markdown.Parse("x.Age = 25");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<Equal>());
|
||||
var equal = (Equal)result;
|
||||
Assert.That(equal.Left, Is.InstanceOf<Property>());
|
||||
Assert.That(equal.Right, Is.InstanceOf<NumberLiteral>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_NotEqual_ReturnsNotEqual()
|
||||
{
|
||||
var result = Markdown.Parse("x.Status != 'active'");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<NotEqual>());
|
||||
var notEqual = (NotEqual)result;
|
||||
Assert.That(notEqual.Left, Is.InstanceOf<Property>());
|
||||
Assert.That(notEqual.Right, Is.InstanceOf<StringLiteral>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_LatexNotEqual_ReturnsNotEqual()
|
||||
{
|
||||
var result = Markdown.Parse("x.Value \\neq 100");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<NotEqual>());
|
||||
var notEqual = (NotEqual)result;
|
||||
Assert.That(notEqual.Left, Is.InstanceOf<Property>());
|
||||
Assert.That(notEqual.Right, Is.InstanceOf<NumberLiteral>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_GreaterThan_ReturnsGreaterThan()
|
||||
{
|
||||
var result = Markdown.Parse("x.Score > 100");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<GreaterThan>());
|
||||
var greaterThan = (GreaterThan)result;
|
||||
Assert.That(greaterThan.Left, Is.InstanceOf<Property>());
|
||||
Assert.That(greaterThan.Right, Is.InstanceOf<NumberLiteral>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_LatexGreaterThan_ReturnsGreaterThan()
|
||||
{
|
||||
var result = Markdown.Parse("x.Total \\gt 500");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<GreaterThan>());
|
||||
var greaterThan = (GreaterThan)result;
|
||||
Assert.That(greaterThan.Left, Is.InstanceOf<Property>());
|
||||
Assert.That(greaterThan.Right, Is.InstanceOf<NumberLiteral>());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Logical Operations
|
||||
|
||||
[Test]
|
||||
public void Parse_And_ReturnsAnd()
|
||||
{
|
||||
var result = Markdown.Parse("x.Age > 18 AND y.Active = true");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<And>());
|
||||
var and = (And)result;
|
||||
Assert.That(and.Left, Is.InstanceOf<GreaterThan>());
|
||||
Assert.That(and.Right, Is.InstanceOf<Equal>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_Or_ReturnsOr()
|
||||
{
|
||||
var result = Markdown.Parse("x.Status = 'pending' OR x.Status = 'active'");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<Or>());
|
||||
var or = (Or)result;
|
||||
Assert.That(or.Left, Is.InstanceOf<Equal>());
|
||||
Assert.That(or.Right, Is.InstanceOf<Equal>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_LatexLand_ReturnsAnd()
|
||||
{
|
||||
var result = Markdown.Parse("x.Valid = true \\land y.Count > 0");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<And>());
|
||||
var and = (And)result;
|
||||
Assert.That(and.Left, Is.InstanceOf<Equal>());
|
||||
Assert.That(and.Right, Is.InstanceOf<GreaterThan>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_LatexLor_ReturnsOr()
|
||||
{
|
||||
var result = Markdown.Parse("a.Type = 1 \\lor b.Type = 2");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<Or>());
|
||||
var or = (Or)result;
|
||||
Assert.That(or.Left, Is.InstanceOf<Equal>());
|
||||
Assert.That(or.Right, Is.InstanceOf<Equal>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_LatexWedge_ReturnsAnd()
|
||||
{
|
||||
var result = Markdown.Parse("x.Active = true \\wedge x.Verified = true");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<And>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_LatexVee_ReturnsOr()
|
||||
{
|
||||
var result = Markdown.Parse("x.Status = 'A' \\vee x.Status = 'B'");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<Or>());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Complex Expressions
|
||||
|
||||
[Test]
|
||||
public void Parse_NestedParentheses_ReturnsCorrectStructure()
|
||||
{
|
||||
var result = Markdown.Parse("(x.Age > 18 AND x.Active = true) OR y.Override = true");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<Or>());
|
||||
var or = (Or)result;
|
||||
Assert.That(or.Left, Is.InstanceOf<And>());
|
||||
Assert.That(or.Right, Is.InstanceOf<Equal>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_LatexParentheses_ReturnsCorrectStructure()
|
||||
{
|
||||
var result = Markdown.Parse("\\left(x.Value = 10\\right) \\land y.Value = 20");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<And>());
|
||||
var and = (And)result;
|
||||
Assert.That(and.Left, Is.InstanceOf<Equal>());
|
||||
Assert.That(and.Right, Is.InstanceOf<Equal>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_ComplexExpression_ReturnsCorrectStructure()
|
||||
{
|
||||
var result = Markdown.Parse("x.Age > 18 AND (y.Status = 'active' OR y.Status = 'pending')");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<And>());
|
||||
var and = (And)result;
|
||||
Assert.That(and.Left, Is.InstanceOf<GreaterThan>());
|
||||
Assert.That(and.Right, Is.InstanceOf<Or>());
|
||||
|
||||
var or = (Or)and.Right;
|
||||
Assert.That(or.Left, Is.InstanceOf<Equal>());
|
||||
Assert.That(or.Right, Is.InstanceOf<Equal>());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Markdown Delimiters
|
||||
|
||||
[Test]
|
||||
public void Parse_InlineMath_RemovesDelimiters()
|
||||
{
|
||||
var result = Markdown.Parse("$x.Age = 25$");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<Equal>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_BlockMath_RemovesDelimiters()
|
||||
{
|
||||
var result = Markdown.Parse("$$\nx.Age > 18\n$$");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<GreaterThan>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_MathCodeFence_RemovesDelimiters()
|
||||
{
|
||||
var result = Markdown.Parse("```math\nx.Active = true\n```");
|
||||
|
||||
Assert.That(result, Is.InstanceOf<Equal>());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Error Handling
|
||||
|
||||
[Test]
|
||||
public void Parse_NullString_ThrowsArgumentException()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => Markdown.Parse(null!));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_EmptyString_ThrowsArgumentException()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => Markdown.Parse(""));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_WhitespaceOnly_ThrowsArgumentException()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => Markdown.Parse(" "));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_InvalidExpression_ThrowsArgumentException()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => Markdown.Parse("@#$%"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_ValidExpression_ReturnsTrue()
|
||||
{
|
||||
var success = Markdown.TryParse("x.Age = 25", out var expression);
|
||||
|
||||
Assert.That(success, Is.True);
|
||||
Assert.That(expression, Is.Not.Null);
|
||||
Assert.That(expression, Is.InstanceOf<Equal>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_InvalidExpression_ReturnsFalse()
|
||||
{
|
||||
var success = Markdown.TryParse("@#$%", out var expression);
|
||||
|
||||
Assert.That(success, Is.False);
|
||||
Assert.That(expression, Is.Null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Integration Tests
|
||||
|
||||
[Test]
|
||||
public void Parse_RealWorldExample_UserAgeAndStatus()
|
||||
{
|
||||
var markdown = "$$\\text{user.Age} > 18 \\land \\text{user.Status} = \\text{active}$$";
|
||||
var result = Markdown.Parse(markdown);
|
||||
|
||||
Assert.That(result, Is.InstanceOf<And>());
|
||||
var and = (And)result;
|
||||
|
||||
// Left side: user.Age > 18
|
||||
Assert.That(and.Left, Is.InstanceOf<GreaterThan>());
|
||||
var greaterThan = (GreaterThan)and.Left;
|
||||
Assert.That(greaterThan.Left, Is.InstanceOf<Property>());
|
||||
var userAge = (Property)greaterThan.Left;
|
||||
Assert.That(userAge.PropertyName, Is.EqualTo("Age"));
|
||||
|
||||
// Right side: user.Status = "active"
|
||||
Assert.That(and.Right, Is.InstanceOf<Equal>());
|
||||
var equal = (Equal)and.Right;
|
||||
Assert.That(equal.Left, Is.InstanceOf<Property>());
|
||||
var userStatus = (Property)equal.Left;
|
||||
Assert.That(userStatus.PropertyName, Is.EqualTo("Status"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_RealWorldExample_ComplexBusinessRule()
|
||||
{
|
||||
var markdown = @"$
|
||||
(invoice.TotalCharges > 1000 AND invoice.Status = 'pending')
|
||||
OR
|
||||
(invoice.Priority = 'urgent' AND invoice.ApprovedBy != '')
|
||||
$";
|
||||
|
||||
var result = Markdown.Parse(markdown);
|
||||
|
||||
Assert.That(result, Is.InstanceOf<Or>());
|
||||
var or = (Or)result;
|
||||
Assert.That(or.Left, Is.InstanceOf<And>());
|
||||
Assert.That(or.Right, Is.InstanceOf<And>());
|
||||
|
||||
// Left AND: TotalCharges > 1000 AND Status = 'pending'
|
||||
var leftAnd = (And)or.Left;
|
||||
Assert.That(leftAnd.Left, Is.InstanceOf<GreaterThan>());
|
||||
Assert.That(leftAnd.Right, Is.InstanceOf<Equal>());
|
||||
|
||||
// Right AND: Priority = 'urgent' AND ApprovedBy != ''
|
||||
var rightAnd = (And)or.Right;
|
||||
Assert.That(rightAnd.Left, Is.InstanceOf<Equal>());
|
||||
Assert.That(rightAnd.Right, Is.InstanceOf<NotEqual>());
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user