Step 2 in renaming Orchard.Scripting to Orchard.Scripting.Dlr

--HG--
branch : dev
rename : src/Orchard.Tests.Modules/Scripting/ScriptingTests.cs => src/Orchard.Tests.Modules/Scripting.Dlr/ScriptingTests.cs
rename : src/Orchard.Tests.Modules/SimpleScripting/EvaluatorTests.cs => src/Orchard.Tests.Modules/Scripting/EvaluatorTests.cs
rename : src/Orchard.Tests.Modules/SimpleScripting/ParserTests.cs => src/Orchard.Tests.Modules/Scripting/ParserTests.cs
rename : src/Orchard.Tests.Modules/SimpleScripting/SimpleScriptingTests.cs => src/Orchard.Tests.Modules/Scripting/SimpleScriptingTests.cs
rename : src/Orchard.Tests.Modules/SimpleScripting/TokenizerTests.cs => src/Orchard.Tests.Modules/Scripting/TokenizerTests.cs
rename : src/Orchard.Web/Modules/Orchard.Scripting.Dlr/Orchard.Scripting.csproj => src/Orchard.Web/Modules/Orchard.Scripting.Dlr/Orchard.Scripting.Dlr.csproj
This commit is contained in:
Renaud Paquay
2010-11-28 10:01:59 -08:00
parent 02b0d69621
commit 5cdb528d2b
16 changed files with 28 additions and 28 deletions

View File

@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using NUnit.Framework;
using Orchard.Widgets.SimpleScripting.Compiler;
namespace Orchard.Tests.Modules.Scripting {
[TestFixture]
public class EvaluatorTests {
[Test]
public void EvaluateSimpleConstant() {
var result = EvaluateSimpleExpression("true and true");
Assert.That(result.IsError, Is.False);
Assert.That(result.Value, Is.EqualTo(true));
}
[Test]
public void EvaluateInvalidBooleanExpression() {
var result = EvaluateSimpleExpression("true and 1");
Assert.That(result.IsError, Is.True);
}
[Test]
public void EvaluateBooleanExpression() {
var result = EvaluateSimpleExpression("not true");
Assert.That(result.IsError, Is.False);
Assert.That(result.BoolValue, Is.EqualTo(false));
}
[Test]
public void EvaluateSimpleArithmetic() {
var result = EvaluateSimpleExpression("1 + 2 * 3 - 6 / 2");
Assert.That(result.IsError, Is.False);
Assert.That(result.Value, Is.EqualTo(4));
}
[Test]
public void EvaluateSimpleMethodCall() {
var result = EvaluateSimpleExpression("print 1 + 2 * 3 - 6 / 2",
(m, args) => (m == "print") ? (int)args[0] * 2 : 0);
Assert.That(result.IsError, Is.False);
Assert.That(result.Value, Is.EqualTo(4 * 2));
}
[Test]
public void EvaluateSimpleMethodCall2() {
var result = EvaluateSimpleExpression("foo 1 + bar 3",
(m, args) =>
(m == "foo") ? (int)args[0] * 2 :
(m == "bar") ? (int)args[0] : 0);
Assert.That(result.IsError, Is.False);
Assert.That(result.Value, Is.EqualTo(2 * (1 + 3)));
}
[Test]
public void EvaluateSimpleMethodCall3() {
var result = EvaluateSimpleExpression("foo(1) + bar(3)",
(m, args) =>
(m == "foo") ? (int)args[0] * 2 :
(m == "bar") ? (int)args[0] : 0);
Assert.That(result.IsError, Is.False);
Assert.That(result.Value, Is.EqualTo(2 + 3));
}
[Test]
public void EvaluateSimpleMethodCall4() {
var result = EvaluateSimpleExpression("foo",
(m, args) => (m == "foo") ? true : false);
Assert.That(result.IsError, Is.False);
Assert.That(result.Value, Is.EqualTo(true));
}
[Test]
public void EvaluateSimpleMethodCall5() {
var result = EvaluateSimpleExpression("foo()",
(m, args) => (m == "foo") ? true : false);
Assert.That(result.IsError, Is.False);
Assert.That(result.Value, Is.EqualTo(true));
}
private EvaluationResult EvaluateSimpleExpression(string expression) {
return EvaluateSimpleExpression(expression, (m, args) => null);
}
private EvaluationResult EvaluateSimpleExpression(
string expression, Func<string, IList<object>, object> methodInvocationCallback) {
var ast = new Parser(expression).Parse();
foreach(var error in ast.GetErrors()) {
Trace.WriteLine(string.Format("Error during parsing of '{0}': {1}", expression, error.Message));
}
Assert.That(ast.GetErrors().Any(), Is.False);
var result = new Interpreter().Evalutate(new EvaluationContext {
Tree = ast,
MethodInvocationCallback = methodInvocationCallback
});
Trace.WriteLine(string.Format("Result of evaluation of '{0}': {1}", expression, result));
return result;
}
}
}

