Example #1
0
        protected void Test(Delegate d, object knownResult = null, bool knownResultNull = false)
        {
            var mi = d.Method;
            //var stackTrace = new StackTrace();
            //var testMethod = stackTrace.GetFrame(1).GetMethod().Name;
            //Console.WriteLine("Test++ {0}", testMethod);
            var method = CecilHelper.GetMethod(d);
            var js     = Js.CreateFrom(method, this.Verbose, true).Js;

            if (this.Verbose)
            {
                Console.WriteLine(js);
            }
            var testDefaultParamGen = mi.GetCustomAttribute <ParamAttribute>()
                                      ?? mi.DeclaringType.GetCustomAttribute <ParamAttribute>()
                                      ?? defaultParamGen;
            var withinAttr        = mi.GetCustomAttribute <WithinAttribute>();
            var withinUlpsAttr    = mi.GetCustomAttribute <WithinUlpsAttribute>();
            var withinPercentAttr = mi.GetCustomAttribute <WithinPercentAttribute>();
            var icAttr            = mi.GetCustomAttribute <IterationCountAttribute>();
            var minIterations     = mi.GetParameters().Max(x =>
                                                           (x.GetCustomAttribute <ParamAttribute>() ?? testDefaultParamGen).MinIterations);
            int iterationCount;

            if (icAttr != null)
            {
                iterationCount = icAttr.IterationCount;
            }
            else
            {
                iterationCount = method.Parameters.Any() ? defaultTestIterations : 1;
            }
            if (iterationCount < minIterations)
            {
                iterationCount = minIterations.Value;
            }
            var range = Enumerable.Range(0, iterationCount);
            var args  = range.Select(i => this.CreateArgs(mi, i, testDefaultParamGen)).ToArray();

            var runResults = range.Select(i => {
                object r    = null;
                Exception e = null;
                try {
                    r = d.DynamicInvoke(args[i]);
                } catch (TargetInvocationException ex) {
                    e = ex.InnerException;
                }
                if (knownResult != null || knownResultNull)
                {
                    Assert.That(r, Is.EqualTo(knownResult));
                }
                return(Tuple.Create(r, e));
            }).ToArray();

            var usingNamespace = NamespaceSetup.Chrome != null;
            var chrome         = usingNamespace ? NamespaceSetup.Chrome : new ChromeDriver();

            try {
                for (int i = 0; i < args.Length; i++)
                {
                    var arg = args[i];
                    if (!mi.IsStatic)
                    {
                        arg = arg.Prepend(null).ToArray();
                    }
                    var jsArgs = string.Join(", ", arg.Select(x => this.ConvertArgToJavascript(x)));
                    //Console.WriteLine("JS args: '{0}'", jsArgs);
                    var jsCall   = @"
var r;
try {
    r = main(" + jsArgs + @");
    console.log(r);
} catch (e) {
    return {exception:[e._.$$TypeNamespace, e._.$$TypeName, e.$$_message]};
}
if (typeof r === 'number') {
    if (isNaN(r)) {
        return 'NaN';
    }
    if (r === Number.POSITIVE_INFINITY) {
        return '+Infinity';
    }
    if (r === Number.NEGATIVE_INFINITY) {
        return '-Infinity';
    }
    return r.toString();
}
return r;
";
                    var jsResult = chrome.ExecuteScript(js + jsCall);
                    if (jsResult != null && jsResult is Dictionary <string, object> )
                    {
                        // Exception
                        Assert.That(runResults[i].Item1, Is.Null, "JS threw exception, but exception not expected");
                        var jsExInfo       = ((ICollection <object>)((Dictionary <string, object>)jsResult)["exception"]).Cast <string>().ToArray();
                        var jsExType       = jsExInfo[0] + "." + jsExInfo[1];
                        var expectedExType = runResults[i].Item2.GetType().FullName;
                        Assert.That(jsExType, Is.EqualTo(expectedExType));
                    }
                    else
                    {
                        var returnTypeCode = Type.GetTypeCode(d.Method.ReturnType);
                        if (jsResult != null && jsResult.GetType() != d.Method.ReturnType)
                        {
                            switch (returnTypeCode)
                            {
                            case TypeCode.Int64: {
                                var array = (IList <object>)jsResult;
                                var hi    = Convert.ToUInt64(array[0]);
                                var lo    = Convert.ToUInt64(array[1]);
                                jsResult = (long)(((ulong)hi) << 32 | (ulong)lo);
                            }
                            break;

                            case TypeCode.UInt64: {
                                var array = (IList <object>)jsResult;
                                var hi    = Convert.ToUInt64(array[0]);
                                var lo    = Convert.ToUInt64(array[1]);
                                jsResult = ((ulong)hi) << 32 | (ulong)lo;
                            }
                            break;

                            case TypeCode.Single:
                                switch (jsResult as string)
                                {
                                case "NaN": jsResult = Single.NaN; break;

                                case "+Infinity": jsResult = Single.PositiveInfinity; break;

                                case "-Infinity": jsResult = Single.NegativeInfinity; break;

                                default: jsResult = Single.Parse(jsResult as string); break;
                                }
                                break;

                            case TypeCode.Double:
                                switch (jsResult as string)
                                {
                                case "NaN": jsResult = Double.NaN; break;

                                case "+Infinity": jsResult = Double.PositiveInfinity; break;

                                case "-Infinity": jsResult = Double.NegativeInfinity; break;

                                default: jsResult = Double.Parse(jsResult as string); break;
                                }
                                break;

                            case TypeCode.Char:
                                jsResult = (char)int.Parse(jsResult as string);
                                break;

                            default:
                                jsResult = Convert.ChangeType(jsResult, d.Method.ReturnType);
                                break;
                            }
                        }
                        Assert.That(runResults[i].Item2, Is.Null, "Exception expected in JS, but not thrown");
                        EqualConstraint    equalTo  = Is.EqualTo(runResults[i].Item1);
                        IResolveConstraint expected = equalTo;
                        if (withinAttr != null)
                        {
                            expected = equalTo.Within(withinAttr.Delta);
                        }
                        else if (withinUlpsAttr != null)
                        {
                            expected = equalTo.Within(withinUlpsAttr.Ulps).Ulps;
                        }
                        else if (withinPercentAttr != null)
                        {
                            expected = equalTo.Within(withinPercentAttr.Percent).Percent;
                        }
                        else
                        {
                            switch (returnTypeCode)
                            {
                            case TypeCode.Single:
                                // Always allow a little inaccuracy with Singles
                                expected = equalTo.Within(0.0001).Percent;
                                break;

                            case TypeCode.Double:
                                expected = equalTo.Within(0.0001).Percent;
                                break;
                            }
                        }
                        Assert.That(jsResult, expected);
                    }
                }
            } finally {
                if (!usingNamespace)
                {
                    chrome.Quit();
                    chrome.Dispose();
                }
            }

            //Console.WriteLine("Test-- {0}", testMethod);
        }
 public static void That(DateTime?result, EqualConstraint constraint) => Assert.That(result, constraint.Within(1).Seconds);