115 lines
4.7 KiB
C#
115 lines
4.7 KiB
C#
using FinalFactory.Rendezvous.Contracts;
|
|
using FinalFactory.Rendezvous.Server.Browser;
|
|
using FinalFactory.Rendezvous.Server.State;
|
|
|
|
namespace FinalFactory.Rendezvous.Tests.State;
|
|
|
|
internal sealed class ManualRendezvousClock : IWallClock, IMonotonicClock
|
|
{
|
|
public ManualRendezvousClock(DateTimeOffset? utcNow = null) =>
|
|
UtcNow = utcNow ?? new DateTimeOffset(2026, 7, 16, 0, 0, 0, TimeSpan.Zero);
|
|
|
|
public DateTimeOffset UtcNow { get; private set; }
|
|
public TimeSpan Elapsed { get; private set; }
|
|
|
|
public void Advance(TimeSpan duration)
|
|
{
|
|
Elapsed += duration;
|
|
UtcNow += duration;
|
|
}
|
|
|
|
public void MoveWall(TimeSpan duration) => UtcNow += duration;
|
|
}
|
|
|
|
internal sealed class EphemeralStateFixture
|
|
{
|
|
private int _sequence;
|
|
|
|
public EphemeralStateFixture(
|
|
EphemeralStoreOptions? options = null,
|
|
SessionChangeJournal? changes = null)
|
|
{
|
|
Clock = new();
|
|
Store = new(options ?? new EphemeralStoreOptions(), Clock, Clock, changes);
|
|
}
|
|
|
|
public ManualRendezvousClock Clock { get; }
|
|
public InMemoryEphemeralRendezvousStore Store { get; }
|
|
public TenantScope Scope { get; } = new(new GameId("space-game"), new EnvironmentId("test"));
|
|
|
|
public CreateListingCommand ListingCommand(
|
|
string owner = "publisher-1",
|
|
string? idempotencyKey = null,
|
|
string? requestFingerprint = null)
|
|
{
|
|
int sequence = Interlocked.Increment(ref _sequence);
|
|
return new(
|
|
idempotencyKey ?? $"register-{sequence}",
|
|
requestFingerprint ?? $"request-{sequence}",
|
|
new ListingDefinition
|
|
{
|
|
ListingId = NewListingId(),
|
|
LeaseId = NewLeaseId(),
|
|
Scope = Scope,
|
|
OwnerSubject = owner,
|
|
RegionId = new RegionId("eu-central"),
|
|
ProtocolVersion = 7,
|
|
BuildVersion = "1.2.3",
|
|
DisplayName = "Test host",
|
|
Visibility = ListingVisibility.Public,
|
|
TrustMode = PublisherTrustMode.ManagedDedicated,
|
|
CurrentPlayers = 1,
|
|
MaximumPlayers = 8,
|
|
Metadata = new Dictionary<string, string>(StringComparer.Ordinal) { ["mode"] = "coop" },
|
|
LeaseFingerprint = Fingerprint($"lease-{sequence}"),
|
|
HostPresenceHandle = NewHandle(),
|
|
HostPresenceFingerprint = Fingerprint($"presence-{sequence}"),
|
|
CapabilityDerivationSalt = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
|
});
|
|
}
|
|
|
|
public StoredListing CreateVisibleListing(out CreateListingCommand command)
|
|
{
|
|
command = ListingCommand();
|
|
StoreResult<StoredListing> created = Store.CreateListing(command);
|
|
Assert.True(created.Succeeded);
|
|
StoreResult<StoredListing> bound = Store.BindHostPresence(new(
|
|
command.Listing.HostPresenceHandle,
|
|
command.Listing.HostPresenceFingerprint,
|
|
PublicEndpoint(40_000),
|
|
LocalEndpoint(40_000)));
|
|
Assert.True(bound.Succeeded);
|
|
return bound.Value!;
|
|
}
|
|
|
|
public CreateJoinAttemptCommand AttemptCommand(StoredListing listing, string owner = "client-1")
|
|
{
|
|
int sequence = Interlocked.Increment(ref _sequence);
|
|
return new()
|
|
{
|
|
IdempotencyOwner = owner,
|
|
IdempotencyKey = $"join-{sequence}",
|
|
RequestFingerprint = $"join-request-{sequence}",
|
|
ClientSubject = owner,
|
|
AttemptId = NewAttemptId(),
|
|
MediationHandle = NewHandle(),
|
|
Scope = listing.Definition.Scope,
|
|
ListingId = listing.Definition.ListingId,
|
|
ProtocolVersion = listing.Definition.ProtocolVersion,
|
|
HostCapabilityFingerprint = Fingerprint($"host-{sequence}"),
|
|
ClientCapabilityFingerprint = Fingerprint($"client-{sequence}"),
|
|
ConnectionTicketFingerprint = Fingerprint($"ticket-{sequence}"),
|
|
CapabilityDerivationSalt = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
|
};
|
|
}
|
|
|
|
public static SecretFingerprint Fingerprint(string value) => new(value);
|
|
public static ObservedEndpoint PublicEndpoint(int port) => new(AddressFamilyKind.Ipv4, "203.0.113.10", port);
|
|
public static ObservedEndpoint OtherPublicEndpoint(int port) => new(AddressFamilyKind.Ipv4, "198.51.100.20", port);
|
|
public static ObservedEndpoint LocalEndpoint(int port) => new(AddressFamilyKind.Ipv4, "192.168.1.20", port);
|
|
public static SessionListingId NewListingId() => new(Guid.NewGuid());
|
|
public static LeaseId NewLeaseId() => new(Guid.NewGuid());
|
|
public static JoinAttemptId NewAttemptId() => new(Guid.NewGuid());
|
|
public static MediationHandle NewHandle() => new(Guid.NewGuid());
|
|
}
|