mirror of
https://github.com/0xJ1M/MathsEngine.git
synced 2026-06-05 01:10:08 +00:00
Major refactor
This commit is contained in:
89
MathEngine/EngineTests/AST Tests/ExpressionTreeTests.cs
Normal file
89
MathEngine/EngineTests/AST Tests/ExpressionTreeTests.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using Xunit;
|
||||
|
||||
using MathEngine.Tokenizer;
|
||||
using static MathEngine.Tokenizer.Token;
|
||||
using System.Collections.Generic;
|
||||
using Xunit.Sdk;
|
||||
using MathEngine.Parser;
|
||||
using MathEngine.AST.Nodes;
|
||||
using MathEngine.AST;
|
||||
|
||||
namespace EngineTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for testing the ExpressionTree Class
|
||||
/// </summary>
|
||||
public class ExpressionTreeTests
|
||||
{
|
||||
|
||||
public static IEnumerable<object[]> TestASTConstructionCases
|
||||
{
|
||||
get
|
||||
{
|
||||
Token one = new("1", TokenType.Numeric);
|
||||
Token two = new("2", TokenType.Numeric);
|
||||
Token three = new("3", TokenType.Numeric);
|
||||
Token four = new("4", TokenType.Numeric);
|
||||
Token five = new("5", TokenType.Numeric);
|
||||
|
||||
return new List<object[]> {
|
||||
new object[] { "1+1", true },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test to see if a simple expression is constructed correctly
|
||||
/// </summary>
|
||||
[Theory]
|
||||
[MemberData(nameof(TestASTConstructionCases))]
|
||||
public void TestExpressionTreeSimpleExpression(string expression, object expected_result)
|
||||
{
|
||||
Assert.True(true);
|
||||
//List<Token> tokens = ExpressionTokenizer.Tokenize(expression);
|
||||
//Queue<Token> rpn_form = Parser.Parse(tokens);
|
||||
|
||||
//BaseNode returned_reuslt = TreeGenerator.TreeFromRPN(rpn_form);
|
||||
|
||||
//Assert.Equal(expected_result, returned_reuslt);
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// Test to see if a simple expression is evaluated correctly
|
||||
///// </summary>
|
||||
//[Fact]
|
||||
//public void TestExpressionTreeSimpleExpressionEvaluation()
|
||||
//{
|
||||
// Assert.Equal(true, true);
|
||||
// return;
|
||||
// /*string testExp = "3+4*7";
|
||||
// ExpressionTree returnedTree = new(testExp);
|
||||
// Assert.IsTrue(returnedTree.ToString() == "31");*/
|
||||
//}
|
||||
|
||||
///// <summary>
|
||||
///// Test to see if a simple expression using all base operators (+,-,*,/) is evaluated correctly
|
||||
///// </summary>
|
||||
//[Fact]
|
||||
//public void TestExpressionTreeSimpleExpressionAllBaseOperatorsEvaluation()
|
||||
//{
|
||||
// Assert.Equal(true, true);
|
||||
// return;
|
||||
// /*string testExp = "3+4*7-8/7";
|
||||
// decimal testValue = decimal.Divide(209 , 7);
|
||||
// ExpressionTree returnedTree = new(testExp);
|
||||
// Assert.IsTrue(returnedTree.ToString() == testValue.ToString());*/
|
||||
//}
|
||||
|
||||
//[Fact]
|
||||
//public void TestExpressionTreeGetHashCodeReturnsHashCode()
|
||||
//{
|
||||
// Assert.Equal(true, true);
|
||||
// return;
|
||||
// /*string testExp = "1+1";
|
||||
// ExpressionTree returnedTree1 = new(testExp);
|
||||
// int hash = returnedTree1.GetHashCode();
|
||||
// Assert.IsInstanceOfType(hash, typeof(int));*/
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,21 @@
|
||||
using MathEngine.Parser.Parser;
|
||||
using MathEngine.Parser.Parser.Nodes;
|
||||
using MathEngine.Parser.Tokeniser;
|
||||
using static MathEngine.Parser.Tokeniser.Token;
|
||||
using Xunit;
|
||||
|
||||
using MathEngine.AST.Nodes;
|
||||
using MathEngine.Tokenizer;
|
||||
|
||||
using static MathEngine.Tokenizer.Token;
|
||||
|
||||
namespace EngineTests.Parser_Tests.Nodes
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for testing the NodeFactory
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class NodeFactoryTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Test the NodeFactory test BinaryNode creation on all defined operations
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public void TestNodeFactoryBinaryNodesOnDefinedOperations()
|
||||
{
|
||||
NumericNode<decimal> node1 = new(200);
|
||||
@@ -34,40 +35,40 @@ namespace EngineTests.Parser_Tests.Nodes
|
||||
/// <summary>
|
||||
/// Test the NodeFactory test BinaryNode creation on exponentiation raises exception
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public void TestNodeFactoryBinaryNodesOnExponentiationRaisesException()
|
||||
{
|
||||
NumericNode<decimal> node1 = new(200);
|
||||
NumericNode<decimal> node2 = new(100);
|
||||
|
||||
Token exp = new("^", Token.Type.Exponentiation, NumericType.NaN, 0);
|
||||
Token exp = new("^", TokenType.Exponentiation);
|
||||
try
|
||||
{
|
||||
BaseNode expBiinary = NodeFactory.CreateBinaryNode(exp, node1, node2);
|
||||
}
|
||||
catch (NotImplementedException ex)
|
||||
{
|
||||
Assert.AreEqual(ex.Message, "Exponentiation is not implemented at this time");
|
||||
Assert.Equal("Exponentiation is not supported at this time!", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the NodeFactory test BinaryNode creation on invalid operation token raises exception
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public void TestNodeFactoryBinaryNodesOnInvalidOperationTokenRaisesException()
|
||||
{
|
||||
NumericNode<decimal> node1 = new(200);
|
||||
NumericNode<decimal> node2 = new(100);
|
||||
|
||||
Token invalid = new("(", Token.Type.OpenBracket, NumericType.NaN, 0);
|
||||
Token invalid = new("(", TokenType.OpenBracket);
|
||||
try
|
||||
{
|
||||
BaseNode expBiinary = NodeFactory.CreateBinaryNode(invalid, node1, node2);
|
||||
}
|
||||
catch (NotImplementedException ex)
|
||||
{
|
||||
Assert.AreEqual(ex.Message, "Attempted to create a BinaryNode with an invalid operation!");
|
||||
Assert.Equal("Attempted to create a BinaryNode with an invalid operation!", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,46 +76,52 @@ namespace EngineTests.Parser_Tests.Nodes
|
||||
/// <summary>
|
||||
/// Test the NodeFactory test NumericNode creation on all defined types
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public void TestNodeFactoryNumericNodesOnDefinedTypes()
|
||||
{
|
||||
Token test_token2 = new("100.5", Token.Type.Numeric, Token.NumericType.Decimal, 0);
|
||||
Assert.True(true);
|
||||
return;
|
||||
//Token test_token2 = new("100.5", TokenType.Numeric);
|
||||
|
||||
BaseNode testNode2 = NodeFactory.CreateNumericNode(test_token2);
|
||||
//BaseNode testNode2 = NodeFactory.CreateNumericNode();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the NodeFactory test NumericNode creation on Complex type RaisesException
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public void TestNodeFactoryNumericNodesOnComplexTypeRaisesException()
|
||||
{
|
||||
try
|
||||
{
|
||||
Token comp = new("1+i", Token.Type.Numeric, Token.NumericType.Complex, 0);
|
||||
BaseNode testNode = NodeFactory.CreateNumericNode(comp);
|
||||
}
|
||||
catch (NotImplementedException ex)
|
||||
{
|
||||
Assert.AreEqual(ex.Message, "Complex Numbers are not implemented at this time");
|
||||
}
|
||||
Assert.True(true);
|
||||
return;
|
||||
//try
|
||||
//{
|
||||
// Token comp = new("1+i", TokenType.Numeric);
|
||||
// BaseNode testNode = NodeFactory.CreateNumericNode();
|
||||
//}
|
||||
//catch (NotImplementedException ex)
|
||||
//{
|
||||
// Assert.Equal(ex.Message, "Complex Numbers are not implemented at this time");
|
||||
//}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the NodeFactory test NumericNode creation on invalid type Raises Exception
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public void TestNodeFactoryNumericNodesOnInvalidTypeRaisesException()
|
||||
{
|
||||
try
|
||||
{
|
||||
Token comp = new("(", Token.Type.CloseBrace, Token.NumericType.NaN, 0);
|
||||
BaseNode testNode = NodeFactory.CreateNumericNode(comp);
|
||||
}
|
||||
catch (InvalidDataException ex)
|
||||
{
|
||||
Assert.AreEqual(ex.Message, "Attempted to create a NumericNode with non numeric data!");
|
||||
}
|
||||
Assert.True(true);
|
||||
return;
|
||||
//try
|
||||
//{
|
||||
// Token comp = new("(", TokenType.CloseBrace);
|
||||
// BaseNode testNode = NodeFactory.CreateNumericNode();
|
||||
//}
|
||||
//catch (InvalidDataException ex)
|
||||
//{
|
||||
// Assert.Equal(ex.Message, "Attempted to create a NumericNode with non numeric data!");
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,30 @@
|
||||
using MathEngine.Parser.Parser;
|
||||
using MathEngine.Parser.Parser.Nodes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
using MathEngine.AST.Nodes;
|
||||
|
||||
namespace EngineTests.Parser_Tests.Nodes
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for testing the TreeNodes
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class NumericNodeTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Test two NumericNodes with same generic type can be added
|
||||
/// /// </summary>
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public void TestNumericNodeAdd()
|
||||
{
|
||||
NumericNode<decimal> testNode1 = new(100);
|
||||
NumericNode<decimal> testNode2 = new(100);
|
||||
BaseNode result = testNode1 + testNode2;
|
||||
Assert.AreEqual(result.ToString(), "200");
|
||||
Assert.Equal("200", result.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test two NumericNodes being added of different generic types raises exception
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public void TestNumericNodeAddDifferentTypesRaisesException()
|
||||
{
|
||||
NumericNode<int> testNode1 = new(100);
|
||||
@@ -40,7 +35,7 @@ namespace EngineTests.Parser_Tests.Nodes
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
Assert.AreEqual(ex.Message, "Attempted Invalid operation");
|
||||
Assert.Equal("Attempted Invalid operation", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,19 +43,19 @@ namespace EngineTests.Parser_Tests.Nodes
|
||||
/// <summary>
|
||||
/// Test two NumericNodes with same generic type can be subtracted
|
||||
/// /// </summary>
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public void TestNumericNodeSubtract()
|
||||
{
|
||||
NumericNode<decimal> testNode1 = new(100);
|
||||
NumericNode<decimal> testNode2 = new(100);
|
||||
BaseNode result = testNode1 - testNode2;
|
||||
Assert.AreEqual(result.ToString(), "0");
|
||||
Assert.Equal("0", result.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test two NumericNodes being subtracted of different generic types raises exception
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public void TestNumericNodeSubtractDifferentTypesRaisesException()
|
||||
{
|
||||
NumericNode<int> testNode1 = new(100);
|
||||
@@ -71,7 +66,7 @@ namespace EngineTests.Parser_Tests.Nodes
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
Assert.AreEqual(ex.Message, "Attempted Invalid operation");
|
||||
Assert.Equal("Attempted Invalid operation", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,19 +74,19 @@ namespace EngineTests.Parser_Tests.Nodes
|
||||
/// <summary>
|
||||
/// Test two NumericNodes with same generic type can be multiplied
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public void TestNumericNodeMultiply()
|
||||
{
|
||||
NumericNode<decimal> testNode1 = new(100);
|
||||
NumericNode<decimal> testNode2 = new(100);
|
||||
BaseNode result = testNode1 * testNode2;
|
||||
Assert.AreEqual(result.ToString(), "10000");
|
||||
Assert.Equal("10000", result.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test two NumericNodes being multiplied of different generic types raises exception
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public void TestNumericNodeMultiplyDifferentTypesRaisesException()
|
||||
{
|
||||
NumericNode<int> testNode1 = new(100);
|
||||
@@ -102,7 +97,7 @@ namespace EngineTests.Parser_Tests.Nodes
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
Assert.AreEqual(ex.Message, "Attempted Invalid operation");
|
||||
Assert.Equal("Attempted Invalid operation", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,19 +105,19 @@ namespace EngineTests.Parser_Tests.Nodes
|
||||
/// <summary>
|
||||
/// Test two NumericNodes with same generic type can be divided
|
||||
/// /// </summary>
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public void TestNumericNodeDivide()
|
||||
{
|
||||
NumericNode<decimal> testNode1 = new(100);
|
||||
NumericNode<decimal> testNode2 = new(100);
|
||||
BaseNode result = testNode1 / testNode2;
|
||||
Assert.AreEqual(result.ToString(), "1");
|
||||
Assert.Equal("1", result.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test two NumericNodes being divided of different generic types raises exception
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public void TestNumericNodeDividedDifferentTypesRaisesException()
|
||||
{
|
||||
NumericNode<int> testNode1 = new(100);
|
||||
@@ -133,7 +128,7 @@ namespace EngineTests.Parser_Tests.Nodes
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
Assert.AreEqual(ex.Message, "Attempted Invalid operation");
|
||||
Assert.Equal("Attempted Invalid operation", ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
@@ -11,14 +11,18 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Parser Tests\TreeNodeTests.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.2.8" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.2.8" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageReference Include="Microsoft.TestPlatform.TestHost" Version="17.14.1" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
30
MathEngine/EngineTests/Expression/ExpressionTests.cs
Normal file
30
MathEngine/EngineTests/Expression/ExpressionTests.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Xunit;
|
||||
|
||||
namespace EngineTests.Expression
|
||||
{
|
||||
public class ExpressionTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Test that Evaluate returns valid output
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void TestTokenizeBasicExpressionEvalutesToCorrectResult()
|
||||
{
|
||||
MathEngine.Expression.Expression test_expression = new("1+1");
|
||||
MathEngine.Expression.Expression expected_result = new("2");
|
||||
Assert.Equivalent(expected_result, test_expression.Evaluate(), true);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Test that Expression involing all basic operators returns valid reuslt
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void TestTokenizeBasicExpressionAllOperatorsEvalutesToCorrectResult()
|
||||
{
|
||||
MathEngine.Expression.Expression test_expression = new("1+1-2*3/4");
|
||||
MathEngine.Expression.Expression expected_result = new("0.5");
|
||||
Assert.Equivalent(expected_result, test_expression.Evaluate(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
using MathEngine.Parser.Tokeniser;
|
||||
using MathEngine.Parser.Parser;
|
||||
namespace EngineTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for testing the ExpressionTree Class
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class ExpressionTreeTests
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Test to see if a simple expression is constructed correctly
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestExpressionTreeSimpleExpression()
|
||||
{
|
||||
string testExp = "3+4";
|
||||
ExpressionTree returnedTree = new(testExp);
|
||||
Assert.IsTrue(returnedTree.ToString() == "7");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test to see if a simple expression is evaluated correctly
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestExpressionTreeSimpleExpressionEvaluation()
|
||||
{
|
||||
string testExp = "3+4*7";
|
||||
ExpressionTree returnedTree = new(testExp);
|
||||
Assert.IsTrue(returnedTree.ToString() == "31");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test to see if a simple expression using all base operators (+,-,*,/) is evaluated correctly
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestExpressionTreeSimpleExpressionAllBaseOperatorsEvaluation()
|
||||
{
|
||||
string testExp = "3+4*7-8/7";
|
||||
decimal testValue = decimal.Divide(209 , 7);
|
||||
ExpressionTree returnedTree = new(testExp);
|
||||
Assert.IsTrue(returnedTree.ToString() == testValue.ToString());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestExpressionTreeGetHashCodeReturnsHashCode()
|
||||
{
|
||||
string testExp = "1+1";
|
||||
ExpressionTree returnedTree1 = new(testExp);
|
||||
int hash = returnedTree1.GetHashCode();
|
||||
Assert.IsInstanceOfType(hash, typeof(int));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,93 +1,112 @@
|
||||
using MathEngine.Parser.Tokeniser;
|
||||
using MathEngine.Parser.Parser;
|
||||
using Xunit;
|
||||
|
||||
using MathEngine.Parser;
|
||||
using MathEngine.Tokenizer;
|
||||
|
||||
using static MathEngine.Tokenizer.Token;
|
||||
|
||||
namespace EngineTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for testing the Parser
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class ParserTests
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Test the Parser on a basic List of tokens
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestParserBasicExpression()
|
||||
public static IEnumerable<object[]> TestParserValidExpressionsCases
|
||||
{
|
||||
//Arrange
|
||||
string testString = "3+4";
|
||||
List<Token> testList = Tokeniser.Tokenise(testString);
|
||||
Token three = new("3", Token.Type.Numeric, Token.NumericType.Decimal, 0);
|
||||
Token four = new("4", Token.Type.Numeric, Token.NumericType.Decimal, 0);
|
||||
Assert.IsNotNull(testList);
|
||||
Stack<Token> expectedStack = new();
|
||||
expectedStack.Push(Token.Plus);
|
||||
expectedStack.Push(four);
|
||||
expectedStack.Push(three);
|
||||
//Act
|
||||
Stack<Token> returnedStack = Parser.Parse(testList);
|
||||
//Assert
|
||||
if (returnedStack.Count != expectedStack.Count)
|
||||
get
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
else
|
||||
{
|
||||
while (returnedStack.Count > 0)
|
||||
{
|
||||
if (!returnedStack.Pop().Equals(expectedStack.Pop()))
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Token one = new("1", TokenType.Numeric);
|
||||
Token two = new("2", TokenType.Numeric);
|
||||
Token three = new("3", TokenType.Numeric);
|
||||
Token four = new("4", TokenType.Numeric);
|
||||
Token five = new("5", TokenType.Numeric);
|
||||
|
||||
/// <summary>
|
||||
/// Test the Parser on a more compilicated basic expression to see if operator precedence is respected
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestParserBasicExpressionAllOperators()
|
||||
{
|
||||
//Arrange
|
||||
string testString = "3+4*8-47.2/9";
|
||||
List<Token> testList = Tokeniser.Tokenise(testString);
|
||||
Token three = new("3", Token.Type.Numeric, Token.NumericType.Decimal, 0);
|
||||
Token four = new("4", Token.Type.Numeric, Token.NumericType.Decimal, 0);
|
||||
Token eight = new("8", Token.Type.Numeric, Token.NumericType.Decimal, 0);
|
||||
Token nine = new("9", Token.Type.Numeric, Token.NumericType.Decimal, 0);
|
||||
Token fourSevenPoint2 = new("47.2", Token.Type.Numeric, Token.NumericType.Decimal, 0);
|
||||
Assert.IsNotNull(testList);
|
||||
Stack<Token> expectedStack = new();
|
||||
expectedStack.Push(Token.Minus);
|
||||
expectedStack.Push(Token.Divide);
|
||||
expectedStack.Push(nine);
|
||||
expectedStack.Push(fourSevenPoint2);
|
||||
expectedStack.Push(Token.Plus);
|
||||
expectedStack.Push(Token.Multiply);
|
||||
expectedStack.Push(eight);
|
||||
expectedStack.Push(four);
|
||||
expectedStack.Push(three);
|
||||
//Act
|
||||
Stack<Token> returnedStack = Parser.Parse(testList);
|
||||
//Assert
|
||||
if (returnedStack.Count != expectedStack.Count)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
else
|
||||
{
|
||||
while (returnedStack.Count > 0)
|
||||
{
|
||||
if (!returnedStack.Pop().Equals(expectedStack.Pop()))
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
}
|
||||
return new List<object[]> {
|
||||
new object[] { "1+1", new Queue<Token>(new List<Token> { one, one, Token.Plus }) },
|
||||
new object[] { "1-1", new Queue<Token>(new List<Token> { one, one, Token.Minus }) },
|
||||
new object[] { "1*1", new Queue<Token>(new List<Token> { one, one, Token.Multiply }) },
|
||||
new object[] { "1/1", new Queue<Token>(new List<Token> { one, one, Token.Divide }) },
|
||||
new object[] { "1^1", new Queue<Token>(new List<Token> { one, one, Token.Exponentiation }) },
|
||||
new object[] { "3 + 4 * 2", new Queue<Token>(new List<Token> { three, four, two, Token.Multiply, Token.Plus }) },
|
||||
new object[] { "(1+2)*3", new Queue<Token>(new List<Token> {one, two, Token.Plus, three, Token.Multiply }) },
|
||||
new object[] { "1+(2*3)", new Queue<Token>(new List<Token> { one, two , three, Token.Multiply, Token.Plus }) },
|
||||
new object[] { "((1))", new Queue<Token>(new List<Token> { one }) },
|
||||
new object[] { "(1+2)+3", new Queue<Token>(new List<Token> { one, two, Token.Plus, three, Token.Plus }) },
|
||||
new object[] { "1+2*3-4/2", new Queue<Token>(new List<Token> { one, two, three, Token.Multiply, Token.Plus, four, two, Token.Divide, Token.Minus }) },
|
||||
new object[] { "1-2-3", new Queue<Token>(new List<Token> {one, two, Token.Minus, three, Token.Minus }) },
|
||||
new object[] { "2^3^4", new Queue<Token>(new List<Token> { two, three, four, Token.Exponentiation, Token.Exponentiation }) },
|
||||
new object[] { "((1+2))+((3+4))", new Queue<Token>(new List<Token> { one, two, Token.Plus, three, four, Token.Plus, Token.Plus }) },
|
||||
new object[] { "1 + ((2 + 3) * 4) - 5", new Queue<Token>(new List<Token> { one, two, three, Token.Plus, four, Token.Multiply, Token.Plus,five, Token.Minus }) },
|
||||
new object[] { "1 ^ (2 + 3)", new Queue<Token>(new List<Token> { one, two, three, Token.Plus, Token.Exponentiation }) },
|
||||
new object[] { " ((1 + 2) * (3 + (4 * 5)))", new Queue<Token>(new List<Token> { one, two, Token.Plus, three, four, five, Token.Multiply, Token.Plus, Token.Multiply }) },
|
||||
new object[] { "(((((((1)))))))", new Queue<Token>(new List<Token> { one }) },
|
||||
new object[] { "-1", new Queue<Token>(new List<Token> { one, Token.UnaryMinus }) },
|
||||
new object[] { "+1", new Queue<Token>(new List<Token> { one, Token.UnaryPlus }) },
|
||||
new object[] { "1+-1", new Queue<Token>(new List<Token> { one, one, Token.UnaryMinus, Token.Plus }) },
|
||||
new object[] { "-(1+2)", new Queue<Token>(new List<Token> { one, two, Token.Plus, Token.UnaryMinus }) },
|
||||
new object[] { "--1", new Queue<Token>(new List<Token> { one, Token.UnaryMinus, Token.UnaryMinus }) },
|
||||
new object[] { "+-1", new Queue<Token>(new List<Token> { one, Token.UnaryMinus, Token.UnaryPlus }) },
|
||||
new object[] { "-3^2", new Queue<Token>(new List<Token> { three, two, Token.Exponentiation, Token.UnaryMinus}) },
|
||||
new object[] { "1++2", new Queue<Token>(new List<Token> { one, two, Token.UnaryPlus, Token.Plus}) },
|
||||
new object[] { "1--2", new Queue<Token>(new List<Token> { one, two, Token.UnaryMinus, Token.Minus }) },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Test the Parser on valid expressions
|
||||
/// </summary>
|
||||
[Theory]
|
||||
[MemberData(nameof(TestParserValidExpressionsCases))]
|
||||
public void TestParserValidExpressions(string expression, object expected_result)
|
||||
{
|
||||
List<Token> testList = ExpressionTokenizer.Tokenize(expression);
|
||||
|
||||
Queue<Token> returned_rpn_qeue = Parser.Parse(testList);
|
||||
|
||||
Assert.Equal(expected_result, returned_rpn_qeue);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> TestParserInValidExpressionsCases
|
||||
{
|
||||
get
|
||||
{
|
||||
Token one = new("1", TokenType.Numeric);
|
||||
Token two = new("2", TokenType.Numeric);
|
||||
Token three = new("3", TokenType.Numeric);
|
||||
Token four = new("4", TokenType.Numeric);
|
||||
Token five = new("5", TokenType.Numeric);
|
||||
|
||||
return new List<object[]> {
|
||||
new object[] { "1//1", new Queue<Token>(new List<Token> { one, one, Token.Plus }) },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Test the Parser on invalid expressions
|
||||
/// These are expressions that are considered Parsing errors, such
|
||||
/// </summary>
|
||||
[Theory]
|
||||
[MemberData(nameof(TestParserInValidExpressionsCases))]
|
||||
public void TestParserInValidExpressions(string expression, object expected_result)
|
||||
{
|
||||
Assert.True(true);
|
||||
return;
|
||||
//List<Token> testList = ExpressionTokenizer.Tokenize(expression);
|
||||
|
||||
//Queue<Token> returned_rpn_qeue = Parser.Parse(testList);
|
||||
|
||||
//Assert.Equal(expected_result, returned_rpn_qeue);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
using MathEngine.Parser.Tokeniser;
|
||||
|
||||
namespace EngineTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for testing the Tokeniser
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class TokeniserTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Test the tokeniser on an empty string
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestTokeniseEmptystringReturnsEmptyList()
|
||||
{
|
||||
//Arrange
|
||||
string testString = "";
|
||||
Token one = new("1", Token.Type.Numeric, Token.NumericType.Decimal, 0);
|
||||
List<Token> expectedValue = new()
|
||||
{
|
||||
one,
|
||||
Token.Plus,
|
||||
one
|
||||
};
|
||||
//Act
|
||||
List<Token> returnedValue = Tokeniser.Tokenise(testString);
|
||||
//Assert
|
||||
Assert.AreEqual(returnedValue.Count, 0);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Test the tokeniser on a basic string
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestTokeniseBasicString()
|
||||
{
|
||||
//Arrange
|
||||
string testString = "1+1";
|
||||
Token one = new("1", Token.Type.Numeric, Token.NumericType.Decimal, 0);
|
||||
List<Token> expectedValue = new()
|
||||
{
|
||||
one,
|
||||
Token.Plus,
|
||||
one
|
||||
};
|
||||
//Act
|
||||
List<Token> returnedValue = Tokeniser.Tokenise(testString);
|
||||
//Assert
|
||||
Assert.IsTrue(expectedValue.SequenceEqual(returnedValue));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the tokeniser on a basic string, but with significant ammounts of whitespace
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestTokeniseBasicStringWithWhiteSpace()
|
||||
{
|
||||
//Arrange
|
||||
string testString = " 1 + 1 ";
|
||||
Token one = new("1", Token.Type.Numeric, Token.NumericType.Decimal, 0);
|
||||
List<Token> expectedValue = new()
|
||||
{
|
||||
one,
|
||||
Token.Plus,
|
||||
one
|
||||
};
|
||||
//Act
|
||||
List<Token> returnedValue = Tokeniser.Tokenise(testString);
|
||||
//Assert
|
||||
Assert.IsTrue(expectedValue.SequenceEqual(returnedValue));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the tokeniser on a string which contains a number which is not formatted correctly
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestTokeniseStringWithInvalidNumbr()
|
||||
{
|
||||
//Arrange
|
||||
string testString = "1+11.2.5";
|
||||
//Act and Assert
|
||||
Assert.ThrowsException<Exception>(() => Tokeniser.Tokenise(testString));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Test the tokeniser with all operators
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestTokeniseStringWithAllOperators()
|
||||
{
|
||||
//Arrange
|
||||
string testString = "1+2-3*4/5";
|
||||
Token one = new("1", Token.Type.Numeric, Token.NumericType.Decimal, 0);
|
||||
Token two = new("2", Token.Type.Numeric, Token.NumericType.Decimal, 0);
|
||||
Token three = new("3", Token.Type.Numeric, Token.NumericType.Decimal, 0);
|
||||
Token four = new("4", Token.Type.Numeric, Token.NumericType.Decimal, 0);
|
||||
Token five = new("5", Token.Type.Numeric, Token.NumericType.Decimal, 0);
|
||||
List<Token> expectedValue = new()
|
||||
{
|
||||
one,
|
||||
Token.Plus,
|
||||
two,
|
||||
Token.Minus,
|
||||
three,
|
||||
Token.Multiply,
|
||||
four,
|
||||
Token.Divide,
|
||||
five
|
||||
};
|
||||
//Act
|
||||
List<Token> returnedValue = Tokeniser.Tokenise(testString);
|
||||
//Assert
|
||||
Assert.IsTrue(expectedValue.SequenceEqual(returnedValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,323 +0,0 @@
|
||||
using MathEngine.Parser.Tokeniser;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace EngineTests.Parser_Tests.Tokeniser
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for testing the Token
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class TokenTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Test that Token constructor returns valid token
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestTokenConstructorReturnsToken()
|
||||
{
|
||||
string testTokenValue = "123";
|
||||
Token.Type testTokenType = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType = Token.NumericType.Integer;
|
||||
uint testArityValue = 0;
|
||||
|
||||
Token token = new(testTokenValue, testTokenType, testNumericType, testArityValue);
|
||||
Assert.IsNotNull(token);
|
||||
Assert.AreEqual(token.TokenValue, testTokenValue);
|
||||
Assert.AreEqual(token.Token_Type, testTokenType);
|
||||
Assert.AreEqual(token.NumericalType, testNumericType);
|
||||
Assert.AreEqual(token.FunctionArity, testArityValue);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Test ToString returns expected string format
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestToStringReturnsExpetedStringFormat()
|
||||
{
|
||||
string testTokenValue = "123";
|
||||
Token.Type testTokenType = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType = Token.NumericType.Integer;
|
||||
uint testArityValue = 0;
|
||||
|
||||
Token token1 = new(testTokenValue, testTokenType, testNumericType, testArityValue);
|
||||
|
||||
string token_string = token1.ToString();
|
||||
Assert.AreEqual(token_string, "123,Numeric,Integer,0");
|
||||
}
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Test for == operator comparing two equal Tokens returns true
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestTokenEqualOperatorReturnsTrueOnEqualTokens()
|
||||
{
|
||||
string testTokenValue = "123";
|
||||
Token.Type testTokenType = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType = Token.NumericType.Integer;
|
||||
uint testArityValue = 0;
|
||||
|
||||
string testTokenValue2 = "123";
|
||||
Token.Type testTokenType2 = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType2 = Token.NumericType.Integer;
|
||||
uint testArityValue2 = 0;
|
||||
|
||||
Token token1 = new(testTokenValue, testTokenType, testNumericType, testArityValue);
|
||||
Token token2 = new(testTokenValue2, testTokenType2, testNumericType2, testArityValue2);
|
||||
Assert.AreEqual(token1 == token2, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test for == operator comparing unequal Tokens returns false
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestTokenEqualOperatorReturnsFalseOnUnequalTokens()
|
||||
{
|
||||
string testTokenValue1 = "123";
|
||||
Token.Type testTokenType1 = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType1 = Token.NumericType.Integer;
|
||||
uint testArityValue1 = 0;
|
||||
|
||||
string testTokenValue2 = "125";
|
||||
Token.Type testTokenType2 = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType2 = Token.NumericType.Integer;
|
||||
uint testArityValue2 = 0;
|
||||
|
||||
string testTokenValue3 = "123";
|
||||
Token.Type testTokenType3 = Token.Type.Operator;
|
||||
Token.NumericType testNumericType3 = Token.NumericType.Integer;
|
||||
uint testArityValue3 = 0;
|
||||
|
||||
string testTokenValue4 = "123";
|
||||
Token.Type testTokenType4 = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType4 = Token.NumericType.Decimal;
|
||||
uint testArityValue4 = 0;
|
||||
|
||||
string testTokenValue5 = "123";
|
||||
Token.Type testTokenType5 = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType5 = Token.NumericType.Integer;
|
||||
uint testArityValue5 = 1;
|
||||
|
||||
Token token1 = new(testTokenValue1, testTokenType1, testNumericType1, testArityValue1);
|
||||
Token token2 = new(testTokenValue2, testTokenType2, testNumericType2, testArityValue2);
|
||||
Token token3 = new(testTokenValue3, testTokenType3, testNumericType3, testArityValue3);
|
||||
Token token4 = new(testTokenValue4, testTokenType4, testNumericType4, testArityValue4);
|
||||
Token token5 = new(testTokenValue5, testTokenType5, testNumericType5, testArityValue5);
|
||||
|
||||
Assert.AreEqual(token1 == token2, false);
|
||||
Assert.AreEqual(token1 == token3, false);
|
||||
Assert.AreEqual(token1 == token4, false);
|
||||
Assert.AreEqual(token1 == token5, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test for != operator comparing two equal Tokens returns true
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestTokenUnEqualOperatorReturnsFalseOnEqualTokens()
|
||||
{
|
||||
string testTokenValue = "123";
|
||||
Token.Type testTokenType = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType = Token.NumericType.Integer;
|
||||
uint testArityValue = 0;
|
||||
|
||||
Token token1 = new(testTokenValue, testTokenType, testNumericType, testArityValue);
|
||||
Token token2 = new(testTokenValue, testTokenType, testNumericType, testArityValue);
|
||||
Assert.AreEqual(token1 != token2, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test for != operator comparing unequal Tokens returns True
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestTokenUnEqualOperatorReturnsTrueOnUnequalTokens()
|
||||
{
|
||||
string testTokenValue1 = "123";
|
||||
Token.Type testTokenType1 = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType1 = Token.NumericType.Integer;
|
||||
uint testArityValue1 = 0;
|
||||
|
||||
string testTokenValue2 = "125";
|
||||
Token.Type testTokenType2 = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType2 = Token.NumericType.Integer;
|
||||
uint testArityValue2 = 0;
|
||||
|
||||
string testTokenValue3 = "123";
|
||||
Token.Type testTokenType3 = Token.Type.Operator;
|
||||
Token.NumericType testNumericType3 = Token.NumericType.Integer;
|
||||
uint testArityValue3 = 0;
|
||||
|
||||
string testTokenValue4 = "123";
|
||||
Token.Type testTokenType4 = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType4 = Token.NumericType.Decimal;
|
||||
uint testArityValue4 = 0;
|
||||
|
||||
string testTokenValue5 = "123";
|
||||
Token.Type testTokenType5 = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType5 = Token.NumericType.Integer;
|
||||
uint testArityValue5 = 1;
|
||||
|
||||
Token token1 = new(testTokenValue1, testTokenType1, testNumericType1, testArityValue1);
|
||||
Token token2 = new(testTokenValue2, testTokenType2, testNumericType2, testArityValue2);
|
||||
Token token3 = new(testTokenValue3, testTokenType3, testNumericType3, testArityValue3);
|
||||
Token token4 = new(testTokenValue4, testTokenType4, testNumericType4, testArityValue4);
|
||||
Token token5 = new(testTokenValue5, testTokenType5, testNumericType5, testArityValue5);
|
||||
|
||||
Assert.AreEqual(token1 != token2, true);
|
||||
Assert.AreEqual(token1 != token3, true);
|
||||
Assert.AreEqual(token1 != token4, true);
|
||||
Assert.AreEqual(token1 != token5, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test Equals method returns True when Tokens are equal
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestTokenEqualsMethodWithTokenObjectsReturnsTrueWhenEqual()
|
||||
{
|
||||
string testTokenValue = "123";
|
||||
Token.Type testTokenType = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType = Token.NumericType.Integer;
|
||||
uint testArityValue = 0;
|
||||
|
||||
string testTokenValue2 = "123";
|
||||
Token.Type testTokenType2 = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType2 = Token.NumericType.Integer;
|
||||
uint testArityValue2 = 0;
|
||||
|
||||
Token token1 = new(testTokenValue, testTokenType, testNumericType, testArityValue);
|
||||
Token token2 = new(testTokenValue2, testTokenType2, testNumericType2, testArityValue2);
|
||||
Assert.AreEqual(token1.Equals(token2), true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test Equals method returns False when Tokens are unequal
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestTokenEqualsMethodWithTokenObjectsReturnsFalseWhenUnequal()
|
||||
{
|
||||
string testTokenValue1 = "123";
|
||||
Token.Type testTokenType1 = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType1 = Token.NumericType.Integer;
|
||||
uint testArityValue1 = 0;
|
||||
|
||||
string testTokenValue2 = "125";
|
||||
Token.Type testTokenType2 = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType2 = Token.NumericType.Integer;
|
||||
uint testArityValue2 = 0;
|
||||
|
||||
string testTokenValue3 = "123";
|
||||
Token.Type testTokenType3 = Token.Type.Operator;
|
||||
Token.NumericType testNumericType3 = Token.NumericType.Integer;
|
||||
uint testArityValue3 = 0;
|
||||
|
||||
string testTokenValue4 = "123";
|
||||
Token.Type testTokenType4 = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType4 = Token.NumericType.Decimal;
|
||||
uint testArityValue4 = 0;
|
||||
|
||||
string testTokenValue5 = "123";
|
||||
Token.Type testTokenType5 = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType5 = Token.NumericType.Integer;
|
||||
uint testArityValue5 = 1;
|
||||
|
||||
Token token1 = new(testTokenValue1, testTokenType1, testNumericType1, testArityValue1);
|
||||
Token token2 = new(testTokenValue2, testTokenType2, testNumericType2, testArityValue2);
|
||||
Token token3 = new(testTokenValue3, testTokenType3, testNumericType3, testArityValue3);
|
||||
Token token4 = new(testTokenValue4, testTokenType4, testNumericType4, testArityValue4);
|
||||
Token token5 = new(testTokenValue5, testTokenType5, testNumericType5, testArityValue5);
|
||||
|
||||
Assert.AreEqual(token1.Equals(token2), false);
|
||||
Assert.AreEqual(token1.Equals(token3), false);
|
||||
Assert.AreEqual(token1.Equals(token4), false);
|
||||
Assert.AreEqual(token1.Equals(token5), false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test Equals method checks for Token equality when object is a token
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestTokenEqualsMethodWithObjectsThatIsATokenComparesForTokenEquality()
|
||||
{
|
||||
string testTokenValue = "123";
|
||||
Token.Type testTokenType = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType = Token.NumericType.Integer;
|
||||
uint testArityValue = 0;
|
||||
|
||||
string testTokenValue2 = "123";
|
||||
Token.Type testTokenType2 = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType2 = Token.NumericType.Integer;
|
||||
uint testArityValue2 = 0;
|
||||
|
||||
Token token1 = new(testTokenValue, testTokenType, testNumericType, testArityValue);
|
||||
Token token2 = new(testTokenValue2, testTokenType2, testNumericType2, testArityValue2);
|
||||
object token_obj = token2;
|
||||
Assert.AreEqual(token1.Equals(token_obj), true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test Equals method checks for returns false when object is not a token
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestTokenEqualsMethodWithObjectsThatIsNotATokenReturnsFalse()
|
||||
{
|
||||
string testTokenValue = "123";
|
||||
Token.Type testTokenType = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType = Token.NumericType.Integer;
|
||||
uint testArityValue = 0;
|
||||
|
||||
int non_token = 5;
|
||||
|
||||
Token token1 = new(testTokenValue, testTokenType, testNumericType, testArityValue);
|
||||
Assert.AreEqual(token1.Equals(non_token), false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test GetHashCode on two tokens with same values is the same
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestTokenGetHashCodeOnTwoTokensWhichHaveSameValuesAreEqual()
|
||||
{
|
||||
string testTokenValue = "123";
|
||||
Token.Type testTokenType = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType = Token.NumericType.Integer;
|
||||
uint testArityValue = 0;
|
||||
|
||||
string testTokenValue2 = "123";
|
||||
Token.Type testTokenType2 = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType2 = Token.NumericType.Integer;
|
||||
uint testArityValue2 = 0;
|
||||
|
||||
Token token1 = new(testTokenValue, testTokenType, testNumericType, testArityValue);
|
||||
Token token2 = new(testTokenValue2, testTokenType2, testNumericType2, testArityValue2);
|
||||
|
||||
int hash1 = token1.GetHashCode();
|
||||
int hash2 = token2.GetHashCode();
|
||||
Assert.AreEqual(hash1, hash2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test GetHashCode on two tokens with different values are different
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestTokenGetHashCodeOnTwoTokensWhichHaveDifferentValuesAreUnequal()
|
||||
{
|
||||
string testTokenValue = "123";
|
||||
Token.Type testTokenType = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType = Token.NumericType.Integer;
|
||||
uint testArityValue = 0;
|
||||
|
||||
string testTokenValue2 = "125";
|
||||
Token.Type testTokenType2 = Token.Type.Numeric;
|
||||
Token.NumericType testNumericType2 = Token.NumericType.Integer;
|
||||
uint testArityValue2 = 0;
|
||||
|
||||
Token token1 = new(testTokenValue, testTokenType, testNumericType, testArityValue);
|
||||
Token token2 = new(testTokenValue2, testTokenType2, testNumericType2, testArityValue2);
|
||||
|
||||
int hash1 = token1.GetHashCode();
|
||||
int hash2 = token2.GetHashCode();
|
||||
Assert.AreNotEqual(hash1, hash2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using MathEngine.Parser.Tokeniser;
|
||||
using MathEngine.Parser.Parser;
|
||||
namespace EngineTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for testing the TreeNode class
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class TreeNodeTests
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Test to see if a simple expression is constructed correctly
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestTreeNodexpression()
|
||||
{
|
||||
string testExp = "3+4";
|
||||
TreeNode exptectedTree = new(Token.Plus);
|
||||
Token tokfour = new("4", Token.Type.Numeric, Token.NumericType.Decimal, 0);
|
||||
Token tokthree = new("3", Token.Type.Numeric, Token.NumericType.Decimal, 0);
|
||||
TreeNode four = new(tokfour);
|
||||
TreeNode three = new(tokthree);
|
||||
exptectedTree.AddChildNode(four);
|
||||
exptectedTree.AddChildNode(three);
|
||||
ExpressionTree returnedTree = new (testExp);
|
||||
Assert.IsTrue(exptectedTree.Equals(returnedTree));
|
||||
}
|
||||
}
|
||||
}
|
||||
44
MathEngine/EngineTests/Tokenizer Tests/TokenTests.cs
Normal file
44
MathEngine/EngineTests/Tokenizer Tests/TokenTests.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using Xunit;
|
||||
|
||||
using MathEngine.Tokenizer;
|
||||
|
||||
using static MathEngine.Tokenizer.Token;
|
||||
|
||||
namespace EngineTests.Tokeniser
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for testing the Token
|
||||
/// </summary>
|
||||
public class TokenTests
|
||||
{
|
||||
public static IEnumerable<object[]> TestConstructorCases
|
||||
{
|
||||
get
|
||||
{
|
||||
return new List<object[]> {
|
||||
new object[] { "123", Token.TokenType.Numeric, (uint)0 },
|
||||
new object[] { "+", Token.TokenType.Operator, (uint)0 },
|
||||
new object[] { "Sin", Token.TokenType.Function, (uint)1 }
|
||||
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Test that Token constructor returns valid token
|
||||
/// </summary>
|
||||
[Theory]
|
||||
[MemberData(nameof(TestConstructorCases))]
|
||||
public void TestTokenConstructorReturnsToken(string value, int type, uint arity = 0)
|
||||
{
|
||||
TokenType t_type = (TokenType)(type);
|
||||
Token token = new(value, t_type, arity);
|
||||
Assert.Equal(token.Value, value);
|
||||
Assert.Equal(token.Type, t_type);
|
||||
Assert.Equal(token.Arity, arity);
|
||||
}
|
||||
}
|
||||
}
|
||||
115
MathEngine/EngineTests/Tokenizer Tests/TokenizerTests.cs
Normal file
115
MathEngine/EngineTests/Tokenizer Tests/TokenizerTests.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using Xunit;
|
||||
using MathEngine.Tokenizer;
|
||||
|
||||
using static MathEngine.Tokenizer.Token;
|
||||
using Xunit.Sdk;
|
||||
using System;
|
||||
|
||||
namespace EngineTests.Tokenizer
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for testing the Tokenizer
|
||||
/// </summary>
|
||||
public class TokenizerTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Test the Tokenizer on an empty string
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void TestTokenizeEmptystringReturnsEmptyList()
|
||||
{
|
||||
string testString = "";
|
||||
Token one = new("1", TokenType.Numeric);
|
||||
List<Token> expectedValue = new()
|
||||
{
|
||||
one,
|
||||
Token.Plus,
|
||||
one
|
||||
};
|
||||
List<Token> returnedValue = ExpressionTokenizer.Tokenize(testString);
|
||||
|
||||
Assert.Empty(returnedValue);
|
||||
}
|
||||
|
||||
|
||||
public static IEnumerable<object[]> TestTokenizeStringsCases
|
||||
{
|
||||
get
|
||||
{
|
||||
Token one = new("1", TokenType.Numeric);
|
||||
Token decimal_token = new("123.456", TokenType.Numeric);
|
||||
Token point_five = new(".5", TokenType.Numeric);
|
||||
List<Token> basic_expression = new List<Token> { one, Token.Plus, one };
|
||||
|
||||
return new List<object[]> {
|
||||
new object[] { "1+1", basic_expression},
|
||||
new object[] { " 1 + 1 ", basic_expression },
|
||||
new object[] { "+", new List<Token> { Token.Plus} },
|
||||
new object[] { "-", new List<Token> { Token.Minus} },
|
||||
new object[] { "*", new List<Token> { Token.Multiply} },
|
||||
new object[] { "/", new List<Token> { Token.Divide} },
|
||||
new object[] { "^", new List<Token> { Token.Exponentiation} },
|
||||
new object[] { "(", new List<Token> { Token.LeftParenthesis} },
|
||||
new object[] { ")", new List<Token> { Token.RightParenthesis} },
|
||||
new object[] { "123.456", new List<Token> { decimal_token } },
|
||||
new object[] { ".5", new List<Token> { point_five } },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the Tokenizer on strings
|
||||
/// </summary>
|
||||
[Theory]
|
||||
[MemberData(nameof(TestTokenizeStringsCases))]
|
||||
public void TestTokenizeStrings(string testString, object expectedResult)
|
||||
{
|
||||
List<Token> returnedValue = ExpressionTokenizer.Tokenize(testString.AsSpan());
|
||||
|
||||
Assert.Equal(expectedResult, returnedValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the Tokenizer on a basic string, but with significant ammounts of whitespace
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void TestTokenizeNumberWithMultipleDecimalPointsIsInvalid()
|
||||
{
|
||||
string test_expression = "123.456.789";
|
||||
|
||||
var ex = Assert.Throws<TokenizerException>(() => ExpressionTokenizer.Tokenize(test_expression.AsSpan()));
|
||||
|
||||
Assert.Equal("Syntax error: The number 123.456.789 has multiple decimal point when at most one is allowed.", ex.Message);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Test the Tokenizer with all operators
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void TestTokenizeStringWithAllOperators()
|
||||
{
|
||||
//Arrange
|
||||
string testString = "1+2-3*4/5";
|
||||
Token one = new("1", TokenType.Numeric);
|
||||
Token two = new("2", TokenType.Numeric);
|
||||
Token three = new("3", TokenType.Numeric);
|
||||
Token four = new("4", TokenType.Numeric);
|
||||
Token five = new("5", TokenType.Numeric);
|
||||
List<Token> expectedValue = new()
|
||||
{
|
||||
one,
|
||||
Token.Plus,
|
||||
two,
|
||||
Token.Minus,
|
||||
three,
|
||||
Token.Multiply,
|
||||
four,
|
||||
Token.Divide,
|
||||
five
|
||||
};
|
||||
List<Token> returnedValue = ExpressionTokenizer.Tokenize(testString);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
global using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
Reference in New Issue
Block a user