using SQLInsight.Core.Servers; using SQLInsight.Servers; using SQLInsight.Servers.Synthetic; namespace SQLInsight.Servers.Tests; public class ServerErrorTests { private static ServerAccessException Describe(uint? code, string? kind = null, string message = "Windows' tekst", string? area = ServerArea.Services, string protocol = "WS-Man") => ServerErrors.Describe(code, kind, message, area, "aos01", @"FIRMA\AGENT01$", protocol); [Fact] public void Access_denied_names_the_right_and_the_script_never_local_admin() { var error = Describe(ServerErrors.AccessDenied); Assert.Equal(ServerAccessProblem.AccessDenied, error.Problem); Assert.Contains(@"FIRMA\AGENT01$", error.Message, StringComparison.Ordinal); Assert.Contains("Service Control Manager", error.Message, StringComparison.Ordinal); Assert.Contains("grant-windows-server.ps1", error.Message, StringComparison.Ordinal); Assert.Contains("ikke være lokal administrator", error.Message, StringComparison.Ordinal); Assert.Contains("0x80070005", error.Message, StringComparison.Ordinal); Assert.Contains("Event Log Readers", Describe(ServerErrors.WbemAccessDenied, area: ServerArea.Events).Message, StringComparison.Ordinal); Assert.Contains("Distributed COM Users", Describe(null, "AccessDenied", area: null, protocol: "DCOM").Message, StringComparison.Ordinal); Assert.Contains("Remote Management Users", Describe(null, "AccessDenied", area: null, protocol: "WS-Man").Message, StringComparison.Ordinal); } [Fact] public void Missing_namespace_unreachable_and_timeouts() { var tasks = Describe(ServerErrors.InvalidNamespace, "InvalidNamespace", area: ServerArea.Tasks); Assert.Equal(ServerAccessProblem.NotAvailable, tasks.Problem); Assert.Contains("Windows Server 2012", tasks.Message, StringComparison.Ordinal); var rpc = Describe(ServerErrors.RpcUnavailable, "Failed", "The RPC server is unavailable.", area: null, protocol: "DCOM"); Assert.Equal(ServerAccessProblem.Unreachable, rpc.Problem); Assert.Contains("TCP 135", rpc.Message, StringComparison.Ordinal); var winrm = Describe(null, "Failed", "The client cannot connect to the destination specified in the request. ... WinRM ...", area: null); Assert.Equal(ServerAccessProblem.Unreachable, winrm.Problem); Assert.Contains("5985", winrm.Message, StringComparison.Ordinal); Assert.Equal(ServerAccessProblem.Timeout, Describe(ServerErrors.MiTimeout, "Failed", "Timed out").Problem); Assert.Equal(ServerAccessProblem.Other, Describe(0x80004005, "Failed", "Unspecified error").Problem); } [Fact] public void Hints_by_problem() { Assert.Contains("tildelingsscriptet", WindowsServerTester.Hint(ServerAccessProblem.AccessDenied), StringComparison.Ordinal); Assert.Contains("5985", WindowsServerTester.Hint(ServerAccessProblem.Unreachable), StringComparison.Ordinal); Assert.Equal(UnsupportedWindowsServerSource.Reason, WindowsServerTester.Hint(ServerAccessProblem.NotSupported)); } [Fact] public async Task An_agent_not_on_windows_says_so() { var error = await Assert.ThrowsAsync(() => new UnsupportedWindowsServerSource().ConnectAsync("aos01", CancellationToken.None)); var test = await WindowsServerTester.TestAsync(new UnsupportedWindowsServerSource(), "aos01", null, DateTimeOffset.UtcNow, CancellationToken.None); Assert.Equal(ServerAccessProblem.NotSupported, error.Problem); Assert.False(test.Reachable); Assert.Equal(UnsupportedWindowsServerSource.Reason, test.Error); } } public class CimQueryTests { [Fact] public void Wql_literals_and_times() { Assert.Equal(@"AOS60$01", CimQueries.Wql("AOS60$01")); Assert.Equal(@"a\\b\'c", CimQueries.Wql(@"a\b'c")); Assert.Equal("SELECT Name, DisplayName, State, StartMode, ExitCode FROM Win32_Service WHERE Name = 'O\\'Brien'", CimQueries.SingleServiceQuery("O'Brien")); var at = new DateTimeOffset(2026, 10, 2, 14, 5, 6, TimeSpan.FromHours(2)); Assert.Equal("20261002120506.000000+000", CimQueries.Dmtf(at)); Assert.Equal("*[System[(Level=1 or Level=2) and TimeCreated[@SystemTime>'2026-10-02T12:05:06.000Z']]]", CimQueries.EventXPath(at)); Assert.Contains("Logfile = 'System' AND EventType = 1 AND TimeGenerated > '20261002120506.000000+000'", CimQueries.EventQuery("System", at), StringComparison.Ordinal); } [Fact] public void Queries_only_read() { var queries = new[] { CimQueries.OperatingSystemQuery, CimQueries.ComputerSystemQuery, CimQueries.ProcessorQuery, CimQueries.MemoryQuery, CimQueries.VolumeQuery, CimQueries.LogicalDiskQuery, CimQueries.ServiceQuery, CimQueries.TaskQuery, }; Assert.All(queries, q => Assert.StartsWith("SELECT ", q, StringComparison.Ordinal)); } } public class AxBusinessConnectorTests { private static readonly BusinessConnectorInstallation Ax2012 = BusinessConnectorLocator.Describe(@"C:\Program Files\Microsoft Dynamics AX\60\BusinessConnector\Bin\Microsoft.Dynamics.BusinessConnectorNet.dll"); private static readonly BusinessConnectorInstallation Ax2009 = BusinessConnectorLocator.Describe(@"C:\Program Files (x86)\Microsoft Dynamics AX\50\Client\Bin\Microsoft.Dynamics.BusinessConnectorNet.dll"); [Fact] public void Versions_and_bitness_from_the_path() { Assert.Equal(("AX 2012", false, false), (Ax2012.Version, Ax2012.Is32Bit, Ax2012.NeedsClr2)); Assert.Equal(("AX 2009", true, true), (Ax2009.Version, Ax2009.Is32Bit, Ax2009.NeedsClr2)); } [Fact] public void Locator_uses_the_configured_path_first() { var configured = @"D:\AX\Microsoft.Dynamics.BusinessConnectorNet.dll"; if (OperatingSystem.IsWindows()) { Assert.Equal(configured, new BusinessConnectorLocator(configured, p => p == configured).Find()!.Path); } Assert.Null(new BusinessConnectorLocator(null, _ => false).Find()); } [Fact] public void Command_picks_powershell_and_never_puts_parameters_on_the_command_line() { var (file2012, args2012) = AxLogonClient.Command(Ax2012, @"C:\Windows"); var (file2009, args2009) = AxLogonClient.Command(Ax2009, @"C:\Windows"); var environment = AxLogonClient.Environment(Ax2012, "DAT", "01@aos01:2712", null); Assert.Equal(@"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe", file2012); Assert.DoesNotContain("-Version", args2012); Assert.EndsWith(@"WindowsPowerShell\v1.0\powershell.exe", file2009, StringComparison.Ordinal); Assert.Equal(["-Version", "2"], args2009.Take(2)); Assert.Contains("-EncodedCommand", args2012); Assert.DoesNotContain(args2012, a => a.Contains("aos01", StringComparison.Ordinal)); Assert.Equal(("DAT", "01@aos01:2712", string.Empty), (environment["SQLINSIGHT_AX_COMPANY"], environment["SQLINSIGHT_AX_SERVER"], environment["SQLINSIGHT_AX_CONFIG"])); var script = System.Text.Encoding.Unicode.GetString(Convert.FromBase64String(args2012[^1])); Assert.Contains("Logon(", script, StringComparison.Ordinal); Assert.Contains("Logoff()", script, StringComparison.Ordinal); } [Fact] public void Parse_the_helpers_answer() { Assert.Equal((true, 812, "Logon i AX lykkedes."), AxLogonClient.Parse(new ProcessResult(0, "noise\r\nSQLINSIGHT-AX-OK 812\r\n", string.Empty, false), Ax2012)); var notUser = AxLogonClient.Parse(new ProcessResult(1, "SQLINSIGHT-AX-ERROR You are not a recognized user of Microsoft Dynamics AX.", string.Empty, false), Ax2012); Assert.False(notUser.Ok); Assert.Contains("ikke bruger i AX", notUser.Message, StringComparison.Ordinal); Assert.Contains("PowerShell 2.0", AxLogonClient.Parse(new ProcessResult(1, string.Empty, "Version v2.0.50727 of the .NET Framework is not installed", false), Ax2009).Message, StringComparison.Ordinal); Assert.Contains("i tide", AxLogonClient.Parse(new ProcessResult(-1, string.Empty, string.Empty, true), Ax2012).Message, StringComparison.Ordinal); Assert.Contains("kode 3", AxLogonClient.Parse(new ProcessResult(3, string.Empty, string.Empty, false), Ax2012).Message, StringComparison.Ordinal); } }