New project SQLInsight.Servers: - CimWindowsServerSource (Microsoft.Management.Infrastructure, the API behind Get-CimInstance): WS-Man first, DCOM if that fails, a local session for the agent's own computer, as the agent's identity. Only SELECT queries (CimQueries) and Task Scheduler's read-only GetInfo. CPU and paging from raw counters, disks (Win32_Volume, Win32_LogicalDisk fallback), services, scheduled tasks, and the System/Application logs through the Event Log service (MS-EVEN6, XPath filter on the server) with Win32_NTLogEvent as fallback. - ServerErrors: access denied, missing namespace, RPC/WinRM unreachable and timeouts become "ikke målbar" reasons that name the missing right and the grant script; never local administrator. - WindowsServerTester: tries every area once for the web UI's test. - SyntheticCheckRunner: TCP, HTTP(S) with expected status/text and TLS certificate expiry (also for refused certificates), SQL login + read-only query (re-validated, in a transaction that is always rolled back), DNS, and the Dynamics AX logon: AOS port, then a logon through the .NET Business Connector in a separate Windows PowerShell process with a timeout when it is installed; otherwise the result says clearly that only the port was tested. Tests: error mapping, queries, AX command/parsing, runners against local TCP and HTTP(S) servers with a self-signed certificate, the CIM source against this computer, and the SQL check against the test instance. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
93 lines
4.1 KiB
C#
93 lines
4.1 KiB
C#
using SQLInsight.Core.Servers;
|
|
using SQLInsight.Servers;
|
|
|
|
namespace SQLInsight.Servers.Tests;
|
|
|
|
/// <summary>
|
|
/// The CIM implementation against this computer (a local CIM session, as for the agent's own server). Remote access over
|
|
/// WS-Man/DCOM with least privilege cannot be tested here; it needs a domain with a second server.
|
|
/// </summary>
|
|
[Trait("Category", "Windows")]
|
|
[System.Runtime.Versioning.SupportedOSPlatform("windows")]
|
|
public class LocalCimTests
|
|
{
|
|
private static async Task<IWindowsServerSession?> ConnectAsync()
|
|
{
|
|
if (!OperatingSystem.IsWindows())
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return await new CimWindowsServerSource(new ServerConnectionOptions()).ConnectAsync(Environment.MachineName, CancellationToken.None);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Reads_os_performance_disks_services_events_and_tasks()
|
|
{
|
|
using var session = await ConnectAsync();
|
|
if (session is null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var os = await session.GetOperatingSystemAsync(CancellationToken.None);
|
|
var first = await session.GetPerformanceAsync(DateTimeOffset.UtcNow, CancellationToken.None);
|
|
await Task.Delay(1500);
|
|
var second = await session.GetPerformanceAsync(DateTimeOffset.UtcNow, CancellationToken.None);
|
|
var sample = ServerPerformanceMath.Sample(first, second, os);
|
|
var disks = await session.GetDisksAsync(CancellationToken.None);
|
|
var services = await session.GetServicesAsync(CancellationToken.None);
|
|
var service = await session.GetServiceAsync(services[0].Name, CancellationToken.None);
|
|
var events = await session.GetEventsAsync(DateTimeOffset.UtcNow.AddDays(-7), 200, CancellationToken.None);
|
|
var tasks = await session.GetTasksAsync(name => !TaskResults.IsMicrosoftTask(name), 3, CancellationToken.None);
|
|
|
|
Assert.Equal("lokal", session.Protocol);
|
|
Assert.Contains("Windows", os.Caption, StringComparison.OrdinalIgnoreCase);
|
|
Assert.True(os.LastBootUpTime < DateTimeOffset.UtcNow);
|
|
Assert.True(os.TotalMemoryMb > 0);
|
|
Assert.True(os.LogicalProcessors > 0);
|
|
Assert.InRange(sample.CpuPercent!.Value, 0, 100);
|
|
Assert.True(sample.AvailableMb > 0);
|
|
Assert.InRange(sample.CommitPercent!.Value, 0, 100);
|
|
Assert.NotEmpty(disks);
|
|
Assert.All(disks, d => Assert.False(d.Volume.StartsWith(@"\\?\", StringComparison.Ordinal)));
|
|
Assert.All(disks, d => Assert.InRange(d.FreeGb, 0, d.SizeGb));
|
|
Assert.Contains(services, s => s.IsRunning && s.IsAutomatic);
|
|
Assert.Equal(services[0].Name, service!.Name);
|
|
Assert.Null(await session.GetServiceAsync("SQLInsight-findes-ikke", CancellationToken.None));
|
|
Assert.Equal("Event Log (RPC)", events.Method);
|
|
Assert.All(events.Entries, e => Assert.InRange(e.Level, 1, 2));
|
|
Assert.True(tasks.Visible > 0);
|
|
Assert.All(tasks.Watched, t => Assert.False(TaskResults.IsMicrosoftTask(t.FullName)));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task The_test_reports_every_area()
|
|
{
|
|
if (!OperatingSystem.IsWindows())
|
|
{
|
|
return;
|
|
}
|
|
|
|
var result = await WindowsServerTester.TestAsync(new CimWindowsServerSource(new ServerConnectionOptions()), "localhost", "test", DateTimeOffset.UtcNow, CancellationToken.None);
|
|
|
|
Assert.True(result.Reachable, result.Error);
|
|
Assert.Equal(ServerArea.All, result.Areas.Select(a => a.Area));
|
|
Assert.All(result.Areas, a => Assert.True(a.Ok, a.Detail));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task An_unknown_host_is_unreachable_with_a_reason()
|
|
{
|
|
if (!OperatingSystem.IsWindows())
|
|
{
|
|
return;
|
|
}
|
|
|
|
var source = new CimWindowsServerSource(new ServerConnectionOptions { OperationTimeout = TimeSpan.FromSeconds(5) });
|
|
var error = await Assert.ThrowsAsync<ServerAccessException>(() => source.ConnectAsync("sqlinsight-findes-ikke.invalid", CancellationToken.None));
|
|
|
|
Assert.Equal(ServerAccessProblem.Unreachable, error.Problem);
|
|
Assert.Contains("sqlinsight-findes-ikke.invalid", error.Message, StringComparison.Ordinal);
|
|
}
|
|
}
|