- Replace method-based `IsOpen()` checks with property-based `IsOpen` usage in `ISerialDriver` and related classes. - Simplify `Open()` and add `Close()` methods to unify connection management. - Introduce `InitializeThreeChannelState()` helper in `GenesisSmartReaderTest` for multi-channel state initialization. - Adjust calculations in `CalculateTimeByChannels()` and `CalculateVolumeByChannels()` for clarity. - Add new tests for multi-channel processing and validation of updated telegram handling logic.
204 lines
7.5 KiB
C#
204 lines
7.5 KiB
C#
using System;
|
|
using System.Reflection;
|
|
using JetBrains.Annotations;
|
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
using TBF.Rig;
|
|
using TBF.Rig.RegisterReaders.GenesisRegReader;
|
|
using TBF.Rig.RegisterReaders.GenesisRegReader.implementations;
|
|
|
|
namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
|
{
|
|
[TestClass]
|
|
[TestSubject(typeof(GenesisSmartReader))]
|
|
public class GenesisSmartReaderTest
|
|
{
|
|
private const int ChannelCount = 3;
|
|
|
|
private static GenesisCfg CreateCfg()
|
|
{
|
|
Factory factory = new Factory();
|
|
return new GenesisCfg(factory);
|
|
}
|
|
|
|
private static void SetPrivateField(object target, string fieldName, object value)
|
|
{
|
|
var field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
|
|
if (field == null)
|
|
throw new MissingFieldException(target.GetType().FullName, fieldName);
|
|
|
|
field.SetValue(target, value);
|
|
}
|
|
|
|
private static T GetPrivateField<T>(object target, string fieldName)
|
|
{
|
|
var field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
|
|
if (field == null)
|
|
throw new MissingFieldException(target.GetType().FullName, fieldName);
|
|
|
|
return (T)field.GetValue(target);
|
|
}
|
|
|
|
private static void InitializeThreeChannelState(GenesisSmartReader reader)
|
|
{
|
|
SetPrivateField(reader, "volumeRawExtLast", new double[ChannelCount]);
|
|
SetPrivateField(reader, "timestampExtLast", new double[ChannelCount]);
|
|
|
|
SetPrivateField(reader, "lastVolumeRaw", new double[ChannelCount]);
|
|
SetPrivateField(reader, "lastTimestamp", new double[ChannelCount]);
|
|
|
|
SetPrivateField(reader, "volumeLtr", new[] { 0.0, 0.0, 0.0 });
|
|
SetPrivateField(reader, "volumeLtr0", new[] { 0.0, 0.0, 0.0 });
|
|
|
|
SetPrivateField(reader, "timestampSec", new[] { 0.0, 0.0, 0.0 });
|
|
SetPrivateField(reader, "timestampSec0", new[] { 0.0, 0.0, 0.0 });
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Start_ShouldOpenPort_AndEnableProcessing()
|
|
{
|
|
var fake = new FakeSerialDriver();
|
|
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
|
|
|
reader.Initialize();
|
|
reader.Start();
|
|
|
|
Assert.IsTrue(fake.IsOpen);
|
|
Assert.IsTrue(fake.OpenCalls >= 1);
|
|
Assert.AreEqual(1, fake.DiscardInCalls);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Stop_ShouldClosePort()
|
|
{
|
|
var fake = new FakeSerialDriver();
|
|
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
|
|
|
reader.Initialize();
|
|
reader.Start();
|
|
|
|
Assert.IsTrue(fake.IsOpen);
|
|
|
|
reader.Stop();
|
|
|
|
Assert.IsFalse(fake.IsOpen);
|
|
Assert.AreEqual(2, fake.CloseCalls);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Run_ShouldCaptureStartTelegramIndex_WhenTimeReached()
|
|
{
|
|
var fake = new FakeSerialDriver();
|
|
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
|
|
|
reader.Initialize();
|
|
|
|
SetPrivateField(reader, "currentTelegramIx", 12);
|
|
SetPrivateField(reader, "timeFromStart", 7);
|
|
|
|
InitializeThreeChannelState(reader);
|
|
|
|
var ev = reader.Run();
|
|
|
|
Assert.AreEqual(Event.ReadRegisterDone, ev);
|
|
Assert.AreEqual(12, reader.TestStartTelegramIx);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void ProcessOptoLine_ShouldIncreaseOptoDataCount()
|
|
{
|
|
var fake = new FakeSerialDriver();
|
|
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
|
|
|
reader.Initialize();
|
|
InitializeThreeChannelState(reader);
|
|
|
|
var line = "@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331";
|
|
|
|
reader.optoSerialPort = fake;
|
|
fake.Open();
|
|
|
|
reader.ProcessOptoLine(line, DataStreamState.ProcessAndSave);
|
|
|
|
int optoDataCount = GetPrivateField<int>(reader, "optoDataCount");
|
|
Assert.AreEqual(1, optoDataCount);
|
|
}
|
|
|
|
[DataTestMethod]
|
|
[DataRow("@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331", 0)]
|
|
[DataRow("@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD", 1)]
|
|
[DataRow("@h 3 0 0A1DF1D5 00017EA8 00118037 741F80F3 00000400 00001998 7E58A62E 7CC2C606 000191E6 0C 062E5BAE D40E", 2)]
|
|
public void ProcessOptoLine_ShouldUpdateExpectedChannel(string line, int expectedChannelIndex)
|
|
{
|
|
var fake = new FakeSerialDriver();
|
|
fake.Open();
|
|
|
|
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
|
reader.Initialize();
|
|
|
|
reader.optoSerialPort = fake;
|
|
InitializeThreeChannelState(reader);
|
|
|
|
reader.ProcessOptoLine(line, DataStreamState.ProcessAndSave);
|
|
|
|
var volumeRawExtLast = GetPrivateField<double[]>(reader, "volumeRawExtLast");
|
|
var timestampExtLast = GetPrivateField<double[]>(reader, "timestampExtLast");
|
|
|
|
for (int i = 0; i < ChannelCount; i++)
|
|
{
|
|
if (i == expectedChannelIndex)
|
|
{
|
|
Assert.IsTrue(
|
|
volumeRawExtLast[i] != 0 || timestampExtLast[i] != 0,
|
|
$"Channel {i} was expected to be updated, but it was not.");
|
|
}
|
|
else
|
|
{
|
|
Assert.AreEqual(0.0, volumeRawExtLast[i], $"Unexpected volume update in channel {i}");
|
|
Assert.AreEqual(0.0, timestampExtLast[i], $"Unexpected timestamp update in channel {i}");
|
|
}
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Run_WhenChannel0IsAverageModeMinus2_ShouldReadUsingAllThreeChannels()
|
|
{
|
|
var fake = new FakeSerialDriver();
|
|
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
|
|
|
reader.Initialize();
|
|
reader.Start();
|
|
|
|
SetPrivateField(reader, "channel0", -2);
|
|
SetPrivateField(reader, "volumeLtr0", new[] { 10.0, 20.0, 30.0 });
|
|
SetPrivateField(reader, "volumeLtr", new[] { 13.0, 24.0, 35.0 });
|
|
SetPrivateField(reader, "timestampSec0", new[] { 100.0, 100.0, 100.0 });
|
|
SetPrivateField(reader, "timestampSec", new[] { 110.0, 112.0, 114.0 });
|
|
|
|
var ev = reader.Run();
|
|
|
|
Assert.AreEqual(Event.ReadRegisterDone, ev);
|
|
Assert.AreEqual(4.0, reader.WMVolume, 1E-6); // average of (3, 4, 5)
|
|
Assert.AreEqual(4000, reader.WMPulses);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void ProcessOptoLine_FirstValidTelegram_ShouldSetCurrentTelegramIndex()
|
|
{
|
|
var fake = new FakeSerialDriver();
|
|
fake.Open();
|
|
|
|
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
|
reader.Initialize();
|
|
|
|
reader.optoSerialPort = fake;
|
|
InitializeThreeChannelState(reader);
|
|
|
|
var line = "@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD";
|
|
|
|
reader.ProcessOptoLine(line, DataStreamState.ProcessAndSave);
|
|
|
|
int currentTelegramIx = GetPrivateField<int>(reader, "currentTelegramIx");
|
|
Assert.AreEqual(0, currentTelegramIx);
|
|
}
|
|
}
|
|
} |