FIX GENESIS
Enhance Genesis configuration and validation mechanisms - Introduce new test methods for testing Genesis properties, boundary validations, runtime behavior, and tooltips with culture-specific fallback. - Expand configuration validation logic with enhanced error messaging and logging. - Simplify Genesis property UI: remove legacy settings and refactor controls for robust behavior. - Add detailed logging for runtime and configuration updates. - Provide tooltips and localized support for Genesis properties in multiple languages (e.g., `de`, `sk`). - Update project file to include new test files.
This commit is contained in:
parent
52bd0d01ce
commit
02de7c6c57
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
@ -1776,4 +1776,46 @@
|
||||
<data name="IperlCalibFactorNominalTooltip" xml:space="preserve">
|
||||
<value>Nominální surový kalibrační faktor odpovídající 100 %. Tato hodnota se používá pro výpočet položky „iPerl CalibFactor (%)“ v konfiguraci výsledků.</value>
|
||||
</data>
|
||||
<data name="GenesisTooltip_nameTextBox" xml:space="preserve"><value>Name
|
||||
|
||||
Účel: Identifikuje komponentu, na kterou odkazují testy procedury.
|
||||
Použití: Vyhledání komponenty a výběr Method v proceduře.
|
||||
Rozsah hodnot: Jedinečný název komponenty.
|
||||
Výchozí hodnota: SmartCommunicationGenesis
|
||||
Uplatnění: Po přejmenování je nutný restart; zkontrolujte odkazy v procedurách.</value></data>
|
||||
<data name="GenesisTooltip_commTimeoutTextBox" xml:space="preserve"><value>CommTimeout
|
||||
|
||||
Účel: Časový limit pro požadavek na zrušení jednotlivého Genesis GCI volání.
|
||||
Použití: Volání GciBridge z GenesisCommunicationForm (připojení, login, registry a související slot operace).
|
||||
Rozsah hodnot: Celé číslo: 500–5000 ms.
|
||||
Výchozí hodnota: 1800 ms.
|
||||
Uplatnění: Načte se na začátku aktivity vodoměru. Každé volání/pokus má vlastní limit; více kroků může trvat déle. Zrušení musí podporovat spodní vrstva ovladače. Ostatní uživatelé bridge zachovají původní limity.</value></data>
|
||||
<data name="GenesisTooltip_maxCommRetriesTextBox" xml:space="preserve"><value>MaxCommRetries
|
||||
|
||||
Účel: Uložené nastavení opakování komunikace.
|
||||
Použití: Aktuální tok Genesis slot/GCI jej nečte; nespouští opakování neúspěšné operace.
|
||||
Rozsah hodnot: Celé číslo: 1–10.
|
||||
Výchozí hodnota: 4
|
||||
Uplatnění: Zachováno pro kompatibilitu; bez vlivu na opakování slot/GCI.</value></data>
|
||||
<data name="GenesisTooltip_delayBetweenRetriesTextBox" xml:space="preserve"><value>DelayBetweenRetries
|
||||
|
||||
Účel: Uložená prodleva mezi opakováními komunikace.
|
||||
Použití: Aktuální tok Genesis slot/GCI ji nečte; neřídí zpoždění zavření formuláře.
|
||||
Rozsah hodnot: Celé číslo: 0–5000 ms.
|
||||
Výchozí hodnota: 0 ms
|
||||
Uplatnění: Zachováno pro kompatibilitu; bez vlivu na prodlevy slot/GCI.</value></data>
|
||||
<data name="GenesisTooltip_nrThreadsTextBox" xml:space="preserve"><value>NrThreads
|
||||
|
||||
Účel: Počet pracovních vláken pro nakonfigurované hlavy Genesis.
|
||||
Použití: GenesisCommunicationForm: vytvoření vláken a rozdělení slotů. Nemění počet vodoměrů.
|
||||
Rozsah hodnot: Celé číslo: 1–10.
|
||||
Výchozí hodnota: 10
|
||||
Uplatnění: Vyžaduje restart. Sestavení TURA_SPECIAL používají samostatné přidělování slotů.</value></data>
|
||||
<data name="GenesisTooltip_iperlCheckErrorsToStopTextBox" xml:space="preserve"><value>IperlCheckErrorsToStop
|
||||
|
||||
Účel: Počet neúspěšných vodoměrů, při kterém se zobrazí výsledek kontroly.
|
||||
Použití: GenesisCommunicationSeq: aktivita iPERL_check při sestavení s IPERL. Uživatel může pokračovat nebo přerušit; nejde o obecný limit chyb slotů.
|
||||
Rozsah hodnot: Celé číslo: 1–40. Práh: počet neúspěšných >= nastavení.
|
||||
Výchozí hodnota: 10
|
||||
Uplatnění: Použije se při následující příslušné kontrole; ne při běžných slot aktivitách.</value></data>
|
||||
</root>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
@ -2238,4 +2238,46 @@
|
||||
<data name="IperlCalibFactorNominalTooltip" xml:space="preserve">
|
||||
<value>Roher Kalibrierfaktor, der 100 % entspricht. Dieser Wert wird zur Berechnung von „iPerl CalibFactor (%)“ in der Ergebnis-Konfiguration verwendet.</value>
|
||||
</data>
|
||||
<data name="GenesisTooltip_nameTextBox" xml:space="preserve"><value>Name
|
||||
|
||||
Zweck: Identifiziert die Komponente, auf die die Tests der Prozedur verweisen.
|
||||
Verwendung: Komponentensuche und Auswahl von Method in der Prozedur.
|
||||
Wertebereich: Eindeutiger Komponentenname.
|
||||
Standardwert: SmartCommunicationGenesis
|
||||
Anwendung: Nach Umbenennung neu starten und Prozedurverweise prüfen.</value></data>
|
||||
<data name="GenesisTooltip_commTimeoutTextBox" xml:space="preserve"><value>CommTimeout
|
||||
|
||||
Zweck: Frist für die Abbruchanforderung eines einzelnen Genesis-GCI-Aufrufs.
|
||||
Verwendung: GciBridge-Aufrufe aus GenesisCommunicationForm (Verbindung, Login, Register und zugehörige Slot-Operationen).
|
||||
Wertebereich: Ganzzahl: 500–5000 ms.
|
||||
Standardwert: 1800 ms.
|
||||
Anwendung: Zu Beginn jeder Zähleraktivität gelesen. Jeder Aufruf/Versuch erhält eine eigene Frist; mehrere Schritte können länger dauern. Der Treiber muss den Abbruch unterstützen. Andere Bridge-Aufrufer behalten ihre bisherigen Zeitlimits.</value></data>
|
||||
<data name="GenesisTooltip_maxCommRetriesTextBox" xml:space="preserve"><value>MaxCommRetries
|
||||
|
||||
Zweck: Gespeicherte Einstellung für Kommunikationswiederholungen.
|
||||
Verwendung: Der aktuelle Genesis-Slot/GCI-Ablauf liest diesen Wert nicht; fehlgeschlagene Operationen werden dadurch nicht wiederholt.
|
||||
Wertebereich: Ganzzahl: 1–10.
|
||||
Standardwert: 4
|
||||
Anwendung: Für Kompatibilität gespeichert; keine Wirkung auf Slot/GCI-Wiederholungen.</value></data>
|
||||
<data name="GenesisTooltip_delayBetweenRetriesTextBox" xml:space="preserve"><value>DelayBetweenRetries
|
||||
|
||||
Zweck: Gespeicherte Pause zwischen Kommunikationswiederholungen.
|
||||
Verwendung: Der aktuelle Genesis-Slot/GCI-Ablauf liest diesen Wert nicht; die Verzögerung beim Schließen des Formulars bleibt unverändert.
|
||||
Wertebereich: Ganzzahl: 0–5000 ms.
|
||||
Standardwert: 0 ms
|
||||
Anwendung: Für Kompatibilität gespeichert; keine Wirkung auf Slot/GCI-Pausen.</value></data>
|
||||
<data name="GenesisTooltip_nrThreadsTextBox" xml:space="preserve"><value>NrThreads
|
||||
|
||||
Zweck: Anzahl der Arbeitsthreads für konfigurierte Genesis-Köpfe.
|
||||
Verwendung: GenesisCommunicationForm: Thread-Erstellung und Slot-Verteilung. Ändert nicht die Anzahl der Zähler.
|
||||
Wertebereich: Ganzzahl: 1–10.
|
||||
Standardwert: 10
|
||||
Anwendung: Neustart erforderlich. TURA_SPECIAL-Builds verwenden eine separate Slot-Zuweisung.</value></data>
|
||||
<data name="GenesisTooltip_iperlCheckErrorsToStopTextBox" xml:space="preserve"><value>IperlCheckErrorsToStop
|
||||
|
||||
Zweck: Anzahl fehlgeschlagener Zähler, ab der das Prüfergebnis angezeigt wird.
|
||||
Verwendung: GenesisCommunicationSeq: Aktivität iPERL_check bei Builds mit IPERL. Der Benutzer kann fortfahren oder abbrechen; kein allgemeiner Grenzwert für Slot-Fehler.
|
||||
Wertebereich: Ganzzahl: 1–40. Schwelle: Fehleranzahl >= Einstellung.
|
||||
Standardwert: 10
|
||||
Anwendung: Gilt bei der nächsten entsprechenden Prüfung, nicht bei normalen Slot-Aktivitäten.</value></data>
|
||||
</root>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
@ -2509,4 +2509,46 @@
|
||||
<data name="IperlCalibFactorNominalTooltip" xml:space="preserve">
|
||||
<value>Raw calibration factor representing 100 %. This value is used to calculate 'iPerl CalibFactor (%)' in the results configuration.</value>
|
||||
</data>
|
||||
<data name="GenesisTooltip_nameTextBox" xml:space="preserve"><value>Name
|
||||
|
||||
Purpose: Identifies the component referenced by procedure tests.
|
||||
Used in: Component lookup and procedure Method selection.
|
||||
Allowed values: Use a unique component name.
|
||||
Default: SmartCommunicationGenesis.
|
||||
Application: Restart required after renaming; review procedure references.</value></data>
|
||||
<data name="GenesisTooltip_commTimeoutTextBox" xml:space="preserve"><value>CommTimeout
|
||||
|
||||
Purpose: Cancellation deadline for each Genesis GCI request.
|
||||
Used in: GciBridge requests made by GenesisCommunicationForm (connect, login, registers and related slot operations).
|
||||
Allowed values: Integer: 500–5000 ms.
|
||||
Default: 1800 ms.
|
||||
Application: Read at the start of each meter activity. Each request/attempt gets its own deadline; a multi-step test can take longer. Cancellation is cooperative: the underlying driver must honor the token. Legacy callers outside this flow retain their original timeouts.</value></data>
|
||||
<data name="GenesisTooltip_maxCommRetriesTextBox" xml:space="preserve"><value>MaxCommRetries
|
||||
|
||||
Purpose: Stored communication retry setting.
|
||||
Used in: Not consumed by the current Genesis slot/GCI workflow; does not cause failed slot operations to retry.
|
||||
Allowed values: Integer: 1–10.
|
||||
Default: 4.
|
||||
Application: Stored for compatibility; no slot/GCI retry effect.</value></data>
|
||||
<data name="GenesisTooltip_delayBetweenRetriesTextBox" xml:space="preserve"><value>DelayBetweenRetries
|
||||
|
||||
Purpose: Stored delay between communication retries.
|
||||
Used in: Not consumed by the current Genesis slot/GCI workflow; does not control the form closing delay.
|
||||
Allowed values: Integer: 0–5000 ms.
|
||||
Default: 0 ms.
|
||||
Application: Stored for compatibility; no slot/GCI delay effect.</value></data>
|
||||
<data name="GenesisTooltip_nrThreadsTextBox" xml:space="preserve"><value>NrThreads
|
||||
|
||||
Purpose: Number of worker threads for processing configured Genesis heads.
|
||||
Used in: GenesisCommunicationForm: worker creation and slot distribution. Does not change the number of configured meters.
|
||||
Allowed values: Integer: 1–10.
|
||||
Default: 10.
|
||||
Application: Restart required. TURA_SPECIAL builds use a separate slot scheduling branch.</value></data>
|
||||
<data name="GenesisTooltip_iperlCheckErrorsToStopTextBox" xml:space="preserve"><value>IperlCheckErrorsToStop
|
||||
|
||||
Purpose: Number of failed meters that triggers a check-result prompt.
|
||||
Used in: GenesisCommunicationSeq: iPERL_check activity, when compiled with IPERL. User may Continue or Abort. Not a general slot-error stop limit.
|
||||
Allowed values: Integer: 1–40.
|
||||
Default: 10. Threshold uses failed count >= setting.
|
||||
Application: Applied to the next applicable check; no effect on ordinary slot activities.</value></data>
|
||||
</root>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
@ -274,4 +274,46 @@
|
||||
<data name="IperlCalibFactorNominalTooltip" xml:space="preserve">
|
||||
<value>Nominálny surový kalibračný faktor zodpovedajúci 100 %. Táto hodnota sa používa na výpočet položky „iPerl CalibFactor (%)“ v konfigurácii výsledkov.</value>
|
||||
</data>
|
||||
<data name="GenesisTooltip_nameTextBox" xml:space="preserve"><value>Name
|
||||
|
||||
Účel: Identifikuje komponent, na ktorý odkazujú testy procedúry.
|
||||
Použitie: Vyhľadanie komponentu a výber Method v procedúre.
|
||||
Rozsah hodnôt: Jedinečný názov komponentu.
|
||||
Prednastavená hodnota: SmartCommunicationGenesis
|
||||
Uplatnenie: Po premenovaní je potrebný reštart; skontrolujte odkazy v procedúrach.</value></data>
|
||||
<data name="GenesisTooltip_commTimeoutTextBox" xml:space="preserve"><value>CommTimeout
|
||||
|
||||
Účel: Časový limit pre požiadavku na zrušenie jednotlivého Genesis GCI volania.
|
||||
Použitie: Volania GciBridge z GenesisCommunicationForm (pripojenie, login, registre a súvisiace slot operácie).
|
||||
Rozsah hodnôt: Celé číslo: 500–5000 ms.
|
||||
Prednastavená hodnota: 1800 ms.
|
||||
Uplatnenie: Načíta sa na začiatku aktivity vodomera. Každé volanie/pokus má vlastný limit; viac krokov môže trvať dlhšie. Zrušenie musí podporovať spodná vrstva ovládača. Ostatní používatelia bridge zachovajú pôvodné limity.</value></data>
|
||||
<data name="GenesisTooltip_maxCommRetriesTextBox" xml:space="preserve"><value>MaxCommRetries
|
||||
|
||||
Účel: Uložené nastavenie opakovania komunikácie.
|
||||
Použitie: Aktuálny tok Genesis slot/GCI ho nečíta; nespúšťa opakovanie neúspešnej operácie.
|
||||
Rozsah hodnôt: Celé číslo: 1–10.
|
||||
Prednastavená hodnota: 4
|
||||
Uplatnenie: Zachované pre kompatibilitu; bez vplyvu na opakovanie slot/GCI.</value></data>
|
||||
<data name="GenesisTooltip_delayBetweenRetriesTextBox" xml:space="preserve"><value>DelayBetweenRetries
|
||||
|
||||
Účel: Uložená pauza medzi opakovaniami komunikácie.
|
||||
Použitie: Aktuálny tok Genesis slot/GCI ju nečíta; neriadi oneskorenie zatvorenia formulára.
|
||||
Rozsah hodnôt: Celé číslo: 0–5000 ms.
|
||||
Prednastavená hodnota: 0 ms
|
||||
Uplatnenie: Zachované pre kompatibilitu; bez vplyvu na pauzy slot/GCI.</value></data>
|
||||
<data name="GenesisTooltip_nrThreadsTextBox" xml:space="preserve"><value>NrThreads
|
||||
|
||||
Účel: Počet pracovných vlákien pre nakonfigurované hlavy Genesis.
|
||||
Použitie: GenesisCommunicationForm: vytvorenie vlákien a rozdelenie slotov. Nemení počet vodomerov.
|
||||
Rozsah hodnôt: Celé číslo: 1–10.
|
||||
Prednastavená hodnota: 10
|
||||
Uplatnenie: Vyžaduje reštart. Zostavenia TURA_SPECIAL používajú samostatné prideľovanie slotov.</value></data>
|
||||
<data name="GenesisTooltip_iperlCheckErrorsToStopTextBox" xml:space="preserve"><value>IperlCheckErrorsToStop
|
||||
|
||||
Účel: Počet neúspešných vodomerov, pri ktorom sa zobrazí výsledok kontroly.
|
||||
Použitie: GenesisCommunicationSeq: aktivita iPERL_check pri zostavení s IPERL. Používateľ môže pokračovať alebo prerušiť; nejde o všeobecný limit chýb slotov.
|
||||
Rozsah hodnôt: Celé číslo: 1–40. Prah: počet neúspešných >= nastavenie.
|
||||
Prednastavená hodnota: 10
|
||||
Uplatnenie: Použije sa pri nasledujúcej príslušnej kontrole; nie pri bežných slot aktivitách.</value></data>
|
||||
</root>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using CordonelPreadjustmentUi;
|
||||
using CordonelPreadjustmentUi;
|
||||
using CordonelPreadjustmentUi.Processes.Itinerary;
|
||||
using GenesisCordonelInterface.API;
|
||||
using GenesisCordonelInterface.Core;
|
||||
@ -37,6 +37,41 @@ using UdsWriterType = TBF.Rig.Output.DataStorage.UniDataStorageWriter.Writer;
|
||||
|
||||
namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
{
|
||||
/// <summary>Per-async-flow Genesis request timeout; absent for legacy callers.</summary>
|
||||
public static class GenesisRequestTimeout
|
||||
{
|
||||
private static readonly AsyncLocal<int?> current = new AsyncLocal<int?>();
|
||||
private static readonly ILog timeoutLog = LogManager.GetLogger(typeof(GenesisRequestTimeout));
|
||||
|
||||
public static IDisposable Begin(int milliseconds)
|
||||
{
|
||||
if (milliseconds < 500 || milliseconds > 5000) throw new ArgumentOutOfRangeException(nameof(milliseconds));
|
||||
var previous = current.Value;
|
||||
current.Value = milliseconds;
|
||||
return new Scope(previous);
|
||||
}
|
||||
|
||||
public static CancellationTokenSource CreateDeadline(CancellationToken callerToken, string operation)
|
||||
{
|
||||
var milliseconds = current.Value;
|
||||
if (!milliseconds.HasValue) return null;
|
||||
var source = CancellationTokenSource.CreateLinkedTokenSource(callerToken);
|
||||
timeoutLog.DebugFormat("Genesis CommTimeout applied: Operation={0}, TimeoutMs={1}", operation, milliseconds.Value);
|
||||
source.Token.Register(() => timeoutLog.WarnFormat("Genesis request cancellation requested: Operation={0}, TimeoutMs={1}, CallerCancelled={2}", operation, milliseconds.Value, callerToken.IsCancellationRequested));
|
||||
source.CancelAfter(milliseconds.Value);
|
||||
return source;
|
||||
}
|
||||
|
||||
private sealed class Scope : IDisposable
|
||||
{
|
||||
private readonly int? previous;
|
||||
private bool disposed;
|
||||
public Scope(int? previous) { this.previous = previous; }
|
||||
public void Dispose() { if (!disposed) { current.Value = previous; disposed = true; } }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// TBF bridge component for integration with the sibling GCI project.
|
||||
/// The component can be linked to UniDataStorage reader and writer components.
|
||||
@ -288,6 +323,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
GciPublicModels.GciInitSlotRequest request,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "InitSlotAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
EnsureExternalInterface();
|
||||
|
||||
if (request == null)
|
||||
@ -369,6 +406,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
GciPublicModels.GciInitSlotRequest request,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "UpdateSlotAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
EnsureExternalInterface();
|
||||
|
||||
if (request == null)
|
||||
@ -447,6 +486,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
int slotId,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "GetSlotAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
EnsureExternalInterface();
|
||||
|
||||
if (slotId <= 0)
|
||||
@ -523,6 +564,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "CleanSlotAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
EnsureExternalInterface();
|
||||
|
||||
if (slot <= 0)
|
||||
@ -599,6 +642,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
public async Task<GciPublicModels.GciCleanAllSlotsResult> CleanAllSlotsAsync(
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "CleanAllSlotsAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
EnsureExternalInterface();
|
||||
|
||||
GciPublicModels.GciCleanAllSlotsResult result =
|
||||
@ -671,6 +716,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
int slotId,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "GetPcbIdAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
EnsureExternalInterface();
|
||||
|
||||
if (slotId <= 0)
|
||||
@ -788,6 +835,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "ConnectAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
EnsureExternalInterface();
|
||||
|
||||
if (slot <= 0)
|
||||
@ -820,6 +869,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
int slotId,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "LoginAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
EnsureExternalInterface();
|
||||
|
||||
if (slotId <= 0)
|
||||
@ -891,6 +942,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
int slotId,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "DisconnectAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
EnsureExternalInterface();
|
||||
|
||||
if (slotId <= 0)
|
||||
@ -970,6 +1023,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
string password,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "SetPasswordAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
EnsureExternalInterface();
|
||||
|
||||
if (slotId <= 0)
|
||||
@ -1046,6 +1101,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
string registerName,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "ReadRegisterAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
EnsureExternalInterface();
|
||||
|
||||
if (slotId <= 0)
|
||||
@ -1136,6 +1193,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
bool refreshSystemState = false,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "WriteRegisterAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
EnsureExternalInterface();
|
||||
|
||||
if (slotId <= 0)
|
||||
@ -1239,6 +1298,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
string pcbId,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "GetPasswordAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
EnsureReader();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(pcbId))
|
||||
@ -1317,6 +1378,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
int meterSize,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "GetPreAdjustmentCalibrationParamsAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
EnsureReader();
|
||||
|
||||
if (meterSize < 0)
|
||||
@ -1504,6 +1567,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
/// <returns>Complete workflow result including all retry statistics and operation results.</returns>
|
||||
public async Task<GciFullLoginResult> ConnectFullPassLoginWithRetryAsync(int slotId, CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "ConnectFullPassLoginWithRetryAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
EnsureExternalInterface();
|
||||
EnsureReader();
|
||||
|
||||
@ -1605,6 +1670,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
IEnumerable<GciPublicModels.MeterBatchDebugStatus> selectedSlots,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "PreAdjustment_DetectAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
const string operation = nameof(PreAdjustment_DetectAsync);
|
||||
|
||||
try
|
||||
@ -1678,6 +1745,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "PreAdjustment_PreparationAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
const string operation = nameof(PreAdjustment_PreparationAsync);
|
||||
|
||||
try
|
||||
@ -1758,6 +1827,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "PreAdjustment_AmplitudeTestAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
const string operation = nameof(PreAdjustment_AmplitudeTestAsync);
|
||||
|
||||
try
|
||||
@ -1838,6 +1909,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "PreAdjustment_TemperatureCalibrationAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
const string operation = nameof(PreAdjustment_TemperatureCalibrationAsync);
|
||||
|
||||
try
|
||||
@ -1945,6 +2018,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "PreAdjustment_OffsetTestAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
const string operation = nameof(PreAdjustment_OffsetTestAsync);
|
||||
|
||||
try
|
||||
@ -2025,6 +2100,8 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
||||
int slot,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "PreAdjustment_CompletionAsync");
|
||||
token = deadline == null ? token : deadline.Token;
|
||||
const string operation = nameof(PreAdjustment_CompletionAsync);
|
||||
|
||||
try
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
///
|
||||
///
|
||||
/// Copyright (c) 2015-2019 Sensus Metering Systems
|
||||
/// Author: Milan Hanajík
|
||||
///
|
||||
@ -7,8 +7,44 @@ using TBF.Rig.RegisterReaders.GenesisRegReader.implementations;
|
||||
|
||||
namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
{
|
||||
/// <summary>Tracks one completion per worker, activity and group.</summary>
|
||||
public sealed class GenesisWorkerGroupCompletion
|
||||
{
|
||||
private readonly int workerCount;
|
||||
private readonly System.Collections.Generic.HashSet<int> completed = new System.Collections.Generic.HashSet<int>();
|
||||
private int activity, group;
|
||||
private bool released;
|
||||
public GenesisWorkerGroupCompletion(int workerCount)
|
||||
{
|
||||
if (workerCount < 1 || workerCount > 10) throw new ArgumentOutOfRangeException(nameof(workerCount));
|
||||
this.workerCount = workerCount;
|
||||
}
|
||||
public void Begin(int activityStep, int groupNumber)
|
||||
{
|
||||
lock (completed) { activity = activityStep; group = groupNumber; released = false; completed.Clear(); }
|
||||
}
|
||||
public bool Complete(int activityStep, int groupNumber, int worker)
|
||||
{
|
||||
lock (completed)
|
||||
{
|
||||
if (released || activityStep != activity || groupNumber != group || worker < 0 || worker >= workerCount) return false;
|
||||
if (!completed.Add(worker) || completed.Count != workerCount) return false;
|
||||
released = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public static System.Collections.Generic.IEnumerable<int> BoardIndexes(int worker, int workers, int boards)
|
||||
{
|
||||
if (workers < 1 || workers > 10 || worker < 0 || worker >= workers || boards < 0) throw new ArgumentOutOfRangeException();
|
||||
for (int index = worker; index < boards; index += workers) yield return index;
|
||||
}
|
||||
}
|
||||
|
||||
public class CommCompletedEventArgs : EventArgs
|
||||
{
|
||||
public bool WorkerGroupCompleted;
|
||||
public int ActivityStep;
|
||||
public int Group;
|
||||
public int ThreadId;
|
||||
public int WMNr0; /// 0-based water meter position
|
||||
public GenesisSmartReader Ihead;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using TBF.Rig.TestMethods.iPerlCommunication;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication;
|
||||
///
|
||||
/// Copyright (c) 2015-2023 Sensus Slovensko a.s.
|
||||
///
|
||||
@ -204,14 +204,14 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
static IList<iPerlCommunicationParams> multiTestParams;
|
||||
|
||||
|
||||
static int currentActivityStep;
|
||||
static int currentGroup; /// form -> worker thread (0 = none)
|
||||
static volatile int currentActivityStep;
|
||||
static volatile int currentGroup; /// form -> worker thread (0 = none)
|
||||
static int lastGroup;
|
||||
static int completedCommCount; /// Number of completed communication steps
|
||||
private GenesisWorkerGroupCompletion groupCompletion;
|
||||
|
||||
static IList<Thread> workerThreads;
|
||||
static IList<int> muxBrdOrGroup14Nrs;
|
||||
static bool stopWorkerThreads; /// form -> worker thread
|
||||
static volatile bool stopWorkerThreads; /// form -> worker thread
|
||||
|
||||
|
||||
/// <summary> Parameterless constructor (without watermeters, threads) </summary>
|
||||
@ -384,7 +384,6 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
///
|
||||
currentActivityStep = 0;
|
||||
currentGroup = 0;
|
||||
completedCommCount = 0;
|
||||
stopWorkerThreads = false;
|
||||
|
||||
/// group numbers are >=1, lastGroup == 0 means there is no group
|
||||
@ -409,6 +408,9 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
if (!muxBrdOrGroup14Nrs.Contains(iPerl.MuxBoardNrOrGroup14)) muxBrdOrGroup14Nrs.Add(iPerl.MuxBoardNrOrGroup14);
|
||||
}
|
||||
|
||||
groupCompletion = new GenesisWorkerGroupCompletion(workerThreads.Count);
|
||||
groupCompletion.Begin(0, 1);
|
||||
log.InfoFormat("Genesis workers configured: Threads={0}, Group1Count={1}, LastGroup2={2}", workerThreads.Count, muxBrdOrGroup14Nrs.Count, lastGroup);
|
||||
log.WarnFormat("nrThreads = {0}", workerThreads.Count);
|
||||
}
|
||||
|
||||
@ -666,6 +668,8 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
|
||||
for (int i = 0; i < multiTestParams.Count; i++ )
|
||||
{
|
||||
while (activityStep != currentActivityStep && !stopWorkerThreads) Thread.Sleep(50);
|
||||
if (stopWorkerThreads) break;
|
||||
Test currentTest = tests[i];
|
||||
iPerlCommunicationParams currentTestParams = multiTestParams[i];
|
||||
string currentActivity = currentTestParams.Activity; /// Current activity
|
||||
@ -732,7 +736,7 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
#if TURA_SPECIAL
|
||||
int threadIx = threadID; /// Just one thread for TURA_SPECIAL
|
||||
#else
|
||||
for (int threadIx = threadID; threadIx < threadID + 10; threadIx += cfg.NrThreads)// - max threads = 4 => 10
|
||||
foreach (int threadIx in GenesisWorkerGroupCompletion.BoardIndexes(threadID, workerThreads.Count, muxBrdOrGroup14Nrs.Count))
|
||||
#endif
|
||||
{
|
||||
bool wmFound = false;
|
||||
@ -759,6 +763,8 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
|
||||
CommErr error;
|
||||
string resultStr = string.Empty;
|
||||
using var requestTimeout = TBF.Rig.BridgeComponents.GciBridge.GenesisRequestTimeout.Begin(cfg.CommTimeout);
|
||||
|
||||
|
||||
///
|
||||
/// RFID communication activity call
|
||||
@ -884,8 +890,11 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
if (stopWorkerThreads) break;
|
||||
}
|
||||
|
||||
if (stopWorkerThreads) break;
|
||||
} /// for (int group
|
||||
if (stopWorkerThreads) break;
|
||||
log.DebugFormat("Genesis worker group completed: Activity={0}, Group2={1}, Worker={2}", activityStep, group, threadID);
|
||||
OnCommCompleted(null, new CommCompletedEventArgs(threadID, -1, null, null, string.Empty, CommErr.None)
|
||||
{ WorkerGroupCompleted = true, ActivityStep = activityStep, Group = group });
|
||||
} /// for (int group
|
||||
|
||||
TBF.UiBridge.Bridge.OnTestProgress(null, new TBF.UiBridge.TestProgressEventArgs(tests[i], Progress.Completed));
|
||||
activityStep++;
|
||||
@ -1608,21 +1617,17 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
}
|
||||
}
|
||||
|
||||
#if !TURA_SPECIAL
|
||||
///
|
||||
/// Branch
|
||||
///
|
||||
lock (this)
|
||||
{
|
||||
if (++completedCommCount < 4) return;
|
||||
completedCommCount = 0;
|
||||
}
|
||||
#endif
|
||||
// Per-meter results update the UI only. Advance after every worker
|
||||
// has finished all of its Group 1 assignments for this Group 2.
|
||||
if (!data.WorkerGroupCompleted || !groupCompletion.Complete(data.ActivityStep, data.Group, data.ThreadId)) return;
|
||||
log.InfoFormat("Genesis group completed: Activity={0}, Group2={1}, Workers={2}", data.ActivityStep, data.Group, workerThreads.Count);
|
||||
|
||||
|
||||
if (currentGroup < lastGroup)
|
||||
{
|
||||
/// Go to the next step / next group
|
||||
currentGroup++;
|
||||
groupCompletion.Begin(currentActivityStep, currentGroup);
|
||||
}
|
||||
else if (currentActivityStep + 1 < multiTestParams.Count)
|
||||
{
|
||||
@ -1630,16 +1635,17 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
currentActivityStep++;
|
||||
activityLabel.Text = multiTestParams[currentActivityStep].Activity;
|
||||
currentGroup++;
|
||||
groupCompletion.Begin(currentActivityStep, currentGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.Debug("Wait for finish workerThreads 4 seconds");
|
||||
|
||||
Thread lastThread = workerThreads[data.ThreadId];
|
||||
Thread[] finishingThreads = workerThreads.ToArray();
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
lastThread.Join(2000);
|
||||
foreach (var thread in finishingThreads) thread.Join();
|
||||
|
||||
if (!CanUseUi()) return;
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
///
|
||||
///
|
||||
/// Copyright (c) 2015-2022 Sensus Slovensko a.s.
|
||||
///
|
||||
|
||||
@ -58,6 +58,9 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
testMethodCfg.UseWebService = tmpCfg.UseWebService;
|
||||
testMethodCfg.BaseUrl = tmpCfg.BaseUrl;
|
||||
testMethodCfg.RelativeUrl = tmpCfg.RelativeUrl;
|
||||
log.InfoFormat("Genesis runtime configuration applied: Name={0}, CommTimeout={1}ms, MaxRetries={2}, DelayBetweenRetries={3}ms, ErrorsToStop={4}",
|
||||
Name, testMethodCfg.CommTimeout, testMethodCfg.MaxCommRetries,
|
||||
testMethodCfg.DelayBetweenRetries, testMethodCfg.IperlCheckErrorsToStop);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -80,6 +83,12 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
: base(cfg)
|
||||
{
|
||||
testMethodCfg = cfg as TestMethodCfg;
|
||||
if (testMethodCfg != null)
|
||||
log.InfoFormat("Genesis component configuration loaded: Name={0}, CommTimeout={1}ms, MaxRetries={2}, DelayBetweenRetries={3}ms, NrThreads={4}, ErrorsToStop={5}",
|
||||
testMethodCfg.Name, testMethodCfg.CommTimeout, testMethodCfg.MaxCommRetries,
|
||||
testMethodCfg.DelayBetweenRetries, testMethodCfg.NrThreads, testMethodCfg.IperlCheckErrorsToStop);
|
||||
else
|
||||
log.Error("Genesis component received an incompatible or null configuration.");
|
||||
CreateMilestonesAndConditions();
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
///
|
||||
///
|
||||
/// Copyright (c) 2015-2020 Sensus Slovensko a.s.
|
||||
///
|
||||
|
||||
@ -12,15 +12,21 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
{
|
||||
public partial class TestMethodCfgCtrl : Configs.ConfigCtrlUtils, IComponentCfgCtrl
|
||||
{
|
||||
public bool ShowMore { get { return false; } }
|
||||
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(TestMethodCfgCtrl));
|
||||
|
||||
iPerlCommunication.TestMethodCfg config;
|
||||
public bool ShowMore { get { return false; } }
|
||||
|
||||
TestMethodCfg config;
|
||||
public IComponentCfg Config
|
||||
{
|
||||
get { return config as IComponentCfg; }
|
||||
set
|
||||
{
|
||||
config = value as iPerlCommunication.TestMethodCfg;
|
||||
config = value as TestMethodCfg;
|
||||
if (config == null)
|
||||
log.ErrorFormat("Genesis Properties configuration rejected: expected {0}, received {1}", typeof(TestMethodCfg).FullName, value == null ? "null" : value.GetType().FullName);
|
||||
else
|
||||
LogConfiguration("loaded");
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
@ -28,6 +34,7 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
public TestMethodCfgCtrl()
|
||||
{
|
||||
InitializeComponent();
|
||||
InitializeSettingToolTips();
|
||||
dfltQ2corrFactorsGroupBox.Visible = false;
|
||||
useWebServiceGroupBox.Visible = false;
|
||||
var factorHint = new System.Windows.Forms.Label
|
||||
@ -50,7 +57,7 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
void Redraw()
|
||||
{
|
||||
if (config == null) return; /// Control was not loaded, settings were not changed
|
||||
classNameLabel.Text = config.Factory.ClassName;
|
||||
classNameLabel.Text = config.Factory == null ? "TestMethods.GenesisCommunication" : config.Factory.ClassName;
|
||||
nameTextBox.Text = config.Name;
|
||||
commTimeoutTextBox.Text = config.CommTimeout.ToString();
|
||||
maxCommRetriesTextBox.Text = config.MaxCommRetries.ToString();
|
||||
@ -58,22 +65,7 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
nrThreadsTextBox.Text = config.NrThreads.ToString();
|
||||
iperlCheckErrorsToStopTextBox.Text = config.IperlCheckErrorsToStop.ToString();
|
||||
|
||||
textBox15rl.Text = config.DfltQ2c_15_rl.ToString();
|
||||
textBox15lr.Text = config.DfltQ2c_15_lr.ToString();
|
||||
textBox20rl.Text = config.DfltQ2c_20_rl.ToString();
|
||||
textBox20lr.Text = config.DfltQ2c_20_lr.ToString();
|
||||
textBox25_63rl.Text = config.DfltQ2c_25_63_rl.ToString();
|
||||
textBox25_63lr.Text = config.DfltQ2c_25_63_lr.ToString();
|
||||
textBox25_10rl.Text = config.DfltQ2c_25_10_rl.ToString();
|
||||
textBox25_10lr.Text = config.DfltQ2c_25_10_lr.ToString();
|
||||
textBox32rl.Text = config.DfltQ2c_32_rl.ToString();
|
||||
textBox32lr.Text = config.DfltQ2c_32_lr.ToString();
|
||||
textBox40rl.Text = config.DfltQ2c_40_rl.ToString();
|
||||
textBox40lr.Text = config.DfltQ2c_40_lr.ToString();
|
||||
|
||||
useWebServiceCheckBox.Checked = config.UseWebService;
|
||||
baseUrlTextBox.Text = config.BaseUrl;
|
||||
relativeUrlTextBox.Text = config.RelativeUrl;
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
@ -85,28 +77,18 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
nrThreadsTextBox.Enabled = true;
|
||||
iperlCheckErrorsToStopTextBox.Enabled = true;
|
||||
|
||||
textBox15rl.Enabled = true;
|
||||
textBox15lr.Enabled = true;
|
||||
textBox20rl.Enabled = true;
|
||||
textBox20lr.Enabled = true;
|
||||
textBox25_63rl.Enabled = true;
|
||||
textBox25_63lr.Enabled = true;
|
||||
textBox25_10rl.Enabled = true;
|
||||
textBox25_10lr.Enabled = true;
|
||||
textBox32rl.Enabled = true;
|
||||
textBox32lr.Enabled = true;
|
||||
textBox40rl.Enabled = true;
|
||||
textBox40lr.Enabled = true;
|
||||
|
||||
useWebServiceCheckBox.Enabled = true;
|
||||
ManageCheckGroupBox(useWebServiceCheckBox, useWebServiceGroupBox);
|
||||
baseUrlTextBox.Enabled = useWebServiceCheckBox.Enabled;
|
||||
relativeUrlTextBox.Enabled = useWebServiceCheckBox.Enabled;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags VerifyCfg(ref string message)
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
if (config == null)
|
||||
{
|
||||
message += Environment.NewLine + "Genesis configuration is not loaded.";
|
||||
log.Error("Genesis Properties validation failed: configuration is not loaded.");
|
||||
return CfgUpdateFlags.Error;
|
||||
}
|
||||
|
||||
int dummy;
|
||||
if (!int.TryParse(commTimeoutTextBox.Text, out dummy) || dummy < 500 || dummy > 5000)
|
||||
@ -122,79 +104,21 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
if (!int.TryParse(delayBetweenRetriesTextBox.Text, out dummy) || dummy < 0 || dummy > 5000)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Comm. timeout' should be in range 0 .. 5000";
|
||||
message += Environment.NewLine + "'Delay between retries' should be in range 0 .. 5000";
|
||||
}
|
||||
if (!int.TryParse(nrThreadsTextBox.Text, out dummy) || (dummy < 1 || dummy > 10))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Nr. threads' should be in range 1 .. 10";
|
||||
}
|
||||
if (!int.TryParse(iperlCheckErrorsToStopTextBox.Text, out dummy) || ((dummy < 1) && (dummy > 40)))
|
||||
if (!int.TryParse(iperlCheckErrorsToStopTextBox.Text, out dummy) || ((dummy < 1) || (dummy > 40)))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + string.Format(Strings.Invalid_0, iperlCheckErrorsToStopLabel.Text);
|
||||
}
|
||||
|
||||
if (!int.TryParse(textBox15rl.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Default Q2 correction factor DN15 RL should be in range -50 .. 50";
|
||||
}
|
||||
if (!int.TryParse(textBox15lr.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Default Q2 correction factor DN15 LR should be in range -50 .. 50";
|
||||
}
|
||||
if (!int.TryParse(textBox20rl.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Default Q2 correction factor DN20 RL should be in range -50 .. 50";
|
||||
}
|
||||
if (!int.TryParse(textBox20lr.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Default Q2 correction factor DN20 LR should be in range -50 .. 50";
|
||||
}
|
||||
if (!int.TryParse(textBox25_63rl.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Default Q2 correction factor DN25 Q3 6.3 RL should be in range -50 .. 50";
|
||||
}
|
||||
if (!int.TryParse(textBox25_63lr.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Default Q2 correction factor DN25 Q3 6.3 LR should be in range -50 .. 50";
|
||||
}
|
||||
if (!int.TryParse(textBox25_10rl.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Default Q2 correction factor DN25 Q3 10 RL should be in range -50 .. 50";
|
||||
}
|
||||
if (!int.TryParse(textBox25_10lr.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Default Q2 correction factor DN25 Q3 10 LR should be in range -50 .. 50";
|
||||
}
|
||||
if (!int.TryParse(textBox32rl.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Default Q2 correction factor DN32 RL should be in range -50 .. 50";
|
||||
}
|
||||
if (!int.TryParse(textBox32lr.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Default Q2 correction factor DN32 LR should be in range -50 .. 50";
|
||||
}
|
||||
if (!int.TryParse(textBox40rl.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Default Q2 correction factor DN40 RL should be in range -50 .. 50";
|
||||
}
|
||||
if (!int.TryParse(textBox40lr.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Default Q2 correction factor DN40 LR should be in range -50 .. 50";
|
||||
}
|
||||
if ((flags & CfgUpdateFlags.Error) != 0)
|
||||
log.WarnFormat("Genesis Properties validation failed: {0}", message);
|
||||
|
||||
return flags;
|
||||
}
|
||||
@ -203,7 +127,8 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
|
||||
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
|
||||
string message = string.Empty;
|
||||
if ((VerifyCfg(ref message) & CfgUpdateFlags.Error) != 0) return CfgUpdateFlags.Error;
|
||||
|
||||
if (config.Name != nameTextBox.Text)
|
||||
{
|
||||
@ -211,26 +136,11 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
flags |= (CfgUpdateFlags.AnyChange | CfgUpdateFlags.RestartRqrd);
|
||||
}
|
||||
|
||||
var CommTimeout = config.CommTimeout;;
|
||||
var CommTimeout = config.CommTimeout;
|
||||
var MaxCommRetries = config.MaxCommRetries;
|
||||
var DelayBetweenRetries = config.DelayBetweenRetries;
|
||||
var NrThreads = config.NrThreads;
|
||||
var IperlCheckErrorsToStop = config.IperlCheckErrorsToStop;
|
||||
var DfltQ2c_15_rl = config.DfltQ2c_15_rl;
|
||||
var DfltQ2c_15_lr = config.DfltQ2c_15_lr;
|
||||
var DfltQ2c_20_rl = config.DfltQ2c_20_rl;
|
||||
var DfltQ2c_20_lr = config.DfltQ2c_20_lr;
|
||||
var DfltQ2c_25_63_rl = config.DfltQ2c_25_63_rl;
|
||||
var DfltQ2c_25_63_lr = config.DfltQ2c_25_63_lr;
|
||||
var DfltQ2c_25_10_rl = config.DfltQ2c_25_10_rl;
|
||||
var DfltQ2c_25_10_lr = config.DfltQ2c_25_10_lr;
|
||||
var DfltQ2c_32_rl = config.DfltQ2c_32_rl;
|
||||
var DfltQ2c_32_lr = config.DfltQ2c_32_lr;
|
||||
var DfltQ2c_40_rl = config.DfltQ2c_40_rl;
|
||||
var DfltQ2c_40_lr = config.DfltQ2c_40_lr;
|
||||
var UseWebService = config.UseWebService;
|
||||
var BaseUrl = config.BaseUrl;
|
||||
var RelativeUrl = config.RelativeUrl;
|
||||
|
||||
flags |= UpdateDifferent(ref CommTimeout, commTimeoutTextBox.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||
flags |= UpdateDifferent(ref MaxCommRetries, maxCommRetriesTextBox.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||
@ -238,22 +148,7 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
flags |= UpdateDifferent(ref NrThreads, nrThreadsTextBox.Text, CfgUpdateFlags.RestartRqrd | CfgUpdateFlags.AnyChange);
|
||||
flags |= UpdateDifferent(ref IperlCheckErrorsToStop, iperlCheckErrorsToStopTextBox.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||
|
||||
flags |= UpdateDifferent(ref DfltQ2c_15_rl, textBox15rl.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||
flags |= UpdateDifferent(ref DfltQ2c_15_lr, textBox15lr.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||
flags |= UpdateDifferent(ref DfltQ2c_20_rl, textBox20rl.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||
flags |= UpdateDifferent(ref DfltQ2c_20_lr, textBox20lr.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||
flags |= UpdateDifferent(ref DfltQ2c_25_63_rl, textBox25_63rl.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||
flags |= UpdateDifferent(ref DfltQ2c_25_63_lr, textBox25_63lr.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||
flags |= UpdateDifferent(ref DfltQ2c_25_10_rl, textBox25_10rl.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||
flags |= UpdateDifferent(ref DfltQ2c_25_10_lr, textBox25_10lr.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||
flags |= UpdateDifferent(ref DfltQ2c_32_rl, textBox32rl.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||
flags |= UpdateDifferent(ref DfltQ2c_32_lr, textBox32lr.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||
flags |= UpdateDifferent(ref DfltQ2c_40_rl, textBox40rl.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||
flags |= UpdateDifferent(ref DfltQ2c_40_lr, textBox40lr.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||
|
||||
flags |= UpdateDifferent(ref UseWebService, useWebServiceCheckBox.Checked, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||
flags |= UpdateDifferent(ref BaseUrl, baseUrlTextBox.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||
flags |= UpdateDifferent(ref RelativeUrl, relativeUrlTextBox.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||
|
||||
|
||||
config.CommTimeout = CommTimeout;
|
||||
@ -261,30 +156,44 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
||||
config.DelayBetweenRetries = DelayBetweenRetries;
|
||||
config.NrThreads = NrThreads;
|
||||
config.IperlCheckErrorsToStop = IperlCheckErrorsToStop;
|
||||
config.DfltQ2c_15_rl = DfltQ2c_15_rl;
|
||||
config.DfltQ2c_15_lr = DfltQ2c_15_lr;
|
||||
config.DfltQ2c_20_rl = DfltQ2c_20_rl;
|
||||
config.DfltQ2c_20_lr = DfltQ2c_20_lr;
|
||||
config.DfltQ2c_25_63_rl = DfltQ2c_25_63_rl;
|
||||
config.DfltQ2c_25_63_lr = DfltQ2c_25_63_lr;
|
||||
config.DfltQ2c_25_10_rl = DfltQ2c_25_10_rl;
|
||||
config.DfltQ2c_25_10_lr = DfltQ2c_25_10_lr;
|
||||
config.DfltQ2c_32_rl = DfltQ2c_32_rl;
|
||||
config.DfltQ2c_32_lr = DfltQ2c_32_lr;
|
||||
config.DfltQ2c_40_rl = DfltQ2c_40_rl;
|
||||
config.DfltQ2c_40_lr = DfltQ2c_40_lr;
|
||||
config.UseWebService = UseWebService;
|
||||
config.BaseUrl = BaseUrl;
|
||||
config.RelativeUrl = RelativeUrl;
|
||||
|
||||
LogConfiguration("updated; flags=" + flags);
|
||||
|
||||
if ((flags & CfgUpdateFlags.InvokeCfgChange) != 0)
|
||||
{
|
||||
iPerlCommunication.TestMethod.OnCfgChange(this, new CfgChangeArgs(CfgChangeCmd.CfgChange, config));
|
||||
TestMethod.OnCfgChange(this, new CfgChangeArgs(CfgChangeCmd.CfgChange, config));
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
private ToolTip settingsToolTip;
|
||||
|
||||
private void InitializeSettingToolTips()
|
||||
{
|
||||
if (components == null) components = new System.ComponentModel.Container();
|
||||
settingsToolTip = new ToolTip(components) { AutoPopDelay = 30000, InitialDelay = 400, ReshowDelay = 100, ShowAlways = true };
|
||||
settingsToolTip.SetToolTip(nameTextBox, Strings.ResourceManager.GetString("GenesisTooltip_nameTextBox", Strings.Culture));
|
||||
settingsToolTip.SetToolTip(nameLabel, settingsToolTip.GetToolTip(nameTextBox));
|
||||
settingsToolTip.SetToolTip(commTimeoutTextBox, Strings.ResourceManager.GetString("GenesisTooltip_commTimeoutTextBox", Strings.Culture));
|
||||
settingsToolTip.SetToolTip(commTimeoutLabel, settingsToolTip.GetToolTip(commTimeoutTextBox));
|
||||
settingsToolTip.SetToolTip(maxCommRetriesTextBox, Strings.ResourceManager.GetString("GenesisTooltip_maxCommRetriesTextBox", Strings.Culture));
|
||||
settingsToolTip.SetToolTip(maxNrRetriesLabel, settingsToolTip.GetToolTip(maxCommRetriesTextBox));
|
||||
settingsToolTip.SetToolTip(delayBetweenRetriesTextBox, Strings.ResourceManager.GetString("GenesisTooltip_delayBetweenRetriesTextBox", Strings.Culture));
|
||||
settingsToolTip.SetToolTip(delayBetweenRetriesLabel, settingsToolTip.GetToolTip(delayBetweenRetriesTextBox));
|
||||
settingsToolTip.SetToolTip(nrThreadsTextBox, Strings.ResourceManager.GetString("GenesisTooltip_nrThreadsTextBox", Strings.Culture));
|
||||
settingsToolTip.SetToolTip(nrThreadsLabel, settingsToolTip.GetToolTip(nrThreadsTextBox));
|
||||
settingsToolTip.SetToolTip(iperlCheckErrorsToStopTextBox, Strings.ResourceManager.GetString("GenesisTooltip_iperlCheckErrorsToStopTextBox", Strings.Culture));
|
||||
settingsToolTip.SetToolTip(iperlCheckErrorsToStopLabel, settingsToolTip.GetToolTip(iperlCheckErrorsToStopTextBox));
|
||||
}
|
||||
|
||||
private void LogConfiguration(string action)
|
||||
{
|
||||
log.InfoFormat("Genesis Properties {0}: Name={1}, CommTimeout={2}ms, MaxRetries={3}, DelayBetweenRetries={4}ms, NrThreads={5}, ErrorsToStop={6}; Q3 source=WaterMeterData.Text1-Text3; legacy fields preserved",
|
||||
action, config.Name, config.CommTimeout, config.MaxCommRetries,
|
||||
config.DelayBetweenRetries, config.NrThreads, config.IperlCheckErrorsToStop);
|
||||
}
|
||||
|
||||
private void ManageCheckGroupBox(CheckBox chk, GroupBox grp)
|
||||
{
|
||||
/// Make sure the CheckBox isn't in the GroupBox. This will only happen the first time.
|
||||
|
||||
@ -165,6 +165,195 @@ namespace TBFTests
|
||||
|
||||
// ReSharper restore SqlResolve
|
||||
|
||||
[TestMethod]
|
||||
public void GenesisPropertiesLoadUpdateAndPreserveLegacySettings()
|
||||
{
|
||||
var cfg = new TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfg(new TBF.Rig.TestMethods.GenesisCommunication.Factory());
|
||||
cfg.Name = "Genesis test";
|
||||
cfg.DfltQ2c_15_rl = 17969;
|
||||
cfg.UseWebService = true;
|
||||
cfg.BaseUrl = "legacy-base";
|
||||
cfg.RelativeUrl = "legacy-path";
|
||||
// Exercise the existing XML contract before opening Properties.
|
||||
using (var writer = new StringWriter())
|
||||
{
|
||||
TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfg.Serializer.Serialize(writer, cfg);
|
||||
using (var reader = new StringReader(writer.ToString()))
|
||||
cfg = (TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfg)TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfg.Serializer.Deserialize(reader);
|
||||
}
|
||||
// Name is stored in the component entity, outside the XML payload.
|
||||
cfg.Name = "Genesis test";
|
||||
using (var ctrl = new TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfgCtrl())
|
||||
{
|
||||
ctrl.Config = cfg;
|
||||
Assert.AreSame(cfg, ctrl.Config);
|
||||
Assert.AreEqual("Genesis test", ctrl.Controls.Find("nameTextBox", true)[0].Text);
|
||||
Assert.AreEqual("1800", ctrl.Controls.Find("commTimeoutTextBox", true)[0].Text);
|
||||
string message = "";
|
||||
Assert.AreEqual(Common.CfgUpdateFlags.None, ctrl.VerifyCfg(ref message), message);
|
||||
ctrl.Unlock();
|
||||
ctrl.Controls.Find("commTimeoutTextBox", true)[0].Text = "2300";
|
||||
bool notified = false;
|
||||
EventHandler<TBF.Rig.CfgChangeArgs> handler = (sender, args) => { notified = true; };
|
||||
TBF.Rig.TestMethods.GenesisCommunication.TestMethod.CfgChangeHandler += handler;
|
||||
try { ctrl.UpdateCfg(); }
|
||||
finally { TBF.Rig.TestMethods.GenesisCommunication.TestMethod.CfgChangeHandler -= handler; }
|
||||
Assert.IsTrue(notified);
|
||||
Assert.AreEqual(2300, cfg.CommTimeout);
|
||||
Assert.AreEqual(17969, cfg.DfltQ2c_15_rl);
|
||||
Assert.IsTrue(cfg.UseWebService);
|
||||
Assert.AreEqual("legacy-base", cfg.BaseUrl);
|
||||
Assert.AreEqual("legacy-path", cfg.RelativeUrl);
|
||||
ctrl.Controls.Find("iperlCheckErrorsToStopTextBox", true)[0].Text = "41";
|
||||
ctrl.Controls.Find("commTimeoutTextBox", true)[0].Text = "2400";
|
||||
Assert.AreNotEqual(0, (int)(ctrl.UpdateCfg() & Common.CfgUpdateFlags.Error));
|
||||
Assert.AreEqual(2300, cfg.CommTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GenesisPropertiesValidateAllNumericBoundariesAndExposeTooltips()
|
||||
{
|
||||
var cfg = new TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfg(new TBF.Rig.TestMethods.GenesisCommunication.Factory());
|
||||
using (var ctrl = new TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfgCtrl())
|
||||
{
|
||||
ctrl.Config = cfg;
|
||||
ctrl.Unlock();
|
||||
var tips = (System.Windows.Forms.ToolTip)typeof(TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfgCtrl)
|
||||
.GetField("settingsToolTip", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(ctrl);
|
||||
var names = new[] { "commTimeoutTextBox", "maxCommRetriesTextBox", "delayBetweenRetriesTextBox", "nrThreadsTextBox", "iperlCheckErrorsToStopTextBox" };
|
||||
var minima = new[] { 500, 1, 0, 1, 1 };
|
||||
var maxima = new[] { 5000, 10, 5000, 10, 40 };
|
||||
for (int i = 0; i < names.Length; i++)
|
||||
{
|
||||
var field = ctrl.Controls.Find(names[i], true)[0];
|
||||
string original = field.Text;
|
||||
Assert.IsFalse(string.IsNullOrWhiteSpace(tips.GetToolTip(field)));
|
||||
Assert.IsTrue(tips.GetToolTip(field).Split('\n').Length >= 6);
|
||||
foreach (var value in new[] { minima[i], maxima[i] })
|
||||
{
|
||||
field.Text = value.ToString();
|
||||
string message = "";
|
||||
Assert.AreEqual(Common.CfgUpdateFlags.None, ctrl.VerifyCfg(ref message), names[i] + message);
|
||||
}
|
||||
foreach (var value in new[] { (minima[i] - 1).ToString(), (maxima[i] + 1).ToString(), "bad", "", "1.5" })
|
||||
{
|
||||
field.Text = value;
|
||||
string message = "";
|
||||
Assert.AreNotEqual(0, (int)(ctrl.VerifyCfg(ref message) & Common.CfgUpdateFlags.Error), names[i] + ":" + value);
|
||||
}
|
||||
field.Text = original;
|
||||
}
|
||||
ctrl.Controls.Find("commTimeoutTextBox", true)[0].Text = "2500";
|
||||
ctrl.Controls.Find("maxCommRetriesTextBox", true)[0].Text = "6";
|
||||
ctrl.Controls.Find("delayBetweenRetriesTextBox", true)[0].Text = "300";
|
||||
ctrl.Controls.Find("nrThreadsTextBox", true)[0].Text = "3";
|
||||
ctrl.Controls.Find("iperlCheckErrorsToStopTextBox", true)[0].Text = "2";
|
||||
var flags = ctrl.UpdateCfg();
|
||||
Assert.AreNotEqual(0, (int)(flags & Common.CfgUpdateFlags.RestartRqrd));
|
||||
Assert.AreEqual(2500, cfg.CommTimeout);
|
||||
Assert.AreEqual(6, cfg.MaxCommRetries);
|
||||
Assert.AreEqual(300, cfg.DelayBetweenRetries);
|
||||
Assert.AreEqual(3, cfg.NrThreads);
|
||||
Assert.AreEqual(2, cfg.IperlCheckErrorsToStop);
|
||||
StringAssert.Contains(tips.GetToolTip(ctrl.Controls.Find("commTimeoutTextBox", true)[0]), "Genesis");
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GenesisRuntimeReceivesLiveSettingsButKeepsRestartOnlyThreadCount()
|
||||
{
|
||||
var factory = new TBF.Rig.TestMethods.GenesisCommunication.Factory();
|
||||
var runtimeCfg = new TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfg(factory);
|
||||
var editedCfg = new TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfg(factory);
|
||||
var component = new TBF.Rig.TestMethods.GenesisCommunication.TestMethod(runtimeCfg);
|
||||
var eventField = typeof(TBF.Rig.TestMethods.GenesisCommunication.TestMethod).GetField("CfgChangeHandler",
|
||||
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
|
||||
var originalHandlers = eventField.GetValue(null);
|
||||
try
|
||||
{
|
||||
component.StartChangeHandler();
|
||||
using (var ctrl = new TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfgCtrl())
|
||||
{
|
||||
ctrl.Config = editedCfg;
|
||||
ctrl.Unlock();
|
||||
ctrl.Controls.Find("commTimeoutTextBox", true)[0].Text = "2500";
|
||||
ctrl.Controls.Find("maxCommRetriesTextBox", true)[0].Text = "6";
|
||||
ctrl.Controls.Find("delayBetweenRetriesTextBox", true)[0].Text = "300";
|
||||
ctrl.Controls.Find("iperlCheckErrorsToStopTextBox", true)[0].Text = "2";
|
||||
ctrl.Controls.Find("nrThreadsTextBox", true)[0].Text = "3";
|
||||
ctrl.UpdateCfg();
|
||||
Assert.AreEqual(2500, runtimeCfg.CommTimeout);
|
||||
Assert.AreEqual(6, runtimeCfg.MaxCommRetries);
|
||||
Assert.AreEqual(300, runtimeCfg.DelayBetweenRetries);
|
||||
Assert.AreEqual(2, runtimeCfg.IperlCheckErrorsToStop);
|
||||
Assert.AreEqual(10, runtimeCfg.NrThreads);
|
||||
Assert.AreEqual(3, editedCfg.NrThreads);
|
||||
}
|
||||
}
|
||||
finally { eventField.SetValue(null, originalHandlers); }
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GenesisTooltipsFollowUiCultureAndFallbackToEnglish()
|
||||
{
|
||||
var original = System.Threading.Thread.CurrentThread.CurrentUICulture;
|
||||
try
|
||||
{
|
||||
var cultures = new[] { "en-US", "sk-SK", "cs-CZ", "de-DE", "fr-FR" };
|
||||
var headings = new[] { "Default:", "Prednastaven\u00e1 hodnota:", "V\u00fdchoz\u00ed hodnota:", "Standardwert:", "Default:" };
|
||||
for (int i = 0; i < cultures.Length; i++)
|
||||
{
|
||||
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(cultures[i]);
|
||||
using (var ctrl = new TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfgCtrl())
|
||||
{
|
||||
var tips = (System.Windows.Forms.ToolTip)typeof(TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfgCtrl)
|
||||
.GetField("settingsToolTip", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(ctrl);
|
||||
foreach (var field in new[] { "nameTextBox", "commTimeoutTextBox", "maxCommRetriesTextBox", "delayBetweenRetriesTextBox", "nrThreadsTextBox", "iperlCheckErrorsToStopTextBox" })
|
||||
StringAssert.Contains(tips.GetToolTip(ctrl.Controls.Find(field, true)[0]), headings[i], cultures[i] + field);
|
||||
var timeout = tips.GetToolTip(ctrl.Controls.Find("commTimeoutTextBox", true)[0]);
|
||||
StringAssert.Contains(timeout, "500\u20135000 ms");
|
||||
StringAssert.Contains(timeout, "1800 ms");
|
||||
Assert.AreEqual(timeout, tips.GetToolTip(ctrl.Controls.Find("commTimeoutLabel", true)[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
finally { System.Threading.Thread.CurrentThread.CurrentUICulture = original; }
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async System.Threading.Tasks.Task GenesisTimeoutChangesCancellationDeadlineAndPreservesLegacyCallers()
|
||||
{
|
||||
Assert.IsNull(TBF.Rig.BridgeComponents.GciBridge.GenesisRequestTimeout.CreateDeadline(System.Threading.CancellationToken.None, "legacy"));
|
||||
using (TBF.Rig.BridgeComponents.GciBridge.GenesisRequestTimeout.Begin(5000))
|
||||
using (var longDeadline = TBF.Rig.BridgeComponents.GciBridge.GenesisRequestTimeout.CreateDeadline(System.Threading.CancellationToken.None, "long-test"))
|
||||
{
|
||||
using (TBF.Rig.BridgeComponents.GciBridge.GenesisRequestTimeout.Begin(500))
|
||||
using (var shortDeadline = TBF.Rig.BridgeComponents.GciBridge.GenesisRequestTimeout.CreateDeadline(System.Threading.CancellationToken.None, "short-test"))
|
||||
{
|
||||
try
|
||||
{
|
||||
await System.Threading.Tasks.Task.Delay(3000, shortDeadline.Token);
|
||||
Assert.Fail("Expected the configured 500 ms deadline to cancel the operation.");
|
||||
}
|
||||
catch (System.OperationCanceledException) { Assert.IsTrue(shortDeadline.IsCancellationRequested); }
|
||||
Assert.IsFalse(longDeadline.IsCancellationRequested);
|
||||
}
|
||||
using (var restored = TBF.Rig.BridgeComponents.GciBridge.GenesisRequestTimeout.CreateDeadline(System.Threading.CancellationToken.None, "restored-test"))
|
||||
{
|
||||
await System.Threading.Tasks.Task.Delay(700);
|
||||
Assert.IsFalse(restored.IsCancellationRequested);
|
||||
}
|
||||
using (var caller = new System.Threading.CancellationTokenSource())
|
||||
using (var linked = TBF.Rig.BridgeComponents.GciBridge.GenesisRequestTimeout.CreateDeadline(caller.Token, "caller-test"))
|
||||
{
|
||||
caller.Cancel();
|
||||
Assert.IsTrue(linked.IsCancellationRequested);
|
||||
}
|
||||
}
|
||||
Assert.IsNull(TBF.Rig.BridgeComponents.GciBridge.GenesisRequestTimeout.CreateDeadline(System.Threading.CancellationToken.None, "legacy-after"));
|
||||
}
|
||||
|
||||
private static void Execute(SQLiteConnection connection, string sql)
|
||||
{
|
||||
using (var command = connection.CreateCommand()) { command.CommandText = sql; command.ExecuteNonQuery(); }
|
||||
|
||||
@ -231,7 +231,7 @@
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
<ItemGroup><Compile Include="GenesisRecoveryTests.cs" /></ItemGroup>
|
||||
<ItemGroup><Compile Include="GenesisRecoveryTests.cs" /><Compile Include="GenesisParallelSchedulingTests.cs" /><Compile Include="Rig\RegisterReaders\GenesisRegReader\GenesisReadDataRegressionTests.cs" /></ItemGroup>
|
||||
<!-- Project dependencies may copy an older SQLite interop DLL with a newer timestamp. -->
|
||||
<Target Name="EnsureMatchingSQLiteInterop" AfterTargets="Build">
|
||||
<Copy SourceFiles="@(SQLiteInteropFiles)"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user