diff --git a/Common/LaaPackages b/Common/LaaPackages index afd07e09..e7aa3e27 160000 --- a/Common/LaaPackages +++ b/Common/LaaPackages @@ -1 +1 @@ -Subproject commit afd07e091de9b5a5a7894370403688205222b572 +Subproject commit e7aa3e2723a435f0a714df661dc5d86dfd45a71c diff --git a/Common/Production/ProductionUiCordonel.UnitTests/Steps/CommonProductionProcessSteps.cs b/Common/Production/ProductionUiCordonel.UnitTests/Steps/CommonProductionProcessSteps.cs index 424c4045..e9f59df4 100644 --- a/Common/Production/ProductionUiCordonel.UnitTests/Steps/CommonProductionProcessSteps.cs +++ b/Common/Production/ProductionUiCordonel.UnitTests/Steps/CommonProductionProcessSteps.cs @@ -86,7 +86,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps /// /// The exec path of the assembly for debug in environment. /// - private readonly String _assemblyExecRootPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + private readonly String _assemblyExecRootPath = + Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? ""; /// /// Fw package path relative to solution main folder. @@ -146,7 +147,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps set; get; } - public MockGenesis Meter + public MockGenesis? Meter { set; get; } @@ -256,6 +257,10 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps /// public CommonSteps() { + MethodToTest = ""; + PropertyToCheck = ""; + ObjectTypeName = ""; + TestName = ""; var subFolder = Path.Combine("Hardware", "WaterMeter", "Genesis", "MockGenesis"); var solutionPath = ""; if (NCrunchEnvironment.NCrunchIsResident()) @@ -264,7 +269,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps } else { - if (_assemblyExecRootPath != null) + if (!string.IsNullOrWhiteSpace(_assemblyExecRootPath)) { // We are in the Unit test folder "..\Common\Production\ProductionUiCordonel.UnitTests\bin\Debug" // and need to go back to "..\Common" @@ -570,12 +575,12 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps case "ExecFinalParametrization": // Load parameters - if (meterSizeForParams != testCase.Meter.MeterSize || regionForParams != testCase.Meter.Region || + if (meterSizeForParams != testCase.Meter?.MeterSize || regionForParams != testCase.Meter?.Region || !unmodifiedParamsUsableAsReferenceForNextTest) { var rawProgParams = new List(); if (!RegisterRestorer.ImportRawProgrammingParametersFromFile(_mockRawParamsRootPath, - testCase.Meter.Region, testCase.Meter.MeterSize, rawProgParams)) + testCase.Meter?.Region, testCase.Meter?.MeterSize, rawProgParams)) { var errorMsg = $"TestNo: {testCase.TestNo}\n ERROR: Could not load programming parameters\n"; Console.WriteLine(errorMsg); @@ -597,8 +602,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps intermediateRecoveryRegisters.Clear(); intermediateRecoveryRegisters.AddRange(testCase.RegisterRestorer.RecoveryRegisters); - meterSizeForParams = testCase.Meter.MeterSize; - regionForParams = testCase.Meter.Region; + meterSizeForParams = testCase.Meter?.MeterSize; + regionForParams = testCase.Meter?.Region; unmodifiedParamsUsableAsReferenceForNextTest = true; } // Take the parameters from the last run if those haven't changed meanwhile (identical meter size and region) @@ -659,7 +664,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps } if (string.IsNullOrEmpty(testResult.EOLProgress.ProductionStatusFwVersion)) - testResult.EOLProgress.ProductionStatusFwVersion = testCase.Meter.FwVersion; + testResult.EOLProgress.ProductionStatusFwVersion = testCase.Meter?.FwVersion; break; case "CheckFinalParametrization": @@ -668,9 +673,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps { registerName = "SYSTEM_UpgradePermissions"; var readValue = RegisterConverter.ByteArrayToValue( - testCase.Meter.ReadRegister(registerName)); + testCase.Meter?.ReadRegister(registerName)); readValue++; - testCase.Meter.WriteRegister(registerName, readValue); + testCase.Meter?.WriteRegister(registerName, readValue); paramsCheckWillSucceed = false; } @@ -709,8 +714,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps testPp.ProductionStatus = testCase.CordonelDeviceStatus; testPp.RegisterRestorer = testCase.RegisterRestorer; - // The new Object[]{null} is a placeholder for the out return if needed for the method type reflection - var parameters = new Object[] { null }; + // The new Object?[]{null} is a placeholder for the out return if needed for the method type reflection + var parameters = new Object?[] { null }; // Public methods do NOT return a variable if (!IsPrivateMethod) parameters = null; @@ -739,8 +744,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps if (testResult.StatusReturn != StatusReturn.Failed) testResult.StatusReturn = statusReturn; - if (parameters != null) - testResult.FeedbackMsg += $"{(String)parameters[0]} "; + if (parameters?[0] is String) + testResult.FeedbackMsg += $"{parameters[0]} "; } /// @@ -874,7 +879,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps // Login is needed for building the MeterAppListVersion and generating the accessible register list. // This register list will be used to check for valid ranges. - testCase.Meter.Login(); + testCase.Meter?.Login(); // This is the multiple row test table defining individual test cases ReadTable(row, ref testCase); @@ -901,7 +906,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps // Login is needed for building the MeterAppListVersion and generating the accessible register list. // This register list will be used to check for valid ranges. - _presets.Meter.Login(); + _presets.Meter?.Login(); // A preset table is limited to exclusively one row, those settings will be used for every test of the // test-cases! @@ -949,7 +954,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps if (ParseInt(tableRow, "EOL Id", out strValue, out var intValue)) { - parsedTableRow.RequiredEOLProgress.Id = (Int32)intValue; + if (intValue != null) parsedTableRow.RequiredEOLProgress.Id = (Int32)intValue; } var strHeader = "EOL StartDate"; @@ -1020,12 +1025,13 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps if (ParseInt(tableRow, "Cordonel ProdOrderNo", out strValue, out intValue)) { - parsedTableRow.Meter.OrderNumber = (Int32)intValue; + if (parsedTableRow.Meter != null && intValue != null) + parsedTableRow.Meter.OrderNumber = (Int32)intValue; } if (ParseInt(tableRow, "Requirement ProdOrderNo", out strValue, out intValue)) { - parsedTableRow.ProductionRequirements.ProductionOrderNr = (Int32)intValue; + if (intValue != null) parsedTableRow.ProductionRequirements.ProductionOrderNr = (Int32)intValue; parsedTableRow.RequiredEOLProgress.RequirementOrderChecked = EOLStatus.OK; } @@ -1035,7 +1041,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps if (ParseInt(tableRow, "Cordonel PcbId", out strValue, out intValue)) { - parsedTableRow.Meter.PcbId = strValue; + if (parsedTableRow.Meter != null) parsedTableRow.Meter.PcbId = strValue; } if (ParseInt(tableRow, "Requirement PcbId", out strValue, out intValue)) @@ -1046,7 +1052,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps if (ParseInt(tableRow, "EOL PcbId", out strValue, out intValue)) { - parsedTableRow.RequiredEOLProgress.PcbId = (Int32)intValue; + if (intValue != null) parsedTableRow.RequiredEOLProgress.PcbId = (Int32)intValue; } #endregion @@ -1055,7 +1061,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps if (ParseString(tableRow, "Cordonel LUT CRC", out strValue)) { - parsedTableRow.Meter.LutCrc = strValue; + if (parsedTableRow.Meter != null) parsedTableRow.Meter.LutCrc = strValue; } if (ParseString(tableRow, "Requirement LUT CRC", out strValue)) @@ -1070,7 +1076,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps if (ParseString(tableRow, "Cordonel Region", out strValue)) { - parsedTableRow.Meter.Region = strValue; + if (parsedTableRow.Meter != null) parsedTableRow.Meter.Region = strValue; } if (ParseString(tableRow, "Requirement Region", out strValue)) @@ -1085,7 +1091,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps if (ParseString(tableRow, "Cordonel Meter Size", out strValue)) { - parsedTableRow.Meter.MeterSize = strValue; + if (parsedTableRow.Meter != null) parsedTableRow.Meter.MeterSize = strValue; } if (ParseString(tableRow, "Requirement Meter Size", out strValue)) @@ -1131,9 +1137,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps { // Login needed to install the FW from hard-coded package description file. This is essential as only // then one App could be erased or modified - parsedTableRow.Meter.Login(); + parsedTableRow.Meter?.Login(); parsedTableRow.RequiredEOLProgress.ProductionStatusFwVersion = strValue; - var isInstalled = parsedTableRow.Meter.InstallNewMockFw(fwName: strValue); + var isInstalled = parsedTableRow.Meter != null && parsedTableRow.Meter.InstallNewMockFw(fwName: strValue); var errorMsg = $"FW \"{strValue}\" could not be found in \"MockFwExamples\", parsing or " + "installation failed!"; Assert.That(isInstalled, errorMsg); @@ -1145,9 +1151,12 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps // Initially needed to install MockFw and set up the initial core revision. If the login will be // delayed then the "Core Revision" is going to be overwritten from the content of the firmware // package description file. - parsedTableRow.Meter.Login(); - parsedTableRow.Meter.CoreRevision = (Int32)(floatValue * 100); - parsedTableRow.Meter.StrCoreRevision = strValue; + if (parsedTableRow.Meter != null) + { + parsedTableRow.Meter.Login(); + if (floatValue != null) parsedTableRow.Meter.CoreRevision = (Int32)(floatValue * 100); + parsedTableRow.Meter.StrCoreRevision = strValue; + } } if (ParseString(tableRow, "Requirement FW Version", out strValue)) @@ -1161,7 +1170,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps if (modifyAppId != null) { - parsedTableRow.Meter.ModifyMockApp((Byte)modifyAppId, appVersion, appCrc, eraseApp); + parsedTableRow.Meter?.ModifyMockApp((Byte)modifyAppId, appVersion, appCrc, eraseApp); } #endregion @@ -1214,18 +1223,23 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps if (ParseFloat(tableRow, "Actual Lifetime [days]", out strValue, out floatValue)) { - parsedTableRow.CordonelDeviceStatus.ExceededLifeTime_s = (UInt64)(floatValue * 24 * 3600); + if (floatValue != null) parsedTableRow.CordonelDeviceStatus.ExceededLifeTime_s = + (UInt64)(floatValue * 24 * 3600); parsedTableRow.RequiredEOLProgress.ProductionStatusBatteryLoadChecked = EOLStatus.OK; parsedTableRow.RequiredEOLProgress.ProductionStatusRemainingLifeTimeChecked = EOLStatus.OK; } if (ParseFloat(tableRow, "Actual Drained [%]", out strValue, out floatValue)) { - parsedTableRow.CordonelDeviceStatus.DrainedBatteryLoad_uAs = - (UInt64)(floatValue * parsedTableRow.CordonelDeviceStatus.InitialBatteryLoad_mAh * - parsedTableRow.CordonelDeviceStatus.BatteryQuantity * 1000 * 3600 / 100); - - parsedTableRow.RequiredEOLProgress.ProductionStatusDrainedBatteryLoad = floatValue; + if (floatValue != null) + { + parsedTableRow.CordonelDeviceStatus.DrainedBatteryLoad_uAs = + (UInt64)(floatValue * parsedTableRow.CordonelDeviceStatus.InitialBatteryLoad_mAh * + parsedTableRow.CordonelDeviceStatus.BatteryQuantity * 1000 * 3600 / 100); + + parsedTableRow.RequiredEOLProgress.ProductionStatusDrainedBatteryLoad = floatValue; + } + //GenesisStatusHandler.CalculateLifeTime(parsedTableRow.CordonelDeviceStatus); //parsedTableRow.RequiredEOLProgress.ProductionStatusRemainingLifeTime = // parsedTableRow.CordonelDeviceStatus.RemainingLifeTimeYears; @@ -1275,14 +1289,16 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps if (ParseInt(tableRow, "Test Bench State[4]", out strValue, out intValue)) { - if (parsedTableRow.TestBenchState != null && parsedTableRow.TestBenchState.Count >= 5) - parsedTableRow.TestBenchState[4] = strValue; + if (parsedTableRow.TestBenchState.Count >= 5) + if (strValue != null) + parsedTableRow.TestBenchState[4] = strValue; } if (ParseInt(tableRow, "Test Bench State[5]", out strValue, out intValue)) { - if (parsedTableRow.TestBenchState != null && parsedTableRow.TestBenchState.Count >= 6) - parsedTableRow.TestBenchState[5] = strValue; + if (parsedTableRow.TestBenchState.Count >= 6) + if (strValue != null) + parsedTableRow.TestBenchState[5] = strValue; } if (ParseInt(tableRow, "Meter Calib Fact 1", out strValue, out intValue)) @@ -1294,8 +1310,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps parsedTableRow.RequiredEOLProgress.ProductionStatusZeroFlowChecked = EOLStatus.OK; if (intValue != null) { - PresetRegisterRestorer(parsedTableRow.CalibCheckRegisterRestorer, "GENESISFLOW_CalFactor1", null, - RegisterConverter.ValueToByteArray((UInt16)intValue)); + PresetRegisterRestorer(parsedTableRow.CalibCheckRegisterRestorer, "GENESISFLOW_CalFactor1", + readBackValue: RegisterConverter.ValueToByteArray((UInt16)intValue)); } } @@ -1303,8 +1319,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps { if (intValue != null) { - PresetRegisterRestorer(parsedTableRow.CalibCheckRegisterRestorer, "GENESISFLOW_CalFactor2", null, - RegisterConverter.ValueToByteArray((UInt16)intValue)); + PresetRegisterRestorer(parsedTableRow.CalibCheckRegisterRestorer, "GENESISFLOW_CalFactor2", + readBackValue: RegisterConverter.ValueToByteArray((UInt16)intValue)); } } @@ -1312,8 +1328,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps { if (intValue != null) { - PresetRegisterRestorer(parsedTableRow.CalibCheckRegisterRestorer, "GENESISFLOW_CalFactor3", null, - RegisterConverter.ValueToByteArray((UInt16)intValue)); + PresetRegisterRestorer(parsedTableRow.CalibCheckRegisterRestorer, "GENESISFLOW_CalFactor3", + readBackValue: RegisterConverter.ValueToByteArray((UInt16)intValue)); } } @@ -1350,7 +1366,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps { if (!string.IsNullOrEmpty(strValue) && strValue.Equals("X")) { - parsedTableRow.Meter.KillConfigRegisters(); + parsedTableRow.Meter?.KillConfigRegisters(); parsedTableRow.RequiredEOLProgress.ParametrizationCompareChecked = EOLStatus.FAIL; parsedTableRow.RequiredEOLProgress.ParametrizationDoneChecked = EOLStatus.FAIL; } @@ -1433,7 +1449,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps if (!string.IsNullOrEmpty(strValue) && strValue.Equals("X") && !singleSelectionLock) { singleSelectionLock = true; - parsedTableRow.Meter.OrderNumber = 0; + if (parsedTableRow.Meter != null) parsedTableRow.Meter.OrderNumber = 0; parsedTableRow.RequiredEOLProgress.RequirementOrderChecked = EOLStatus.FAIL; } } @@ -1463,7 +1479,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps if (!string.IsNullOrEmpty(strValue) && strValue.Equals("X")) { singleSelectionLock = true; - parsedTableRow.Meter.Region = "?"; + if (parsedTableRow.Meter != null) parsedTableRow.Meter.Region = "?"; parsedTableRow.RequiredEOLProgress.RequirementRegionChecked = EOLStatus.FAIL; } } @@ -1478,7 +1494,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps if (!string.IsNullOrEmpty(strValue) && strValue.Equals("X")) { singleSelectionLock = true; - parsedTableRow.Meter.LutCrc = "?"; + if (parsedTableRow.Meter != null) parsedTableRow.Meter.LutCrc = "?"; parsedTableRow.RequiredEOLProgress.ProductionStatusLutCrc = ""; } } @@ -1492,7 +1508,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps else if (!string.IsNullOrEmpty(strValue) && strValue.Equals("X")) { singleSelectionLock = true; - parsedTableRow.Meter.MeterSize = "?"; + if (parsedTableRow.Meter != null) parsedTableRow.Meter.MeterSize = "?"; parsedTableRow.RequiredEOLProgress.ProductionStatusMeterSize = ""; } } @@ -1589,9 +1605,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps { if (!string.IsNullOrEmpty(strValue) && strValue.Equals("X") && !singleSelectionLock) { - parsedTableRow.Meter.ReLogin(); - PresetRegisterRestorer(parsedTableRow.CalibCheckRegisterRestorer, "GENESISFLOW_CalFactor1", null, - RegisterConverter.ValueToByteArray((UInt16)0)); + if (parsedTableRow.Meter != null) parsedTableRow.Meter.ReLogin(); + PresetRegisterRestorer(parsedTableRow.CalibCheckRegisterRestorer, "GENESISFLOW_CalFactor1", + readBackValue: RegisterConverter.ValueToByteArray((UInt16)0)); parsedTableRow.RequiredEOLProgress.ProductionStatusCalibrationChecked = EOLStatus.FAIL; } } @@ -1605,8 +1621,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps { if (ObjectTypeName.Equals(strHeader.Replace(" ", ""))) { - ClassAccess.SetPropertyValue(parsedTableRow.RequiredEOLProgress, - PropertyToCheck, GetEOLStatusFromName(strValue)); + ClassAccess.SetPropertyValue(parsedTableRow.RequiredEOLProgress, PropertyToCheck, + GetEOLStatusFromName(strValue)); } } @@ -1615,8 +1631,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps { if (ObjectTypeName.Equals(strHeader)) { - ClassAccess.SetPropertyValue(parsedTableRow.RequiredEOLProgress, - PropertyToCheck, strValue); + ClassAccess.SetPropertyValue(parsedTableRow.RequiredEOLProgress, PropertyToCheck, strValue); } } @@ -1641,7 +1656,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps /// - Initial. /// private static void PresetRegisterRestorer(RegisterRestorer regRestorer, String regName, - Byte[] writeValue = null, Byte[] readBackValue = null) + Byte[]? writeValue = null, Byte[]? readBackValue = null) { try { @@ -1703,7 +1718,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps /// /// - Initial. /// - private static Boolean ParseFloat(TableRow tableRow, String strHeader, out String strValue, + private static Boolean ParseFloat(TableRow tableRow, String strHeader, out String? strValue, out Double? value) { value = null; @@ -1740,7 +1755,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps /// /// - Accept "null" as input. /// - private static Boolean ParseInt(TableRow tableRow, String strHeader, out String strValue, + private static Boolean ParseInt(TableRow tableRow, String strHeader, out String? strValue, out Int32? value) { value = null;