using DodoSSH.Contracts;
namespace DodoSSH.Client.Sync.Tests;
///
/// The registry of synchronised item types, and the one property that has to hold about it.
///
///
/// Adding an item type touches a cipher, a codec, a merge, a repository and a view. The failure this pins is
/// the one that none of those would reveal: a type that can be created, encrypted, merged and listed
/// perfectly, and is never asked for in a pull — so it works on the machine that made it and exists nowhere
/// else. Deriving the filter from the registry is what prevents it; these tests are what notice if the
/// derivation stops holding.
///
public sealed class ItemKindsTests
{
[Fact]
public void ThePullFilterNamesEveryTypeThisBuildSynchronises()
{
ItemKinds.SyncedTypes.ShouldBe(
[SyncEntityType.Host, SyncEntityType.SshKey, SyncEntityType.Credential]);
}
[Fact]
public void ThePullFilterIsNotEmpty()
{
// Stated separately from the list above because the consequence of an empty one is quiet rather
// than loud: the contract says an empty filter means every type, so the client would ask the server
// for everything it holds and then discard most of the answer in ApplyAsync. The way it could
// actually become empty is a static initialisation order slip — SyncedTypes projects Registry, and a
// reordering of the two declarations would leave it reading an unassigned array.
ItemKinds.SyncedTypes.ShouldNotBeEmpty();
}
[Fact]
public async Task EveryTypeInThePullFilter_HasAReconciler()
{
using var harness = await SyncHarness.CreateAsync();
var reconcilers = ItemKinds.Reconcilers(
harness.First.Outbox, harness.First.Conflicts, harness.First.Keyring);
reconcilers.Keys.Order().ShouldBe(ItemKinds.SyncedTypes.Order());
}
}