public void Add_Update_Remove_Group_ReturnsResult() { using var nodes = new Nodes(); nodes.AddGroup("MyGroup"); nodes.AddGroup("MyGroupWithPlugin"); nodes.AddNodeToGroup("MyGroup", "MyNode", "github.com", 443); nodes.AddNodeToGroup("MyGroupWithPlugin", "MyNodeWithPlugin", "github.com", 443, "v2ray-plugin", "server;tls;host=github.com"); var users = new Users(); users.AddUser("root"); users.AddUser("http"); Assert.True(users.UserDict.ContainsKey("root")); Assert.True(users.UserDict.ContainsKey("http")); // Add var successAdd = users.AddUserToGroup("root", "MyGroup"); var anotherSuccessAdd = users.AddUserToGroup("http", "MyGroup"); var yetAnotherSuccessAdd = users.AddUserToGroup("root", "MyGroupWithPlugin"); var duplicateAdd = users.AddUserToGroup("root", "MyGroup"); var badUserAdd = users.AddUserToGroup("nobody", "MyGroup"); var rootUserMemberships = users.UserDict["root"].Memberships; var httpUserMemberships = users.UserDict["http"].Memberships; var rootMyGroupMembership = rootUserMemberships["MyGroup"]; var rootMyGroupWithPluginMembership = rootUserMemberships["MyGroupWithPlugin"]; var httpMyGroupMembership = httpUserMemberships["MyGroup"]; Assert.Equal(0, successAdd); Assert.Equal(0, anotherSuccessAdd); Assert.Equal(0, yetAnotherSuccessAdd); Assert.Equal(1, duplicateAdd); Assert.Equal(-1, badUserAdd); Assert.True(rootUserMemberships.ContainsKey("MyGroup")); Assert.True(rootUserMemberships.ContainsKey("MyGroupWithPlugin")); Assert.True(httpUserMemberships.ContainsKey("MyGroup")); // Update users.UpdateCredentialGroupsForAllUsers("MyGroup", "MyGroupNew"); Assert.False(rootUserMemberships.ContainsKey("MyGroup")); Assert.False(httpUserMemberships.ContainsKey("MyGroup")); Assert.True(rootUserMemberships.ContainsKey("MyGroupNew")); Assert.True(rootUserMemberships.ContainsKey("MyGroupWithPlugin")); Assert.True(httpUserMemberships.ContainsKey("MyGroupNew")); Assert.Equal(rootMyGroupMembership, rootUserMemberships["MyGroupNew"]); Assert.Equal(rootMyGroupWithPluginMembership, rootUserMemberships["MyGroupWithPlugin"]); Assert.Equal(httpMyGroupMembership, httpUserMemberships["MyGroupNew"]); // Remove var successRemoval = users.RemoveUserFromGroup("root", "MyGroupWithPlugin"); var nonExistingUserRemoval = users.RemoveUserFromGroup("nobody", "MyGroup"); var nonExistingGroupRemoval = users.RemoveUserFromGroup("root", "MyGroupWithoutPlugin"); Assert.Equal(0, successRemoval); Assert.Equal(-2, nonExistingUserRemoval); Assert.Equal(1, nonExistingGroupRemoval); Assert.Single(rootUserMemberships); }
public void Add_Remove_Credential_ReturnsResult() { using var nodes = new Nodes(); nodes.AddGroup("MyGroup"); nodes.AddGroup("MyGroupWithPlugin"); nodes.AddNodeToGroup("MyGroup", "MyNode", "github.com", 443); nodes.AddNodeToGroup("MyGroupWithPlugin", "MyNodeWithPlugin", "github.com", 443, "v2ray-plugin", "server;tls;host=github.com"); var users = new Users(); users.AddUser("root"); users.AddUser("http"); Assert.True(users.UserDict.ContainsKey("root")); Assert.True(users.UserDict.ContainsKey("http")); // Add var successAdd = users.AddCredentialToUser("root", "MyGroup", "Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTp5bWdoaVIjNzVUTnFwYQ"); var anotherSuccessAdd = users.AddCredentialToUser("http", "MyGroup", "YWVzLTEyOC1nY206dEsqc2shOU44QDg2OlVWbWM"); var yetAnotherSuccessAdd = users.AddCredentialToUser("root", "MyGroupWithPlugin", "YWVzLTEyOC1nY206dkFBbiY4a1I6JGlBRTQ0JA"); var duplicateAdd = users.AddCredentialToUser("root", "MyGroup", "aes-256-gcm", "wLhN2STZ"); var badUserAdd = users.AddCredentialToUser("nobody", "MyGroup", "aes-256-gcm", "wLhN2STZ"); var badUserinfoAdd = users.AddCredentialToUser("http", "MyGroupWithPlugin", "PR6Lf9UR22C5LNBhzEcpsWxd6WpsaeSs"); var rootUserMemberships = users.UserDict["root"].Memberships; var httpUserMemberships = users.UserDict["http"].Memberships; Assert.Equal(0, successAdd); Assert.Equal(0, anotherSuccessAdd); Assert.Equal(0, yetAnotherSuccessAdd); Assert.Equal(2, duplicateAdd); Assert.Equal(-1, badUserAdd); Assert.Equal(-2, badUserinfoAdd); Assert.True(rootUserMemberships.ContainsKey("MyGroup")); Assert.True(rootUserMemberships.ContainsKey("MyGroupWithPlugin")); Assert.True(httpUserMemberships.ContainsKey("MyGroup")); Assert.True(rootUserMemberships["MyGroup"].HasCredential); Assert.True(rootUserMemberships["MyGroupWithPlugin"].HasCredential); Assert.True(httpUserMemberships["MyGroup"].HasCredential); // Remove var successRemoval = users.RemoveCredentialFromUser("root", "MyGroupWithPlugin"); var nonExistingUserRemoval = users.RemoveCredentialFromUser("nobody", "MyGroupNew"); var nonExistingGroupRemoval = users.RemoveCredentialFromUser("root", "MyGroupWithoutPlugin"); Assert.Equal(0, successRemoval); Assert.Equal(-2, nonExistingUserRemoval); Assert.Equal(-1, nonExistingGroupRemoval); Assert.True(rootUserMemberships["MyGroup"].HasCredential); Assert.True(httpUserMemberships["MyGroup"].HasCredential); Assert.False(rootUserMemberships["MyGroupWithPlugin"].HasCredential); // Remove from all users.RemoveCredentialsFromAllUsers(new string[] { "MyGroup" }); Assert.False(rootUserMemberships["MyGroup"].HasCredential); Assert.False(httpUserMemberships["MyGroup"].HasCredential); }
public void Add_Remove_Node_ReturnsResult() { using var nodes = new Nodes(); nodes.AddGroup("A"); nodes.AddGroup("B"); nodes.AddGroup("C"); // Add var successAdd = nodes.AddNodeToGroup("A", "MyNode0", "github.com", 443); var successAddWithPlugin = nodes.AddNodeToGroup("B", "MyNode1", "github.com", 443, "v2ray-plugin", "1.0", "server;tls;host=github.com", "-vvvvvv"); var successAddWithOwnerAndTags = nodes.AddNodeToGroup("C", "MyNode2", "github.com", 443, null, null, null, null, "a2865866-5dc8-4eae-9772-692d10c274df", "direct", "US"); var duplicateAdd = nodes.AddNodeToGroup("A", "MyNode0", "github.com", 443); var badGroupAdd = nodes.AddNodeToGroup("D", "MyNode0", "github.com", 443); Assert.Equal(0, successAdd); Assert.Equal(0, successAddWithPlugin); Assert.Equal(0, successAddWithOwnerAndTags); Assert.Equal(-1, duplicateAdd); Assert.Equal(-2, badGroupAdd); Assert.True(nodes.Groups.ContainsKey("A")); Assert.True(nodes.Groups["A"].NodeDict.ContainsKey("MyNode0")); var addedNodeInA = nodes.Groups["A"].NodeDict["MyNode0"]; Assert.Equal("github.com", addedNodeInA.Host); Assert.Equal(443, addedNodeInA.Port); Assert.True(nodes.Groups.ContainsKey("B")); Assert.True(nodes.Groups["B"].NodeDict.ContainsKey("MyNode1")); var addedNodeInB = nodes.Groups["B"].NodeDict["MyNode1"]; Assert.Equal("github.com", addedNodeInB.Host); Assert.Equal(443, addedNodeInB.Port); Assert.Equal("v2ray-plugin", addedNodeInB.Plugin); Assert.Equal("1.0", addedNodeInB.PluginVersion); Assert.Equal("server;tls;host=github.com", addedNodeInB.PluginOpts); Assert.Equal("-vvvvvv", addedNodeInB.PluginArguments); Assert.True(nodes.Groups.ContainsKey("C")); Assert.True(nodes.Groups["C"].NodeDict.ContainsKey("MyNode2")); var addedNodeInC = nodes.Groups["C"].NodeDict["MyNode2"]; Assert.Equal("github.com", addedNodeInC.Host); Assert.Equal(443, addedNodeInC.Port); Assert.Equal("a2865866-5dc8-4eae-9772-692d10c274df", addedNodeInC.OwnerUuid); Assert.Equal(new string[] { "direct", "US", }, addedNodeInC.Tags); // Remove var successRemoval = nodes.RemoveNodeFromGroup("A", "MyNode0"); var nonExistingNodeRemoval = nodes.RemoveNodeFromGroup("A", "MyNode1"); var nonExistingGroupRemoval = nodes.RemoveNodeFromGroup("D", "MyNode0"); Assert.Equal(0, successRemoval); Assert.Equal(-1, nonExistingNodeRemoval); Assert.Equal(-2, nonExistingGroupRemoval); Assert.True(nodes.Groups.ContainsKey("A")); Assert.Empty(nodes.Groups["A"].NodeDict); }
public void Activate_Deactivate_Nodes_OnlineConfig_SSLinks() { var settings = new Settings(); using var nodes = new Nodes(); nodes.AddGroup("MyGroup"); nodes.AddGroup("MyGroupWithPlugin"); nodes.AddNodeToGroup("MyGroup", "MyNode", "github.com", 443); nodes.AddNodeToGroup("MyGroupWithPlugin", "MyNodeWithPlugin", "github.com", 443, "v2ray-plugin", "server;tls;host=github.com"); var users = new Users(); users.AddUser("root"); users.AddCredentialToUser("root", "MyGroup", "Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTp5bWdoaVIjNzVUTnFwYQ"); users.AddCredentialToUser("root", "MyGroupWithPlugin", "aes-256-gcm", "wLhN2STZ"); var user = users.UserDict.First(); // Initial status: all activated var userOnlineConfigDict = SIP008StaticGen.GenerateForUser(user, users, nodes, settings); var userSsLinks = user.Value.GetSSUris(nodes); Assert.Equal(2, userOnlineConfigDict.First().Value.Servers.Count); Assert.Equal(2, userSsLinks.Count); // Deactivate first node nodes.Groups["MyGroup"].NodeDict["MyNode"].Deactivated = true; userOnlineConfigDict = SIP008StaticGen.GenerateForUser(user, users, nodes, settings); userSsLinks = user.Value.GetSSUris(nodes); Assert.Single(userOnlineConfigDict.First().Value.Servers); Assert.Single(userSsLinks); // Reactivate first node and deactivate second node nodes.Groups["MyGroup"].NodeDict["MyNode"].Deactivated = false; nodes.Groups["MyGroupWithPlugin"].NodeDict["MyNodeWithPlugin"].Deactivated = true; userOnlineConfigDict = SIP008StaticGen.GenerateForUser(user, users, nodes, settings); userSsLinks = user.Value.GetSSUris(nodes); Assert.Single(userOnlineConfigDict.First().Value.Servers); Assert.Single(userSsLinks); }
public void Rename_Group_ReturnsResult(string[] groupsToAdd, string oldName, string newName, int expectedResult) { using var nodes = new Nodes(); foreach (var group in groupsToAdd) { nodes.AddGroup(group); } var count = nodes.Groups.Count; var oldNameExists = nodes.Groups.TryGetValue(oldName, out var targetGroup); var result = nodes.RenameGroup(oldName, newName); Assert.Equal(expectedResult, result); Assert.Equal(count, nodes.Groups.Count); // Verify Group object if (oldNameExists) { var currentName = result == 0 ? newName : oldName; Assert.Equal(targetGroup, nodes.Groups[currentName]); } }
public void Add_Remove_Groups(string[] groupsToAdd, int[] expectedAddResults, string[] groupsToRemove, bool[] expectedRemovalResults, string[] expectedRemainingGroups) { using var nodes = new Nodes(); var addResults = new int[groupsToAdd.Length]; for (var i = 0; i < groupsToAdd.Length; i++) { addResults[i] = nodes.AddGroup(groupsToAdd[i]); } var removalResults = new bool[groupsToRemove.Length]; for (var i = 0; i < groupsToRemove.Length; i++) { removalResults[i] = nodes.RemoveGroup(groupsToRemove[i]); } var remainingGroups = nodes.Groups.Select(x => x.Key).ToArray(); Assert.Equal(expectedAddResults, addResults); Assert.Equal(expectedRemovalResults, removalResults); Assert.Equal(expectedRemainingGroups, remainingGroups); }
public void Rename_Node_ReturnsResult(string addToGroup, string[] nodesToAdd, string group, string oldName, string newName, int expectedResult) { using var nodes = new Nodes(); nodes.AddGroup(addToGroup); foreach (var nodeName in nodesToAdd) { nodes.AddNodeToGroup(addToGroup, nodeName, "github.com", 443); } var nodeDict = nodes.Groups[addToGroup].NodeDict; var count = nodeDict.Count; var oldNameExists = nodeDict.TryGetValue(oldName, out var node); var result = nodes.RenameNodeInGroup(group, oldName, newName); Assert.Equal(expectedResult, result); Assert.Equal(count, nodeDict.Count); // Verify Node object if (oldNameExists) { var currentName = result == 0 ? newName : oldName; Assert.Equal(node, nodeDict[currentName]); } }
public async Task Save_Clean_OnlineConfig_ForAllUsers() { var settings = new Settings(); var directory = FileHelper.GetAbsolutePath(settings.OnlineConfigOutputDirectory); using var nodes = new Nodes(); nodes.AddGroup("MyGroup"); nodes.AddGroup("MyGroupWithPlugin"); nodes.AddNodeToGroup("MyGroup", "MyNode", "github.com", 443); nodes.AddNodeToGroup("MyGroupWithPlugin", "MyNodeWithPlugin", "github.com", 443, "v2ray-plugin", "server;tls;host=github.com"); var users = new Users(); users.AddUser("root"); users.AddUser("http"); users.AddUser("nobody"); users.AddCredentialToUser("root", "MyGroup", "Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTp5bWdoaVIjNzVUTnFwYQ"); users.AddCredentialToUser("http", "MyGroupWithPlugin", "aes-256-gcm", "wLhN2STZ"); var rootUser = users.UserDict["root"]; var httpUser = users.UserDict["http"]; var nobodyUser = users.UserDict["nobody"]; // Disable delivery by group settings.OnlineConfigDeliverByGroup = false; // Save var genResult = await SIP008StaticGen.GenerateAndSave(users, nodes, settings); Assert.Null(genResult); Assert.True(Directory.Exists(directory)); foreach (var user in users.UserDict.Values) { Assert.True(File.Exists($"{directory}/{user.Uuid}.json")); } // Clean SIP008StaticGen.Remove(users, settings); Assert.True(Directory.Exists(directory)); foreach (var user in users.UserDict.Values) { Assert.False(File.Exists($"{directory}/{user.Uuid}.json")); } // Delete working directory. Directory.Delete(directory); // Enable delivery by group settings.OnlineConfigDeliverByGroup = true; // Save var genByGroupResult = await SIP008StaticGen.GenerateAndSave(users, nodes, settings); Assert.Null(genByGroupResult); Assert.True(Directory.Exists(directory)); foreach (var user in users.UserDict.Values) { Assert.True(File.Exists($"{directory}/{user.Uuid}.json")); } Assert.True(Directory.Exists($"{directory}/{rootUser.Uuid}")); Assert.True(File.Exists($"{directory}/{rootUser.Uuid}/MyGroup.json")); Assert.False(File.Exists($"{directory}/{rootUser.Uuid}/MyGroupWithPlugin.json")); Assert.True(Directory.Exists($"{directory}/{httpUser.Uuid}")); Assert.False(File.Exists($"{directory}/{httpUser.Uuid}/MyGroup.json")); Assert.True(File.Exists($"{directory}/{httpUser.Uuid}/MyGroupWithPlugin.json")); Assert.False(Directory.Exists($"{directory}/{nobodyUser.Uuid}")); // Clean SIP008StaticGen.Remove(users, settings); Assert.True(Directory.Exists(directory)); foreach (var user in users.UserDict.Values) { Assert.False(File.Exists($"{directory}/{user.Uuid}.json")); } Assert.False(Directory.Exists($"{directory}/{rootUser.Uuid}")); Assert.False(Directory.Exists($"{directory}/{httpUser.Uuid}")); Assert.False(Directory.Exists($"{directory}/{nobodyUser.Uuid}")); // Delete working directory. Directory.Delete(directory); }
public void Generate_OnlineConfig_Properties() { var settings = new Settings(); using var nodes = new Nodes(); nodes.AddGroup("MyGroup"); nodes.AddGroup("MyGroupWithPlugin"); var users = new Users(); users.AddUser("root"); users.AddCredentialToUser("root", "MyGroup", "Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTp5bWdoaVIjNzVUTnFwYQ"); users.AddCredentialToUser("root", "MyGroupWithPlugin", "aes-256-gcm", "wLhN2STZ"); var user = users.UserDict.First(); nodes.AddNodeToGroup("MyGroup", "MyNode", "github.com", 443); nodes.AddNodeToGroup("MyGroupWithPlugin", "MyNodeWithPlugin", "github.com", 443, "v2ray-plugin", "1.0", "server;tls;host=github.com", "-vvvvvv", user.Value.Uuid, "test"); var myNode = nodes.Groups["MyGroup"].NodeDict["MyNode"]; var myNodeWithPlugin = nodes.Groups["MyGroupWithPlugin"].NodeDict["MyNodeWithPlugin"]; settings.OnlineConfigDeliverByGroup = false; var userSingleOnlineConfigDict = SIP008StaticGen.GenerateForUser(user, users, nodes, settings); settings.OnlineConfigDeliverByGroup = true; var userPerGroupOnlineConfigDict = SIP008StaticGen.GenerateForUser(user, users, nodes, settings); // userSingleOnlineConfigDict Assert.Single(userSingleOnlineConfigDict); var userSingleOnlineConfig = userPerGroupOnlineConfigDict[user.Value.Uuid]; // userSingleOnlineConfig Assert.Equal(1, userSingleOnlineConfig.Version); Assert.Equal("root", userSingleOnlineConfig.Username); Assert.Equal(user.Value.Uuid, userSingleOnlineConfig.Id); Assert.Null(userSingleOnlineConfig.BytesUsed); Assert.Null(userSingleOnlineConfig.BytesRemaining); Assert.Equal(2, userSingleOnlineConfig.Servers.Count); var singleServer = userSingleOnlineConfig.Servers[0]; Assert.Equal(myNode.Uuid, singleServer.Id); Assert.Equal("MyNode", singleServer.Name); Assert.Equal("github.com", singleServer.Host); Assert.Equal(443, singleServer.Port); Assert.Equal("chacha20-ietf-poly1305", singleServer.Method); Assert.Equal("ymghiR#75TNqpa", singleServer.Password); Assert.Null(singleServer.PluginName); Assert.Null(singleServer.PluginVersion); Assert.Null(singleServer.PluginOptions); Assert.Null(singleServer.PluginArguments); Assert.Equal("MyGroup", singleServer.Group); Assert.Null(singleServer.Owner); Assert.Null(singleServer.Tags); var singleServerWithPlugin = userSingleOnlineConfig.Servers[1]; Assert.Equal(myNodeWithPlugin.Uuid, singleServerWithPlugin.Id); Assert.Equal("MyNodeWithPlugin", singleServerWithPlugin.Name); Assert.Equal("github.com", singleServerWithPlugin.Host); Assert.Equal(443, singleServerWithPlugin.Port); Assert.Equal("aes-256-gcm", singleServerWithPlugin.Method); Assert.Equal("wLhN2STZ", singleServerWithPlugin.Password); Assert.Equal("v2ray-plugin", singleServerWithPlugin.PluginName); Assert.Equal("1.0", singleServerWithPlugin.PluginVersion); Assert.Equal("server;tls;host=github.com", singleServerWithPlugin.PluginOptions); Assert.Equal("-vvvvvv", singleServerWithPlugin.PluginArguments); Assert.Equal("root", singleServerWithPlugin.Owner); Assert.Single(singleServerWithPlugin.Tags, "test"); // userPerGroupOnlineConfigDict Assert.Equal(3, userPerGroupOnlineConfigDict.Count); var userOnlineConfig = userPerGroupOnlineConfigDict[user.Value.Uuid]; var userMyGroupOnlineConfig = userPerGroupOnlineConfigDict[$"{user.Value.Uuid}/MyGroup"]; var userMyGroupWithPluginOnlineConfig = userPerGroupOnlineConfigDict[$"{user.Value.Uuid}/MyGroupWithPlugin"]; // userOnlineConfig Assert.Equal(1, userOnlineConfig.Version); Assert.Equal("root", userOnlineConfig.Username); Assert.Equal(user.Value.Uuid, userOnlineConfig.Id); Assert.Null(userOnlineConfig.BytesUsed); Assert.Null(userOnlineConfig.BytesRemaining); Assert.Equal(2, userOnlineConfig.Servers.Count); var server = userOnlineConfig.Servers[0]; Assert.Equal(myNode.Uuid, server.Id); Assert.Equal("MyNode", server.Name); Assert.Equal("github.com", server.Host); Assert.Equal(443, server.Port); Assert.Equal("chacha20-ietf-poly1305", server.Method); Assert.Equal("ymghiR#75TNqpa", server.Password); Assert.Null(server.PluginName); Assert.Null(server.PluginVersion); Assert.Null(server.PluginOptions); Assert.Null(server.PluginArguments); Assert.Equal("MyGroup", server.Group); Assert.Null(server.Owner); Assert.Null(server.Tags); var serverWithPlugin = userOnlineConfig.Servers[1]; Assert.Equal(myNodeWithPlugin.Uuid, serverWithPlugin.Id); Assert.Equal("MyNodeWithPlugin", serverWithPlugin.Name); Assert.Equal("github.com", serverWithPlugin.Host); Assert.Equal(443, serverWithPlugin.Port); Assert.Equal("aes-256-gcm", serverWithPlugin.Method); Assert.Equal("wLhN2STZ", serverWithPlugin.Password); Assert.Equal("v2ray-plugin", serverWithPlugin.PluginName); Assert.Equal("1.0", serverWithPlugin.PluginVersion); Assert.Equal("server;tls;host=github.com", serverWithPlugin.PluginOptions); Assert.Equal("-vvvvvv", serverWithPlugin.PluginArguments); Assert.Equal("root", serverWithPlugin.Owner); Assert.Single(serverWithPlugin.Tags, "test"); // userMyGroupOnlineConfig Assert.Equal(1, userMyGroupOnlineConfig.Version); Assert.Equal("root", userMyGroupOnlineConfig.Username); Assert.Equal(user.Value.Uuid, userMyGroupOnlineConfig.Id); Assert.Null(userMyGroupOnlineConfig.BytesUsed); Assert.Null(userMyGroupOnlineConfig.BytesRemaining); Assert.Single(userMyGroupOnlineConfig.Servers); var serverMyGroup = userMyGroupOnlineConfig.Servers[0]; Assert.Equal(myNode.Uuid, serverMyGroup.Id); Assert.Equal("MyNode", serverMyGroup.Name); Assert.Equal("github.com", serverMyGroup.Host); Assert.Equal(443, serverMyGroup.Port); Assert.Equal("chacha20-ietf-poly1305", serverMyGroup.Method); Assert.Equal("ymghiR#75TNqpa", serverMyGroup.Password); Assert.Null(serverMyGroup.PluginName); Assert.Null(serverMyGroup.PluginVersion); Assert.Null(serverMyGroup.PluginOptions); Assert.Null(serverMyGroup.PluginArguments); Assert.Equal("MyGroup", serverMyGroup.Group); Assert.Null(serverMyGroup.Owner); Assert.Null(serverMyGroup.Tags); // userMyGroupWithPluginOnlineConfig Assert.Equal(1, userMyGroupWithPluginOnlineConfig.Version); Assert.Equal("root", userMyGroupWithPluginOnlineConfig.Username); Assert.True(Guid.TryParse(userMyGroupWithPluginOnlineConfig.Id, out _)); Assert.Single(userMyGroupWithPluginOnlineConfig.Servers); var serverMyGroupWithPlugin = userMyGroupWithPluginOnlineConfig.Servers[0]; Assert.Equal(myNodeWithPlugin.Uuid, serverMyGroupWithPlugin.Id); Assert.Equal("MyNodeWithPlugin", serverMyGroupWithPlugin.Name); Assert.Equal("github.com", serverMyGroupWithPlugin.Host); Assert.Equal(443, serverMyGroupWithPlugin.Port); Assert.Equal("aes-256-gcm", serverMyGroupWithPlugin.Method); Assert.Equal("wLhN2STZ", serverMyGroupWithPlugin.Password); Assert.Equal("v2ray-plugin", serverMyGroupWithPlugin.PluginName); Assert.Equal("1.0", serverMyGroupWithPlugin.PluginVersion); Assert.Equal("server;tls;host=github.com", serverMyGroupWithPlugin.PluginOptions); Assert.Equal("-vvvvvv", serverMyGroupWithPlugin.PluginArguments); Assert.Equal("root", serverMyGroupWithPlugin.Owner); Assert.Single(serverMyGroupWithPlugin.Tags, "test"); }