From 52cbe800c1a12c8299c8d4186460ae2b6e1a14e8 Mon Sep 17 00:00:00 2001 From: Michael Krisper <michael.krisper@tugraz.at> Date: Wed, 13 Jan 2016 16:34:33 +0100 Subject: [PATCH] better validation (also private and protected members, and even static members) --- .../Simulation/Impl/SimulatorFactory.cs | 53 +---- VectoCore/Utils/Validation.cs | 17 +- VectoCore/VectoCore.csproj | 6 +- .../SimulationComponentData/ValidationTest.cs | 186 ++++++++++++++++-- VectoCoreTest/VectoCoreTest.csproj | 3 + 5 files changed, 193 insertions(+), 72 deletions(-) diff --git a/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs b/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs index 99af792574..1f1ae655a9 100644 --- a/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs +++ b/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs @@ -16,6 +16,7 @@ using System.Collections.Generic; using System.IO; +using System.Linq; using System.Reflection; using System.Security.Principal; using System.Threading; @@ -67,7 +68,6 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl default: throw new VectoException("Unkown factory mode in SimulatorFactory: {0}", mode); } - //DataReader.SetJobFile(jobFile); } public IVectoRunDataFactory DataReader { get; private set; } @@ -89,12 +89,6 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl { var i = 0; foreach (var data in DataReader.NextRun()) { - CheckLossMapRangeForFullLoadCurves(data.GearboxData, data.EngineData, data.AxleGearData); - - //var modFileName = Path.Combine(data.BasePath, - // data.JobName.Replace(Constants.FileExtensions.VectoJobFile, "") + "_{0}{1}" + - // Constants.FileExtensions.ModDataFile); - // -> string.Format(modFileName, data.Cycle.Name, data.ModFileSuffix ?? "") var d = data; IModalDataContainer modContainer = new ModalDataContainer(data, ModWriter, @@ -114,50 +108,17 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl if (data.IsEngineOnly) { run = new TimeRun(builder.Build(data)); } else { - //var runCaption = string.Format("{0}-{1}-{2}", - // Path.GetFileNameWithoutExtension(data.JobName), data.Cycle.Name, data.ModFileSuffix); run = new DistanceRun(builder.Build(data)); } - yield return run; - } - } + var validationErrors = ValidationHelper.Validate(run); + if (validationErrors.Any()) { + throw new VectoException("Validation of Run-Data Failed: " + + string.Join("; ", validationErrors.Select(r => r.ErrorMessage))); + } - internal static void CheckLossMapRangeForFullLoadCurves(GearboxData gearboxData, CombustionEngineData engineData, - AxleGearData axleGearData) - { - if (gearboxData == null) { - return; - } - foreach (var gear in gearboxData.Gears) { - for (var angularVelocity = engineData.IdleSpeed; - angularVelocity < engineData.FullLoadCurve.RatedSpeed; - angularVelocity += 2.0 / 3.0 * (engineData.FullLoadCurve.RatedSpeed - engineData.IdleSpeed) / 10.09) { - for (var inTorque = engineData.FullLoadCurve.FullLoadStationaryTorque(angularVelocity) / 3; - inTorque < engineData.FullLoadCurve.FullLoadStationaryTorque(angularVelocity); - inTorque += 2.0 / 3.0 * engineData.FullLoadCurve.FullLoadStationaryTorque(angularVelocity) / 10.0) { - NewtonMeter axleTorque; - try { - axleTorque = gear.Value.LossMap.GetOutTorque(angularVelocity, inTorque); - } catch (VectoException ex) { - throw new VectoException( - string.Format("Interpolation of Gear-{0}-LossMap failed with torque={1} and angularSpeed={2}", - gear.Key, inTorque, angularVelocity.ConvertTo().Rounds.Per.Minute), ex); - } - - if (axleGearData != null) { - var axleAngularVelocity = angularVelocity / gear.Value.Ratio; - try { - axleGearData.LossMap.GetOutTorque(axleAngularVelocity, axleTorque); - } catch (VectoException ex) { - throw new VectoException( - string.Format("Interpolation of AxleGear-LossMap failed with torque={0} and angularSpeed={1}", - axleTorque, axleAngularVelocity.ConvertTo().Rounds.Per.Minute), ex); - } - } - } - } + yield return run; } } } diff --git a/VectoCore/Utils/Validation.cs b/VectoCore/Utils/Validation.cs index dea997a566..5ceb056f83 100644 --- a/VectoCore/Utils/Validation.cs +++ b/VectoCore/Utils/Validation.cs @@ -18,22 +18,26 @@ namespace TUGraz.VectoCore.Utils Validator.TryValidateObject(entity, new ValidationContext(entity), results, true); foreach ( - var p in entity.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic)) { + var p in + entity.GetType() + .GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public | + BindingFlags.FlattenHierarchy)) { var val = p.GetValue(entity); var attrs = p.GetCustomAttributes(typeof(ValidationAttribute)).Cast<ValidationAttribute>(); - context.MemberName = p.Name; context.DisplayName = p.Name; + context.MemberName = p.Name; Validator.TryValidateValue(val, context, results, attrs); } foreach ( var f in entity.GetType() - .GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)) { + .GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public | + BindingFlags.FlattenHierarchy)) { var val = f.GetValue(entity); var attrs = f.GetCustomAttributes(typeof(ValidationAttribute)).Cast<ValidationAttribute>(); - context.MemberName = f.Name; context.DisplayName = f.Name; + context.MemberName = f.Name; Validator.TryValidateValue(val, context, results, attrs); } @@ -63,7 +67,7 @@ namespace TUGraz.VectoCore.Utils if (results.Any()) { return new ValidationResult( - string.Format("Validation for Element {0} in {1} failed: {2}.", i, validationContext.DisplayName, + string.Format("Validation for list {1}[{0}] in {1} failed: {2}", i, validationContext.DisplayName, string.Join(" ", results))); } i++; @@ -72,7 +76,8 @@ namespace TUGraz.VectoCore.Utils var results = value.Validate(); if (results.Any()) { return new ValidationResult( - string.Format("Validation for {0} failed: {1}.", validationContext.DisplayName, string.Join(" ", results))); + string.Format("Validation for object {{{0}}} failed: {1}", validationContext.DisplayName, + string.Join(" ", results))); } } diff --git a/VectoCore/VectoCore.csproj b/VectoCore/VectoCore.csproj index 4d9033dbdb..81706a3d75 100644 --- a/VectoCore/VectoCore.csproj +++ b/VectoCore/VectoCore.csproj @@ -94,6 +94,7 @@ <HintPath>..\packages\NLog.4.2.0\lib\net45\NLog.dll</HintPath> </Reference> <Reference Include="System" /> + <Reference Include="System.ComponentModel.DataAnnotations" /> <Reference Include="System.Core" /> <Reference Include="System.Drawing" /> <Reference Include="System.Runtime.Serialization" /> @@ -251,7 +252,9 @@ <Compile Include="Models\SimulationComponent\IWheels.cs" /> <Compile Include="Models\SimulationComponent\VectoSimulationComponent.cs" /> <Compile Include="Models\SimulationComponent\Impl\EngineOnlyDrivingCycle.cs" /> - <Compile Include="Models\Simulation\Data\ModalResult.cs" /> + <Compile Include="Models\Simulation\Data\ModalResult.cs"> + <SubType>Component</SubType> + </Compile> <Compile Include="Models\Simulation\IVectoRun.cs" /> <Compile Include="Models\Simulation\Impl\SimulatorFactory.cs" /> <Compile Include="Models\Simulation\Impl\VectoRun.cs" /> @@ -265,6 +268,7 @@ <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Utils\StringExtensionMethods.cs" /> <Compile Include="Utils\SwitchExtension.cs" /> + <Compile Include="Utils\Validation.cs" /> <Compile Include="Utils\VectoCSVFile.cs" /> <Compile Include="Utils\VectoMath.cs" /> <Compile Include="Utils\DelauneyMap.cs" /> diff --git a/VectoCoreTest/Models/SimulationComponentData/ValidationTest.cs b/VectoCoreTest/Models/SimulationComponentData/ValidationTest.cs index e8ab961675..80788fff07 100644 --- a/VectoCoreTest/Models/SimulationComponentData/ValidationTest.cs +++ b/VectoCoreTest/Models/SimulationComponentData/ValidationTest.cs @@ -1,11 +1,6 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.Data; -using System.Diagnostics; using System.Linq; -using System.Reflection; -using System.Runtime.Serialization; using Microsoft.VisualStudio.TestTools.UnitTesting; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Models.Simulation.Impl; @@ -89,31 +84,184 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData [TestMethod] public void Validation_Test() { - var data = new Data(); - data.lu = new deep(); - var results = data.Validate(); - Assert.IsFalse(results.Any(), "Validation Failed: " + string.Join(" ", results.Select(r => r.ErrorMessage))); + var results = new DataObject().Validate(); + + // every field and property should be tested except private parent fields and properties and + // (4*4+1) * 2 = 17*2= 34 - 4 private parent fields (+2 public field and property which are tested twice) = 32 + Assert.AreEqual(32, results.Count, "Validation Error: " + string.Join("\n", results.Select(r => r.ErrorMessage))); } - public class deep + public class DeepDataObject { - [Required, Range(10, 16)] public int mah = 45; + [Required, Range(41, 42)] protected int public_field = 5; } - public abstract class Muh + public abstract class ParentDataObject { - [Required, Range(6, 9)] - protected int higss { get; set; } + #region 4 parent instance fields - [Required, ValidateObject] public deep lu; - } + [Required, Range(1, 2)] private int private_parent_field = 7; + [Required, Range(3, 4)] protected int protected_parent_field = 7; + [Required, Range(5, 6)] internal int internal_parent_field = 7; + [Required, Range(7, 8)] public int public_parent_field = 5; + + #endregion + + #region 4 parent static field + + [Required, Range(43, 44)] private static int private_static_parent_field = 7; + [Required, Range(43, 44)] protected static int protected_static_parent_field = 7; + [Required, Range(50, 51)] internal static int internal_static_parent_field = 7; + [Required, Range(45, 46)] public static int public_static_parent_field = 7; + + #endregion + + #region 4 parent instance properties + + [Required, Range(11, 12)] + private int private_parent_property + { + get { return 7; } + } + + [Required, Range(13, 14)] + protected int protected_parent_property + { + get { return 7; } + } + + [Required, Range(15, 16)] + internal int internal_parent_property + { + get { return 7; } + } + + [Required, Range(17, 18)] + public int public_parent_property + { + get { return 7; } + } + + #endregion + + #region 4 parent static properties + + [Required, Range(19, 20)] + private static int private_static_parent_property + { + get { return 7; } + } + + [Required, Range(19, 20)] + protected static int protected_static_parent_property + { + get { return 7; } + } + + [Required, Range(19, 20)] + internal static int internal_static_parent_property + { + get { return 7; } + } + + [Required, Range(19, 20)] + public static int public_static_parent_property + { + get { return 7; } + } + + #endregion + + #region 1 parent sub objects + + [Required, ValidateObject] public DeepDataObject parent_sub_object = new DeepDataObject(); + #endregion + } - public class Data : Muh + public class DataObject : ParentDataObject { - [Required, Range(2, 5)] private int bla = 7; + #region 4 instance fields + + [Required, Range(1, 2)] private int private_field = 7; + [Required, Range(3, 4)] protected int protected_field = 7; + [Required, Range(5, 6)] internal int internal_field = 7; + [Required, Range(7, 8)] public int public_field = 5; + + #endregion + + #region 4 static field + + [Required, Range(43, 44)] private static int private_static_field = 7; + [Required, Range(43, 44)] protected static int protected_static_field = 7; + [Required, Range(50, 51)] internal static int internal_static_field = 7; + [Required, Range(45, 46)] public static int public_static_field = 7; + + #endregion + + #region 4 instance properties + + [Required, Range(11, 12)] + private int private_property + { + get { return 7; } + } + + [Required, Range(13, 14)] + protected int protected_property + { + get { return 7; } + } + + [Required, Range(15, 16)] + internal int internal_property + { + get { return 7; } + } + + [Required, Range(17, 18)] + public int public_property + { + get { return 7; } + } + + #endregion + + #region 4 static properties + + [Required, Range(19, 20)] + private static int private_static_property + { + get { return 7; } + } + + [Required, Range(19, 20)] + protected static int protected_static_property + { + get { return 7; } + } + + [Required, Range(19, 20)] + internal static int internal_static_property + { + get { return 7; } + } + + [Required, Range(19, 20)] + public static int public_static_property + { + get { return 7; } + } + + #endregion + + #region 1 sub objects + + [Required, ValidateObject] public DeepDataObject sub_object = new DeepDataObject(); + + #endregion } } } \ No newline at end of file diff --git a/VectoCoreTest/VectoCoreTest.csproj b/VectoCoreTest/VectoCoreTest.csproj index b651c3762c..6da7ec8584 100644 --- a/VectoCoreTest/VectoCoreTest.csproj +++ b/VectoCoreTest/VectoCoreTest.csproj @@ -44,10 +44,12 @@ <HintPath>..\packages\NLog.4.0.1\lib\net45\NLog.dll</HintPath> </Reference> <Reference Include="System" /> + <Reference Include="System.ComponentModel.DataAnnotations" /> <Reference Include="System.Data" /> <Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Design" /> <Reference Include="System.Drawing" /> + <Reference Include="System.Runtime.Serialization" /> <Reference Include="System.Windows.Forms" /> <Reference Include="System.Windows.Forms.DataVisualization" /> <Reference Include="System.Xml" /> @@ -76,6 +78,7 @@ <SubType>Code</SubType> </Compile> <Compile Include="Integration\DeclarationReportTest.cs" /> + <Compile Include="Models\SimulationComponentData\ValidationTest.cs" /> <Compile Include="Models\Simulation\FactoryTest.cs" /> <Compile Include="Models\Simulation\LossMapRangeValidationTest.cs" /> <Compile Include="Reports\SumWriterTest.cs" /> -- GitLab