// Copyright (c) Umbraco. // See LICENSE for more details. using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Configuration; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.HealthChecks; using Umbraco.Cms.Core.HealthChecks.NotificationMethods; using Umbraco.Cms.Core.Logging; using Umbraco.Cms.Core.Runtime; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Sync; using Umbraco.Cms.Infrastructure.HostedServices; using Umbraco.Cms.Infrastructure.Scoping; using Umbraco.Cms.Tests.Common; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.HostedServices; [TestFixture] [Obsolete("Replaced by BackgroundJobs.Jobs.HealthCheckNotifierJobTests")] public class HealthCheckNotifierTests { private Mock _mockNotificationMethod; private const string Check1Id = "00000000-0000-0000-0000-000000000001"; private const string Check2Id = "00000000-0000-0000-0000-000000000002"; private const string Check3Id = "00000000-0000-0000-0000-000000000003"; [Test] public async Task Does_Not_Execute_When_Not_Enabled() { var sut = CreateHealthCheckNotifier(false); await sut.PerformExecuteAsync(null); VerifyNotificationsNotSent(); } [TestCase(RuntimeLevel.Boot)] [TestCase(RuntimeLevel.Install)] [TestCase(RuntimeLevel.Unknown)] [TestCase(RuntimeLevel.Upgrade)] [TestCase(RuntimeLevel.BootFailed)] public async Task Does_Not_Execute_When_Runtime_State_Is_Not_Run(RuntimeLevel runtimeLevel) { var sut = CreateHealthCheckNotifier(runtimeLevel: runtimeLevel); await sut.PerformExecuteAsync(null); VerifyNotificationsNotSent(); } [Test] public async Task Does_Not_Execute_When_Server_Role_Is_Subscriber() { var sut = CreateHealthCheckNotifier(serverRole: ServerRole.Subscriber); await sut.PerformExecuteAsync(null); VerifyNotificationsNotSent(); } [Test] public async Task Does_Not_Execute_When_Server_Role_Is_Unknown() { var sut = CreateHealthCheckNotifier(serverRole: ServerRole.Unknown); await sut.PerformExecuteAsync(null); VerifyNotificationsNotSent(); } [Test] public async Task Does_Not_Execute_When_Not_Main_Dom() { var sut = CreateHealthCheckNotifier(isMainDom: false); await sut.PerformExecuteAsync(null); VerifyNotificationsNotSent(); } [Test] public async Task Does_Not_Execute_With_No_Enabled_Notification_Methods() { var sut = CreateHealthCheckNotifier(notificationEnabled: false); await sut.PerformExecuteAsync(null); VerifyNotificationsNotSent(); } [Test] public async Task Executes_With_Enabled_Notification_Methods() { var sut = CreateHealthCheckNotifier(); await sut.PerformExecuteAsync(null); VerifyNotificationsSent(); } [Test] public async Task Executes_Only_Enabled_Checks() { var sut = CreateHealthCheckNotifier(); await sut.PerformExecuteAsync(null); _mockNotificationMethod.Verify( x => x.SendAsync( It.Is(y => y.ResultsAsDictionary.Count == 1 && y.ResultsAsDictionary.ContainsKey("Check1"))), Times.Once); } private HealthCheckNotifier CreateHealthCheckNotifier( bool enabled = true, RuntimeLevel runtimeLevel = RuntimeLevel.Run, ServerRole serverRole = ServerRole.Single, bool isMainDom = true, bool notificationEnabled = true) { var settings = new HealthChecksSettings { Notification = new HealthChecksNotificationSettings { Enabled = enabled, DisabledChecks = new List { new() { Id = Guid.Parse(Check3Id) } }, }, DisabledChecks = new List { new() { Id = Guid.Parse(Check2Id) } }, }; var checks = new HealthCheckCollection(() => new List { new TestHealthCheck1(), new TestHealthCheck2(), new TestHealthCheck3(), }); _mockNotificationMethod = new Mock(); _mockNotificationMethod.SetupGet(x => x.Enabled).Returns(notificationEnabled); var notifications = new HealthCheckNotificationMethodCollection(() => new List { _mockNotificationMethod.Object }); var mockRunTimeState = new Mock(); mockRunTimeState.SetupGet(x => x.Level).Returns(runtimeLevel); var mockServerRegistrar = new Mock(); mockServerRegistrar.Setup(x => x.CurrentServerRole).Returns(serverRole); var mockMainDom = new Mock(); mockMainDom.SetupGet(x => x.IsMainDom).Returns(isMainDom); var mockScopeProvider = new Mock(); var mockLogger = new Mock>(); var mockProfilingLogger = new Mock(); return new HealthCheckNotifier( new TestOptionsMonitor(settings), checks, notifications, mockRunTimeState.Object, mockServerRegistrar.Object, mockMainDom.Object, mockScopeProvider.Object, mockLogger.Object, mockProfilingLogger.Object, Mock.Of()); } private void VerifyNotificationsNotSent() => VerifyNotificationsSentTimes(Times.Never()); private void VerifyNotificationsSent() => VerifyNotificationsSentTimes(Times.Once()); private void VerifyNotificationsSentTimes(Times times) => _mockNotificationMethod.Verify(x => x.SendAsync(It.IsAny()), times); [HealthCheck(Check1Id, "Check1")] private class TestHealthCheck1 : TestHealthCheck { } [HealthCheck(Check2Id, "Check2")] private class TestHealthCheck2 : TestHealthCheck { } [HealthCheck(Check3Id, "Check3")] private class TestHealthCheck3 : TestHealthCheck { } private class TestHealthCheck : HealthCheck { public override HealthCheckStatus ExecuteAction(HealthCheckAction action) => new("Check message"); public override async Task> GetStatus() => Enumerable.Empty(); } }