blob: e03c2ddf35f13ec7f42441d2036f293cbd7397f2 [file] [log] [blame]
using Lucene.Net.Util;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using JCG = J2N.Collections.Generic;
namespace Lucene.Net.Expressions.JS
{
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
[TestFixture]
public class TestCustomFunctions : LuceneTestCase
{
private static double DELTA = 0.0000001;
/// <summary>empty list of methods</summary>
[Test]
public virtual void TestEmpty()
{
IDictionary<string, MethodInfo> functions = new JCG.Dictionary<string,MethodInfo>();
try
{
JavascriptCompiler.Compile("sqrt(20)", functions);
Assert.Fail();
}
catch (ArgumentException e)
{
Assert.IsTrue(e.Message.Contains("Unrecognized method"));
}
}
/// <summary>using the default map explicitly</summary>
[Test]
public virtual void TestDefaultList()
{
IDictionary<string, MethodInfo> functions = JavascriptCompiler.DEFAULT_FUNCTIONS;
var expr = JavascriptCompiler.Compile("sqrt(20)", functions);
Assert.AreEqual(Math.Sqrt(20), expr.Evaluate(0, null), DELTA);
}
public static double ZeroArgMethod()
{
return 5;
}
/// <summary>tests a method with no arguments</summary>
[Test]
public virtual void TestNoArgMethod()
{
IDictionary<string, MethodInfo> functions = new Dictionary<string, MethodInfo>();
functions["foo"] = GetType().GetMethod("ZeroArgMethod");
var expr = JavascriptCompiler.Compile("foo()", functions);
Assert.AreEqual(5, expr.Evaluate(0, null), DELTA);
}
public static double OneArgMethod(double arg1)
{
return 3 + arg1;
}
/// <summary>tests a method with one arguments</summary>
[Test]
public virtual void TestOneArgMethod()
{
IDictionary<string, MethodInfo> functions = new Dictionary<string, MethodInfo>();
functions["foo"] = GetType().GetMethod("OneArgMethod", new []{ typeof(double)});
var expr = JavascriptCompiler.Compile("foo(3)", functions);
Assert.AreEqual(6, expr.Evaluate(0, null), DELTA);
}
public static double ThreeArgMethod(double arg1, double arg2, double arg3)
{
return arg1 + arg2 + arg3;
}
/// <summary>tests a method with three arguments</summary>
[Test]
public virtual void TestThreeArgMethod()
{
IDictionary<string, MethodInfo> functions = new Dictionary<string, MethodInfo>();
functions["foo"] = GetType().GetMethod("ThreeArgMethod", new []{ typeof(double), typeof(
double), typeof(double)});
var expr = JavascriptCompiler.Compile("foo(3, 4, 5)", functions);
Assert.AreEqual(12, expr.Evaluate(0, null), DELTA);
}
/// <summary>tests a map with 2 functions</summary>
[Test]
public virtual void TestTwoMethods()
{
IDictionary<string, MethodInfo> functions = new Dictionary<string, MethodInfo>();
functions["foo"] = GetType().GetMethod("ZeroArgMethod");
functions["bar"] = GetType().GetMethod("OneArgMethod", new []{typeof(double)});
var expr = JavascriptCompiler.Compile("foo() + bar(3)", functions);
Assert.AreEqual(11, expr.Evaluate(0, null), DELTA);
}
public static string BogusReturnType()
{
return "bogus!";
}
/// <summary>wrong return type: must be double</summary>
[Test]
public virtual void TestWrongReturnType()
{
IDictionary<string, MethodInfo> functions = new Dictionary<string, MethodInfo>();
functions["foo"] = GetType().GetMethod("BogusReturnType");
try
{
JavascriptCompiler.Compile("foo()", functions);
Assert.Fail();
}
catch (ArgumentException e)
{
Assert.IsTrue(e.Message.Contains("does not return a double"));
}
}
public static double BogusParameterType(string s)
{
return 0;
}
/// <summary>wrong param type: must be doubles</summary>
[Test]
public virtual void TestWrongParameterType()
{
IDictionary<string, MethodInfo> functions = new Dictionary<string, MethodInfo>();
functions["foo"] = GetType().GetMethod("BogusParameterType", new []{ typeof(string)});
try
{
JavascriptCompiler.Compile("foo(2)", functions);
Assert.Fail();
}
catch (ArgumentException e)
{
Assert.IsTrue(e.Message.Contains("must take only double parameters"
));
}
}
public virtual double NonStaticMethod()
{
return 0;
}
/// <summary>wrong modifiers: must be static</summary>
[Test]
public virtual void TestWrongNotStatic()
{
IDictionary<string, MethodInfo> functions = new Dictionary<string, MethodInfo>();
functions["foo"] = GetType().GetMethod("NonStaticMethod");
try
{
JavascriptCompiler.Compile("foo()", functions);
Assert.Fail();
}
catch (ArgumentException e)
{
Assert.IsTrue(e.Message.Contains("is not static"));
}
}
internal static double NonPublicMethod()
{
return 0;
}
/// <summary>wrong modifiers: must be public</summary>
[Test]
public virtual void TestWrongNotPublic()
{
IDictionary<string, MethodInfo> functions = new Dictionary<string, MethodInfo>();
functions["foo"] = GetType().GetMethod("NonPublicMethod",BindingFlags.NonPublic|BindingFlags.Static);
try
{
JavascriptCompiler.Compile("foo()", functions);
Assert.Fail();
}
catch (ArgumentException e)
{
Assert.IsTrue(e.Message.Contains("is not public"));
}
}
internal class NestedNotPublic
{
public static double Method()
{
return 0;
}
}
/// <summary>wrong class modifiers: class containing method is not public</summary>
[Test]
public virtual void TestWrongNestedNotPublic()
{
IDictionary<string, MethodInfo> functions = new Dictionary<string, MethodInfo>();
functions["foo"] = typeof(NestedNotPublic).GetMethod("Method");
try
{
JavascriptCompiler.Compile("foo()", functions);
Assert.Fail();
}
catch (ArgumentException e)
{
Assert.IsTrue(e.Message.Contains("is not public"));
}
}
internal static string MESSAGE = "This should not happen but it happens";
public class StaticThrowingException
{
public static double Method()
{
throw new ArithmeticException(MESSAGE);
}
}
/// <summary>the method throws an exception.</summary>
/// <remarks>the method throws an exception. We should check the stack trace that it contains the source code of the expression as file name.
/// </remarks>
[Test]
public virtual void TestThrowingException()
{
IDictionary<string, MethodInfo> functions = new Dictionary<string, MethodInfo>();
functions["foo"] = typeof(StaticThrowingException).GetMethod("Method");
string source = "3 * foo() / 5";
var expr = JavascriptCompiler.Compile(source, functions);
try
{
expr.Evaluate(0, null);
Assert.Fail();
}
catch (ArithmeticException e)
{
Assert.AreEqual(MESSAGE, e.Message);
StringWriter sw = new StringWriter();
e.printStackTrace();
//.NET Port
Assert.IsTrue(e.StackTrace.Contains("Lucene.Net.Expressions.CompiledExpression.Evaluate(Int32 , FunctionValues[] )"));
}
}
/// <summary>test that namespaces work with custom expressions.</summary>
/// <remarks>test that namespaces work with custom expressions.</remarks>
[Test]
public virtual void TestNamespaces()
{
IDictionary<string, MethodInfo> functions = new Dictionary<string, MethodInfo>();
functions["foo.bar"] = GetType().GetMethod("ZeroArgMethod");
string source = "foo.bar()";
var expr = JavascriptCompiler.Compile(source, functions);
Assert.AreEqual(5, expr.Evaluate(0, null), DELTA);
}
}
}