diff --git a/src/UnitTests/ArgumentCheckContract.cs b/src/UnitTests/ArgumentCheckContract.cs new file mode 100644 index 00000000..7779adb9 --- /dev/null +++ b/src/UnitTests/ArgumentCheckContract.cs @@ -0,0 +1,119 @@ +// +// Math.NET Numerics, part of the Math.NET Project +// http://mathnet.opensourcedotnet.info +// +// Copyright (c) 2009 Math.NET +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +namespace MathNet.Numerics.UnitTests +{ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + using MbUnit.Framework; + using MbUnit.Framework.ContractVerifiers; + + internal class ArgumentCheckContract : AbstractContract + { + public Expression> TypicalUse { get; set; } + public Expression>[] TypicalUses { get; set; } + public Func BadUse { get; set; } + public Func[] BadUses { get; set; } + + protected override IEnumerable GetContractVerificationTests() + { + if (TypicalUse != null) + { + yield return CreateNullArgumentCheckTest(TypicalUse); + } + + if (TypicalUses != null) + { + foreach (var typicalUse in TypicalUses) + { + yield return CreateNullArgumentCheckTest(typicalUse); + } + } + + if (BadUse != null) + { + yield return CreateBadArgumentCheckTest(BadUse); + } + + if (BadUses != null) + { + foreach (var badUse in BadUses) + { + yield return CreateBadArgumentCheckTest(badUse); + } + } + } + + private static Test CreateNullArgumentCheckTest(Expression> typicalUse) + { + return new TestCase( + "NullArgumentCheck " + typicalUse.Body, + () => + { + Assert.DoesNotThrow(() => typicalUse.Compile()()); + + // we only support method calls and constructors for now. + if (typicalUse.Body.NodeType != ExpressionType.New + && typicalUse.Body.NodeType != ExpressionType.Call) + { + Assert.Fail( + "Subject '{0}' is neither a constructor or a method call.", + typicalUse.ToString()); + return; + } + + var badUses = typicalUse.ApplySingleMapEachArgument( + t => !t.IsValueType, + e => Expression.Constant(null, e.Type)); + + foreach (var badUse in badUses) + { + var closureBadUseReference = badUse; + + Assert.Throws( + typeof (ArgumentNullException), + () => closureBadUseReference.Compile()(), + "Subject '{0}' must check for null arguments", + closureBadUseReference.ToString()); + } + }); + } + + private static Test CreateBadArgumentCheckTest(Func badUse) + { + return new TestCase( + "BadArgumentCheck " + badUse.Method, + () => Assert.Throws( + typeof (ArgumentException), + () => badUse(), + "Subject '{0}' must check for bad arguments", + badUse.ToString())); + } + } +} diff --git a/src/UnitTests/InterpolationTests/FunctionalHelpers.cs b/src/UnitTests/FunctionalHelpers.cs similarity index 75% rename from src/UnitTests/InterpolationTests/FunctionalHelpers.cs rename to src/UnitTests/FunctionalHelpers.cs index e2d91552..ada4d89c 100644 --- a/src/UnitTests/InterpolationTests/FunctionalHelpers.cs +++ b/src/UnitTests/FunctionalHelpers.cs @@ -26,13 +26,11 @@ // OTHER DEALINGS IN THE SOFTWARE. // -using System.Collections.Generic; -using System.Linq.Expressions; -using MathNet.Numerics.Interpolation; - -namespace MathNet.Numerics.UnitTests.InterpolationTests +namespace MathNet.Numerics.UnitTests { using System; + using System.Collections.Generic; + using System.Linq.Expressions; internal static class FunctionalHelpers { @@ -50,16 +48,24 @@ namespace MathNet.Numerics.UnitTests.InterpolationTests return newList; } - internal static IEnumerable>> ApplySingleMapEachArgument( + internal static IEnumerable>> ApplySingleMapEachArgument( this LambdaExpression lambda, Func predicate, Func replace) { var body = lambda.Body; + var bodyCall = body as MethodCallExpression; + var bodyCtor = body as NewExpression; + + if (bodyCall == null && bodyCtor == null) + { + throw new NotSupportedException(); + } + var arguments = - body is NewExpression - ? ((NewExpression)body).Arguments - : ((MethodCallExpression)body).Arguments; + bodyCall != null + ? bodyCall.Arguments + : bodyCtor.Arguments; for (int i = 0; i < arguments.Count; i++) { @@ -70,13 +76,14 @@ namespace MathNet.Numerics.UnitTests.InterpolationTests var mappedArguments = ApplySingleMap(arguments, i, replace); - yield return Expression.Lambda>( - body is NewExpression - ? (Expression)Expression.New( - ((NewExpression)body).Constructor, + yield return Expression.Lambda>( + bodyCtor != null + ? (Expression) Expression.New( + bodyCtor.Constructor, mappedArguments) - : (Expression)Expression.Call( - ((MethodCallExpression)body).Method, + : (Expression) Expression.Call( + bodyCall.Object, + bodyCall.Method, mappedArguments)); } } diff --git a/src/UnitTests/IntegralTransformsTests/InverseTransformTest.cs b/src/UnitTests/IntegralTransformsTests/InverseTransformTest.cs index dc663072..436ed383 100644 --- a/src/UnitTests/IntegralTransformsTests/InverseTransformTest.cs +++ b/src/UnitTests/IntegralTransformsTests/InverseTransformTest.cs @@ -141,7 +141,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests VerifyIsReversibleReal( 0x80, - 1e-10, + 1e-9, s => dht.NaiveForward(s, options), s => dht.NaiveInverse(s, options)); } diff --git a/src/UnitTests/InterpolationTests/InterpolationInfrastructureContract.cs b/src/UnitTests/InterpolationTests/InterpolationInfrastructureContract.cs index 45c08c28..3f3cddb0 100644 --- a/src/UnitTests/InterpolationTests/InterpolationInfrastructureContract.cs +++ b/src/UnitTests/InterpolationTests/InterpolationInfrastructureContract.cs @@ -112,7 +112,7 @@ namespace MathNet.Numerics.UnitTests.InterpolationTests continue; } - var modifiedFactories = factory.ApplySingleMapEachArgument( + var modifiedFactories = factory.ApplySingleMapEachArgument( t => !t.IsValueType, e => Expression.Constant(null, e.Type)); @@ -148,7 +148,7 @@ namespace MathNet.Numerics.UnitTests.InterpolationTests continue; } - var modifiedFactories = factory.ApplySingleMapEachArgument( + var modifiedFactories = factory.ApplySingleMapEachArgument( t => !t.IsValueType, e => Expression.Constant(new double[MinimumSampleCount - 1], typeof(double[]))); @@ -194,7 +194,7 @@ namespace MathNet.Numerics.UnitTests.InterpolationTests continue; } - var modifiedFactories = factory.ApplySingleMapEachArgument( + var modifiedFactories = factory.ApplySingleMapEachArgument( t => !t.IsValueType, e => { diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj index 74f53267..003f5f22 100644 --- a/src/UnitTests/UnitTests.csproj +++ b/src/UnitTests/UnitTests.csproj @@ -59,6 +59,7 @@ + @@ -74,7 +75,7 @@ - +