From b92bac6363e76ee9bc29485f8cded3f3de590a3f Mon Sep 17 00:00:00 2001 From: Michael Krisper <michael.krisper@tugraz.at> Date: Tue, 12 May 2015 14:06:14 +0200 Subject: [PATCH] VECTO-101 moddata engine only fields, sum file corrected header, tests --- .../Models/Simulation/Data/ModalDataWriter.cs | 63 +++++++++++++- .../Simulation/Data/SummaryFileWriter.cs | 50 +++++------ .../Models/Simulation/Impl/JobContainer.cs | 2 +- .../Simulation/Impl/SimulatorFactory.cs | 51 +++++++----- VectoCore/Utils/VectoCSVFile.cs | 28 +++---- .../Models/Simulation/SimulationTests.cs | 77 ++++------------- .../MockPorts.cs | 0 VectoCoreTest/Utils/ResultFileHelper.cs | 82 +++++++++++++++++++ .../Simulation => Utils}/TestSumWriter.cs | 0 VectoCoreTest/VectoCoreTest.csproj | 7 +- 10 files changed, 232 insertions(+), 128 deletions(-) rename VectoCoreTest/{Models/SimulationComponent => Utils}/MockPorts.cs (100%) create mode 100644 VectoCoreTest/Utils/ResultFileHelper.cs rename VectoCoreTest/{Models/Simulation => Utils}/TestSumWriter.cs (100%) diff --git a/VectoCore/Models/Simulation/Data/ModalDataWriter.cs b/VectoCore/Models/Simulation/Data/ModalDataWriter.cs index 56ad553c78..86b3fdda83 100644 --- a/VectoCore/Models/Simulation/Data/ModalDataWriter.cs +++ b/VectoCore/Models/Simulation/Data/ModalDataWriter.cs @@ -1,22 +1,24 @@ -using System.Collections.Generic; -using System.Data; +using System.Data; using System.Linq; +using System.Collections.Generic; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.Simulation.Data { public class ModalDataWriter : IModalDataWriter { + private readonly bool _engineOnly; private ModalResults Data { get; set; } private DataRow CurrentRow { get; set; } private string ModFileName { get; set; } - public ModalDataWriter(string modFileName) + public ModalDataWriter(string modFileName, bool engineOnly) { ModFileName = modFileName; Data = new ModalResults(); CurrentRow = Data.NewRow(); + _engineOnly = engineOnly; } public void CommitSimulationStep() @@ -27,9 +29,62 @@ namespace TUGraz.VectoCore.Models.Simulation.Data public void Finish() { - VectoCSVFile.Write(ModFileName, Data); + var dataColumns = new List<ModalResultField> { ModalResultField.time }; + + if (!_engineOnly) { + dataColumns.AddRange(new[] { + ModalResultField.time, + ModalResultField.dist, + ModalResultField.v_act, + ModalResultField.v_targ, + ModalResultField.acc, + ModalResultField.grad + }); + } + + dataColumns.AddRange(new[] { + ModalResultField.n, + ModalResultField.Tq_eng, + ModalResultField.Tq_clutch, + ModalResultField.Tq_full, + ModalResultField.Tq_drag, + ModalResultField.Pe_eng, + ModalResultField.Pe_full, + ModalResultField.Pe_drag, + ModalResultField.Pe_clutch, + ModalResultField.PaEng, + ModalResultField.Paux + }); + + if (!_engineOnly) { + dataColumns.AddRange(new[] { + ModalResultField.Gear, + ModalResultField.PlossGB, + ModalResultField.PlossDiff, + ModalResultField.PlossRetarder, + ModalResultField.PaGB, + ModalResultField.PaVeh, + ModalResultField.Proll, + ModalResultField.Pair, + ModalResultField.Pgrad, + ModalResultField.Pwheel, + ModalResultField.Pbrake + }); + + //todo only add if (GBX.TCon) + dataColumns.AddRange(new[] { + ModalResultField.TCν, + ModalResultField.TCmu, + ModalResultField.TC_M_Out, + ModalResultField.TC_n_Out + }); + + //todo: auxiliaries + } + VectoCSVFile.Write(ModFileName, new DataView(Data).ToTable(false, dataColumns.Select(x => x.GetName()).ToArray())); } + public object Compute(string expression, string filter) { return Data.Compute(expression, filter); diff --git a/VectoCore/Models/Simulation/Data/SummaryFileWriter.cs b/VectoCore/Models/Simulation/Data/SummaryFileWriter.cs index cc0bcde5e2..1ec8730c7c 100644 --- a/VectoCore/Models/Simulation/Data/SummaryFileWriter.cs +++ b/VectoCore/Models/Simulation/Data/SummaryFileWriter.cs @@ -15,26 +15,26 @@ namespace TUGraz.VectoCore.Models.Simulation.Data private const string JOB = "Job [-]"; private const string INPUTFILE = "Input File [-]"; private const string CYCLE = "Cycle [-]"; - private const string TIME = "Time [s]"; + private const string TIME = "time [s]"; private const string DISTANCE = "distance [km]"; private const string SPEED = "speed [km/h]"; private const string ALTITUDE = "∆altitude [m]"; - private const string PPOS = "Ppos [kw]"; - private const string PNEG = "Pneg [kw]"; - private const string FC = "FC [g/km]"; - private const string FCAUXC = "FC-AUXc [g/km]"; - private const string FCWHTCC = "FC-WHTCc [g/km]"; - private const string PBRAKE = "Pbrake [kw]"; - private const string EPOSICE = "EposICE [kwh]"; - private const string ENEGICE = "EnegICE [kwh]"; - private const string EAIR = "Eair [kwh]"; - private const string EROLL = "Eroll [kwh]"; - private const string EGRAD = "Egrad [kwh]"; - private const string EACC = "Eacc [kwh]"; - private const string EAUX = "Eaux [kwh]"; - private const string EBRAKE = "Ebrake [kwh]"; - private const string ETRANSM = "Etransm [kwh]"; - private const string ERETARDER = "Eretarder [kwh]"; + private const string PPOS = "Ppos [kW]"; + private const string PNEG = "Pneg [kW]"; + private const string FC = "FC [g/h]"; + private const string FCAUXC = "FC-AUXc [g/h]"; + private const string FCWHTCC = "FC-WHTCc [g/h]"; + private const string PBRAKE = "Pbrake [kW]"; + private const string EPOSICE = "EposICE [kWh]"; + private const string ENEGICE = "EnegICE [kWh]"; + private const string EAIR = "Eair [kWh]"; + private const string EROLL = "Eroll [kWh]"; + private const string EGRAD = "Egrad [kWh]"; + private const string EACC = "Eacc [kWh]"; + private const string EAUX = "Eaux [kWh]"; + private const string EBRAKE = "Ebrake [kWh]"; + private const string ETRANSM = "Etransm [kWh]"; + private const string ERETARDER = "Eretarder [kWh]"; private const string MASS = "Mass [kg]"; private const string LOADING = "Loading [kg]"; private const string A = "a [m/s2]"; @@ -233,10 +233,10 @@ namespace TUGraz.VectoCore.Models.Simulation.Data /// </summary> public class SumWriterDecoratorFullPowertrain : SummaryFileWriter, ISummaryDataWriter { - protected SummaryFileWriter _writer; - protected string _jobFileName; - protected string _jobName; - protected string _cycleFileName; + private readonly SummaryFileWriter _writer; + private readonly string _jobFileName; + private readonly string _jobName; + private readonly string _cycleFileName; public SumWriterDecoratorFullPowertrain(SummaryFileWriter writer, string jobFileName, string jobName, string cycleFileName) @@ -259,10 +259,10 @@ public class SumWriterDecoratorFullPowertrain : SummaryFileWriter, ISummaryDataW /// </summary> public class SumWriterDecoratorEngineOnly : SummaryFileWriter, ISummaryDataWriter { - protected SummaryFileWriter _writer; - protected string _jobFileName; - protected string _jobName; - protected string _cycleFileName; + private readonly SummaryFileWriter _writer; + private readonly string _jobFileName; + private readonly string _jobName; + private readonly string _cycleFileName; public SumWriterDecoratorEngineOnly(SummaryFileWriter writer, string jobFileName, string jobName, string cycleFileName) { diff --git a/VectoCore/Models/Simulation/Impl/JobContainer.cs b/VectoCore/Models/Simulation/Impl/JobContainer.cs index 231bf70250..93b3a56df7 100644 --- a/VectoCore/Models/Simulation/Impl/JobContainer.cs +++ b/VectoCore/Models/Simulation/Impl/JobContainer.cs @@ -38,8 +38,8 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl { var sumFileName = Path.GetFileNameWithoutExtension(data.JobFileName); var sumFilePath = Path.GetDirectoryName(data.JobFileName); - _sumWriter = new SummaryFileWriter(string.Format("{0}.vsum", Path.Combine(sumFilePath, sumFileName))); + AddJobs(data); } diff --git a/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs b/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs index 15fb6d027d..5015f3f24d 100644 --- a/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs +++ b/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs @@ -1,5 +1,5 @@ -using System.Collections.Generic; using System.IO; +using System.Collections.Generic; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Models.SimulationComponent; using TUGraz.VectoCore.Models.SimulationComponent.Data; @@ -15,16 +15,14 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl /// Creates a simulation job for time based engine only powertrain. /// </summary> public static IVectoSimulator CreateTimeBasedEngineOnlyJob(string engineFile, string cycleFile, string jobFileName, - string jobName, - IModalDataWriter dataWriter, SummaryFileWriter sumWriter) + string jobName, IModalDataWriter dataWriter, SummaryFileWriter sumWriter) { - var builder = new SimulatorBuilder(dataWriter, - new SumWriterDecoratorEngineOnly(sumWriter, jobFileName, jobName, cycleFile), engineOnly: true); + var sumWriterDecorator = new SumWriterDecoratorEngineOnly(sumWriter, jobFileName, jobName, cycleFile); + var builder = new SimulatorBuilder(dataWriter, sumWriterDecorator, engineOnly: true); builder.AddEngine(engineFile); - var simulator = builder.Build(cycleFile); - return simulator; + return builder.Build(cycleFile); } /// <summary> @@ -41,14 +39,10 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl var jobName = string.Format("{0}-{1}", jobNumber, i); var modFileName = string.Format("{0}_{1}.vmod", Path.GetFileNameWithoutExtension(data.JobFileName), Path.GetFileNameWithoutExtension(cycleFile)); - _dataWriter = new ModalDataWriter(modFileName); - ISummaryDataWriter sumWriterDecorator; - if (data.IsEngineOnly) { - sumWriterDecorator = new SumWriterDecoratorEngineOnly(sumWriter, data.JobFileName, jobName, cycleFile); - } else { - sumWriterDecorator = new SumWriterDecoratorFullPowertrain(sumWriter, data.JobFileName, jobName, cycleFile); - } + _dataWriter = new ModalDataWriter(modFileName, data.IsEngineOnly); + + var sumWriterDecorator = DecorateSumWriter(data.IsEngineOnly, sumWriter, data.JobFileName, jobName, cycleFile); var builder = new SimulatorBuilder(_dataWriter, sumWriterDecorator, data.IsEngineOnly); builder.AddEngine(data.EngineFile); @@ -57,21 +51,38 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl builder.AddVehicle(data.VehicleFile); builder.AddGearbox(data.GearboxFile); - foreach (var aux in data.Aux) { builder.AddAuxiliary(aux.Path, aux.ID); } - builder.AddDriver(data.StartStop, data.OverSpeedEcoRoll, data.LookAheadCoasting, - data.AccelerationLimitingFile); + builder.AddDriver(data.StartStop, data.OverSpeedEcoRoll, data.LookAheadCoasting, data.AccelerationLimitingFile); } + yield return builder.Build(cycleFile); + } + } - var job = builder.Build(cycleFile); - - yield return job; + /// <summary> + /// Decorates the sum writer with a correct decorator (either EngineOnly or FullPowertrain). + /// </summary> + /// <param name="engineOnly">if set to <c>true</c> [engine only].</param> + /// <param name="sumWriter">The sum writer.</param> + /// <param name="jobFileName">Name of the job file.</param> + /// <param name="jobName">Name of the job.</param> + /// <param name="cycleFile">The cycle file.</param> + /// <returns></returns> + private static ISummaryDataWriter DecorateSumWriter(bool engineOnly, SummaryFileWriter sumWriter, + string jobFileName, string jobName, string cycleFile) + { + if (engineOnly) { + return new SumWriterDecoratorEngineOnly(sumWriter, jobFileName, jobName, cycleFile); } + + return new SumWriterDecoratorFullPowertrain(sumWriter, jobFileName, jobName, cycleFile); } + /// <summary> + /// Provides Methods to build a simulator with a powertrain step by step. + /// </summary> public class SimulatorBuilder { private readonly bool _engineOnly; diff --git a/VectoCore/Utils/VectoCSVFile.cs b/VectoCore/Utils/VectoCSVFile.cs index c230e3756c..ee2d56b886 100644 --- a/VectoCore/Utils/VectoCSVFile.cs +++ b/VectoCore/Utils/VectoCSVFile.cs @@ -17,7 +17,7 @@ namespace TUGraz.VectoCore.Utils /// </summary> /// <remarks> /// The following format applies to all CSV (Comma-separated values) Input Files used in VECTO: - /// List Separator: Comma "," + /// List DELIMITER: Comma "," /// Decimal-Mark: Dot "." /// Comments: "#" at the beginning of the comment line. Number and position of comment lines is not limited. /// Header: One header line (not a comment line) at the beginning of the file. @@ -27,7 +27,7 @@ namespace TUGraz.VectoCore.Utils /// </remarks> public static class VectoCSVFile { - private const char Separator = ','; + private const char Delimiter = ','; private const char Comment = '#'; /// <summary> @@ -48,7 +48,7 @@ namespace TUGraz.VectoCore.Utils // Valid Columns found => header was valid => skip header line lines = lines.Skip(1).ToArray(); } else { - var log = LogManager.GetLogger(typeof (VectoCSVFile)); + var log = LogManager.GetLogger(typeof(VectoCSVFile)); log.Warn("No valid Data Header found. Interpreting the first line as data line."); // set the validColumns to: {"0", "1", "2", "3", ...} for all columns in first line. validColumns = GetColumns(lines.First()).Select((_, index) => index.ToString()).ToArray(); @@ -62,13 +62,13 @@ namespace TUGraz.VectoCore.Utils for (var i = 0; i < lines.Length; i++) { var line = lines[i]; - var cells = line.Split(Separator); + var cells = line.Split(Delimiter); if (!ignoreEmptyColumns && cells.Length != table.Columns.Count) { throw new CSVReadException(string.Format("Line {0}: The number of values is not correct.", i)); } try { - table.Rows.Add(line.Split(Separator)); + table.Rows.Add(line.Split(Delimiter)); } catch (InvalidCastException e) { throw new CSVReadException( string.Format("Line {0}: The data format of a value is not correct. {1}", i, e.Message), e); @@ -98,7 +98,7 @@ namespace TUGraz.VectoCore.Utils line = Regex.Replace(line, @"\(.*?\)", ""); line = line.Replace("<", ""); line = line.Replace(">", ""); - return line.Split(Separator).Select(col => col.Trim()); + return line.Split(Delimiter).Select(col => col.Trim()); } private static string[] RemoveComments(string[] lines) @@ -112,18 +112,18 @@ namespace TUGraz.VectoCore.Utils return lines; } - /// <summary> - /// Writes the datatable to the csv file. - /// Uses the column caption as header (with fallback to column name) for the csv header. - /// </summary> - /// <param name="fileName">Path to the file.</param> - /// <param name="table">The Datatable.</param> + /// <summary> + /// Writes the datatable to the csv file. + /// Uses the column caption as header (with fallback to column name) for the csv header. + /// </summary> + /// <param name="fileName">Path to the file.</param> + /// <param name="table">The Datatable.</param> public static void Write(string fileName, DataTable table) { var sb = new StringBuilder(); var header = table.Columns.Cast<DataColumn>().Select(col => col.Caption ?? col.ColumnName); - sb.AppendLine(string.Join(", ", header)); + sb.AppendLine(string.Join(Delimiter.ToString(), header)); foreach (DataRow row in table.Rows) { var formattedList = new List<string>(); @@ -134,7 +134,7 @@ namespace TUGraz.VectoCore.Utils : item.ToString(); formattedList.Add(formattedValue); } - sb.AppendLine(string.Join(Separator.ToString(), formattedList)); + sb.AppendLine(string.Join(Delimiter.ToString(), formattedList)); } File.WriteAllText(fileName, sb.ToString()); diff --git a/VectoCoreTest/Models/Simulation/SimulationTests.cs b/VectoCoreTest/Models/Simulation/SimulationTests.cs index b8abaec841..16ac702ffd 100644 --- a/VectoCoreTest/Models/Simulation/SimulationTests.cs +++ b/VectoCoreTest/Models/Simulation/SimulationTests.cs @@ -1,11 +1,13 @@ using System.IO; using System.Linq; +using System.Security.Cryptography.X509Certificates; using Microsoft.VisualStudio.TestTools.UnitTesting; using TUGraz.VectoCore.Exceptions; using TUGraz.VectoCore.Models.Simulation; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.Utils; +using TUGraz.VectoCore.Tests.Utils; namespace TUGraz.VectoCore.Tests.Models.Simulation { @@ -27,53 +29,38 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation Assert.AreEqual(0U, container.Gear()); } - [TestMethod] public void TestEngineOnly_JobRun() { - var resultFileName = "TestEngineOnly_JobRun-result.vmod"; - var expectedResultsName = @"TestData\Results\EngineOnlyCycles\24tCoach_EngineOnly short.vmod"; + var actual = "TestEngineOnly_JobRun-result.vmod"; + var expected = @"TestData\Results\EngineOnlyCycles\24tCoach_EngineOnly short.vmod"; - var job = CreateJob(resultFileName); + var job = CreateJob(actual); job.Run(); - var results = ModalResults.ReadFromFile(resultFileName); - var expectedResults = ModalResults.ReadFromFile(expectedResultsName); - - Assert.AreEqual(expectedResults.Rows.Count, results.Rows.Count, "Moddata: Row count differs."); + ResultFileHelper.TestModFile(expected, actual); } [TestMethod] public void TestEngineOnly_SimulatorRun() { - var resultFileName = "TestEngineOnly_SimulatorRun-result.vmod"; - var expectedResultsName = @"TestData\Results\EngineOnlyCycles\24tCoach_EngineOnly short.vmod"; + var actual = @"TestEngineOnly_SimulatorRun-result.vmod"; + var expected = @"TestData\Results\EngineOnlyCycles\24tCoach_EngineOnly short.vmod"; - var job = CreateJob(resultFileName); + var job = CreateJob(actual); var sim = new JobContainer(new TestSumWriter()); sim.AddJob(job); sim.RunJobs(); - var results = ModalResults.ReadFromFile(resultFileName); - var expectedResults = ModalResults.ReadFromFile(expectedResultsName); - - Assert.AreEqual(expectedResults.Rows.Count, results.Rows.Count, "Moddata: Row count differs."); + ResultFileHelper.TestModFile(expected, actual); } public IVectoSimulator CreateJob(string resultFileName) { var sumFileName = resultFileName.Substring(0, resultFileName.Length - 4) + "vsum"; - if (File.Exists(resultFileName)) { - File.Delete(resultFileName); - } - - if (File.Exists(sumFileName)) { - File.Delete(sumFileName); - } - - var dataWriter = new ModalDataWriter(resultFileName); + var dataWriter = new ModalDataWriter(resultFileName, engineOnly: true); var sumWriter = new SummaryFileWriter(sumFileName); var job = SimulatorFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, jobFileName: "", jobName: "", dataWriter: dataWriter, sumWriter: sumWriter); @@ -90,62 +77,30 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation @"TestEngineOnly-MultipleJobs-result2", @"TestEngineOnly-MultipleJobs-result3" }; - var expectedResultsName = @"TestData\Results\EngineOnlyCycles\24tCoach_EngineOnly short.vmod"; - var expectedResults = ModalResults.ReadFromFile(expectedResultsName); var simulation = new JobContainer(new TestSumWriter()); foreach (var resultFile in resultFiles) { simulation.AddJob(CreateJob(resultFile)); } - - resultFiles = resultFiles.Select(x => x + "_Coach Engine Only short.vmod").ToArray(); - simulation.RunJobs(); - foreach (var resultFile in resultFiles) { - var results = ModalResults.ReadFromFile(resultFile); - Assert.AreEqual(expectedResults.Rows.Count, results.Rows.Count, "Moddata: Row count differs."); - } + ResultFileHelper.TestModFiles(resultFiles.Select(x => x + "_Coach Engine Only short.vmod"), + Enumerable.Repeat(@"TestData\Results\EngineOnlyCycles\24tCoach_EngineOnly short.vmod", resultFiles.Length)); } [TestMethod] public void Test_VectoJob() { - //run jobs var jobData = VectoJobData.ReadFromFile(@"TestData\Jobs\24t Coach.vecto"); var jobContainer = new JobContainer(jobData); jobContainer.RunJobs(); - - // check sum file - var expectedSumFile = @"TestData\Results\EngineOnlyCycles\24t Coach.vsum"; - var sumFile = @"TestData\Jobs\24t Coach.vsum"; - Assert.IsTrue(File.Exists(sumFile), "sum file is missing: " + sumFile); - Assert.AreEqual(File.ReadAllLines(sumFile).Length, File.ReadAllLines(expectedSumFile).Length, - string.Format("sum file row count differs. Expected File: {0}, Actual File: {1}", expectedSumFile, sumFile)); - - // check vmod files - var expectedResultFiles = new[] { + ResultFileHelper.TestSumFile(@"TestData\Results\EngineOnlyCycles\24t Coach.vsum", @"TestData\Jobs\24t Coach.vsum"); + ResultFileHelper.TestModFiles(new[] { @"TestData\Results\EngineOnlyCycles\24t Coach_Engine Only1.vmod", @"TestData\Results\EngineOnlyCycles\24t Coach_Engine Only2.vmod", @"TestData\Results\EngineOnlyCycles\24t Coach_Engine Only3.vmod" - }; - var resultFiles = expectedResultFiles.Select(x => Path.GetFileName(x)); - foreach (var result in resultFiles) { - Assert.IsTrue(File.Exists(result), "vmod file is missing: " + result); - } - - var resultFileIt = resultFiles.GetEnumerator(); - - foreach (var expectedResultFile in expectedResultFiles) { - resultFileIt.MoveNext(); - var results = ModalResults.ReadFromFile(resultFileIt.Current); - var expectedResults = ModalResults.ReadFromFile(expectedResultFile); - - Assert.AreEqual(expectedResults.Rows.Count, results.Rows.Count, - string.Format("Moddata: Row count differs. Expected File: {0}, Actual File: {1}", expectedResultFile, - resultFileIt.Current)); - } + }, new[] { "24t Coach_Engine Only1.vmod", "24t Coach_Engine Only2.vmod", "24t Coach_Engine Only3.vmod" }); } } } \ No newline at end of file diff --git a/VectoCoreTest/Models/SimulationComponent/MockPorts.cs b/VectoCoreTest/Utils/MockPorts.cs similarity index 100% rename from VectoCoreTest/Models/SimulationComponent/MockPorts.cs rename to VectoCoreTest/Utils/MockPorts.cs diff --git a/VectoCoreTest/Utils/ResultFileHelper.cs b/VectoCoreTest/Utils/ResultFileHelper.cs new file mode 100644 index 0000000000..57d4aba48e --- /dev/null +++ b/VectoCoreTest/Utils/ResultFileHelper.cs @@ -0,0 +1,82 @@ +using System; +using System.IO; +using System.Data; +using System.Linq; +using System.Collections.Generic; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using TUGraz.VectoCore.Models.Simulation.Data; + +namespace TUGraz.VectoCore.Tests.Utils +{ + public static class ResultFileHelper + { + public static void TestModFile(string expectedFile, string actualFile) + { + TestModFiles(new[] { expectedFile }, new[] { actualFile }); + } + + public static IEnumerable<TResult> ZipAll<TFirst, TSecond, TResult>(this IEnumerable<TFirst> first, + IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector) + { + var firstEnum = first.GetEnumerator(); + var secondEnum = second.GetEnumerator(); + while (true) { + var firstHadNext = firstEnum.MoveNext(); + var secondHadNext = secondEnum.MoveNext(); + if (firstHadNext && secondHadNext) { + yield return resultSelector(firstEnum.Current, secondEnum.Current); + } else if (firstHadNext != secondHadNext) { + throw new IndexOutOfRangeException("The argument enumerables must have the same length."); + } else { + yield break; + } + } + } + + public static void TestModFiles(IEnumerable<string> expectedFiles, IEnumerable<string> actualFiles) + { + var resultFiles = expectedFiles.ZipAll(actualFiles, (expectedFile, actualFile) => new { expectedFile, actualFile }); + foreach (var result in resultFiles) { + Assert.IsTrue(File.Exists(result.actualFile), "MOD File is missing: " + result); + + var expected = ModalResults.ReadFromFile(result.expectedFile); + var actual = ModalResults.ReadFromFile(result.actualFile); + + Assert.AreEqual(expected.Rows.Count, actual.Rows.Count, + string.Format("Moddata: Row count differs.\nExpected {0} Rows in {1}\nGot {2} Rows in {3}", expected.Rows.Count, + result.expectedFile, actual.Rows.Count, result.actualFile)); + + Assert.AreEqual(expected.Columns.Count, actual.Columns.Count, + string.Format("Moddata: Columns count differs.\nExpected {0} Columns in {1}\nGot {2} Columns in {3}", + expected.Columns.Count, + result.expectedFile, actual.Columns.Count, result.actualFile)); + + var actualCols = actual.Columns.Cast<DataColumn>().Select(x => x.ColumnName).ToList(); + var expectedCols = expected.Columns.Cast<DataColumn>().Select(x => x.ColumnName).ToList(); + + Assert.IsTrue(expectedCols.SequenceEqual(actualCols), + string.Format("Moddata: Columns differ:\nExpected: {0}\nActual: {1}", string.Join(", ", expectedCols), + string.Join(", ", actualCols))); + + // todo: Test Contents of MOD File. + } + } + + public static void TestSumFile(string expectedFile, string actualFile) + { + Assert.IsTrue(File.Exists(actualFile), "SUM File is missing: " + actualFile); + + var expected = File.ReadAllLines(expectedFile); + var actual = File.ReadAllLines(actualFile); + + Assert.AreEqual(expected.Length, actual.Length, + string.Format("SUM File row count differs.\nExpected {0} Rows in {1}\nGot {2} Rows in {3}", expected.Length, + expectedFile, actual.Length, actualFile)); + + Assert.AreEqual(expected.First(), actual.First(), + string.Format("SUM File Header differs:\nExpected: '{0}'\nActual : '{1}'", expected.First(), actual.First())); + + // todo: test contents of sum file + } + } +} \ No newline at end of file diff --git a/VectoCoreTest/Models/Simulation/TestSumWriter.cs b/VectoCoreTest/Utils/TestSumWriter.cs similarity index 100% rename from VectoCoreTest/Models/Simulation/TestSumWriter.cs rename to VectoCoreTest/Utils/TestSumWriter.cs diff --git a/VectoCoreTest/VectoCoreTest.csproj b/VectoCoreTest/VectoCoreTest.csproj index 8b687e5032..06dc4b36c2 100644 --- a/VectoCoreTest/VectoCoreTest.csproj +++ b/VectoCoreTest/VectoCoreTest.csproj @@ -78,9 +78,10 @@ <Compile Include="Models\SimulationComponent\GearboxTest.cs" /> <Compile Include="Models\SimulationComponent\RetarderTest.cs" /> <Compile Include="Models\Simulation\DrivingCycleTests.cs" /> - <Compile Include="Models\SimulationComponent\MockPorts.cs" /> + <Compile Include="Utils\ResultFileHelper.cs" /> + <Compile Include="Utils\MockPorts.cs" /> <Compile Include="Models\Simulation\SimulationTests.cs" /> - <Compile Include="Models\Simulation\TestSumWriter.cs" /> + <Compile Include="Utils\TestSumWriter.cs" /> <Compile Include="Models\Simulation\VechicleContainerTests.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\Settings.Designer.cs"> @@ -190,7 +191,7 @@ <None Include="TestData\Cycles\Coach Engine Only.vdri"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> - <None Include="TestData\EngineFullLoadJumps.csv"> + <None Include="TestData\EngineFullLoadJumps.csv"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> <None Include="TestData\Results\EngineFullLoadJumps\EngineFLJ_1000rpm_10Hz.csv"> -- GitLab