View File

@@ -0,0 +1,197 @@
using System;
using System.Diagnostics;
using NUnit.Framework;
using Orchard.Widgets.SimpleScripting.Ast;
using Orchard.Widgets.SimpleScripting.Compiler;
namespace Orchard.Tests.Modules.Scripting {
[TestFixture]
public class ParserTests {
[Test]
public void ParserShouldUnderstandConstantExpressions() {
var tree = new Parser("true").Parse();
CheckTree(tree, new object[] {
"const", true,
});
}
[Test]
public void ParserShouldUnderstandBinaryExpressions() {
var tree = new Parser("true+true").Parse();
CheckTree(tree, new object[] {
"binop", TokenKind.Plus,
"const", true,
"const", true,
});
}
[Test]
public void ParserShouldUnderstandCommandExpressions() {
var tree = new Parser("print 'foo', 'bar'").Parse();
CheckTree(tree, new object[] {
"call", TokenKind.Identifier, "print",
"const", "foo",
"const", "bar",
});
}
[Test]
public void ParserShouldUnderstandCallExpressions() {
var tree = new Parser("print('foo', 'bar')").Parse();
CheckTree(tree, new object[] {
"call", TokenKind.Identifier, "print",
"const", "foo",
"const", "bar",
});
}
[Test]
public void ParserShouldUnderstandCallExpressions2() {
var tree = new Parser("print 1+2").Parse();
CheckTree(tree, new object[] {
"call", TokenKind.Identifier, "print",
"binop", TokenKind.Plus,
"const", 1,
"const", 2,
});
}
[Test]
public void ParserShouldUnderstandOperatorPrecedence() {
var tree = new Parser("1+2*3").Parse();
CheckTree(tree, new object[] {
"binop", TokenKind.Plus,
"const", 1,
"binop", TokenKind.Mul,
"const", 2,
"const", 3,
});
}
[Test]
public void ParserShouldUnderstandOperatorPrecedence2() {
var tree = new Parser("1*2+3").Parse();
CheckTree(tree, new object[] {
"binop", TokenKind.Plus,
"binop", TokenKind.Mul,
"const", 1,
"const", 2,
"const", 3,
});
}
[Test]
public void ParserShouldUnderstandOperatorPrecedence3() {
var tree = new Parser("not true or true").Parse();
CheckTree(tree, new object[] {
"binop", TokenKind.Or,
"unop", TokenKind.Not,
"const", true,
"const", true,
});
}
[Test]
public void ParserShouldUnderstandOperatorPrecedence4() {
var tree = new Parser("not (true or true)").Parse();
CheckTree(tree, new object[] {
"unop", TokenKind.Not,
"binop", TokenKind.Or,
"const", true,
"const", true,
});
}
[Test]
public void ParserShouldUnderstandParenthesis() {
var tree = new Parser("1*(2+3)").Parse();
CheckTree(tree, new object[] {
"binop", TokenKind.Mul,
"const", 1,
"binop", TokenKind.Plus,
"const", 2,
"const", 3,
});
}
[Test]
public void ParserShouldUnderstandComplexExpressions() {
var tree = new Parser("not 1 * (2 / 4 * 6 + (3))").Parse();
CheckTree(tree, new object[] {
"unop", TokenKind.Not,
"binop", TokenKind.Mul,
"const", 1,
"binop", TokenKind.Plus,
"binop", TokenKind.Div,
"const", 2,
"binop", TokenKind.Mul,
"const", 4,
"const", 6,
"const", 3,
});
}
[Test]
public void ParserShouldContainErrorExpressions() {
var tree = new Parser("1 + not 3").Parse();
CheckTree(tree, new object[] {
"binop", TokenKind.Plus,
"const", 1,
"error",
});
}
private void CheckTree(AbstractSyntaxTree tree, object[] objects) {
Assert.That(tree, Is.Not.Null);
Assert.That(tree.Root, Is.Not.Null);
int index = 0;
CheckExpression(tree.Root, 0, objects, ref index);
Assert.That(index, Is.EqualTo(objects.Length));
}
private void CheckExpression(AstNode astNode, int indent, object[] objects, ref int index) {
var exprName = (string)objects[index++];
Type type = null;
switch (exprName) {
case "const":
type = typeof(ConstantAstNode);
break;
case "binop":
type = typeof(BinaryAstNode);
break;
case "unop":
type = typeof(UnaryAstNode);
break;
case "call":
type = typeof(MethodCallAstNode);
break;
case "error":
type = typeof(ErrorAstNode);
break;
}
Trace.WriteLine(string.Format("{0}: {1}{2} (Current: {3})", indent, new string(' ', indent * 2), type.Name, astNode));
Assert.That(astNode.GetType(), Is.EqualTo(type));
if (exprName == "const") {
Assert.That((astNode as ConstantAstNode).Value, Is.EqualTo(objects[index++]));
}
else if (exprName == "binop") {
Assert.That((astNode as BinaryAstNode).Operator.Kind, Is.EqualTo(objects[index++]));
}
else if (exprName == "unop") {
Assert.That((astNode as UnaryAstNode).Operator.Kind, Is.EqualTo(objects[index++]));
}
else if (exprName == "call") {
Assert.That((astNode as MethodCallAstNode).Token.Kind, Is.EqualTo(objects[index++]));
Assert.That((astNode as MethodCallAstNode).Token.Value, Is.EqualTo(objects[index++]));
}
foreach (var child in astNode.Children) {
CheckExpression(child, indent + 1, objects, ref index);
}
}
}
}

