Update GenesisReaderTests: add real input parsing, format variation handling, and rollover cases; remove outdated Q3 calibration tests; increment version to 3.9.3056.1
This commit is contained in:
parent
3eb0b87f0d
commit
33ef914984
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
|||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("3.9.3055.1")]
|
[assembly: AssemblyVersion("3.9.3056.1")]
|
||||||
[assembly: AssemblyFileVersion("3.9.3055.1")]
|
[assembly: AssemblyFileVersion("3.9.3056.1")]
|
||||||
|
|||||||
@ -1299,6 +1299,15 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
|
|||||||
void DataStreamPostProcessing()
|
void DataStreamPostProcessing()
|
||||||
{
|
{
|
||||||
PrepareCalculatedChannelData();
|
PrepareCalculatedChannelData();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
log.DebugFormat("DataStreamPostProcessing() - harcoded call GetQ3Calibration(200.0, 120.0, 15625.0);");
|
||||||
|
GetQ3Calibration(200.0, 120.0, 15625.0);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
log.Error($"DataStreamPostProcessing -- Q3 CALIBRATION -- failed: {ex}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -3886,51 +3895,86 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
|
|||||||
|
|
||||||
public void GetQ3Calibration(double refVolume, double refTime, double initCalibFactor)
|
public void GetQ3Calibration(double refVolume, double refTime, double initCalibFactor)
|
||||||
{
|
{
|
||||||
|
log.Debug("=== Q3 CALIBRATION START ===");
|
||||||
|
|
||||||
isQ3CalibValid = false;
|
isQ3CalibValid = false;
|
||||||
q3Calib = 0.0;
|
q3Calib = 0.0;
|
||||||
|
|
||||||
if (_rawStartEndByChannel == null || NoSamples)
|
log.Debug($"Inputs: refVolume={refVolume}, refTime={refTime}, initCalibFactor={initCalibFactor}");
|
||||||
|
|
||||||
|
if (_rawStartEndByChannel == null)
|
||||||
|
{
|
||||||
|
log.Debug("EXIT: _rawStartEndByChannel is NULL");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NoSamples)
|
||||||
|
{
|
||||||
|
log.Debug("EXIT: NoSamples == true");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (refVolume <= 0 || refTime <= 0 || initCalibFactor <= 0)
|
if (refVolume <= 0 || refTime <= 0 || initCalibFactor <= 0)
|
||||||
|
{
|
||||||
|
log.Debug("EXIT: Invalid input values (<= 0)");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
OptoTelegramRaw[][] recalculatedVariablesByChannel = new OptoTelegramRaw[ChannelCount][];
|
OptoTelegramRaw[][] recalculatedVariablesByChannel = new OptoTelegramRaw[ChannelCount][];
|
||||||
|
|
||||||
for (int channel = 0; channel < ChannelCount; channel++)
|
for (int channel = 0; channel < ChannelCount; channel++)
|
||||||
{
|
{
|
||||||
recalculatedVariablesByChannel[channel] = new OptoTelegramRaw[2];
|
recalculatedVariablesByChannel[channel] = new OptoTelegramRaw[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Debug($"ChannelCount={ChannelCount}");
|
||||||
|
|
||||||
for (int iChannel = 0; iChannel < ChannelCount; iChannel++)
|
for (int iChannel = 0; iChannel < ChannelCount; iChannel++)
|
||||||
{
|
{
|
||||||
if (_rawStartEndByChannel[iChannel] == null || _rawStartEndByChannel[iChannel].Length < 2)
|
var channelData = _rawStartEndByChannel[iChannel];
|
||||||
continue;
|
|
||||||
|
|
||||||
var channelStartRecord = _rawStartEndByChannel[iChannel][0];
|
if (channelData == null || channelData.Length < 2)
|
||||||
var channelEndRecord = _rawStartEndByChannel[iChannel][1];
|
{
|
||||||
|
log.Debug($"Channel {iChannel}: SKIPPED (no data)");
|
||||||
if (channelStartRecord == null || channelEndRecord == null)
|
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var start = channelData[0];
|
||||||
|
var end = channelData[1];
|
||||||
|
|
||||||
|
if (start == null || end == null)
|
||||||
|
{
|
||||||
|
log.Debug($"Channel {iChannel}: SKIPPED (null records)");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
recalculatedVariablesByChannel[iChannel][0] = new OptoTelegramRaw();
|
recalculatedVariablesByChannel[iChannel][0] = new OptoTelegramRaw();
|
||||||
recalculatedVariablesByChannel[iChannel][1] = new OptoTelegramRaw();
|
recalculatedVariablesByChannel[iChannel][1] = new OptoTelegramRaw();
|
||||||
|
|
||||||
recalculatedVariablesByChannel[iChannel][0].Copy(channelStartRecord);
|
recalculatedVariablesByChannel[iChannel][0].Copy(start);
|
||||||
recalculatedVariablesByChannel[iChannel][1].Copy(channelEndRecord);
|
recalculatedVariablesByChannel[iChannel][1].Copy(end);
|
||||||
|
|
||||||
double channelDeltaTime =
|
double deltaTime = end.TimestampExt - start.TimestampExt;
|
||||||
channelEndRecord.TimestampExt - channelStartRecord.TimestampExt;
|
double deltaVolume = end.VolumeRawExt - start.VolumeRawExt;
|
||||||
|
|
||||||
double channelDeltaVolume =
|
log.Debug($"Channel {iChannel}:");
|
||||||
channelEndRecord.VolumeRawExt - channelStartRecord.VolumeRawExt;
|
log.Debug($" Start: T={start.TimestampExt}, V={start.VolumeRawExt}");
|
||||||
|
log.Debug($" End: T={end.TimestampExt}, V={end.VolumeRawExt}");
|
||||||
|
log.Debug($" Delta: dT={deltaTime}, dV={deltaVolume}");
|
||||||
|
|
||||||
if (channelDeltaTime > 0)
|
if (deltaTime > 0)
|
||||||
{
|
{
|
||||||
double timeCoef = refTime / channelDeltaTime;
|
double timeCoef = refTime / deltaTime;
|
||||||
double recalculatedDeltaVolume = channelDeltaVolume * timeCoef;
|
double recalculatedDeltaVolume = deltaVolume * timeCoef;
|
||||||
|
|
||||||
recalculatedVariablesByChannel[iChannel][1].VolumeRawExt =
|
recalculatedVariablesByChannel[iChannel][1].VolumeRawExt =
|
||||||
recalculatedVariablesByChannel[iChannel][0].VolumeRawExt + recalculatedDeltaVolume;
|
recalculatedVariablesByChannel[iChannel][0].VolumeRawExt + recalculatedDeltaVolume;
|
||||||
|
|
||||||
|
log.Debug($" Recalc: coef={timeCoef}, new dV={recalculatedDeltaVolume}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.Debug($" WARNING: deltaTime <= 0 → no recalculation");
|
||||||
}
|
}
|
||||||
|
|
||||||
recalculatedVariablesByChannel[iChannel][0].TimestampExt = 0;
|
recalculatedVariablesByChannel[iChannel][0].TimestampExt = 0;
|
||||||
@ -3938,29 +3982,52 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
|
|||||||
}
|
}
|
||||||
|
|
||||||
double scaling = 15625.0;
|
double scaling = 15625.0;
|
||||||
|
log.Debug($"Scaling={scaling}");
|
||||||
|
|
||||||
if (scaling <= 0)
|
if (scaling <= 0)
|
||||||
|
{
|
||||||
|
log.Debug("EXIT: scaling <= 0");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
double avgRawVolume = AverageCachedVolume(recalculatedVariablesByChannel, 0);
|
double avgRawVolume = AverageCachedVolume(recalculatedVariablesByChannel, 0);
|
||||||
|
log.Debug($"AverageCachedVolume={avgRawVolume}");
|
||||||
|
|
||||||
if (avgRawVolume <= 0)
|
if (avgRawVolume <= 0)
|
||||||
|
{
|
||||||
|
log.Debug("EXIT: avgRawVolume <= 0");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
double measuredVolume = avgRawVolume / scaling;
|
double measuredVolume = avgRawVolume / scaling;
|
||||||
|
log.Debug($"MeasuredVolume={measuredVolume}");
|
||||||
|
|
||||||
if (measuredVolume <= 0)
|
if (measuredVolume <= 0)
|
||||||
|
{
|
||||||
|
log.Debug("EXIT: measuredVolume <= 0");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
q3Calib = (refVolume / measuredVolume) * initCalibFactor;
|
q3Calib = (refVolume / measuredVolume) * initCalibFactor;
|
||||||
|
|
||||||
double diffPercent = Math.Abs((q3Calib - initCalibFactor) / initCalibFactor) * 100.0;
|
log.Debug($"Q3Calib (raw)={q3Calib}");
|
||||||
|
|
||||||
|
double diffPercent =
|
||||||
|
Math.Abs((q3Calib - initCalibFactor) / initCalibFactor) * 100.0;
|
||||||
|
|
||||||
|
log.Debug($"DiffPercent={diffPercent}%");
|
||||||
|
|
||||||
isQ3CalibValid = diffPercent <= 5.0;
|
isQ3CalibValid = diffPercent <= 5.0;
|
||||||
|
|
||||||
|
log.Debug($"Validation: {(isQ3CalibValid ? "VALID" : "INVALID")}");
|
||||||
|
|
||||||
if (!isQ3CalibValid)
|
if (!isQ3CalibValid)
|
||||||
{
|
{
|
||||||
q3Calib = 0.0;
|
q3Calib = 0.0;
|
||||||
|
log.Debug("Q3Calib reset to 0 due to invalid result");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Debug("=== Q3 CALIBRATION END ===");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,136 +3,237 @@ using System.Linq;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
using TBF.Rig.RegisterReaders.GenesisRegReader.common;
|
using TBF.Rig.RegisterReaders.GenesisRegReader.common;
|
||||||
|
using TBF.Rig.RegisterReaders.GenesisRegReader.communication;
|
||||||
using TBF.Rig.RegisterReaders.GenesisRegReader.implementations;
|
using TBF.Rig.RegisterReaders.GenesisRegReader.implementations;
|
||||||
|
using TBF.Rig.Sequences;
|
||||||
|
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.common;
|
||||||
|
|
||||||
namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||||
{
|
{
|
||||||
[TestClass]
|
[TestClass]
|
||||||
public class GenesisReaderTests
|
public class GenesisReaderTests
|
||||||
{
|
{
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void PreparedSimulation_ShouldCalculate_StartEndVolumes_AndTimes()
|
public void Debug_ProcessOptoLine_FormatVariants()
|
||||||
{
|
{
|
||||||
var reader = new GenesisSmartReader();
|
var reader = new GenesisSmartReader();
|
||||||
InitializeReaderForTest(reader);
|
InitializeReaderForTest(reader);
|
||||||
|
|
||||||
// Let the production/test helper prepare valid internal start/end data
|
string[] variants =
|
||||||
InvokePrivate(reader, "PrepareCalculatedChannelDataForTest", new object[] { true });
|
{
|
||||||
|
"@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331",
|
||||||
|
"@he 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331",
|
||||||
|
"@he\t1\t0\t0A1F59C4\t00017A43\t00115C45\t72E1596B\t00000400\t00001998\t7D91B652\t7D4F37E6\t000191E6\t0C\t062E4A9C\t5331",
|
||||||
|
"@he \t1\t0\t0A1F59C4\t00017A43\t00115C45\t72E1596B\t00000400\t00001998\t7D91B652\t7D4F37E6\t000191E6\t0C\t062E4A9C\t5331"
|
||||||
|
};
|
||||||
|
|
||||||
Assert.IsFalse(reader.NoSamples, "Simulation did not prepare valid sample data.");
|
for (int i = 0; i < variants.Length; i++)
|
||||||
|
{
|
||||||
|
bool blockCompleted = false;
|
||||||
|
reader.ProcessOptoLine(variants[i], DataStreamState.ProcessAndSave, out blockCompleted);
|
||||||
|
|
||||||
|
int optoDataCount = GetPrivateField<int>(reader, "optoDataCount");
|
||||||
|
|
||||||
|
Console.WriteLine($"Variant {i}: {variants[i]}");
|
||||||
|
Console.WriteLine($" blockCompleted={blockCompleted}");
|
||||||
|
Console.WriteLine($" optoDataCount={optoDataCount}");
|
||||||
|
Console.WriteLine("--------------------------------");
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.Fail("Inspect which variant, if any, is accepted.");
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void RealInput_ShouldCalculate_StartEndVolumes_AndTimes()
|
||||||
|
{
|
||||||
|
var reader = new GenesisSmartReader();
|
||||||
|
InitializeReaderForTest(reader);
|
||||||
|
|
||||||
|
string[] realInputLines = LoadRealInputLines();
|
||||||
|
Assert.IsTrue(realInputLines.Length > 0, "No test input lines were provided.");
|
||||||
|
|
||||||
|
int processedCount = 0;
|
||||||
|
int firstValidIx = -1;
|
||||||
|
int lastValidIx = -1;
|
||||||
|
|
||||||
|
Console.WriteLine("=== BEGIN INPUT PARSING ===");
|
||||||
|
|
||||||
|
for (int i = 0; i < realInputLines.Length; i++)
|
||||||
|
{
|
||||||
|
string line = realInputLines[i];
|
||||||
|
|
||||||
|
bool blockCompleted = false;
|
||||||
|
Exception parseException = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
reader.ProcessOptoLine(line, DataStreamState.ProcessAndSave, out blockCompleted);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
parseException = ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
int optoDataCount = GetPrivateField<int>(reader, "optoDataCount");
|
||||||
|
|
||||||
|
Console.WriteLine($"[{i}] line = {line}");
|
||||||
|
Console.WriteLine($"[{i}] blockCompleted = {blockCompleted}");
|
||||||
|
Console.WriteLine($"[{i}] optoDataCount = {optoDataCount}");
|
||||||
|
|
||||||
|
if (parseException != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[{i}] EXCEPTION = {parseException.GetType().Name}: {parseException.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optoDataCount > processedCount)
|
||||||
|
{
|
||||||
|
if (firstValidIx < 0)
|
||||||
|
firstValidIx = processedCount;
|
||||||
|
|
||||||
|
lastValidIx = optoDataCount - 1;
|
||||||
|
processedCount = optoDataCount;
|
||||||
|
|
||||||
|
Console.WriteLine(
|
||||||
|
$"[{i}] ACCEPTED -> processedCount={processedCount}, firstValidIx={firstValidIx}, lastValidIx={lastValidIx}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[{i}] NOT ACCEPTED");
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("--------------------------------------------------");
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("=== END INPUT PARSING ===");
|
||||||
|
Console.WriteLine($"Final processedCount = {processedCount}");
|
||||||
|
Console.WriteLine($"Final firstValidIx = {firstValidIx}");
|
||||||
|
Console.WriteLine($"Final lastValidIx = {lastValidIx}");
|
||||||
|
|
||||||
|
if (processedCount <= 0)
|
||||||
|
{
|
||||||
|
Assert.Fail(
|
||||||
|
"No valid calibration telegrams were parsed.\n" +
|
||||||
|
"Check the following:\n" +
|
||||||
|
"1. exact telegram prefix (for example @h vs @he)\n" +
|
||||||
|
"2. exact separators (spaces vs tabs)\n" +
|
||||||
|
"3. exact CRC / checksum\n" +
|
||||||
|
"4. whether ProcessOptoLine expects a complete multi-line block format\n" +
|
||||||
|
"See test output for per-line diagnostics.");
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.TestStartTelegramIx = firstValidIx;
|
||||||
|
reader.TestEndTelegramIx = lastValidIx;
|
||||||
|
|
||||||
|
Console.WriteLine("=== BEFORE POST PROCESSING ===");
|
||||||
|
Console.WriteLine($"TestStartTelegramIx = {reader.TestStartTelegramIx}");
|
||||||
|
Console.WriteLine($"TestEndTelegramIx = {reader.TestEndTelegramIx}");
|
||||||
|
|
||||||
|
object[] markArgs = { 0, 0 };
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
InvokePrivate(reader, "AddTestStartEndMarksToData", markArgs);
|
||||||
|
Console.WriteLine("AddTestStartEndMarksToData OK");
|
||||||
|
|
||||||
|
InvokePrivate(reader, "DataStreamPostProcessing");
|
||||||
|
Console.WriteLine("DataStreamPostProcessing OK");
|
||||||
|
|
||||||
|
InvokePrivate(reader, "PrepareCalculatedChannelData");
|
||||||
|
Console.WriteLine("PrepareCalculatedChannelData OK");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Assert.Fail(
|
||||||
|
"Post-processing failed.\n" +
|
||||||
|
$"Exception: {ex.GetType().Name}: {ex.Message}\n" +
|
||||||
|
$"StackTrace:\n{ex.StackTrace}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("=== CALCULATED VALUES ===");
|
||||||
|
Console.WriteLine($"NoSamples = {reader.NoSamples}");
|
||||||
|
Console.WriteLine($"VolumeLtrStart = {reader.VolumeLtrStart}");
|
||||||
|
Console.WriteLine($"VolumeLtrEnd = {reader.VolumeLtrEnd}");
|
||||||
|
Console.WriteLine($"TimestampSecStart = {reader.TimestampSecStart}");
|
||||||
|
Console.WriteLine($"TimestampSecEnd = {reader.TimestampSecEnd}");
|
||||||
|
|
||||||
|
Assert.IsFalse(double.IsNaN(reader.VolumeLtrStart), "VolumeLtrStart is NaN");
|
||||||
|
Assert.IsFalse(double.IsNaN(reader.VolumeLtrEnd), "VolumeLtrEnd is NaN");
|
||||||
|
Assert.IsFalse(double.IsNaN(reader.TimestampSecStart), "TimestampSecStart is NaN");
|
||||||
|
Assert.IsFalse(double.IsNaN(reader.TimestampSecEnd), "TimestampSecEnd is NaN");
|
||||||
|
|
||||||
|
Assert.IsTrue(reader.TimestampSecEnd >= reader.TimestampSecStart,
|
||||||
|
$"Timestamp ordering invalid: start={reader.TimestampSecStart}, end={reader.TimestampSecEnd}");
|
||||||
|
|
||||||
|
Assert.IsTrue(reader.VolumeLtrEnd >= reader.VolumeLtrStart,
|
||||||
|
$"Volume ordering invalid: start={reader.VolumeLtrStart}, end={reader.VolumeLtrEnd}");
|
||||||
|
|
||||||
|
// When parser input is finally correct, replace these expected values:
|
||||||
|
const double expectedVolumeStart = 0.0;
|
||||||
|
const double expectedVolumeEnd = 0.0;
|
||||||
|
const double expectedTimeStart = 0.0;
|
||||||
|
const double expectedTimeEnd = 0.0;
|
||||||
|
const double tolerance = 0.000001;
|
||||||
|
|
||||||
|
Console.WriteLine("=== EXPECTED VS ACTUAL ===");
|
||||||
|
Console.WriteLine($"expectedVolumeStart = {expectedVolumeStart}, actual = {reader.VolumeLtrStart}");
|
||||||
|
Console.WriteLine($"expectedVolumeEnd = {expectedVolumeEnd}, actual = {reader.VolumeLtrEnd}");
|
||||||
|
Console.WriteLine($"expectedTimeStart = {expectedTimeStart}, actual = {reader.TimestampSecStart}");
|
||||||
|
Console.WriteLine($"expectedTimeEnd = {expectedTimeEnd}, actual = {reader.TimestampSecEnd}");
|
||||||
|
|
||||||
|
Assert.AreEqual(expectedVolumeStart, reader.VolumeLtrStart, tolerance, "VolumeLtrStart mismatch");
|
||||||
|
Assert.AreEqual(expectedVolumeEnd, reader.VolumeLtrEnd, tolerance, "VolumeLtrEnd mismatch");
|
||||||
|
Assert.AreEqual(expectedTimeStart, reader.TimestampSecStart, tolerance, "TimestampSecStart mismatch");
|
||||||
|
Assert.AreEqual(expectedTimeEnd, reader.TimestampSecEnd, tolerance, "TimestampSecEnd mismatch");
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void RealInput_ShouldSupport_RolloverNormalization()
|
||||||
|
{
|
||||||
|
var reader = new GenesisSmartReader();
|
||||||
|
InitializeReaderForTest(reader);
|
||||||
|
|
||||||
|
string[] realInputLines = LoadRealInputLinesWithRollover();
|
||||||
|
Assert.IsTrue(realInputLines.Length > 0, "No rollover input lines were provided.");
|
||||||
|
|
||||||
|
for (int i = 0; i < realInputLines.Length; i++)
|
||||||
|
{
|
||||||
|
string line = realInputLines[i];
|
||||||
|
|
||||||
|
bool blockCompleted;
|
||||||
|
reader.ProcessOptoLine(line, DataStreamState.ProcessAndSave, out blockCompleted);
|
||||||
|
|
||||||
|
int optoDataCount = GetPrivateField<int>(reader, "optoDataCount");
|
||||||
|
|
||||||
|
Console.WriteLine($"[{i}] line={line}");
|
||||||
|
Console.WriteLine($"[{i}] optoDataCount={optoDataCount}, blockCompleted={blockCompleted}");
|
||||||
|
}
|
||||||
|
|
||||||
|
int finalOptoDataCount = GetPrivateField<int>(reader, "optoDataCount");
|
||||||
|
|
||||||
|
Assert.IsTrue(
|
||||||
|
finalOptoDataCount > 1,
|
||||||
|
"Need at least 2 valid telegrams. Check exact telegram format / CRC in LoadRealInputLinesWithRollover().");
|
||||||
|
|
||||||
|
reader.TestStartTelegramIx = 0;
|
||||||
|
reader.TestEndTelegramIx = finalOptoDataCount - 1;
|
||||||
|
|
||||||
|
object[] markArgs = { 0, 0 };
|
||||||
|
InvokePrivate(reader, "AddTestStartEndMarksToData", markArgs);
|
||||||
|
InvokePrivate(reader, "DataStreamPostProcessing");
|
||||||
|
InvokePrivate(reader, "PrepareCalculatedChannelData");
|
||||||
|
|
||||||
Console.WriteLine($"VolumeLtrStart={reader.VolumeLtrStart}");
|
Console.WriteLine($"VolumeLtrStart={reader.VolumeLtrStart}");
|
||||||
Console.WriteLine($"VolumeLtrEnd={reader.VolumeLtrEnd}");
|
Console.WriteLine($"VolumeLtrEnd={reader.VolumeLtrEnd}");
|
||||||
Console.WriteLine($"TimestampSecStart={reader.TimestampSecStart}");
|
Console.WriteLine($"TimestampSecStart={reader.TimestampSecStart}");
|
||||||
Console.WriteLine($"TimestampSecEnd={reader.TimestampSecEnd}");
|
Console.WriteLine($"TimestampSecEnd={reader.TimestampSecEnd}");
|
||||||
|
|
||||||
Assert.IsTrue(reader.VolumeLtrEnd >= reader.VolumeLtrStart,
|
|
||||||
"VolumeLtrEnd should be >= VolumeLtrStart.");
|
|
||||||
Assert.IsTrue(reader.TimestampSecEnd >= reader.TimestampSecStart,
|
|
||||||
"TimestampSecEnd should be >= TimestampSecStart.");
|
|
||||||
|
|
||||||
Assert.IsFalse(double.IsNaN(reader.VolumeLtrStart), "VolumeLtrStart is NaN");
|
|
||||||
Assert.IsFalse(double.IsNaN(reader.VolumeLtrEnd), "VolumeLtrEnd is NaN");
|
|
||||||
Assert.IsFalse(double.IsNaN(reader.TimestampSecStart), "TimestampSecStart is NaN");
|
|
||||||
Assert.IsFalse(double.IsNaN(reader.TimestampSecEnd), "TimestampSecEnd is NaN");
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void PreparedSimulation_ShouldSupport_NormalizedStartEndOrdering()
|
|
||||||
{
|
|
||||||
var reader = new GenesisSmartReader();
|
|
||||||
InitializeReaderForTest(reader);
|
|
||||||
|
|
||||||
InvokePrivate(reader, "PrepareCalculatedChannelDataForTest", new object[] { true });
|
|
||||||
|
|
||||||
Assert.IsFalse(reader.NoSamples, "Simulation did not prepare valid sample data.");
|
|
||||||
|
|
||||||
Assert.IsTrue(reader.TimestampSecEnd >= reader.TimestampSecStart,
|
Assert.IsTrue(reader.TimestampSecEnd >= reader.TimestampSecStart,
|
||||||
"Normalized end time should be >= start time");
|
"Normalized end time should be >= start time");
|
||||||
Assert.IsTrue(reader.VolumeLtrEnd >= reader.VolumeLtrStart,
|
Assert.IsTrue(reader.VolumeLtrEnd >= reader.VolumeLtrStart,
|
||||||
"Normalized end volume should be >= start volume");
|
"Normalized end volume should be >= start volume");
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void PreparedSimulation_Q3Calibration_ShouldReturnNonNegativeValue()
|
|
||||||
{
|
|
||||||
var reader = new GenesisSmartReader();
|
|
||||||
InitializeReaderForTest(reader);
|
|
||||||
|
|
||||||
InvokePrivate(reader, "PrepareCalculatedChannelDataForTest", new object[] { true });
|
|
||||||
|
|
||||||
Assert.IsFalse(reader.NoSamples, "Simulation did not prepare valid sample data.");
|
|
||||||
|
|
||||||
reader.GetQ3Calibration(refVolume: 1.0, refTime: 120.0, initCalibFactor: 15625.0);
|
|
||||||
|
|
||||||
Console.WriteLine($"Q3CalibValid={reader.Q3CalibValid}");
|
|
||||||
Console.WriteLine($"Q3CalibValue={reader.Q3CalibValue}");
|
|
||||||
|
|
||||||
Assert.IsTrue(reader.Q3CalibValue >= 0.0, "Q3CalibValue should be non-negative.");
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void Q3Calibration_ShouldReturnInvalid_WhenRefVolumeIsZero()
|
|
||||||
{
|
|
||||||
var reader = new GenesisSmartReader();
|
|
||||||
InitializeReaderForTest(reader);
|
|
||||||
|
|
||||||
InvokePrivate(reader, "PrepareCalculatedChannelDataForTest", new object[] { true });
|
|
||||||
|
|
||||||
Assert.IsFalse(reader.NoSamples, "Simulation did not prepare valid sample data.");
|
|
||||||
|
|
||||||
reader.GetQ3Calibration(refVolume: 0.0, refTime: 120.0, initCalibFactor: 15625.0);
|
|
||||||
|
|
||||||
Assert.IsFalse(reader.Q3CalibValid);
|
|
||||||
Assert.AreEqual(0.0, reader.Q3CalibValue, 0.000001);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void Q3Calibration_ShouldReturnInvalid_WhenRefTimeIsZero()
|
|
||||||
{
|
|
||||||
var reader = new GenesisSmartReader();
|
|
||||||
InitializeReaderForTest(reader);
|
|
||||||
|
|
||||||
InvokePrivate(reader, "PrepareCalculatedChannelDataForTest", new object[] { true });
|
|
||||||
|
|
||||||
Assert.IsFalse(reader.NoSamples, "Simulation did not prepare valid sample data.");
|
|
||||||
|
|
||||||
reader.GetQ3Calibration(refVolume: 1.0, refTime: 0.0, initCalibFactor: 15625.0);
|
|
||||||
|
|
||||||
Assert.IsFalse(reader.Q3CalibValid);
|
|
||||||
Assert.AreEqual(0.0, reader.Q3CalibValue, 0.000001);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void Q3Calibration_ShouldReturnInvalid_WhenInitCalibFactorIsZero()
|
|
||||||
{
|
|
||||||
var reader = new GenesisSmartReader();
|
|
||||||
InitializeReaderForTest(reader);
|
|
||||||
|
|
||||||
InvokePrivate(reader, "PrepareCalculatedChannelDataForTest", new object[] { true });
|
|
||||||
|
|
||||||
Assert.IsFalse(reader.NoSamples, "Simulation did not prepare valid sample data.");
|
|
||||||
|
|
||||||
reader.GetQ3Calibration(refVolume: 1.0, refTime: 120.0, initCalibFactor: 0.0);
|
|
||||||
|
|
||||||
Assert.IsFalse(reader.Q3CalibValid);
|
|
||||||
Assert.AreEqual(0.0, reader.Q3CalibValue, 0.000001);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void Q3Calibration_ShouldReturnInvalid_WhenRawDataIsNull()
|
|
||||||
{
|
|
||||||
var reader = new GenesisSmartReader();
|
|
||||||
InitializeReaderForTest(reader);
|
|
||||||
|
|
||||||
SetPrivateField(reader, "_rawStartEndByChannel", null);
|
|
||||||
|
|
||||||
reader.GetQ3Calibration(refVolume: 1.0, refTime: 120.0, initCalibFactor: 15625.0);
|
|
||||||
|
|
||||||
Assert.IsFalse(reader.Q3CalibValid);
|
|
||||||
Assert.AreEqual(0.0, reader.Q3CalibValue, 0.000001);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void InitializeReaderForTest(GenesisSmartReader reader)
|
private static void InitializeReaderForTest(GenesisSmartReader reader)
|
||||||
{
|
{
|
||||||
const int channelCount = 3;
|
const int channelCount = 3;
|
||||||
@ -167,6 +268,28 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
|||||||
reader.TestEndTelegramIx = 0;
|
reader.TestEndTelegramIx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string[] LoadRealInputLines()
|
||||||
|
{
|
||||||
|
return new[]
|
||||||
|
{
|
||||||
|
// Replace these with REAL, unchanged captured telegram lines from the device.
|
||||||
|
"@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331",
|
||||||
|
"@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD",
|
||||||
|
"@h 3 0 0A1DF1D5 00017EA8 00118037 741F80F3 00000400 00001998 7E58A62E 7CC2C606 000191E6 0C 062E5BAE D40E",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string[] LoadRealInputLinesWithRollover()
|
||||||
|
{
|
||||||
|
return new[]
|
||||||
|
{
|
||||||
|
// Replace these with REAL, unchanged captured telegram lines spanning the rollover case.
|
||||||
|
"@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331",
|
||||||
|
"@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD",
|
||||||
|
"@h 3 0 0A1DF1D5 00017EA8 00118037 741F80F3 00000400 00001998 7E58A62E 7CC2C606 000191E6 0C 062E5BAE D40E",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private static void SetPrivateField(object target, string fieldName, object value)
|
private static void SetPrivateField(object target, string fieldName, object value)
|
||||||
{
|
{
|
||||||
Type type = target.GetType();
|
Type type = target.GetType();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user