Summary
Add unit/integration-style regression tests to verify that the sync model, disk serialization, and compare/apply logic are idempotent and do not re-detect changes after a no-op roundtrip.
This is intended to validate and protect against the behavior reported in #78, where KepwareToDiskAndSecondary can enter a repeated sync loop when changes written from disk to Kepware are immediately detected again as fresh changes.
Problem
The current sync flow can enqueue a follow-up PrimaryKepServer sync after a Disk -> Primary sync when changes were applied. That behavior is only safe if the full roundtrip is idempotent.
If any representation difference remains between:
- in-memory model
- YAML/CSV persisted representation
- reloaded model
- compare/apply input vs API-loaded state
then the next sync cycle may still detect differences and trigger another update, causing a feedback loop.
We need tests that verify:
- whether the roundtrip is actually stable
- that once a change has been applied, a second run with the same effective data produces no further changes
- that future changes do not reintroduce this regression
Goal
Create regression tests that prove the synchronization pipeline is idempotent for unchanged data and does not continuously produce false-positive updates.
Scope
Add tests for the following areas:
1. YAML roundtrip stability
Verify that serializing and deserializing entities does not introduce semantic changes.
Suggested coverage:
Project
Channel
Device
DeviceTagGroup (if practical)
Tag where applicable through CSV path
Suggested assertions:
- important fields remain equal after roundtrip
Hash remains stable after roundtrip
- re-saving the same object does not change the persisted output
2. CSV tag roundtrip stability
Verify that exporting/importing tags via CsvTagSerializer preserves effective values and does not change tag hashes unexpectedly.
Suggested assertions:
- imported tags match exported tag values
- imported tags do not create false-positive compare/update results
- numeric/bool/string fields preserve their intended types/values
3. Project storage roundtrip idempotency
Verify the KepFolderStorage roundtrip:
Project -> ExportProjecAsync -> LoadProject(true)
Suggested assertions:
- loaded project is semantically equivalent to the exported project
- a second export/load cycle does not introduce additional differences
- compare logic against the same effective project reports no updates/inserts/deletes
4. Compare/apply idempotency regression test
Verify that once a source project has been applied, repeating compare/apply with the same effective input does not produce further changes.
Suggested assertions:
- first compare/apply may report changes
- second compare/apply against the already-updated target reports zero changes
- no repeated updates are triggered by representation-only differences
5. Sync loop regression protection
Add a targeted regression test around the sync behavior that models:
- local file sync applies changes
- a follow-up sync from primary occurs
- no further effective changes exist
- no repeated change cascade occurs
This test can be mock-based if a full integration test is too heavy.
Suggested test cases
A. YAML serializer roundtrip preserves entity hash
Examples:
YamlSerializer_Roundtrip_Channel_ShouldPreserveHash
YamlSerializer_Roundtrip_Device_ShouldPreserveHash
B. CSV serializer roundtrip preserves tag semantics
Examples:
CsvTagSerializer_Roundtrip_Tag_ShouldPreserveEffectiveValues
CsvTagSerializer_Roundtrip_Tags_ShouldNotIntroduceHashDifferences
C. Project storage roundtrip is idempotent
Examples:
KepFolderStorage_ProjectRoundtrip_ShouldBeIdempotent
KepFolderStorage_SecondRoundtrip_ShouldProduceNoFurtherDifferences
D. Compare/apply becomes stable after first application
Examples:
CompareAndApply_SameEffectiveProject_SecondRun_ShouldReportNoChanges
CompareAndApply_RoundtripReloadedProject_ShouldReportNoChanges
E. Sync service does not re-trigger indefinitely
Examples:
SyncService_DiskToPrimaryFollowedByPrimarySync_ShouldNotLoopWhenNoEffectiveChangesRemain
Implementation notes
Please pay particular attention to fields that are likely to differ only by representation, for example:
- numeric type conversions (
int, long, etc.)
- boolean conversions
- absent vs default-valued dynamic properties
- YAML/CSV normalization differences
- property ordering / normalization behavior
- values introduced or omitted by cleanup/serialization
Acceptance criteria
Related
Summary
Add unit/integration-style regression tests to verify that the sync model, disk serialization, and compare/apply logic are idempotent and do not re-detect changes after a no-op roundtrip.
This is intended to validate and protect against the behavior reported in #78, where
KepwareToDiskAndSecondarycan enter a repeated sync loop when changes written from disk to Kepware are immediately detected again as fresh changes.Problem
The current sync flow can enqueue a follow-up
PrimaryKepServersync after aDisk -> Primarysync when changes were applied. That behavior is only safe if the full roundtrip is idempotent.If any representation difference remains between:
then the next sync cycle may still detect differences and trigger another update, causing a feedback loop.
We need tests that verify:
Goal
Create regression tests that prove the synchronization pipeline is idempotent for unchanged data and does not continuously produce false-positive updates.
Scope
Add tests for the following areas:
1. YAML roundtrip stability
Verify that serializing and deserializing entities does not introduce semantic changes.
Suggested coverage:
ProjectChannelDeviceDeviceTagGroup(if practical)Tagwhere applicable through CSV pathSuggested assertions:
Hashremains stable after roundtrip2. CSV tag roundtrip stability
Verify that exporting/importing tags via
CsvTagSerializerpreserves effective values and does not change tag hashes unexpectedly.Suggested assertions:
3. Project storage roundtrip idempotency
Verify the
KepFolderStorageroundtrip:Project -> ExportProjecAsync -> LoadProject(true)Suggested assertions:
4. Compare/apply idempotency regression test
Verify that once a source project has been applied, repeating compare/apply with the same effective input does not produce further changes.
Suggested assertions:
5. Sync loop regression protection
Add a targeted regression test around the sync behavior that models:
This test can be mock-based if a full integration test is too heavy.
Suggested test cases
A. YAML serializer roundtrip preserves entity hash
Examples:
YamlSerializer_Roundtrip_Channel_ShouldPreserveHashYamlSerializer_Roundtrip_Device_ShouldPreserveHashB. CSV serializer roundtrip preserves tag semantics
Examples:
CsvTagSerializer_Roundtrip_Tag_ShouldPreserveEffectiveValuesCsvTagSerializer_Roundtrip_Tags_ShouldNotIntroduceHashDifferencesC. Project storage roundtrip is idempotent
Examples:
KepFolderStorage_ProjectRoundtrip_ShouldBeIdempotentKepFolderStorage_SecondRoundtrip_ShouldProduceNoFurtherDifferencesD. Compare/apply becomes stable after first application
Examples:
CompareAndApply_SameEffectiveProject_SecondRun_ShouldReportNoChangesCompareAndApply_RoundtripReloadedProject_ShouldReportNoChangesE. Sync service does not re-trigger indefinitely
Examples:
SyncService_DiskToPrimaryFollowedByPrimarySync_ShouldNotLoopWhenNoEffectiveChangesRemainImplementation notes
Please pay particular attention to fields that are likely to differ only by representation, for example:
int,long, etc.)Acceptance criteria
Related