View File

@@ -1,120 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using Autofac;
using ClaySharp;
using NUnit.Framework;
using Orchard.Scripting.Services;
using Path = Bleroy.FluentPath.Path;
namespace Orchard.Tests.Modules.Scripting {
[TestFixture]
public class ScriptingTests {
private IContainer _container;
private IScriptingRuntime _scriptingRuntime;
private IScriptingManager _scriptingManager;
private readonly Path _tempFixtureFolderName = Path.Get(System.IO.Path.GetTempPath()).Combine("Orchard.Tests.Modules.Scripting");
private Path _tempFolderName;
[SetUp]
public void Init() {
var builder = new ContainerBuilder();
builder.RegisterType<RubyScriptingRuntime>().As<IScriptingRuntime>();
builder.RegisterType<ScriptingManager>().As<IScriptingManager>();
_container = builder.Build();
_scriptingRuntime = _container.Resolve<IScriptingRuntime>();
_scriptingManager = _container.Resolve<IScriptingManager>();
_tempFolderName = _tempFixtureFolderName.Combine(System.IO.Path.GetRandomFileName());
try {
_tempFolderName.Delete();
}
catch { }
_tempFolderName.CreateDirectory();
}
[TearDown]
public void Term() {
try { _tempFixtureFolderName.Delete(true); }
catch { }
}
[Test]
public void CreateScopeReturnsWorkingScope() {
var scope = _scriptingRuntime.CreateScope();
Assert.IsNotNull(scope);
scope.SetVariable("alpha", 42);
Assert.That(scope.GetVariable("alpha"), Is.EqualTo(42));
}
[Test]
public void ScriptingManagerCanGetAndSetRubyVariables() {
_scriptingManager.SetVariable("foo", 42);
Assert.That(_scriptingManager.GetVariable("foo"), Is.EqualTo(42));
}
[Test]
public void ScriptingManagerCanEvalExpression() {
_scriptingManager.SetVariable("foo", 21);
Assert.That(_scriptingManager.ExecuteExpression("foo + 21"), Is.EqualTo(42));
}
[Test]
public void ScriptCanBeExecutedAndScopeProvidesContextIsolation() {
var scriptManager1 = new ScriptingManager(_scriptingRuntime);
var scriptManager2 = new ScriptingManager(_scriptingRuntime);
scriptManager1.SetVariable("foo", 1);
scriptManager2.SetVariable("foo", 2);
var result1 = scriptManager1.ExecuteExpression("3 + foo");
var result2 = scriptManager2.ExecuteExpression("3 + foo");
Assert.That(result1, Is.EqualTo(4));
Assert.That(result2, Is.EqualTo(5));
}
[Test]
public void ScriptingManagerCanExecuteFile() {
var targetPath = _tempFolderName.Combine("SampleMethodDefinition.rb");
File.WriteAllText(targetPath, "def f\r\nreturn 32\r\nend\r\n");
_scriptingManager.ExecuteFile(targetPath);
Assert.That(_scriptingManager.ExecuteExpression("f / 4"), Is.EqualTo(8));
}
[Test]
public void CanDeclareCallbackOnGlobalMethod() {
_scriptingManager.SetVariable("x", new Clay(new ReturnMethodNameLengthBehavior()));
Assert.That(_scriptingManager.ExecuteExpression("3 + x.foo()"), Is.EqualTo(6));
}
public class ReturnMethodNameLengthBehavior : ClayBehavior {
public override object InvokeMemberMissing(Func<object> proceed, object self, string name, INamedEnumerable<object> args) {
Trace.WriteLine("Returning length of " + name);
return name.Length;
}
}
[Test]
public void CanDeclareCallbackOnInstanceEvalWithFile() {
var targetPath = _tempFolderName.Combine("CallbackOnInstanceEval.rb");
File.WriteAllText(targetPath, "class ExecContext\r\ndef initialize(callbacks)\r\n@callbacks = callbacks;\r\nend\r\ndef execute(text)\r\ninstance_eval(text.to_s);\r\nend\r\ndef method_missing(name, *args, &block)\r\n@callbacks.send(name, args, &block);\r\nend\r\nend\r\ndef execute(&block)\r\nExecContext.new(callbacks).instance_eval(&block);\r\nend\r\n");
_scriptingManager.ExecuteFile(targetPath);
_scriptingManager.SetVariable("callbacks", new CallbackApi());
Assert.That(_scriptingManager.ExecuteExpression("execute { 1 + hello + world('yep') }"), Is.EqualTo(11));
}
public class CallbackApi {
public object send(string name, IList<object> args) {
Trace.WriteLine("Returning length of method " + name);
return name.Length;
}
}
}
}

