This commit is contained in:
DHR60
2026-08-19 01:54:51 +00:00
committed by GitHub
parent 7be264c65c
commit c9e843aa3b
11 changed files with 448 additions and 471 deletions
+49 -53
View File
@@ -1,103 +1,99 @@
using AwesomeAssertions;
using ServiceLib.Enums;
using ServiceLib.Handler.Fmt;
using ServiceLib.Models;
using Xunit;
namespace ServiceLib.Tests.Fmt;
public class FmtHandlerTests
{
[Fact]
public void GetShareUriAndResolveConfig_Vmess_ShouldRoundTripBasicFields()
[Test]
public async Task GetShareUriAndResolveConfig_Vmess_ShouldRoundTripBasicFields()
{
var source = CreateVmessProfile();
var resolved = ExportThenImport(source);
var resolved = await ExportThenImport(source);
resolved.ConfigType.Should().Be(EConfigType.VMess);
resolved.Remarks.Should().Be(source.Remarks);
resolved.Address.Should().Be(source.Address);
resolved.Port.Should().Be(source.Port);
resolved.Password.Should().Be(source.Password);
resolved.GetProtocolExtra().AlterId.Should().Be(source.GetProtocolExtra().AlterId);
await resolved.ConfigType.Should().BeEqualTo(EConfigType.VMess);
await resolved.Remarks.Should().BeEqualTo(source.Remarks);
await resolved.Address.Should().BeEqualTo(source.Address);
await resolved.Port.Should().BeEqualTo(source.Port);
await resolved.Password.Should().BeEqualTo(source.Password);
await resolved.GetProtocolExtra().AlterId.Should().BeEqualTo(source.GetProtocolExtra().AlterId);
}
[Fact]
public void GetShareUriAndResolveConfig_Vless_ShouldRoundTripBasicFields()
[Test]
public async Task GetShareUriAndResolveConfig_Vless_ShouldRoundTripBasicFields()
{
var source = CreateVlessProfile();
var resolved = ExportThenImport(source);
var resolved = await ExportThenImport(source);
resolved.ConfigType.Should().Be(EConfigType.VLESS);
resolved.Remarks.Should().Be(source.Remarks);
resolved.Address.Should().Be(source.Address);
resolved.Port.Should().Be(source.Port);
resolved.Password.Should().Be(source.Password);
resolved.GetProtocolExtra().VlessEncryption.Should().Be(Global.None);
await resolved.ConfigType.Should().BeEqualTo(EConfigType.VLESS);
await resolved.Remarks.Should().BeEqualTo(source.Remarks);
await resolved.Address.Should().BeEqualTo(source.Address);
await resolved.Port.Should().BeEqualTo(source.Port);
await resolved.Password.Should().BeEqualTo(source.Password);
await resolved.GetProtocolExtra().VlessEncryption.Should().BeEqualTo(Global.None);
}
[Fact]
public void GetShareUriAndResolveConfig_Shadowsocks_ShouldRoundTripBasicFields()
[Test]
public async Task GetShareUriAndResolveConfig_Shadowsocks_ShouldRoundTripBasicFields()
{
var source = CreateShadowsocksProfile();
var resolved = ExportThenImport(source);
var resolved = await ExportThenImport(source);
resolved.ConfigType.Should().Be(EConfigType.Shadowsocks);
resolved.Remarks.Should().Be(source.Remarks);
resolved.Address.Should().Be(source.Address);
resolved.Port.Should().Be(source.Port);
resolved.Password.Should().Be(source.Password);
resolved.GetProtocolExtra().SsMethod.Should().Be(source.GetProtocolExtra().SsMethod);
await resolved.ConfigType.Should().BeEqualTo(EConfigType.Shadowsocks);
await resolved.Remarks.Should().BeEqualTo(source.Remarks);
await resolved.Address.Should().BeEqualTo(source.Address);
await resolved.Port.Should().BeEqualTo(source.Port);
await resolved.Password.Should().BeEqualTo(source.Password);
await resolved.GetProtocolExtra().SsMethod.Should().BeEqualTo(source.GetProtocolExtra().SsMethod);
}
[Fact]
public void GetShareUriAndResolveConfig_Socks_ShouldRoundTripBasicFields()
[Test]
public async Task GetShareUriAndResolveConfig_Socks_ShouldRoundTripBasicFields()
{
var source = CreateSocksProfile();
var resolved = ExportThenImport(source);
var resolved = await ExportThenImport(source);
resolved.ConfigType.Should().Be(EConfigType.SOCKS);
resolved.Remarks.Should().Be(source.Remarks);
resolved.Address.Should().Be(source.Address);
resolved.Port.Should().Be(source.Port);
resolved.Username.Should().Be(source.Username);
resolved.Password.Should().Be(source.Password);
await resolved.ConfigType.Should().BeEqualTo(EConfigType.SOCKS);
await resolved.Remarks.Should().BeEqualTo(source.Remarks);
await resolved.Address.Should().BeEqualTo(source.Address);
await resolved.Port.Should().BeEqualTo(source.Port);
await resolved.Username.Should().BeEqualTo(source.Username);
await resolved.Password.Should().BeEqualTo(source.Password);
}
[Fact]
public void ResolveConfig_UnsupportedProtocol_ShouldReturnNull()
[Test]
public async Task ResolveConfig_UnsupportedProtocol_ShouldReturnNull()
{
var resolved = FmtHandler.ResolveConfig("not-a-share-uri", out var msg);
resolved.Should().BeNull();
msg.Should().NotBeNullOrWhiteSpace();
await resolved.Should().BeNull();
await msg.Should().NotBeNull();
await msg.Should().NotBeEmpty();
}
[Fact]
public void GetShareUri_UnsupportedConfigType_ShouldReturnNull()
[Test]
public async Task GetShareUri_UnsupportedConfigType_ShouldReturnNull()
{
var item = new ProfileItem { ConfigType = EConfigType.PolicyGroup, Remarks = "group", };
var uri = FmtHandler.GetShareUri(item);
uri.Should().BeNull();
await uri.Should().BeNull();
}
private static ProfileItem ExportThenImport(ProfileItem source)
private static async Task<ProfileItem> ExportThenImport(ProfileItem source)
{
var uri = FmtHandler.GetShareUri(source);
uri.Should().NotBeNullOrWhiteSpace();
uri!.StartsWith(Global.ProtocolShares[source.ConfigType], StringComparison.OrdinalIgnoreCase).Should()
await uri.Should().NotBeNull();
await uri.Should().NotBeEmpty();
await uri!.StartsWith(Global.ProtocolShares[source.ConfigType], StringComparison.OrdinalIgnoreCase).Should()
.BeTrue();
var resolved = FmtHandler.ResolveConfig(uri, out var msg);
resolved.Should().NotBeNull($"uri: {uri}, msg: {msg}");
await resolved.Should().NotBeNull().Because($"uri: {uri}, msg: {msg}");
return resolved!;
}
+37 -42
View File
@@ -1,32 +1,27 @@
using AwesomeAssertions;
using ServiceLib.Handler.Fmt;
using ServiceLib.Models.Dto;
using Xunit;
namespace ServiceLib.Tests.Fmt;
public class HyRealmTests
{
[Fact]
public void TryParse_ShouldParseValidRealm()
[Test]
public async Task TryParse_ShouldParseValidRealm()
{
var str = "realm://public@realm.hy2.io/57f9be7c-2810-4f5b-8cb9-260bc84d6c90?stun=example.stun:3478&stun=example2.stun:3478";
var result = HyRealm.TryParse(str, out var realm);
result.Should().BeTrue();
realm.Should().NotBeNull();
await result.Should().BeTrue();
await realm.Should().NotBeNull();
realm.IsHttp.Should().BeFalse();
realm.Token.Should().Be("public");
realm.RendezvousHost.Should().Be("realm.hy2.io");
realm.RendezvousPort.Should().Be(443);
realm.RealmName.Should().Be("57f9be7c-2810-4f5b-8cb9-260bc84d6c90");
realm.StunList.Should().HaveCount(2);
realm.StunList.Should().Contain("example.stun:3478");
realm.StunList.Should().Contain("example2.stun:3478");
await realm.IsHttp.Should().BeFalse();
await realm.Token.Should().BeEqualTo("public");
await realm.RendezvousHost.Should().BeEqualTo("realm.hy2.io");
await realm.RendezvousPort.Should().BeEqualTo(443);
await realm.RealmName.Should().BeEqualTo("57f9be7c-2810-4f5b-8cb9-260bc84d6c90");
await realm.StunList.Should().HaveCount(2);
await realm.StunList.Should().Contain("example.stun:3478");
await realm.StunList.Should().Contain("example2.stun:3478");
}
[Fact]
public void ToUri_ShouldGenerateValidUri()
[Test]
public async Task ToUri_ShouldGenerateValidUri()
{
var realm = new HyRealm(
IsHttp: false,
@@ -37,32 +32,32 @@ public class HyRealmTests
StunList: ["example.stun:3478", "example2.stun:3478"]
);
var uri = realm.ToUri();
uri.Should().Contain("realm://public@realm.hy2.io");
uri.Should().Contain("/57f9be7c-2810-4f5b-8cb9-260bc84d6c90");
uri.Should().Contain("stun=example.stun:3478");
uri.Should().Contain("stun=example2.stun:3478");
await uri.Should().Contain("realm://public@realm.hy2.io");
await uri.Should().Contain("/57f9be7c-2810-4f5b-8cb9-260bc84d6c90");
await uri.Should().Contain("stun=example.stun:3478");
await uri.Should().Contain("stun=example2.stun:3478");
}
[Fact]
public void GetShareUriAndResolveConfig_Hy2Realm_ShouldRoundTripBasicFields()
[Test]
public async Task GetShareUriAndResolveConfig_Hy2Realm_ShouldRoundTripBasicFields()
{
var str = "hysteria2+realm://mytoken@rendezvous.example.com/my-cabin-1f3a8c2e9b?auth=your_password&insecure=1&pinSHA256=deadbeef#remark";
var resolved = Hysteria2Fmt.ResolveRealm(str, out var msg);
resolved.Should().NotBeNull();
resolved.Password.Should().Be("your_password");
await resolved.Should().NotBeNull();
await resolved.Password.Should().BeEqualTo("your_password");
var result = HyRealm.TryParse(resolved.GetProtocolExtra().Hy2RealmUrl, out var realm);
result.Should().BeTrue();
realm.Should().NotBeNull();
realm.Token.Should().Be("mytoken");
await result.Should().BeTrue();
await realm.Should().NotBeNull();
await realm.Token.Should().BeEqualTo("mytoken");
// To uri
var uri = Hysteria2Fmt.ToUri(resolved);
uri.Should().Contain("hysteria2+realm://mytoken@rendezvous.example.com");
uri.Should().EndWith("#remark");
await uri.Should().Contain("hysteria2+realm://mytoken@rendezvous.example.com");
await uri.Should().EndWith("#remark");
}
[Fact]
public void ToServerUrl_ShouldIncludeSchemeForSingbox()
[Test]
public async Task ToServerUrl_ShouldIncludeSchemeForSingbox()
{
var realm = new HyRealm(
IsHttp: false,
@@ -73,19 +68,19 @@ public class HyRealmTests
StunList: ["turn.cloudflare.com:3478"]
);
realm.ToServerUrl().Should().Be("https://realm.hy2.io:443");
await realm.ToServerUrl().Should().BeEqualTo("https://realm.hy2.io:443");
}
[Fact]
public void ResolveRealm_Issue9635_ShouldProduceHttpsServerUrl()
[Test]
public async Task ResolveRealm_Issue9635_ShouldProduceHttpsServerUrl()
{
var str = "hysteria2+realm://public@realm.hy2.io/my-realm-id?auth=uuid&stun=turn.cloudflare.com%3A3478&sni=cloudflare.com&pinSHA256=xxx#Realm-Test";
var resolved = Hysteria2Fmt.ResolveRealm(str, out _);
resolved.Should().NotBeNull();
await resolved.Should().NotBeNull();
HyRealm.TryParse(resolved!.GetProtocolExtra().Hy2RealmUrl, out var realm).Should().BeTrue();
realm!.ToServerUrl().Should().StartWith("https://");
realm.ToServerUrl().Should().Contain("realm.hy2.io");
realm.StunList.Should().Contain("turn.cloudflare.com:3478");
await HyRealm.TryParse(resolved!.GetProtocolExtra().Hy2RealmUrl, out var realm).Should().BeTrue();
await realm!.ToServerUrl().Should().StartWith("https://");
await realm.ToServerUrl().Should().Contain("realm.hy2.io");
await realm.StunList.Should().Contain("turn.cloudflare.com:3478");
}
}
+9 -12
View File
@@ -1,15 +1,11 @@
using AwesomeAssertions;
using ServiceLib.Enums;
using ServiceLib.Handler.Fmt;
using ServiceLib.Tests.CoreConfig;
using Xunit;
namespace ServiceLib.Tests.Fmt;
public class InnerFmtTests
{
[Fact]
public void ToUriAndResolve_ShouldRoundTripPolicyGroupReferences()
[Test]
public async Task ToUriAndResolve_ShouldRoundTripPolicyGroupReferences()
{
var childA = CoreConfigTestFactory.CreateSocksNode(ECoreType.Xray, "child-a", "child-a");
var childB = CoreConfigTestFactory.CreateVmessNode(ECoreType.Xray, "child-b", "child-b");
@@ -19,19 +15,20 @@ public class InnerFmtTests
var uri = InnerFmt.ToUri([group, childA, childB]);
uri.Should().NotBeNullOrWhiteSpace();
await uri.Should().NotBeNull();
await uri.Should().NotBeEmpty();
var resolved = InnerFmt.Resolve(uri!, "sub-123");
resolved.Should().NotBeNull();
resolved.Should().HaveCount(3);
await resolved.Should().NotBeNull();
await resolved.Should().HaveCount(3);
var resolvedGroup = resolved!.Single(x => x.Remarks == group.Remarks);
var resolvedChildA = resolved.Single(x => x.Remarks == childA.Remarks);
var resolvedChildB = resolved.Single(x => x.Remarks == childB.Remarks);
resolvedGroup.ConfigType.Should().Be(EConfigType.PolicyGroup);
resolvedGroup.GetProtocolExtra().SubChildItems.Should().Be("sub-123");
resolvedGroup.GetProtocolExtra().ChildItems.Should().Be($"{resolvedChildA.IndexId},{resolvedChildB.IndexId}");
await resolvedGroup.ConfigType.Should().BeEqualTo(EConfigType.PolicyGroup);
await resolvedGroup.GetProtocolExtra().SubChildItems.Should().BeEqualTo("sub-123");
await resolvedGroup.GetProtocolExtra().ChildItems.Should().BeEqualTo($"{resolvedChildA.IndexId},{resolvedChildB.IndexId}");
}
}
@@ -1,13 +1,9 @@
using AwesomeAssertions;
using ServiceLib.Handler.Fmt;
using Xunit;
namespace ServiceLib.Tests.Fmt;
public class WireguardFmtTests
{
[Fact]
public void ResolveConfig_ShouldParsePeersAndIgnoreInlineComments()
[Test]
public async Task ResolveConfig_ShouldParsePeersAndIgnoreInlineComments()
{
const string config =
"""
@@ -29,19 +25,19 @@ public class WireguardFmtTests
var resolved = WireguardFmt.ResolveConfig(config);
resolved.Should().NotBeNull();
resolved.Should().HaveCount(2);
await resolved.Should().NotBeNull();
await resolved.Should().HaveCount(2);
var first = resolved![0];
first.Address.Should().Be("2001:db8::1");
first.Port.Should().Be(51820);
first.Password.Should().Be("interface-private-key");
first.GetProtocolExtra().WgReserved.Should().Be("1, 2, 3");
first.GetProtocolExtra().WgInterfaceAddress.Should().Be("10.0.0.2/32, fd00::2/128");
first.GetProtocolExtra().WgMtu.Should().Be(1420);
await first.Address.Should().BeEqualTo("2001:db8::1");
await first.Port.Should().BeEqualTo(51820);
await first.Password.Should().BeEqualTo("interface-private-key");
await first.GetProtocolExtra().WgReserved.Should().BeEqualTo("1, 2, 3");
await first.GetProtocolExtra().WgInterfaceAddress.Should().BeEqualTo("10.0.0.2/32, fd00::2/128");
await first.GetProtocolExtra().WgMtu.Should().BeEqualTo(1420);
var second = resolved[1];
second.Address.Should().Be("example.com");
second.Port.Should().Be(12345);
await second.Address.Should().BeEqualTo("example.com");
await second.Port.Should().BeEqualTo(12345);
}
}