using dy.net.model.dto; using dy.net.storage; using dy.net.Tests.TestInfrastructure; using Xunit; namespace dy.net.Tests; public class LiveWebDavTests { [LiveWebDavFact("ALIST")] public Task AList_ProbeContract() => ProbeAsync("ALIST"); [LiveWebDavFact("OPENLIST")] public Task OpenList_ProbeContract() => ProbeAsync("OPENLIST"); private static async Task ProbeAsync(string provider) { var prefix = $"DYSYNC_TEST_{provider}_"; var basePath = StoragePath.NormalizeRemote(Environment.GetEnvironmentVariable(prefix + "BASE_PATH")); if (basePath == "/" || !basePath.Contains("dysync-test", StringComparison.OrdinalIgnoreCase)) throw new InvalidOperationException($"{prefix}BASE_PATH 必须是包含 dysync-test 的非根目录"); var runPath = StoragePath.CombineRemote(basePath, "run-" + Guid.NewGuid().ToString("N")); var factory = new LiveHttpClientFactory(); using var host = await WebDavTestHost.CreateAsync(factory, factory, new WebDavTestRequest { Endpoint = Environment.GetEnvironmentVariable(prefix + "ENDPOINT"), BasePath = runPath, UserName = Environment.GetEnvironmentVariable(prefix + "USERNAME"), Password = Environment.GetEnvironmentVariable(prefix + "PASSWORD"), AllowInvalidCertificate = ReadBoolean(prefix + "ALLOW_INVALID_CERTIFICATE") }); try { var result = await host.Storage.ProbeAsync(host.Settings); Assert.True(result.Success, result.Message); } finally { // The host is configured to a random child of the explicitly safe test path. // Deleting "/" here deletes only that random child, never the WebDAV account root. await host.Storage.DeleteAsync("/"); } } private static bool ReadBoolean(string name) { var value = Environment.GetEnvironmentVariable(name); return value == "1" || bool.TryParse(value, out var parsed) && parsed; } } [AttributeUsage(AttributeTargets.Method)] internal sealed class LiveWebDavFactAttribute : FactAttribute { public LiveWebDavFactAttribute(string provider) { var prefix = $"DYSYNC_TEST_{provider}_"; var required = new[] { "ENDPOINT", "BASE_PATH", "USERNAME", "PASSWORD" }; var missing = required.Where(name => string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable(prefix + name))).ToList(); if (missing.Count > 0) Skip = $"未配置可选 {provider} 实测环境变量:{string.Join(", ", missing)}"; } }