/* * Copyright (c) 2024 ETH Zürich, IT Services * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ using System; using System.Collections.Generic; using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using SafeExamBrowser.Configuration.Contracts; using SafeExamBrowser.Core.Contracts.OperationModel; using SafeExamBrowser.Lockdown.Contracts; using SafeExamBrowser.Logging.Contracts; using SafeExamBrowser.Service.Operations; using SafeExamBrowser.Settings; namespace SafeExamBrowser.Service.UnitTests.Operations { [TestClass] public class LockdownOperationTests { private Mock backup; private Mock factory; private Mock monitor; private Mock logger; private AppSettings settings; private SessionContext sessionContext; private LockdownOperation sut; [TestInitialize] public void Initialize() { backup = new Mock(); factory = new Mock(); monitor = new Mock(); logger = new Mock(); settings = new AppSettings(); sessionContext = new SessionContext { Configuration = new ServiceConfiguration { Settings = settings, UserName = "TestName", UserSid = "S-1-234-TEST" } }; sut = new LockdownOperation(backup.Object, factory.Object, monitor.Object, logger.Object, sessionContext); } [TestMethod] public void Perform_MustSetConfigurationsCorrectly() { var configuration = new Mock(); var count = typeof(IFeatureConfigurationFactory).GetMethods().Where(m => m.Name.StartsWith("Create") && m.Name != nameof(IFeatureConfigurationFactory.CreateAll)).Count(); configuration.SetReturnsDefault(true); factory.SetReturnsDefault(configuration.Object); settings.Service.DisableChromeNotifications = true; settings.Service.DisableEaseOfAccessOptions = true; settings.Service.DisableSignout = true; settings.Service.SetVmwareConfiguration = true; var result = sut.Perform(); backup.Verify(b => b.Save(It.Is(c => c == configuration.Object)), Times.Exactly(count)); configuration.Verify(c => c.Initialize(), Times.Exactly(count)); configuration.Verify(c => c.DisableFeature(), Times.Exactly(3)); configuration.Verify(c => c.EnableFeature(), Times.Exactly(count - 3)); monitor.Verify(m => m.Observe(It.Is(c => c == configuration.Object), It.Is(s => s == FeatureConfigurationStatus.Disabled)), Times.Exactly(3)); monitor.Verify(m => m.Observe(It.Is(c => c == configuration.Object), It.Is(s => s == FeatureConfigurationStatus.Enabled)), Times.Exactly(count - 3)); monitor.Verify(m => m.Start(), Times.Once); Assert.AreEqual(OperationResult.Success, result); } [TestMethod] public void Perform_MustOnlySetVmwareConfigurationIfEnabled() { var configuration = new Mock(); configuration.SetReturnsDefault(true); factory.SetReturnsDefault(configuration.Object); settings.Service.SetVmwareConfiguration = true; sut.Perform(); factory.Verify(f => f.CreateVmwareOverlayConfiguration(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); factory.Reset(); factory.SetReturnsDefault(configuration.Object); settings.Service.SetVmwareConfiguration = false; sut.Perform(); factory.Verify(f => f.CreateVmwareOverlayConfiguration(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); } [TestMethod] public void Perform_MustUseSameGroupForAllConfigurations() { var configuration = new Mock(); var groupId = default(Guid); configuration.SetReturnsDefault(true); factory .Setup(f => f.CreateChromeNotificationConfiguration(It.IsAny(), It.IsAny(), It.IsAny())) .Returns(configuration.Object) .Callback((id, name, sid) => groupId = id); factory.SetReturnsDefault(configuration.Object); settings.Service.SetVmwareConfiguration = true; sut.Perform(); factory.Verify(f => f.CreateChangePasswordConfiguration(It.Is(id => id == groupId), It.IsAny(), It.IsAny()), Times.Once); factory.Verify(f => f.CreateChromeNotificationConfiguration(It.Is(id => id == groupId), It.IsAny(), It.IsAny()), Times.Once); factory.Verify(f => f.CreateEaseOfAccessConfiguration(It.Is(id => id == groupId)), Times.Once); factory.Verify(f => f.CreateFindPrinterConfiguration(It.Is(id => id == groupId), It.IsAny(), It.IsAny()), Times.Once); factory.Verify(f => f.CreateLockWorkstationConfiguration(It.Is(id => id == groupId), It.IsAny(), It.IsAny()), Times.Once); factory.Verify(f => f.CreateMachinePowerOptionsConfiguration(It.Is(id => id == groupId)), Times.Once); factory.Verify(f => f.CreateNetworkOptionsConfiguration(It.Is(id => id == groupId)), Times.Once); factory.Verify(f => f.CreateRemoteConnectionConfiguration(It.Is(id => id == groupId)), Times.Once); factory.Verify(f => f.CreateSignoutConfiguration(It.Is(id => id == groupId), It.IsAny(), It.IsAny()), Times.Once); factory.Verify(f => f.CreateSwitchUserConfiguration(It.Is(id => id == groupId)), Times.Once); factory.Verify(f => f.CreateTaskManagerConfiguration(It.Is(id => id == groupId), It.IsAny(), It.IsAny()), Times.Once); factory.Verify(f => f.CreateUserPowerOptionsConfiguration(It.Is(id => id == groupId), It.IsAny(), It.IsAny()), Times.Once); factory.Verify(f => f.CreateVmwareOverlayConfiguration(It.Is(id => id == groupId), It.IsAny(), It.IsAny()), Times.Once); factory.Verify(f => f.CreateWindowsUpdateConfiguration(It.Is(id => id == groupId)), Times.Once); } [TestMethod] public void Perform_MustImmediatelyAbortOnFailure() { var configuration = new Mock(); var count = typeof(IFeatureConfigurationFactory).GetMethods().Where(m => m.Name.StartsWith("Create") && m.Name != nameof(IFeatureConfigurationFactory.CreateAll)).Count(); var counter = 0; var offset = 3; configuration.Setup(c => c.EnableFeature()).Returns(() => ++counter < count - offset); factory.SetReturnsDefault(configuration.Object); var result = sut.Perform(); backup.Verify(b => b.Save(It.Is(c => c == configuration.Object)), Times.Exactly(count - offset)); configuration.Verify(c => c.Initialize(), Times.Exactly(count - offset)); configuration.Verify(c => c.DisableFeature(), Times.Never); configuration.Verify(c => c.EnableFeature(), Times.Exactly(count - offset)); monitor.Verify(m => m.Observe(It.Is(c => c == configuration.Object), It.Is(s => s == FeatureConfigurationStatus.Enabled)), Times.Exactly(count - offset - 1)); monitor.Verify(m => m.Start(), Times.Never); Assert.AreEqual(OperationResult.Failed, result); } [TestMethod] public void Revert_MustRestoreConfigurationsCorrectly() { var configuration1 = new Mock(); var configuration2 = new Mock(); var configuration3 = new Mock(); var configuration4 = new Mock(); var configurations = new List { configuration1.Object, configuration2.Object, configuration3.Object, configuration4.Object }; backup.Setup(b => b.GetBy(It.IsAny())).Returns(configurations); configuration1.Setup(c => c.Restore()).Returns(true); configuration2.Setup(c => c.Restore()).Returns(true); configuration3.Setup(c => c.Restore()).Returns(true); configuration4.Setup(c => c.Restore()).Returns(true); var result = sut.Revert(); backup.Verify(b => b.Delete(It.Is(c => c == configuration1.Object)), Times.Once); backup.Verify(b => b.Delete(It.Is(c => c == configuration2.Object)), Times.Once); backup.Verify(b => b.Delete(It.Is(c => c == configuration3.Object)), Times.Once); backup.Verify(b => b.Delete(It.Is(c => c == configuration4.Object)), Times.Once); configuration1.Verify(c => c.DisableFeature(), Times.Never); configuration1.Verify(c => c.EnableFeature(), Times.Never); configuration1.Verify(c => c.Initialize(), Times.Never); configuration1.Verify(c => c.Restore(), Times.Once); configuration2.Verify(c => c.DisableFeature(), Times.Never); configuration2.Verify(c => c.EnableFeature(), Times.Never); configuration2.Verify(c => c.Initialize(), Times.Never); configuration2.Verify(c => c.Restore(), Times.Once); configuration3.Verify(c => c.DisableFeature(), Times.Never); configuration3.Verify(c => c.EnableFeature(), Times.Never); configuration3.Verify(c => c.Initialize(), Times.Never); configuration3.Verify(c => c.Restore(), Times.Once); configuration4.Verify(c => c.DisableFeature(), Times.Never); configuration4.Verify(c => c.EnableFeature(), Times.Never); configuration4.Verify(c => c.Initialize(), Times.Never); configuration4.Verify(c => c.Restore(), Times.Once); monitor.Verify(m => m.Reset(), Times.Once); Assert.AreEqual(OperationResult.Success, result); } [TestMethod] public void Revert_MustContinueToRevertOnFailure() { var configuration1 = new Mock(); var configuration2 = new Mock(); var configuration3 = new Mock(); var configuration4 = new Mock(); var configurations = new List { configuration1.Object, configuration2.Object, configuration3.Object, configuration4.Object }; backup.Setup(b => b.GetBy(It.IsAny())).Returns(configurations); configuration1.Setup(c => c.Restore()).Returns(true); configuration2.Setup(c => c.Restore()).Returns(false); configuration3.Setup(c => c.Restore()).Returns(false); configuration4.Setup(c => c.Restore()).Returns(true); var result = sut.Revert(); backup.Verify(b => b.Delete(It.Is(c => c == configuration1.Object)), Times.Once); backup.Verify(b => b.Delete(It.Is(c => c == configuration2.Object)), Times.Never); backup.Verify(b => b.Delete(It.Is(c => c == configuration3.Object)), Times.Never); backup.Verify(b => b.Delete(It.Is(c => c == configuration4.Object)), Times.Once); configuration1.Verify(c => c.DisableFeature(), Times.Never); configuration1.Verify(c => c.EnableFeature(), Times.Never); configuration1.Verify(c => c.Initialize(), Times.Never); configuration1.Verify(c => c.Restore(), Times.Once); configuration2.Verify(c => c.DisableFeature(), Times.Never); configuration2.Verify(c => c.EnableFeature(), Times.Never); configuration2.Verify(c => c.Initialize(), Times.Never); configuration2.Verify(c => c.Restore(), Times.Once); configuration3.Verify(c => c.DisableFeature(), Times.Never); configuration3.Verify(c => c.EnableFeature(), Times.Never); configuration3.Verify(c => c.Initialize(), Times.Never); configuration3.Verify(c => c.Restore(), Times.Once); configuration4.Verify(c => c.DisableFeature(), Times.Never); configuration4.Verify(c => c.EnableFeature(), Times.Never); configuration4.Verify(c => c.Initialize(), Times.Never); configuration4.Verify(c => c.Restore(), Times.Once); monitor.Verify(m => m.Reset(), Times.Once); Assert.AreEqual(OperationResult.Failed, result); } } }