using LehrerApp.Sync.Crypto; using Xunit; namespace LehrerApp.Sync.Tests; public sealed class SyncKeyRecoveryServiceTests { [Fact] public void CreateRecoveryFileUndRestoreFromFile_Roundtrip() { using var temp = new TempKeyFile(); var originalKey = SyncCrypto.GenerateKey(); var service = new SyncKeyRecoveryService(originalKey, temp.KeyPath); const string code = "TEST-CODE-4711"; var fileContent = service.CreateRecoveryFile(code); // Ein zweites Gerät (anderer aktuell geladener Schlüssel) löst dieselbe Datei ein. var redeemer = new SyncKeyRecoveryService(SyncCrypto.GenerateKey(), temp.KeyPath); redeemer.RestoreFromFile(fileContent, code); Assert.Equal(originalKey, SyncCrypto.LoadKey(temp.KeyPath)); } [Fact] public void RestoreFromFile_FalscherCode_WirftUndSchreibtKeyPathNicht() { using var temp = new TempKeyFile(); var service = new SyncKeyRecoveryService(SyncCrypto.GenerateKey(), temp.KeyPath); var fileContent = service.CreateRecoveryFile("RICHTIGER-CODE"); Assert.ThrowsAny(() => service.RestoreFromFile(fileContent, "FALSCHER-CODE")); Assert.Null(SyncCrypto.LoadKey(temp.KeyPath)); } [Fact] public void RestoreFromFile_UngueltigesDateiformat_WirftInvalidOperationException() { using var temp = new TempKeyFile(); var service = new SyncKeyRecoveryService(SyncCrypto.GenerateKey(), temp.KeyPath); Assert.Throws(() => service.RestoreFromFile("{}", "IRGENDEIN-CODE")); } private sealed class TempKeyFile : IDisposable { private readonly string _directory = Path.Combine( Path.GetTempPath(), $"lehrerapp-synckeyrecovery-tests-{Guid.NewGuid():N}"); public string KeyPath { get; } public TempKeyFile() { Directory.CreateDirectory(_directory); KeyPath = Path.Combine(_directory, "sync.key"); } public void Dispose() { if (Directory.Exists(_directory)) Directory.Delete(_directory, recursive: true); } } }