View File

@@ -0,0 +1,31 @@
using System.Linq;
using NUnit.Framework;
using Orchard.Tests.Stubs;
using Orchard.Widgets.Services;
using Orchard.Widgets.SimpleScripting;
namespace Orchard.Tests.Modules.Scripting {
[TestFixture]
public class SimpleScriptingTests {
[Test]
public void EngineThrowsSyntaxErrors() {
var engine = new ScriptingEngine(Enumerable.Empty<IRuleProvider>(), new StubCacheManager());
Assert.That(() => engine.Matches("true+"), Throws.Exception);
}
[Test]
public void EngineThrowsEvalErrors() {
var engine = new ScriptingEngine(Enumerable.Empty<IRuleProvider>(), new StubCacheManager());
Assert.That(() => engine.Matches("1 + 1"), Throws.Exception);
}
[Test]
public void EngineUnderstandsPrimitiveValues() {
var engine = new ScriptingEngine(Enumerable.Empty<IRuleProvider>(), new StubCacheManager());
Assert.That(engine.Matches("true"), Is.True);
}
[Test]
public void EngineUnderstandsPrimitiveValues2() {
var engine = new ScriptingEngine(Enumerable.Empty<IRuleProvider>(), new StubCacheManager());
Assert.That(engine.Matches("true and true"), Is.True);
}
}
}

