using DodoSSH.Contracts;
using DodoSSH.Domain;
namespace DodoSSH.Api.Tests;
///
/// The two entity-type enums have to agree, and nothing but this makes them.
///
///
///
/// SyncService converts between the wire's and the change log's
/// with a raw (ChangeEntityType)(int) cast in both directions. That
/// works only because two independently maintained enums in two assemblies happen to number their members
/// identically — and they do not even name them identically: Host = 1 against SshHost = 1.
///
///
/// If they ever drift, nothing fails loudly. Changes get filed in the log under a different item type's
/// name, and the next delta pull loads rows of the wrong type — or none — for entities the client asked
/// about. That is silent data loss on the sync path, which is precisely the failure this project has
/// designed everything else to avoid, so the alignment gets a test rather than a comment.
///
///
/// Numeric alignment only. The two lists are deliberately not aligned with
/// CryptoSpec.AadResourceType, which also carries None/User/Device/Vault and therefore numbers the
/// same item types differently — asserting three-way equality would be asserting something false.
///
///
public sealed class EntityTypeAlignmentTests
{
[Fact]
public void EveryWireEntityType_HasAChangeLogTypeWithTheSameValue()
{
var changeValues = Enum.GetValues().Select(value => (int)value).ToHashSet();
foreach (var wire in Enum.GetValues())
{
changeValues.ShouldContain(
(int)wire,
$"SyncEntityType.{wire} = {(int)wire} has no ChangeEntityType with that value, so "
+ "SyncService's cast would produce an undefined enum value.");
}
}
[Fact]
public void EveryChangeLogType_HasAWireTypeWithTheSameValue()
{
// The other direction matters just as much: a pull converts stored changes back to wire types, so a
// change-log type with no wire counterpart would be served to clients as an undefined enum.
var wireValues = Enum.GetValues().Select(value => (int)value).ToHashSet();
foreach (var change in Enum.GetValues())
{
wireValues.ShouldContain(
(int)change,
$"ChangeEntityType.{change} = {(int)change} has no SyncEntityType with that value.");
}
}
[Fact]
public void TheTwoEnums_HaveTheSameNumberOfMembers()
{
// Catches a member added to one list only, which the two checks above would miss if it reused a
// value already present in the other.
Enum.GetValues().Length.ShouldBe(Enum.GetValues().Length);
}
///
/// Spot-checked by name as well, because the pairing that is easiest to get wrong is the one whose names
/// differ. Someone adding an item type may reasonably assume the lists are name-matched, notice
/// Host has no Host on the other side, and renumber to "fix" it.
///
[Fact]
public void TheDifferentlyNamedPair_IsTheOneThatMatches()
{
((int)SyncEntityType.Host).ShouldBe((int)ChangeEntityType.SshHost);
((int)SyncEntityType.SshKey).ShouldBe((int)ChangeEntityType.SshKey);
}
}