using System.Text; using QVPN.Core; public static class SubscriptionTransportTests { public static async Task RunAsync(Func test) { await test("Subscription keeps distinct flow and fingerprint variants of one endpoint", () => { var nodes = Subscription.Parse(string.Join('\n', Link("xtls-rprx-vision", "chrome"), Link("", "chrome"), Link("xtls-rprx-vision", "firefox"), Link("xtls-rprx-vision-udp443", "chrome"))); Check(nodes.Count == 4 && nodes.Select(n => n.Id).Distinct().Count() == 4); Check(nodes.Select(n => (n.Flow, n.Fingerprint)).SequenceEqual(new[] { ("xtls-rprx-vision", "chrome"), ("", "chrome"), ("xtls-rprx-vision", "firefox"), ("xtls-rprx-vision-udp443", "chrome") })); }); await test("Subscription presentation and parameter order do not duplicate a transport", () => { var first = Link("xtls-rprx-vision", "chrome", "First location"); var same = Link("xtls-rprx-vision", "chrome", "Renamed location"); int question = same.IndexOf('?'), fragment = same.IndexOf('#'); same = same[..(question + 1)] + string.Join('&', same[(question + 1)..fragment].Split('&').Reverse()) + same[fragment..]; var nodes = Subscription.Parse(first + "\n" + same); Check(nodes.Count == 1 && nodes[0].Name == "First location"); Check(Subscription.Parse(same).Single().Id == nodes[0].Id); }); await test("Vision UDP443 is preserved in plain and encoded subscriptions and Xray", () => { string link = Link("xtls-rprx-vision-udp443", "chrome"); foreach (string text in new[] { link, Convert.ToBase64String(Encoding.UTF8.GetBytes(link)) }) { var node = Subscription.Parse(text).Single(); Check(node.Flow == "xtls-rprx-vision-udp443"); var user = XrayConfigBuilder.Build(node)["outbounds"]![0]!["settings"]!["vnext"]![0]!["users"]![0]!; Check(user["flow"]!.GetValue() == node.Flow); } }); await test("Subscription accepts only the exact supported flow names", () => { foreach (string flow in new[] { "xtls-rprx-vision-udp", "xtls-rprx-vision-udp443-extra", "XTLS-rprx-vision-udp443", "xtls-rprx-vision\n" }) { try { Subscription.Parse(Link(flow, "chrome")); } catch (InvalidDataException) { continue; } throw new InvalidOperationException("Unsupported subscription flow was accepted."); } }); } private static string Link(string flow, string fingerprint, string name = "Synthetic location") { string uuid = new Guid(Enumerable.Range(1, 16).Select(i => (byte)i).ToArray()).ToString(); string key = Convert.ToBase64String(Enumerable.Range(1, 32).Select(i => (byte)i).ToArray()).TrimEnd('=').Replace('+', '-').Replace('/', '_'); return $"vless://{uuid}@8.8.8.8:443?security=reality&type=tcp&encryption=none&pbk={key}&sid=abcd&sni=example.com&fp={fingerprint}&flow={Uri.EscapeDataString(flow)}#{Uri.EscapeDataString(name)}"; } private static void Check(bool condition) { if (!condition) throw new InvalidOperationException("Subscription transport regression."); } }