Public Access
77 lines
3.1 KiB
C#
77 lines
3.1 KiB
C#
using DodoSSH.Client.Domain;
|
|
using DodoSSH.Contracts;
|
|
|
|
namespace DodoSSH.Client.Sync.Tests;
|
|
|
|
/// <summary>
|
|
/// The registry of synchronised item types, and the one property that has to hold about it.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// 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.
|
|
/// </remarks>
|
|
public sealed class ItemKindsTests
|
|
{
|
|
[Fact]
|
|
public void ThePullFilterNamesEveryTypeThisBuildSynchronises()
|
|
{
|
|
ItemKinds.SyncedTypes.ShouldBe(
|
|
[
|
|
SyncEntityType.Host,
|
|
SyncEntityType.SshKey,
|
|
SyncEntityType.Credential,
|
|
SyncEntityType.KnownHostKey,
|
|
SyncEntityType.HostGroup,
|
|
SyncEntityType.Tag,
|
|
SyncEntityType.Snippet,
|
|
SyncEntityType.ConnectionLogEntry,
|
|
SyncEntityType.ActivityLogEntry,
|
|
SyncEntityType.ObjectStore,
|
|
]);
|
|
}
|
|
|
|
[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());
|
|
}
|
|
|
|
[Fact]
|
|
public void AHostEditThatOnlyChangedItsPins_IsReportedAsChangingPinnedPaths()
|
|
{
|
|
// Pinned paths were the one host field Changes did not look at, so an edit that only pinned or
|
|
// unpinned a directory reached the keychain log as an update that changed nothing.
|
|
var before = new HostSecret
|
|
{
|
|
Label = "db-01",
|
|
Hostname = "db-01.internal",
|
|
PinnedPaths = PinnedPathList.Create(["/var/log"]),
|
|
};
|
|
var after = before with { PinnedPaths = PinnedPathList.Create(["/var/log", "/etc/nginx"]) };
|
|
|
|
HostKind.Instance.Changes(before, after).ShouldBe(["Pinned paths"]);
|
|
HostKind.Instance.Changes(before, before with { PinnedPaths = PinnedPathList.Empty })
|
|
.ShouldBe(["Pinned paths"]);
|
|
HostKind.Instance.Changes(before, before with { }).ShouldBeEmpty();
|
|
}
|
|
}
|