GET returns the SQL login and the URL query redacted; a client that PUTs it back unchanged would otherwise replace the real values. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
88 lines
5.5 KiB
C#
88 lines
5.5 KiB
C#
using SQLInsight.Core.SyntheticChecks;
|
|
|
|
namespace SQLInsight.Core.Tests;
|
|
|
|
public class SyntheticCheckTests
|
|
{
|
|
private static string? Validate(string kind, SyntheticCheckSettings settings, bool hasServer = false, int interval = 300, int timeout = 15) =>
|
|
SyntheticCheckValidation.Validate("tjek", kind, settings, interval, timeout, hasServer);
|
|
|
|
[Fact]
|
|
public void Valid_checks_of_each_kind()
|
|
{
|
|
Assert.Null(Validate(SyntheticCheckKind.Tcp, new() { Host = "aos01", Port = 2712 }));
|
|
Assert.Null(Validate(SyntheticCheckKind.Http, new() { Url = new Uri("https://ep.firma.local/sites/DynamicsAx"), ExpectedStatus = [200, 401], ExpectedText = "Dynamics" }));
|
|
Assert.Null(Validate(SyntheticCheckKind.Sql, new() { Server = @"sql01\AX", Database = "AX2012_PROD", Query = "SELECT COUNT(*) FROM dbo.DATAAREA" }));
|
|
Assert.Null(Validate(SyntheticCheckKind.Sql, new() { Server = "sql01", Authentication = "SqlLogin", UserName = "axapp" }));
|
|
Assert.Null(Validate(SyntheticCheckKind.Dns, new() { Host = "aos01.firma.local", ExpectedAddresses = ["10.0.0.5"] }));
|
|
Assert.Null(Validate(SyntheticCheckKind.AxLogon, new() { Host = "aos01", Company = "DAT", ServiceName = "AOS60$01" }, hasServer: true));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(SyntheticCheckKind.Tcp, "Angiv porten")]
|
|
[InlineData(SyntheticCheckKind.Http, "http://")]
|
|
[InlineData(SyntheticCheckKind.Sql, "Angiv serveren")]
|
|
[InlineData(SyntheticCheckKind.Dns, "Angiv serverens navn")]
|
|
[InlineData(SyntheticCheckKind.AxLogon, "Angiv serverens navn")]
|
|
public void Missing_targets(string kind, string error) =>
|
|
Assert.Contains(error, Validate(kind, kind == SyntheticCheckKind.Tcp ? new() { Host = "aos01" } : new()), StringComparison.Ordinal);
|
|
|
|
[Fact]
|
|
public void A_sql_check_only_reads()
|
|
{
|
|
Assert.Contains("SELECT", Validate(SyntheticCheckKind.Sql, new() { Server = "sql01", Query = "UPDATE dbo.CustTable SET Name = 'x'" }), StringComparison.Ordinal);
|
|
Assert.NotNull(Validate(SyntheticCheckKind.Sql, new() { Server = "sql01", Query = "SELECT 1; DROP TABLE dbo.x" }));
|
|
Assert.NotNull(Validate(SyntheticCheckKind.Sql, new() { Server = "sql01", Query = "SELECT * INTO dbo.Copy FROM dbo.CustTable" }));
|
|
Assert.NotNull(Validate(SyntheticCheckKind.Sql, new() { Server = "sql01", Query = "EXEC sp_who" }));
|
|
}
|
|
|
|
[Fact]
|
|
public void Limits_and_service_needs_a_server()
|
|
{
|
|
Assert.Contains("1 minut", Validate(SyntheticCheckKind.Tcp, new() { Host = "a", Port = 1 }, interval: 30), StringComparison.Ordinal);
|
|
Assert.Contains("kortere end intervallet", Validate(SyntheticCheckKind.Tcp, new() { Host = "a", Port = 1 }, interval: 60, timeout: 60), StringComparison.Ordinal);
|
|
Assert.Contains("Windows-server", Validate(SyntheticCheckKind.Tcp, new() { Host = "a", Port = 1, ServiceName = "W3SVC" }), StringComparison.Ordinal);
|
|
Assert.NotNull(Validate(SyntheticCheckKind.Http, new() { Url = new Uri("https://bruger:kode@ep/") }));
|
|
Assert.NotNull(Validate(SyntheticCheckKind.Http, new() { Url = new Uri("ftp://ep/") }));
|
|
Assert.NotNull(Validate(SyntheticCheckKind.AxLogon, new() { Host = "aos01", Company = "DAT; DROP" }));
|
|
Assert.NotNull(SyntheticCheckValidation.Validate("tjek", "Ping", new(), 300, 15, false));
|
|
Assert.NotNull(SyntheticCheckValidation.Validate(" ", SyntheticCheckKind.Tcp, new() { Host = "a", Port = 1 }, 300, 15, false));
|
|
}
|
|
|
|
[Fact]
|
|
public void An_http_address_has_a_length_limit()
|
|
{
|
|
Assert.Contains("2000 tegn", Validate(SyntheticCheckKind.Http, new() { Url = new Uri("https://ep.firma.local/" + new string('a', SyntheticCheckValidation.MaxUrlLength)) }),
|
|
StringComparison.Ordinal);
|
|
Assert.Null(Validate(SyntheticCheckKind.Http, new() { Url = new Uri("https://ep.firma.local/" + new string('a', 1900)) }));
|
|
}
|
|
|
|
[Fact]
|
|
public void Settings_round_trip_as_json_and_bad_json_is_empty_settings()
|
|
{
|
|
var settings = new SyntheticCheckSettings { Url = new Uri("https://ep/"), ExpectedStatus = [200], UseWindowsAuthentication = true, ServiceName = "W3SVC" };
|
|
|
|
Assert.Equal(settings.ToJson(), SyntheticCheckSettings.FromJson(settings.ToJson()).ToJson());
|
|
Assert.Null(SyntheticCheckSettings.FromJson("{not json").Url);
|
|
Assert.Equal("aos01:2712", new SyntheticCheckSettings { Host = "aos01" }.Target(SyntheticCheckKind.AxLogon));
|
|
Assert.Equal(@"sql01\AX / AXDB", new SyntheticCheckSettings { Server = @"sql01\AX", Database = "AXDB" }.Target(SyntheticCheckKind.Sql));
|
|
}
|
|
|
|
[Fact]
|
|
public void Redacted_values_from_the_api_are_not_saved_back()
|
|
{
|
|
Assert.Contains("[udeladt]", Validate(SyntheticCheckKind.Sql, new() { Server = "sql01", Authentication = "SqlLogin", UserName = "[udeladt]" }), StringComparison.Ordinal);
|
|
Assert.Contains("[udeladt]", Validate(SyntheticCheckKind.Http, new() { Url = new Uri("https://ep/side?[udeladt]") }), StringComparison.Ordinal);
|
|
Assert.Null(Validate(SyntheticCheckKind.Http, new() { Url = new Uri("https://ep/side?a=1") }));
|
|
}
|
|
|
|
[Fact]
|
|
public void A_sql_password_is_bound_to_the_server_and_login()
|
|
{
|
|
var a = new SyntheticCheckSettings { Server = "sql01", UserName = "axapp" }.SecretContext();
|
|
|
|
Assert.NotEqual(a, new SyntheticCheckSettings { Server = "sql02", UserName = "axapp" }.SecretContext());
|
|
Assert.NotEqual(a, new SyntheticCheckSettings { Server = "sql01", UserName = "sa" }.SecretContext());
|
|
Assert.NotEqual(a, Configuration.CredentialEnvelope.Context("sql01", "axapp"));
|
|
}
|
|
}
|