View File

@@ -0,0 +1,76 @@
using NUnit.Framework;
using Orchard.Widgets.SimpleScripting.Compiler;
namespace Orchard.Tests.Modules.Scripting {
[TestFixture]
public class TokenizerTests {
[Test]
public void LexerShouldProcessSingleQuotedStringLiteral() {
TestStringLiteral(@"'toto'", @"toto", TokenKind.SingleQuotedStringLiteral);
TestStringLiteral(@"'to\'to'", @"to'to", TokenKind.SingleQuotedStringLiteral);
TestStringLiteral(@"'to\\to'", @"to\to", TokenKind.SingleQuotedStringLiteral);
TestStringLiteral(@"'to\ato'", @"to\ato", TokenKind.SingleQuotedStringLiteral);
}
[Test]
public void LexerShouldProcessStringLiteral() {
TestStringLiteral(@"""toto""", @"toto", TokenKind.StringLiteral);
TestStringLiteral(@"""to\'to""", @"to'to", TokenKind.StringLiteral);
TestStringLiteral(@"""to\\to""", @"to\to", TokenKind.StringLiteral);
TestStringLiteral(@"""to\ato""", @"toato", TokenKind.StringLiteral);
}
private void TestStringLiteral(string value, string expected, TokenKind expectedTokenKind) {
var lexer = new Tokenizer(value);
var token1 = lexer.NextToken();
Assert.That(token1.Kind, Is.EqualTo(expectedTokenKind));
Assert.That(token1.Value, Is.EqualTo(expected));
var token2 = lexer.NextToken();
Assert.That(token2.Kind, Is.EqualTo(TokenKind.Eof));
}
[Test]
public void LexerShouldProcessReservedWords() {
TestReservedWord("true", true, TokenKind.True);
TestReservedWord("false", false, TokenKind.False);
TestReservedWord("not", null, TokenKind.Not);
TestReservedWord("and", null, TokenKind.And);
TestReservedWord("or", null, TokenKind.Or);
}
private void TestReservedWord(string expression, object value, TokenKind expectedTokenKind) {
var lexer = new Tokenizer(expression);
var token1 = lexer.NextToken();
Assert.That(token1.Kind, Is.EqualTo(expectedTokenKind));
Assert.That(token1.Value, Is.EqualTo(value));
var token2 = lexer.NextToken();
Assert.That(token2.Kind, Is.EqualTo(TokenKind.Eof));
}
[Test]
public void LexerShouldProcesSequenceOfTokens() {
CheckTokenSequence("true false", TokenKind.True, TokenKind.False);
CheckTokenSequence("true toto false", TokenKind.True, TokenKind.Identifier, TokenKind.False);
}
[Test]
public void LexerShouldProcesSequenceOfTokens2() {
CheckTokenSequence("1+2*3", TokenKind.Integer, TokenKind.Plus, TokenKind.Integer, TokenKind.Mul, TokenKind.Integer);
}
private void CheckTokenSequence(string expression, params TokenKind[] tokenKinds) {
var lexer = new Tokenizer(expression);
foreach (var kind in tokenKinds) {
var token = lexer.NextToken();
Assert.That(token.Kind, Is.EqualTo(kind));
}
var token2 = lexer.NextToken();
Assert.That(token2.Kind, Is.EqualTo(TokenKind.Eof));
}
}
}