Mit Roslyn umbenannt (Verweise folgen, Zeichenketten bleiben unberuehrt). Nicht umbenannt, weil gespeichert oder ueber die API gebunden (Stufe 4e): Properties, Record-Parameter, Enum-Member sowie die Parameter der Endpunkt-Handler (Routen-/Query-Bindung ueber den Namen). Die JSON-Felder anonymer Objekte bleiben ausdruecklich benannt (JsonFilter: pfad). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
97 lines
3.1 KiB
C#
97 lines
3.1 KiB
C#
using ClawdDotNet.Core.Backup;
|
|
using ClawdDotNet.Core.Config;
|
|
using ClawdDotNet.Core.Instances;
|
|
using Shouldly;
|
|
|
|
namespace ClawdDotNet.Manager.Tests;
|
|
|
|
/// <summary>
|
|
/// Tests for backup and restore in the manager (#530, stage 6).
|
|
/// </summary>
|
|
public sealed class BackupManagementTests : IDisposable
|
|
{
|
|
private readonly string _root = Path.Combine(
|
|
Path.GetTempPath(), "clawd-tests", "backup-" + Guid.NewGuid().ToString("N")[..8]);
|
|
|
|
public BackupManagementTests()
|
|
{
|
|
Directory.CreateDirectory(_root);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
try { Directory.Delete(_root, recursive: true); }
|
|
catch { }
|
|
}
|
|
|
|
[Fact]
|
|
public void BackupDirectory_resolves_under_Backups_by_default()
|
|
{
|
|
var instancePath = Path.Combine(_root, "TestInstance");
|
|
Directory.CreateDirectory(instancePath);
|
|
|
|
var config = new InstanceConfig { WorkingDirectory = instancePath };
|
|
var backupDir = InstanceLayout.ResolveBackupDirectory(config, instancePath);
|
|
|
|
backupDir.ShouldBe(Path.Combine(instancePath, "Backups"));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Backup_can_be_created_verified_and_restored()
|
|
{
|
|
var instancePath = Path.Combine(_root, "InstanceAlpha");
|
|
Directory.CreateDirectory(instancePath);
|
|
|
|
var settingsPath = Path.Combine(instancePath, "InstanceSettings.json");
|
|
await File.WriteAllTextAsync(settingsPath, """
|
|
{
|
|
"instanceId": "alpha-123",
|
|
"instanceName": "Alpha",
|
|
"workingDirectory": ""
|
|
}
|
|
""");
|
|
|
|
var testDataPath = Path.Combine(instancePath, "data.txt");
|
|
await File.WriteAllTextAsync(testDataPath, "Wichtige Testdaten");
|
|
|
|
var backupDir = InstanceLayout.ResolveBackupDirectory(
|
|
new InstanceConfig { WorkingDirectory = instancePath }, instancePath);
|
|
Directory.CreateDirectory(backupDir);
|
|
|
|
var zipPath = Path.Combine(backupDir, "backup_Alpha_test.zip");
|
|
|
|
var service = new BackupService();
|
|
var backupResult = await service.CreateAsync(instancePath, zipPath, new BackupOptions
|
|
{
|
|
Secrets = SecretMode.Exclude,
|
|
IncludeChatHistory = true,
|
|
IncludeLogs = false
|
|
});
|
|
|
|
File.Exists(zipPath).ShouldBeTrue();
|
|
backupResult.SizeBytes.ShouldBeGreaterThan(0);
|
|
|
|
// Check
|
|
var manifest = await service.InspectAsync(zipPath);
|
|
manifest.InstanceId.ShouldBe("alpha-123");
|
|
manifest.InstanceName.ShouldBe("Alpha");
|
|
manifest.Files.Count.ShouldBeGreaterThan(0);
|
|
|
|
// Modify a file in the target and check the restore
|
|
await File.WriteAllTextAsync(testDataPath, "Überschriebene Testdaten");
|
|
|
|
var restoreResult = await service.RestoreAsync(
|
|
zipPath,
|
|
instancePath,
|
|
new RestoreOptions { Overwrite = true });
|
|
|
|
restoreResult.Written.ShouldContain("data.txt");
|
|
var restoredContent = await File.ReadAllTextAsync(testDataPath);
|
|
restoredContent.ShouldBe("Wichtige Testdaten");
|
|
|
|
// Delete
|
|
File.Delete(zipPath);
|
|
File.Exists(zipPath).ShouldBeFalse();
|
|
}
|
|
}
|