public void ActualVsLegacy(string sampleFileName) { var sampleFolder = new DirectoryInfo("Samples"); var sampleFile = new FileInfo(Path.Combine(sampleFolder.FullName, sampleFileName)); using FileStream sampleStream = sampleFile.OpenRead(); using SampleReader sampleReader = new SampleReader(sampleStream); var legacyDataReader = new LegacyForzaDataReader(); var actualDataReader = new ForzaDataReader(); var sledFields = typeof(ForzaSledDataStruct).GetFields(); var carDashFields = typeof(ForzaCarDashDataStruct).GetFields(); // iterate every chunk while (sampleReader.TryRead(out SampleStruct chunk)) { // read chunk with old and new readers var expectedForzaData = legacyDataReader.Read(chunk.Data); var actualForzaData = actualDataReader.Read(chunk.Data); // comparing read version Assert.AreEqual( expectedForzaData.Version, actualForzaData.Version, $"{nameof(ForzaDataStruct.Version)} comparison failed at chunk Elapsed = {chunk.Elapsed}" ); // comparing each sled field foreach (var sledField in sledFields) { Assert.AreEqual( sledField.GetValue(expectedForzaData.Sled), sledField.GetValue(actualForzaData.Sled), $"{sledField.Name} comparison failed at chunk Elapsed = {chunk.Elapsed}" ); } // comparing each car dash field foreach (var carDashField in carDashFields) { Assert.AreEqual( carDashField.GetValue(expectedForzaData.CarDash), carDashField.GetValue(actualForzaData.CarDash), $"{carDashField.Name} comparison failed at chunk Elapsed = {chunk.Elapsed}" ); } //Trace.WriteLine($"Chunk #{chunk.Elapsed}/byte {sampleStream.Position}: success"); } }
static void Main(string[] args) { try { _args = PowArgs.Parser <Arguments> .Parse(args); } catch (Exception ex) { Console.Error.WriteLine(ex.Message); ShowHelp(); Exit(ExitCodes.ArgsError); return; } if (_args.Help) { ShowHelp(); Exit(ExitCodes.Help); return; } else if (_args.UseTimestamp == _args.UseStaticFrequency) { Console.Error.WriteLine("You must specify which fix to use: timestamp OR frequency"); ShowHelp(); Exit(ExitCodes.ArgsError); return; } var inputFile = new FileInfo(_args.Input); var outputFile = new FileInfo(_args.Output); string typeOfFix = _args.UseTimestamp ? "timestamp" : _args.UseStaticFrequency ? "fixed frequency" : "unknown"; // input file existence if (!inputFile.Exists) { Console.Error.WriteLine($"Input file {inputFile.Name} is not found or its access is denied"); Exit(ExitCodes.InputError); return; } // output directory creation if (!outputFile.Directory.Exists) { outputFile.Directory.Create(); } Console.Out.WriteLine($"Input: {inputFile.Name}"); Console.Out.WriteLine($"Output: {outputFile.Name}"); Console.Out.WriteLine($"Fix: {typeOfFix}"); // input read using (FileStream input = new FileStream(inputFile.FullName, FileMode.Open, FileAccess.Read)) using (FileStream output = new FileStream(outputFile.FullName, FileMode.Create, FileAccess.Write)) using (SampleReader reader = new SampleReader(input)) using (SampleWriter writer = new SampleWriter(output)) { ForzaDataReader dataReader = new ForzaDataReader(); ForzaDataStruct?firstForzaData = null; ForzaDataStruct?prevForzaData = null; int chunkIndex; // iterate every chunk for (chunkIndex = 0; reader.TryRead(out SampleStruct chunk); chunkIndex++) { // decode forza data structure ForzaDataStruct forzaData = dataReader.Read(chunk.Data); if (!firstForzaData.HasValue) { firstForzaData = forzaData; } // if timestamps are used, validate them if (_args.UseTimestamp) { // non increasing timestamps if (prevForzaData?.Sled.TimestampMS > forzaData.Sled.TimestampMS) { if (_args.IgnoreInvalidChunks) { Console.Out.WriteLine($"Ignoring chunk #{chunkIndex}, {chunk.Length} bytes (non increasing timestamp)"); continue; } else { Console.Error.WriteLine($"Non increasing timestamp at chunk #{chunkIndex}, {chunk.Length} bytes"); Exit(ExitCodes.NonIncreasingTimestamps); break; } } // fixing elapsed ticks from previous chunk timestamp diff uint elapsedMilliseconds = forzaData.Sled.TimestampMS - firstForzaData.Value.Sled.TimestampMS; chunk.Elapsed = TimeSpan.FromMilliseconds(elapsedMilliseconds).Ticks; } else if (_args.UseStaticFrequency) { // fixing elapsed ticks with static chunk time uint elapsedMilliseconds = (uint)Math.Round( chunkIndex * ChunkTime, MidpointRounding.AwayFromZero ); chunk.Elapsed = TimeSpan.FromMilliseconds(elapsedMilliseconds).Ticks; } // fixed chunk written to output writer.Write(chunk); prevForzaData = forzaData; } // warning if not on end of stream if (!reader.EndOfStream) { Console.Error.WriteLine($"Can't decode more chunks, the rest of the source is ignored"); } writer.Flush(); outputFile.Refresh(); // final result Console.Out.WriteLine($"Chunks: {reader.Reads} read, {writer.Writes} written (diff: {writer.Writes - reader.Reads})"); Console.Out.WriteLine($"Size: {inputFile.Length} bytes on input, {outputFile.Length} bytes on output, (diff: {outputFile.Length - inputFile.Length})"); } Exit(ExitCodes.OK); }