Remove unused parser
Parser was rendered obsolete upon port to Net Core Tool templates
This commit is contained in:
Родитель
c68aff6433
Коммит
c769ff3970
|
@ -1,157 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Parsers
|
||||
{
|
||||
/// <summary>
|
||||
/// Parser for expressions.
|
||||
/// </summary>
|
||||
public class ExpressionParser
|
||||
{
|
||||
private IEnumerator<Token> _tokens;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ExpressionParser"/> class.
|
||||
/// </summary>
|
||||
/// <param name="expression">The expression in string form.</param>
|
||||
public ExpressionParser(string expression)
|
||||
{
|
||||
_tokens = new Tokenizer().Scan(expression).GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates the expression using the specified parameters.
|
||||
/// </summary>
|
||||
/// <param name="context"> Expression parameter context.</param>
|
||||
/// <returns>The evaluation.</returns>
|
||||
public object Evaluate(Dictionary<string, object> context = null)
|
||||
{
|
||||
if (!_tokens.MoveNext())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var expression = BuildExpression();
|
||||
return expression.Evaluate(context);
|
||||
}
|
||||
|
||||
private Expression BuildExpression()
|
||||
{
|
||||
var operand = BuildOperand();
|
||||
|
||||
if (_tokens.Current is null)
|
||||
{
|
||||
return operand;
|
||||
}
|
||||
|
||||
if (_tokens.Current is OrOperatorToken)
|
||||
{
|
||||
_tokens.MoveNext();
|
||||
return new OrOperation(operand, BuildExpression());
|
||||
}
|
||||
|
||||
if (_tokens.Current is GreaterThanOperatorToken)
|
||||
{
|
||||
_tokens.MoveNext();
|
||||
return new GreaterThanOperation(operand, BuildExpression());
|
||||
}
|
||||
|
||||
throw new ParserException($"Expected operator; actual: {_tokens.Current}");
|
||||
}
|
||||
|
||||
private Expression BuildOperand()
|
||||
{
|
||||
if (_tokens.Current is null)
|
||||
{
|
||||
throw new ParserException($"Expected operand; reached end of expression.");
|
||||
}
|
||||
|
||||
if (!(_tokens.Current is OperandToken))
|
||||
{
|
||||
throw new ParserException($"Expected operand; actual: {_tokens.Current}");
|
||||
}
|
||||
|
||||
if (_tokens.Current is IntegerToken)
|
||||
{
|
||||
var iToken = _tokens.Current as IntegerToken;
|
||||
_tokens.MoveNext();
|
||||
return BuildInteger(iToken);
|
||||
}
|
||||
|
||||
var nToken = _tokens.Current as NameToken;
|
||||
_tokens.MoveNext();
|
||||
if (_tokens.Current is ParenOpenToken)
|
||||
{
|
||||
_tokens.MoveNext();
|
||||
return BuildFunction(nToken);
|
||||
}
|
||||
|
||||
return BuildParameter(nToken);
|
||||
}
|
||||
|
||||
private Expression BuildInteger(IntegerToken iToken)
|
||||
{
|
||||
return new Integer(iToken.Value);
|
||||
}
|
||||
|
||||
private Expression BuildParameter(NameToken nToken)
|
||||
{
|
||||
return new Parameter(nToken.Name);
|
||||
}
|
||||
|
||||
private Expression BuildFunction(NameToken nToken)
|
||||
{
|
||||
if (_tokens.Current is null)
|
||||
{
|
||||
throw new ParserException("Expected operand or close parenthesis; reached end of expression.");
|
||||
}
|
||||
|
||||
if (!(_tokens.Current is NameToken || _tokens.Current is ParenCloseToken))
|
||||
{
|
||||
throw new ParserException($"Expected operand or close parenthesis; actual: {_tokens.Current}");
|
||||
}
|
||||
|
||||
var parameters = new List<Expression>();
|
||||
while (!(_tokens.Current is ParenCloseToken))
|
||||
{
|
||||
if (parameters.Count > 0)
|
||||
{
|
||||
if (!(_tokens.Current is CommaToken))
|
||||
{
|
||||
throw new ParserException("Expected comma or close parenthesis; reached end of expression.");
|
||||
}
|
||||
|
||||
_tokens.MoveNext();
|
||||
}
|
||||
|
||||
if (_tokens.Current is null)
|
||||
{
|
||||
throw new ParserException("Expected operand or close parenthesis; reached end of expression.");
|
||||
}
|
||||
|
||||
if (!(_tokens.Current is NameToken || _tokens.Current is ParenCloseToken))
|
||||
{
|
||||
throw new ParserException($"Expected operand or close parenthesis; actual: {_tokens.Current}");
|
||||
}
|
||||
|
||||
parameters.Add(BuildOperand());
|
||||
}
|
||||
|
||||
if (!(_tokens.Current is ParenCloseToken))
|
||||
{
|
||||
throw new ParserException($"Expected operand or close parenthesis; actual: {_tokens.Current}");
|
||||
}
|
||||
|
||||
_tokens.MoveNext();
|
||||
if (nToken.Name.Equals("count"))
|
||||
{
|
||||
return new Count(parameters);
|
||||
}
|
||||
|
||||
throw new ParserException($"Unknown function: {nToken}");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Parsers
|
||||
{
|
||||
internal abstract class Expression
|
||||
{
|
||||
internal abstract object Evaluate(Dictionary<string, object> context);
|
||||
}
|
||||
|
||||
internal class Integer : Expression
|
||||
{
|
||||
internal Integer(int i)
|
||||
{
|
||||
Value = i;
|
||||
}
|
||||
|
||||
private int Value { get; }
|
||||
|
||||
internal override object Evaluate(Dictionary<string, object> context)
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Parameter : Expression
|
||||
{
|
||||
internal Parameter(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
private string Name { get; }
|
||||
|
||||
internal override object Evaluate(Dictionary<string, object> context)
|
||||
{
|
||||
context.TryGetValue(Name, out var value);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
internal class OrOperation : Expression
|
||||
{
|
||||
internal OrOperation(Expression left, Expression right)
|
||||
{
|
||||
Left = left;
|
||||
Right = right;
|
||||
}
|
||||
|
||||
private Expression Left { get; }
|
||||
|
||||
private Expression Right { get; }
|
||||
|
||||
internal override object Evaluate(Dictionary<string, object> context)
|
||||
{
|
||||
var left = ToBool(Left.Evaluate(context));
|
||||
var right = ToBool(Right.Evaluate(context));
|
||||
return left || right;
|
||||
}
|
||||
|
||||
private static bool ToBool(object value)
|
||||
{
|
||||
if (value is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value is bool b)
|
||||
{
|
||||
return b;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal class GreaterThanOperation : Expression
|
||||
{
|
||||
internal GreaterThanOperation(Expression left, Expression right)
|
||||
{
|
||||
Left = left;
|
||||
Right = right;
|
||||
}
|
||||
|
||||
private Expression Left { get; }
|
||||
|
||||
private Expression Right { get; }
|
||||
|
||||
internal override object Evaluate(Dictionary<string, object> context)
|
||||
{
|
||||
var left = (int)Left.Evaluate(context);
|
||||
var right = (int)Right.Evaluate(context);
|
||||
return left > right;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Count : Expression
|
||||
{
|
||||
internal Count(IEnumerable<Expression> expressions)
|
||||
{
|
||||
Expressions = expressions;
|
||||
}
|
||||
|
||||
private IEnumerable<Expression> Expressions { get; }
|
||||
|
||||
internal override object Evaluate(Dictionary<string, object> context)
|
||||
{
|
||||
int count = 0;
|
||||
foreach (var expression in Expressions)
|
||||
{
|
||||
var value = expression.Evaluate(context);
|
||||
if (value != null)
|
||||
{
|
||||
if (value is bool)
|
||||
{
|
||||
if ((bool)value)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Parsers
|
||||
{
|
||||
/// <summary>
|
||||
/// The exception that is throw when an parser encounters an error.
|
||||
/// </summary>
|
||||
public class ParserException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ParserException"/> class.
|
||||
/// </summary>
|
||||
public ParserException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
# Grammars
|
||||
|
||||
## Expression
|
||||
|
||||
```
|
||||
<expression> := <operand> | <operand> <operator> <expression>
|
||||
<operand> := <parameter> | <function> | <integer>
|
||||
<parameter := <name>
|
||||
<parameter-list> := <parameter> | <parameter> "," <parameter-list>
|
||||
<function> := <name> "(" ")" | <name> "(" <parameter-list> ")"
|
||||
<name> := <letter> | <letter> <char-list>
|
||||
<char-list> := <char> | <char> <char-list>
|
||||
<char> := <letter> | <digit> | <special>
|
||||
<letter> := <upper> | <lower>
|
||||
<upper> := "A" | "B" | ... | "Z"
|
||||
<lower> := "a" | "b" | ... | "z"
|
||||
<integer> := <digit> | <digit> <integer>
|
||||
<digit> := "0" | "1" | ... | "9"
|
||||
<special> := "-"
|
||||
<operator> := "||"
|
||||
```
|
|
@ -1,116 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
[assembly: InternalsVisibleTo("Steeltoe.InitializrApi.Test.Unit")]
|
||||
|
||||
namespace Steeltoe.InitializrApi.Parsers
|
||||
{
|
||||
internal class Tokenizer
|
||||
{
|
||||
private const int EndOfString = -1;
|
||||
|
||||
internal IEnumerable<Token> Scan(string expression)
|
||||
{
|
||||
using var reader = new StringReader(expression);
|
||||
var tokens = new List<Token>();
|
||||
while (reader.Peek() != EndOfString)
|
||||
{
|
||||
var ch = (char)reader.Peek();
|
||||
|
||||
if (char.IsWhiteSpace(ch))
|
||||
{
|
||||
reader.Read();
|
||||
}
|
||||
else if (char.IsDigit(ch))
|
||||
{
|
||||
var i = ReadInteger(reader);
|
||||
tokens.Add(new IntegerToken(i));
|
||||
}
|
||||
else if (char.IsLetter(ch))
|
||||
{
|
||||
var name = ReadName(reader);
|
||||
tokens.Add(new NameToken(name));
|
||||
}
|
||||
else if (ch.Equals(','))
|
||||
{
|
||||
reader.Read();
|
||||
tokens.Add(new CommaToken());
|
||||
}
|
||||
else if (ch.Equals('('))
|
||||
{
|
||||
reader.Read();
|
||||
tokens.Add(new ParenOpenToken());
|
||||
}
|
||||
else if (ch.Equals(')'))
|
||||
{
|
||||
reader.Read();
|
||||
tokens.Add(new ParenCloseToken());
|
||||
}
|
||||
else if (ch.Equals('|'))
|
||||
{
|
||||
reader.Read();
|
||||
ch = (char)reader.Read();
|
||||
if (!ch.Equals('|'))
|
||||
{
|
||||
throw new ArgumentException("expected: '|'");
|
||||
}
|
||||
|
||||
tokens.Add(new OrOperatorToken());
|
||||
}
|
||||
else if (ch.Equals('>'))
|
||||
{
|
||||
reader.Read();
|
||||
tokens.Add(new GreaterThanOperatorToken());
|
||||
}
|
||||
else
|
||||
{
|
||||
tokens.Add(new UnknownToken(ch));
|
||||
reader.Read();
|
||||
}
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
private int ReadInteger(StringReader reader)
|
||||
{
|
||||
var buf = new StringBuilder();
|
||||
while (true)
|
||||
{
|
||||
var ch = (char)reader.Peek();
|
||||
if (!char.IsDigit(ch))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
buf.Append((char)reader.Read());
|
||||
}
|
||||
|
||||
return int.Parse(buf.ToString());
|
||||
}
|
||||
|
||||
private string ReadName(StringReader reader)
|
||||
{
|
||||
var buf = new StringBuilder();
|
||||
while (true)
|
||||
{
|
||||
var ch = (char)reader.Peek();
|
||||
if (!(char.IsLetterOrDigit(ch) || ch == '-'))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
buf.Append((char)reader.Read());
|
||||
}
|
||||
|
||||
return buf.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Steeltoe.InitializrApi.Parsers
|
||||
{
|
||||
internal abstract class Token
|
||||
{
|
||||
}
|
||||
|
||||
internal class UnknownToken : Token
|
||||
{
|
||||
internal UnknownToken(char value) => Value = value;
|
||||
|
||||
internal char Value { get; }
|
||||
|
||||
public override string ToString() => $"'{Value}' (unknown)";
|
||||
}
|
||||
|
||||
internal abstract class OperandToken : Token
|
||||
{
|
||||
}
|
||||
|
||||
internal class IntegerToken : OperandToken
|
||||
{
|
||||
public IntegerToken(int i)
|
||||
{
|
||||
Value = i;
|
||||
}
|
||||
|
||||
internal int Value { get; }
|
||||
|
||||
public override string ToString() => $"'{Value}' (integer)";
|
||||
}
|
||||
|
||||
internal abstract class NamedToken : OperandToken
|
||||
{
|
||||
internal NamedToken(string name) => Name = name;
|
||||
|
||||
internal string Name { get; }
|
||||
}
|
||||
|
||||
internal class NameToken : NamedToken
|
||||
{
|
||||
internal NameToken(string name)
|
||||
: base(name)
|
||||
{
|
||||
}
|
||||
|
||||
public override string ToString() => $"'{Name}' (name)";
|
||||
}
|
||||
|
||||
internal abstract class OperatorToken : Token
|
||||
{
|
||||
}
|
||||
|
||||
internal abstract class BooleanOperatorToken : OperatorToken
|
||||
{
|
||||
}
|
||||
|
||||
internal class OrOperatorToken : BooleanOperatorToken
|
||||
{
|
||||
public override string ToString() => $"'||' (or)";
|
||||
}
|
||||
|
||||
internal class GreaterThanOperatorToken : BooleanOperatorToken
|
||||
{
|
||||
public override string ToString() => $"'>' (greater than)";
|
||||
}
|
||||
|
||||
internal class ParenOpenToken : Token
|
||||
{
|
||||
public override string ToString() => $"'(' (paren open)";
|
||||
}
|
||||
|
||||
internal class ParenCloseToken : Token
|
||||
{
|
||||
public override string ToString() => $"')' (paren close)";
|
||||
}
|
||||
|
||||
internal class CommaToken : Token
|
||||
{
|
||||
public override string ToString() => $"',' (comma)";
|
||||
}
|
||||
}
|
|
@ -1,360 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FluentAssertions;
|
||||
using Steeltoe.InitializrApi.Parsers;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Unit.Parsers
|
||||
{
|
||||
public class ExpressionParserTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void Empty_Token_List_Should_Evaluate_To_Null()
|
||||
{
|
||||
// Arrange
|
||||
var expression = new ExpressionParser(String.Empty);
|
||||
|
||||
// Act
|
||||
var result = expression.Evaluate();
|
||||
|
||||
// Assert
|
||||
result.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Integer_Should_Evaluate_To_Integer()
|
||||
{
|
||||
// Arrange
|
||||
var expression = new ExpressionParser("725");
|
||||
|
||||
// Act
|
||||
var result = expression.Evaluate();
|
||||
|
||||
// Assert
|
||||
result.Should().Be(725);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void True_Parameter_Should_Evaluate_To_True()
|
||||
{
|
||||
// Arrange
|
||||
var expression = new ExpressionParser("my-var");
|
||||
var context = new Dictionary<string, object>
|
||||
{
|
||||
{ "my-var", true },
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = expression.Evaluate(context);
|
||||
|
||||
// Assert
|
||||
result.Should().Be(true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void False_Parameter_Should_Evaluate_To_False()
|
||||
{
|
||||
// Arrange
|
||||
var expression = new ExpressionParser("my-var");
|
||||
var context = new Dictionary<string, object>
|
||||
{
|
||||
{ "my-var", false },
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = expression.Evaluate(context);
|
||||
|
||||
// Assert
|
||||
result.Should().Be(false);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Null_Parameter_Should_Evaluate_To_Null()
|
||||
{
|
||||
// Arrange
|
||||
var expression = new ExpressionParser("my-var");
|
||||
var context = new Dictionary<string, object>();
|
||||
|
||||
// Act
|
||||
var result = expression.Evaluate(context);
|
||||
|
||||
// Assert
|
||||
result.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Or_Operand_Should_Should_Evaluate_Per_Boolean_Rules()
|
||||
{
|
||||
// Arrange
|
||||
var expressionTt = new ExpressionParser("T1 || T2");
|
||||
var expressionTf = new ExpressionParser("T1 || F1");
|
||||
var expressionTn = new ExpressionParser("T1 || N1");
|
||||
var expressionFt = new ExpressionParser("F1 || T1");
|
||||
var expressionFf = new ExpressionParser("F1 || F2");
|
||||
var expressionFn = new ExpressionParser("F1 || N1");
|
||||
var expressionNt = new ExpressionParser("N1 || T1");
|
||||
var expressionNf = new ExpressionParser("N1 || F1");
|
||||
var expressionNn = new ExpressionParser("N1 || N2");
|
||||
var context = new Dictionary<string, object>
|
||||
{
|
||||
{ "T1", true },
|
||||
{ "T2", true },
|
||||
{ "F1", false },
|
||||
{ "F2", false },
|
||||
};
|
||||
|
||||
// Act
|
||||
var resultTt = expressionTt.Evaluate(context);
|
||||
var resultTf = expressionTf.Evaluate(context);
|
||||
var resultTn = expressionTn.Evaluate(context);
|
||||
var resultFt = expressionFt.Evaluate(context);
|
||||
var resultFf = expressionFf.Evaluate(context);
|
||||
var resultFn = expressionFn.Evaluate(context);
|
||||
var resultNt = expressionNt.Evaluate(context);
|
||||
var resultNf = expressionNf.Evaluate(context);
|
||||
var resultNn = expressionNn.Evaluate(context);
|
||||
|
||||
// Assert
|
||||
resultTt.Should().Be(true);
|
||||
resultTf.Should().Be(true);
|
||||
resultTn.Should().Be(true);
|
||||
resultFt.Should().Be(true);
|
||||
resultFf.Should().Be(false);
|
||||
resultFn.Should().Be(false);
|
||||
resultNt.Should().Be(true);
|
||||
resultNf.Should().Be(false);
|
||||
resultNn.Should().Be(false);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GreaterThan_Operand_Should_Should_Evaluate_Any_Operand()
|
||||
{
|
||||
// Arrange
|
||||
var expression1 = new ExpressionParser("1 > 0");
|
||||
var expression2 = new ExpressionParser("1 > 1");
|
||||
var expression3 = new ExpressionParser("1 > 2");
|
||||
var expression4 = new ExpressionParser("count(T1,T2) > 1");
|
||||
var expression5 = new ExpressionParser("count(T1,T2) > 3");
|
||||
var context = new Dictionary<string, object>
|
||||
{
|
||||
{ "T1", true },
|
||||
{ "T2", true },
|
||||
};
|
||||
|
||||
// Act
|
||||
var result1 = expression1.Evaluate(context);
|
||||
var result2 = expression2.Evaluate(context);
|
||||
var result3 = expression3.Evaluate(context);
|
||||
var result4 = expression4.Evaluate(context);
|
||||
var result5 = expression5.Evaluate(context);
|
||||
|
||||
// Assert
|
||||
result1.Should().Be(true);
|
||||
result2.Should().Be(false);
|
||||
result3.Should().Be(false);
|
||||
result4.Should().Be(true);
|
||||
result5.Should().Be(false);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Complex_Or_Operand_Should_Should_Evaluate_Per_Boolean_Rules()
|
||||
{
|
||||
// Arrange
|
||||
var expressionFff = new ExpressionParser("F1 || F2 || F3");
|
||||
var expressionNnn = new ExpressionParser("N1 || N2 || N3");
|
||||
var expressionTtt = new ExpressionParser("T1 || T2 || T3");
|
||||
var expressionTfn = new ExpressionParser("T1 || F1 || N1");
|
||||
var context = new Dictionary<string, object>
|
||||
{
|
||||
{ "T1", true },
|
||||
{ "T2", true },
|
||||
{ "T3", true },
|
||||
{ "F1", false },
|
||||
{ "F2", false },
|
||||
{ "F3", false },
|
||||
};
|
||||
|
||||
// Act
|
||||
var resultFff = expressionFff.Evaluate(context);
|
||||
var resultNnn = expressionNnn.Evaluate(context);
|
||||
var resultTtt = expressionTtt.Evaluate(context);
|
||||
var resultTfn = expressionTfn.Evaluate(context);
|
||||
|
||||
// Assert
|
||||
resultFff.Should().Be(false);
|
||||
resultNnn.Should().Be(false);
|
||||
resultTtt.Should().Be(true);
|
||||
resultTfn.Should().Be(true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Deep_Expression_Should_Should_Evaluate_Per_Boolean_Rules()
|
||||
{
|
||||
// Arrange
|
||||
var expressionNnnnn = new ExpressionParser("N1 || N2 || N3 || N4 || N5");
|
||||
var expressionNnnnt = new ExpressionParser("N1 || N2 || N3 || N4 || T1");
|
||||
var context = new Dictionary<string, object>
|
||||
{
|
||||
{ "T1", true },
|
||||
};
|
||||
|
||||
// Act
|
||||
var resultNnnnn = expressionNnnnn.Evaluate(context);
|
||||
var resultNnnnt = expressionNnnnt.Evaluate(context);
|
||||
|
||||
// Assert
|
||||
resultNnnnn.Should().Be(false);
|
||||
resultNnnnt.Should().Be(true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Count_Should_Count_True_And_NonNull_Values()
|
||||
{
|
||||
// Arrange
|
||||
var expression1 = new ExpressionParser("count(F1)");
|
||||
var expression2 = new ExpressionParser("count(T1)");
|
||||
var expression3 = new ExpressionParser("count(N1)");
|
||||
var expression4 = new ExpressionParser("count(V1)");
|
||||
var expression5 = new ExpressionParser("count(V1,T1,N1,F1,V2,N2,F2)");
|
||||
var context = new Dictionary<string, object>
|
||||
{
|
||||
{ "T1", true },
|
||||
{ "V1", "val1" },
|
||||
{ "V2", "val1" },
|
||||
};
|
||||
|
||||
// Act
|
||||
var result1 = expression1.Evaluate(context);
|
||||
var result2 = expression2.Evaluate(context);
|
||||
var result3 = expression3.Evaluate(context);
|
||||
var result4 = expression4.Evaluate(context);
|
||||
var result5 = expression5.Evaluate(context);
|
||||
|
||||
// Assert
|
||||
result1.Should().Be(0);
|
||||
result2.Should().Be(1);
|
||||
result3.Should().Be(0);
|
||||
result4.Should().Be(1);
|
||||
result5.Should().Be(3);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void Malformed_Expression_Should_Throw_Exception()
|
||||
{
|
||||
// Arrange
|
||||
var expression1 = new ExpressionParser("-");
|
||||
var expression2 = new ExpressionParser("(");
|
||||
var expression3 = new ExpressionParser(")");
|
||||
|
||||
// Act
|
||||
Action act1 = () => expression1.Evaluate();
|
||||
Action act2 = () => expression2.Evaluate();
|
||||
Action act3 = () => expression3.Evaluate();
|
||||
|
||||
// Assert
|
||||
act1.Should().Throw<ParserException>().WithMessage("Expected operand; actual: '-' (unknown)");
|
||||
act2.Should().Throw<ParserException>().WithMessage("Expected operand; actual: '(' (paren open)");
|
||||
act3.Should().Throw<ParserException>().WithMessage("Expected operand; actual: ')' (paren close)");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Missing_Operand_Should_Throw_Exception()
|
||||
{
|
||||
// Arrange
|
||||
var expression1 = new ExpressionParser("||");
|
||||
var expression2 = new ExpressionParser("V ||");
|
||||
var expression3 = new ExpressionParser("V || ||");
|
||||
|
||||
// Act
|
||||
Action act1 = () => expression1.Evaluate();
|
||||
Action act2 = () => expression2.Evaluate();
|
||||
Action act3 = () => expression3.Evaluate();
|
||||
|
||||
// Assert
|
||||
act1.Should().Throw<ParserException>().WithMessage("Expected operand; actual: '||' (or)");
|
||||
act2.Should().Throw<ParserException>().WithMessage("Expected operand; reached end of expression.");
|
||||
act3.Should().Throw<ParserException>().WithMessage("Expected operand; actual: '||' (or)");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Missing_Operator_Should_Throw_Exception()
|
||||
{
|
||||
// Arrange
|
||||
var expression = new ExpressionParser("V V");
|
||||
|
||||
// Act
|
||||
Action act = () => expression.Evaluate();
|
||||
|
||||
// Assert
|
||||
act.Should().Throw<ParserException>().WithMessage("Expected operator; actual: 'V' (name)");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Function_Missing_Paren_Close_Should_Throw_Exception()
|
||||
{
|
||||
// Arrange
|
||||
var expression1 = new ExpressionParser("myfunc(");
|
||||
var expression2 = new ExpressionParser("myfunc(@");
|
||||
var expression3 = new ExpressionParser("myfunc(,");
|
||||
var expression4 = new ExpressionParser("myfunc(V");
|
||||
var expression5 = new ExpressionParser("myfunc(V,");
|
||||
var expression6 = new ExpressionParser("myfunc(V,@");
|
||||
var expression7 = new ExpressionParser("myfunc(V0,V1");
|
||||
var expression8 = new ExpressionParser("myfunc(V0,V1,");
|
||||
var expression9 = new ExpressionParser("myfunc(V0,V1,@");
|
||||
|
||||
// Act
|
||||
Action act1 = () => expression1.Evaluate();
|
||||
Action act2 = () => expression2.Evaluate();
|
||||
Action act3 = () => expression3.Evaluate();
|
||||
Action act4 = () => expression4.Evaluate();
|
||||
Action act5 = () => expression5.Evaluate();
|
||||
Action act6 = () => expression6.Evaluate();
|
||||
Action act7 = () => expression7.Evaluate();
|
||||
Action act8 = () => expression8.Evaluate();
|
||||
Action act9 = () => expression9.Evaluate();
|
||||
|
||||
// Assert
|
||||
act1.Should().Throw<ParserException>()
|
||||
.WithMessage("Expected operand or close parenthesis; reached end of expression.");
|
||||
act2.Should().Throw<ParserException>().WithMessage("Expected operand or close parenthesis; actual: '@' (unknown)");
|
||||
act3.Should().Throw<ParserException>()
|
||||
.WithMessage("Expected operand or close parenthesis; actual: ',' (comma)");
|
||||
act4.Should().Throw<ParserException>()
|
||||
.WithMessage("Expected comma or close parenthesis; reached end of expression.");
|
||||
act5.Should().Throw<ParserException>()
|
||||
.WithMessage("Expected operand or close parenthesis; reached end of expression.");
|
||||
act6.Should().Throw<ParserException>().WithMessage("Expected operand or close parenthesis; actual: '@' (unknown)");
|
||||
act7.Should().Throw<ParserException>()
|
||||
.WithMessage("Expected comma or close parenthesis; reached end of expression.");
|
||||
act8.Should().Throw<ParserException>()
|
||||
.WithMessage("Expected operand or close parenthesis; reached end of expression.");
|
||||
act9.Should().Throw<ParserException>().WithMessage("Expected operand or close parenthesis; actual: '@' (unknown)");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Unknown_Function_Should_Throw_Exception()
|
||||
{
|
||||
// Arrange
|
||||
var expression = new ExpressionParser("unknownF()");
|
||||
|
||||
// Act
|
||||
Action act = () => expression.Evaluate();
|
||||
|
||||
// Assert
|
||||
act.Should().Throw<ParserException>().WithMessage("Unknown function: 'unknownF' (name)");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,215 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using Steeltoe.InitializrApi.Parsers;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Unit.Parsers
|
||||
{
|
||||
public class TokenizerTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void Empty_String_Should_Return_Zero_Tokens()
|
||||
{
|
||||
// Arrange
|
||||
var expr = string.Empty;
|
||||
var tokenizer = new Tokenizer();
|
||||
|
||||
// Act
|
||||
var tokens = tokenizer.Scan(expr).ToList();
|
||||
|
||||
|
||||
// Asserty
|
||||
tokens.Count.Should().Be(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Whitespace_Should_Return_Zero_Tokens()
|
||||
{
|
||||
// Arrange
|
||||
var expr = " \f\n\r\t\v";
|
||||
var tokenizer = new Tokenizer();
|
||||
|
||||
// Act
|
||||
var tokens = tokenizer.Scan(expr).ToList();
|
||||
|
||||
|
||||
// Assert
|
||||
tokens.Count.Should().Be(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Scan_Should_Yield_UnknownToken()
|
||||
{
|
||||
// Arrange
|
||||
var expr = "@";
|
||||
var tokenizer = new Tokenizer();
|
||||
|
||||
// Act
|
||||
var tokens = tokenizer.Scan(expr).ToList();
|
||||
|
||||
|
||||
// Assert
|
||||
tokens.Count.Should().Be(1);
|
||||
var token = Assert.IsType<UnknownToken>(tokens[0]);
|
||||
token.Value.Should().Be('@');
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Scan_Should_Yield_IntegerToken()
|
||||
{
|
||||
// Arrange
|
||||
var expr = "123";
|
||||
var tokenizer = new Tokenizer();
|
||||
|
||||
// Act
|
||||
var tokens = tokenizer.Scan(expr).ToList();
|
||||
|
||||
|
||||
// Assert
|
||||
tokens.Count.Should().Be(1);
|
||||
var token = Assert.IsType<IntegerToken>(tokens[0]);
|
||||
token.Value.Should().Be(123);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Scan_Should_Yield_NameToken()
|
||||
{
|
||||
// Arrange
|
||||
var expr = " my-name ";
|
||||
var tokenizer = new Tokenizer();
|
||||
|
||||
// Act
|
||||
var tokens = tokenizer.Scan(expr).ToList();
|
||||
|
||||
// Assert
|
||||
tokens.Count.Should().Be(1);
|
||||
var token = Assert.IsType<NameToken>(tokens[0]);
|
||||
token.Name.Should().Be("my-name");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Scan_Should_Yield_OrOperatorToken()
|
||||
{
|
||||
// Arrange
|
||||
var expr = "||";
|
||||
var tokenizer = new Tokenizer();
|
||||
|
||||
// Act
|
||||
var tokens = tokenizer.Scan(expr).ToList();
|
||||
|
||||
|
||||
// Assert
|
||||
tokens.Count.Should().Be(1);
|
||||
Assert.IsType<OrOperatorToken>(tokens[0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Scan_Should_Yield_GreaterThanOperatorToken()
|
||||
{
|
||||
// Arrange
|
||||
var expr = ">";
|
||||
var tokenizer = new Tokenizer();
|
||||
|
||||
// Act
|
||||
var tokens = tokenizer.Scan(expr).ToList();
|
||||
|
||||
|
||||
// Assert
|
||||
tokens.Count.Should().Be(1);
|
||||
Assert.IsType<GreaterThanOperatorToken>(tokens[0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Scan_Should_Yield_ParenOpenToken()
|
||||
{
|
||||
// Arrange
|
||||
var expr = "(";
|
||||
var tokenizer = new Tokenizer();
|
||||
|
||||
// Act
|
||||
var tokens = tokenizer.Scan(expr).ToList();
|
||||
|
||||
|
||||
// Assert
|
||||
tokens.Count.Should().Be(1);
|
||||
Assert.IsType<ParenOpenToken>(tokens[0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Scan_Should_Yield_ParenCloseToken()
|
||||
{
|
||||
// Arrange
|
||||
var expr = ")";
|
||||
var tokenizer = new Tokenizer();
|
||||
|
||||
// Act
|
||||
var tokens = tokenizer.Scan(expr).ToList();
|
||||
|
||||
|
||||
// Assert
|
||||
tokens.Count.Should().Be(1);
|
||||
Assert.IsType<ParenCloseToken>(tokens[0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Scan_Should_Yield_CommaToken()
|
||||
{
|
||||
// Arrange
|
||||
var expr = ",";
|
||||
var tokenizer = new Tokenizer();
|
||||
|
||||
// Act
|
||||
var tokens = tokenizer.Scan(expr).ToList();
|
||||
|
||||
|
||||
// Assert
|
||||
tokens.Count.Should().Be(1);
|
||||
Assert.IsType<CommaToken>(tokens[0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Scan_Should_Find_Multiple_Tokens()
|
||||
{
|
||||
// Arrange
|
||||
var expr = "|| MyName";
|
||||
var tokenizer = new Tokenizer();
|
||||
|
||||
// Act
|
||||
var tokens = tokenizer.Scan(expr).ToList();
|
||||
|
||||
|
||||
// Assert
|
||||
tokens.Count.Should().Be(2);
|
||||
Assert.IsType<OrOperatorToken>(tokens[0]);
|
||||
Assert.IsType<NameToken>(tokens[1]);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void Incomplete_Or_Operator_Should_Throw_ArgumentException()
|
||||
{
|
||||
// Arrange
|
||||
var expr = "|";
|
||||
var tokenizer = new Tokenizer();
|
||||
|
||||
// Act
|
||||
Action act = () => tokenizer.Scan(expr);
|
||||
|
||||
|
||||
// Assert
|
||||
act.Should().Throw<ArgumentException>().WithMessage("Expected: '|'");
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче