From bae7ed8a25e304ec72b17aa34759d9ba55ce7a7f Mon Sep 17 00:00:00 2001 From: dbuechel Date: Fri, 12 Oct 2018 15:23:43 +0200 Subject: [PATCH] SEBWIN-221: Fixed unit tests for changes in session handling (introduction of SessionContext). --- .../ClientHostDisconnectionOperationTests.cs | 9 +- .../Operations/WindowMonitorOperationTests.cs | 33 +--- .../Operations/WindowMonitorOperation.cs | 10 -- .../ConfigurationRepositoryTests.cs | 132 +++------------ .../OperationModel/OperationSequenceTests.cs | 6 +- .../Communication/RuntimeHostTests.cs | 5 +- .../Operations/ClientOperationTests.cs | 126 ++++----------- .../ClientTerminationOperationTests.cs | 109 +++++++++++++ .../Operations/ConfigurationOperationTests.cs | 153 ++++++++---------- .../Operations/KioskModeOperationTests.cs | 100 ++++++++---- .../KioskModeTerminationOperationTests.cs | 147 +++++++++++++++++ .../Operations/ServiceOperationTests.cs | 37 ++--- .../SessionActivationOperationTests.cs | 81 ++++++++++ .../SessionInitializationOperationTests.cs | 14 +- .../RuntimeControllerTests.cs | 21 +++ .../SafeExamBrowser.Runtime.UnitTests.csproj | 3 + .../Operations/ClientOperation.cs | 4 +- .../Operations/KioskModeOperation.cs | 56 ++++--- SafeExamBrowser.Runtime/SessionContext.cs | 16 ++ 19 files changed, 655 insertions(+), 407 deletions(-) create mode 100644 SafeExamBrowser.Runtime.UnitTests/Operations/ClientTerminationOperationTests.cs create mode 100644 SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeTerminationOperationTests.cs create mode 100644 SafeExamBrowser.Runtime.UnitTests/Operations/SessionActivationOperationTests.cs diff --git a/SafeExamBrowser.Client.UnitTests/Operations/ClientHostDisconnectionOperationTests.cs b/SafeExamBrowser.Client.UnitTests/Operations/ClientHostDisconnectionOperationTests.cs index e6a750f0..bd243066 100644 --- a/SafeExamBrowser.Client.UnitTests/Operations/ClientHostDisconnectionOperationTests.cs +++ b/SafeExamBrowser.Client.UnitTests/Operations/ClientHostDisconnectionOperationTests.cs @@ -6,8 +6,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -using System; using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using SafeExamBrowser.Client.Operations; @@ -42,7 +43,11 @@ namespace SafeExamBrowser.Client.UnitTests.Operations sut = new ClientHostDisconnectionOperation(clientHost.Object, logger.Object, timeout_ms); - clientHost.SetupGet(h => h.IsConnected).Returns(true).Callback(() => clientHost.Raise(h => h.RuntimeDisconnected += null)); + clientHost.SetupGet(h => h.IsConnected).Returns(true).Callback(() => Task.Run(() => + { + Thread.Sleep(10); + clientHost.Raise(h => h.RuntimeDisconnected += null); + })); stopWatch.Start(); sut.Revert(); diff --git a/SafeExamBrowser.Client.UnitTests/Operations/WindowMonitorOperationTests.cs b/SafeExamBrowser.Client.UnitTests/Operations/WindowMonitorOperationTests.cs index 9b9c59b7..b4e6c7d7 100644 --- a/SafeExamBrowser.Client.UnitTests/Operations/WindowMonitorOperationTests.cs +++ b/SafeExamBrowser.Client.UnitTests/Operations/WindowMonitorOperationTests.cs @@ -31,71 +31,45 @@ namespace SafeExamBrowser.Client.UnitTests.Operations [TestMethod] public void MustPerformCorrectlyForCreateNewDesktop() { - var order = 0; - var hideAll = 0; - var startMonitoring = 0; var sut = new WindowMonitorOperation(KioskMode.CreateNewDesktop, loggerMock.Object, windowMonitorMock.Object); - windowMonitorMock.Setup(w => w.HideAllWindows()).Callback(() => hideAll = ++order); - windowMonitorMock.Setup(w => w.StartMonitoringWindows()).Callback(() => startMonitoring = ++order); - sut.Perform(); windowMonitorMock.Verify(w => w.HideAllWindows(), Times.Never); windowMonitorMock.Verify(w => w.StartMonitoringWindows(), Times.Once); - - Assert.AreEqual(0, hideAll); - Assert.AreEqual(1, startMonitoring); } [TestMethod] public void MustRevertCorrectlyForCreateNewDesktop() { - var order = 0; - var stop = 0; - var restore = 0; var sut = new WindowMonitorOperation(KioskMode.CreateNewDesktop, loggerMock.Object, windowMonitorMock.Object); - windowMonitorMock.Setup(w => w.StopMonitoringWindows()).Callback(() => stop = ++order); - windowMonitorMock.Setup(w => w.RestoreHiddenWindows()).Callback(() => restore = ++order); - sut.Revert(); windowMonitorMock.Verify(w => w.StopMonitoringWindows(), Times.Once); windowMonitorMock.Verify(w => w.RestoreHiddenWindows(), Times.Never); - - Assert.AreEqual(0, restore); - Assert.AreEqual(1, stop); } [TestMethod] public void MustPerformCorrectlyForDisableExplorerShell() { - var order = 0; var sut = new WindowMonitorOperation(KioskMode.DisableExplorerShell, loggerMock.Object, windowMonitorMock.Object); - windowMonitorMock.Setup(w => w.HideAllWindows()).Callback(() => Assert.AreEqual(++order, 1)); - windowMonitorMock.Setup(w => w.StartMonitoringWindows()).Callback(() => Assert.AreEqual(++order, 2)); - sut.Perform(); - windowMonitorMock.Verify(w => w.HideAllWindows(), Times.Once); + windowMonitorMock.Verify(w => w.HideAllWindows(), Times.Never); windowMonitorMock.Verify(w => w.StartMonitoringWindows(), Times.Once); } [TestMethod] public void MustRevertCorrectlyForDisableExplorerShell() { - var order = 0; var sut = new WindowMonitorOperation(KioskMode.DisableExplorerShell, loggerMock.Object, windowMonitorMock.Object); - windowMonitorMock.Setup(w => w.StopMonitoringWindows()).Callback(() => Assert.AreEqual(++order, 1)); - windowMonitorMock.Setup(w => w.RestoreHiddenWindows()).Callback(() => Assert.AreEqual(++order, 2)); - sut.Revert(); windowMonitorMock.Verify(w => w.StopMonitoringWindows(), Times.Once); - windowMonitorMock.Verify(w => w.RestoreHiddenWindows(), Times.Once); + windowMonitorMock.Verify(w => w.RestoreHiddenWindows(), Times.Never); } [TestMethod] @@ -103,6 +77,9 @@ namespace SafeExamBrowser.Client.UnitTests.Operations { var sut = new WindowMonitorOperation(KioskMode.None, loggerMock.Object, windowMonitorMock.Object); + sut.Perform(); + sut.Revert(); + windowMonitorMock.VerifyNoOtherCalls(); } } diff --git a/SafeExamBrowser.Client/Operations/WindowMonitorOperation.cs b/SafeExamBrowser.Client/Operations/WindowMonitorOperation.cs index f043cf80..ecaf8b84 100644 --- a/SafeExamBrowser.Client/Operations/WindowMonitorOperation.cs +++ b/SafeExamBrowser.Client/Operations/WindowMonitorOperation.cs @@ -36,11 +36,6 @@ namespace SafeExamBrowser.Client.Operations logger.Info("Initializing window monitoring..."); StatusChanged?.Invoke(TextKey.OperationStatus_InitializeWindowMonitoring); - if (kioskMode == KioskMode.DisableExplorerShell) - { - windowMonitor.HideAllWindows(); - } - if (kioskMode != KioskMode.None) { windowMonitor.StartMonitoringWindows(); @@ -59,11 +54,6 @@ namespace SafeExamBrowser.Client.Operations windowMonitor.StopMonitoringWindows(); } - if (kioskMode == KioskMode.DisableExplorerShell) - { - windowMonitor.RestoreHiddenWindows(); - } - return OperationResult.Success; } } diff --git a/SafeExamBrowser.Configuration.UnitTests/ConfigurationRepositoryTests.cs b/SafeExamBrowser.Configuration.UnitTests/ConfigurationRepositoryTests.cs index 1010b693..da13aa7c 100644 --- a/SafeExamBrowser.Configuration.UnitTests/ConfigurationRepositoryTests.cs +++ b/SafeExamBrowser.Configuration.UnitTests/ConfigurationRepositoryTests.cs @@ -9,9 +9,7 @@ using System; using System.Reflection; using Microsoft.VisualStudio.TestTools.UnitTesting; -using Moq; -using SafeExamBrowser.Contracts.Communication.Proxies; -using SafeExamBrowser.Contracts.WindowsApi; +using SafeExamBrowser.Contracts.Configuration; namespace SafeExamBrowser.Configuration.UnitTests { @@ -28,130 +26,50 @@ namespace SafeExamBrowser.Configuration.UnitTests sut = new ConfigurationRepository(executablePath, string.Empty, string.Empty, string.Empty); } - [TestMethod] - public void AppConfigMustNeverBeNull() - { - Assert.IsNotNull(sut.AppConfig); - } - - [TestMethod] - public void CurrentSessionIsInitiallyNull() - { - Assert.IsNull(sut.CurrentSession); - } - - [TestMethod] - public void CurrentSettingsAreInitiallyNull() - { - Assert.IsNull(sut.CurrentSettings); - } - - [TestMethod] - public void MustCorrectlyBuildClientConfiguration() - { - sut.LoadDefaultSettings(); - sut.InitializeSessionConfiguration(); - - var appConfig = sut.AppConfig; - var clientConfig = sut.BuildClientConfiguration(); - var session = sut.CurrentSession; - var settings = sut.CurrentSettings; - - Assert.AreEqual(session.Id, clientConfig.SessionId); - Assert.AreSame(appConfig, clientConfig.AppConfig); - Assert.AreSame(settings, clientConfig.Settings); - } - [TestMethod] public void MustCorrectlyInitializeSessionConfiguration() { - sut.InitializeSessionConfiguration(); + var appConfig = sut.InitializeAppConfig(); + var configuration = sut.InitializeSessionConfiguration(); - Assert.IsNull(sut.CurrentSession.ClientProcess); - Assert.IsNull(sut.CurrentSession.ClientProxy); - Assert.IsInstanceOfType(sut.CurrentSession.Id, typeof(Guid)); - Assert.IsInstanceOfType(sut.CurrentSession.StartupToken, typeof(Guid)); + Assert.IsInstanceOfType(configuration.AppConfig, typeof(AppConfig)); + Assert.IsInstanceOfType(configuration.Id, typeof(Guid)); + Assert.IsNull(configuration.Settings); + Assert.IsInstanceOfType(configuration.StartupToken, typeof(Guid)); } [TestMethod] public void MustCorrectlyUpdateAppConfig() { - var clientAddress = sut.AppConfig.ClientAddress; - var clientId = sut.AppConfig.ClientId; - var clientLogFile = sut.AppConfig.ClientLogFile; - var runtimeAddress = sut.AppConfig.RuntimeAddress; - var runtimeId = sut.AppConfig.RuntimeId; - var runtimeLogFile = sut.AppConfig.RuntimeLogFile; + var appConfig = sut.InitializeAppConfig(); + var clientAddress = appConfig.ClientAddress; + var clientId = appConfig.ClientId; + var clientLogFile = appConfig.ClientLogFile; + var runtimeAddress = appConfig.RuntimeAddress; + var runtimeId = appConfig.RuntimeId; + var runtimeLogFile = appConfig.RuntimeLogFile; + var configuration = sut.InitializeSessionConfiguration(); - sut.InitializeSessionConfiguration(); - - Assert.AreNotEqual(sut.AppConfig.ClientAddress, clientAddress); - Assert.AreNotEqual(sut.AppConfig.ClientId, clientId); - Assert.AreEqual(sut.AppConfig.ClientLogFile, clientLogFile); - Assert.AreEqual(sut.AppConfig.RuntimeAddress, runtimeAddress); - Assert.AreEqual(sut.AppConfig.RuntimeId, runtimeId); - Assert.AreEqual(sut.AppConfig.RuntimeLogFile, runtimeLogFile); + Assert.AreNotEqual(configuration.AppConfig.ClientAddress, clientAddress); + Assert.AreNotEqual(configuration.AppConfig.ClientId, clientId); + Assert.AreEqual(configuration.AppConfig.ClientLogFile, clientLogFile); + Assert.AreEqual(configuration.AppConfig.RuntimeAddress, runtimeAddress); + Assert.AreEqual(configuration.AppConfig.RuntimeId, runtimeId); + Assert.AreEqual(configuration.AppConfig.RuntimeLogFile, runtimeLogFile); } [TestMethod] public void MustCorrectlyUpdateSessionConfiguration() { - var process = new Mock(); - var proxy = new Mock(); + var appConfig = sut.InitializeAppConfig(); + var firstSession = sut.InitializeSessionConfiguration(); + var secondSession = sut.InitializeSessionConfiguration(); + var thirdSession = sut.InitializeSessionConfiguration(); - sut.InitializeSessionConfiguration(); - - var firstSession = sut.CurrentSession; - - sut.CurrentSession.ClientProcess = process.Object; - sut.CurrentSession.ClientProxy = proxy.Object; - sut.InitializeSessionConfiguration(); - - var secondSession = sut.CurrentSession; - - Assert.AreSame(firstSession.ClientProcess, secondSession.ClientProcess); - Assert.AreSame(firstSession.ClientProxy, secondSession.ClientProxy); Assert.AreNotEqual(firstSession.Id, secondSession.Id); Assert.AreNotEqual(firstSession.StartupToken, secondSession.StartupToken); - - sut.CurrentSession.ClientProcess = null; - sut.CurrentSession.ClientProxy = null; - sut.InitializeSessionConfiguration(); - - var thirdSession = sut.CurrentSession; - - Assert.IsNull(thirdSession.ClientProcess); - Assert.IsNull(thirdSession.ClientProxy); Assert.AreNotEqual(secondSession.Id, thirdSession.Id); Assert.AreNotEqual(secondSession.StartupToken, thirdSession.StartupToken); } - - [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void MustNotAllowNullForExecutablePath() - { - new ConfigurationRepository(null, null, null, null); - } - - [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void MustNotAllowNullForProgramCopyright() - { - new ConfigurationRepository(string.Empty, null, null, null); - } - - [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void MustNotAllowNullForProgramTitle() - { - new ConfigurationRepository(string.Empty, string.Empty, null, null); - } - - [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void MustNotAllowNullForProgramVersion() - { - new ConfigurationRepository(string.Empty, string.Empty, string.Empty, null); - } } } diff --git a/SafeExamBrowser.Core.UnitTests/OperationModel/OperationSequenceTests.cs b/SafeExamBrowser.Core.UnitTests/OperationModel/OperationSequenceTests.cs index ea17bfcf..fbb72cc9 100644 --- a/SafeExamBrowser.Core.UnitTests/OperationModel/OperationSequenceTests.cs +++ b/SafeExamBrowser.Core.UnitTests/OperationModel/OperationSequenceTests.cs @@ -350,9 +350,9 @@ namespace SafeExamBrowser.Core.UnitTests.OperationModel operationB.Setup(o => o.Perform()).Returns(OperationResult.Success); operationC.Setup(o => o.Perform()).Returns(OperationResult.Success); - operationA.Setup(o => o.Revert()).Callback(() => a = ++current); - operationB.Setup(o => o.Revert()).Callback(() => b = ++current); - operationC.Setup(o => o.Revert()).Callback(() => c = ++current); + operationA.Setup(o => o.Revert()).Returns(OperationResult.Success).Callback(() => a = ++current); + operationB.Setup(o => o.Revert()).Returns(OperationResult.Success).Callback(() => b = ++current); + operationC.Setup(o => o.Revert()).Returns(OperationResult.Success).Callback(() => c = ++current); operations.Enqueue(operationA.Object); operations.Enqueue(operationB.Object); diff --git a/SafeExamBrowser.Runtime.UnitTests/Communication/RuntimeHostTests.cs b/SafeExamBrowser.Runtime.UnitTests/Communication/RuntimeHostTests.cs index bbb79517..a6f9a71d 100644 --- a/SafeExamBrowser.Runtime.UnitTests/Communication/RuntimeHostTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/Communication/RuntimeHostTests.cs @@ -12,7 +12,6 @@ using Moq; using SafeExamBrowser.Contracts.Communication; using SafeExamBrowser.Contracts.Communication.Data; using SafeExamBrowser.Contracts.Communication.Hosts; -using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Runtime.Communication; @@ -21,7 +20,6 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication [TestClass] public class RuntimeHostTests { - private Mock configuration; private Mock hostObject; private Mock hostObjectFactory; private Mock logger; @@ -30,14 +28,13 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication [TestInitialize] public void Initialize() { - configuration = new Mock(); hostObject = new Mock(); hostObjectFactory = new Mock(); logger = new Mock(); hostObjectFactory.Setup(f => f.CreateObject(It.IsAny(), It.IsAny())).Returns(hostObject.Object); - sut = new RuntimeHost("net:pipe://some/address", configuration.Object, hostObjectFactory.Object, logger.Object, 0); + sut = new RuntimeHost("net:pipe://some/address", hostObjectFactory.Object, logger.Object, 0); } [TestMethod] diff --git a/SafeExamBrowser.Runtime.UnitTests/Operations/ClientOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Operations/ClientOperationTests.cs index 9c0e4f8b..2d32890d 100644 --- a/SafeExamBrowser.Runtime.UnitTests/Operations/ClientOperationTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/Operations/ClientOperationTests.cs @@ -26,21 +26,21 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations private Action clientReady; private Action terminated; private AppConfig appConfig; - private Mock configuration; private Mock proxy; private Mock logger; private Mock process; private Mock processFactory; private Mock proxyFactory; private Mock runtimeHost; - private Mock session; + private Mock session; + private SessionContext sessionContext; + private ClientOperation sut; [TestInitialize] public void Initialize() { appConfig = new AppConfig(); - configuration = new Mock(); clientReady = new Action(() => runtimeHost.Raise(h => h.ClientReady += null)); logger = new Mock(); process = new Mock(); @@ -48,20 +48,20 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations proxy = new Mock(); proxyFactory = new Mock(); runtimeHost = new Mock(); - session = new Mock(); + session = new Mock(); + sessionContext = new SessionContext(); terminated = new Action(() => { runtimeHost.Raise(h => h.ClientDisconnected += null); process.Raise(p => p.Terminated += null, 0); }); - configuration.SetupGet(c => c.CurrentSession).Returns(session.Object); - configuration.SetupGet(c => c.AppConfig).Returns(appConfig); + session.SetupGet(s => s.AppConfig).Returns(appConfig); + sessionContext.Current = session.Object; + sessionContext.Next = session.Object; proxyFactory.Setup(f => f.CreateClientProxy(It.IsAny())).Returns(proxy.Object); - session.SetupGet(s => s.ClientProcess).Returns(process.Object); - session.SetupGet(s => s.ClientProxy).Returns(proxy.Object); - sut = new ClientOperation(configuration.Object, logger.Object, processFactory.Object, proxyFactory.Object, runtimeHost.Object, 0); + sut = new ClientOperation(logger.Object, processFactory.Object, proxyFactory.Object, runtimeHost.Object, sessionContext, 0); } [TestMethod] @@ -78,9 +78,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations result = sut.Perform(); - session.VerifySet(s => s.ClientProcess = process.Object, Times.Once); - session.VerifySet(s => s.ClientProxy = proxy.Object, Times.Once); - + Assert.AreEqual(process.Object, sessionContext.ClientProcess); + Assert.AreEqual(proxy.Object, sessionContext.ClientProxy); Assert.AreEqual(OperationResult.Success, result); } @@ -91,9 +90,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations result = sut.Perform(); - session.VerifySet(s => s.ClientProcess = process.Object, Times.Never); - session.VerifySet(s => s.ClientProxy = proxy.Object, Times.Never); - + Assert.IsNull(sessionContext.ClientProcess); + Assert.IsNull(sessionContext.ClientProxy); Assert.AreEqual(OperationResult.Failed, result); } @@ -107,9 +105,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations result = sut.Perform(); - session.VerifySet(s => s.ClientProcess = process.Object, Times.Once); - session.VerifySet(s => s.ClientProxy = proxy.Object, Times.Once); - + Assert.IsNotNull(sessionContext.ClientProcess); + Assert.IsNotNull(sessionContext.ClientProxy); Assert.AreEqual(OperationResult.Failed, result); } @@ -127,9 +124,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations result = sut.Perform(); - session.VerifySet(s => s.ClientProcess = process.Object, Times.Once); - session.VerifySet(s => s.ClientProxy = proxy.Object, Times.Once); - + Assert.IsNotNull(sessionContext.ClientProcess); + Assert.IsNotNull(sessionContext.ClientProxy); Assert.AreEqual(OperationResult.Failed, result); } @@ -147,70 +143,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations result = sut.Repeat(); - session.VerifySet(s => s.ClientProcess = process.Object, Times.Once); - session.VerifySet(s => s.ClientProxy = proxy.Object, Times.Once); - - Assert.AreEqual(OperationResult.Success, result); - } - - [TestMethod] - public void MustTerminateClientOnRepeat() - { - var terminated = new Action(() => - { - runtimeHost.Raise(h => h.ClientDisconnected += null); - process.Raise(p => p.Terminated += null, 0); - }); - - proxy.Setup(p => p.Disconnect()).Callback(terminated); - session.SetupGet(s => s.ClientProcess).Returns(process.Object); - - var result = sut.Repeat(); - - proxy.Verify(p => p.InitiateShutdown(), Times.Once); - proxy.Verify(p => p.Disconnect(), Times.Once); - process.Verify(p => p.Kill(), Times.Never); - session.VerifySet(s => s.ClientProcess = null, Times.Once); - session.VerifySet(s => s.ClientProxy = null, Times.Once); - - Assert.AreEqual(OperationResult.Success, result); - } - - [TestMethod] - public void MustDoNothingIfNoClientCreated() - { - session.SetupGet(s => s.ClientProcess).Returns(null as IProcess); - - var result = sut.Repeat(); - - session.VerifyGet(s => s.ClientProcess, Times.Once); - - process.VerifyNoOtherCalls(); - processFactory.VerifyNoOtherCalls(); - proxy.VerifyNoOtherCalls(); - proxyFactory.VerifyNoOtherCalls(); - runtimeHost.VerifyNoOtherCalls(); - - Assert.AreEqual(OperationResult.Success, result); - } - - [TestMethod] - public void MustDoNothingIfNoClientRunning() - { - process.SetupGet(p => p.HasTerminated).Returns(true); - session.SetupGet(s => s.ClientProcess).Returns(process.Object); - - var result = sut.Repeat(); - - process.VerifyGet(p => p.HasTerminated, Times.Once); - session.VerifyGet(s => s.ClientProcess, Times.Exactly(2)); - - process.VerifyNoOtherCalls(); - processFactory.VerifyNoOtherCalls(); - proxy.VerifyNoOtherCalls(); - proxyFactory.VerifyNoOtherCalls(); - runtimeHost.VerifyNoOtherCalls(); - + Assert.AreEqual(process.Object, sessionContext.ClientProcess); + Assert.AreEqual(proxy.Object, sessionContext.ClientProxy); Assert.AreEqual(OperationResult.Success, result); } @@ -225,8 +159,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations proxy.Verify(p => p.InitiateShutdown(), Times.Once); proxy.Verify(p => p.Disconnect(), Times.Once); process.Verify(p => p.Kill(), Times.Never); - session.VerifySet(s => s.ClientProcess = null, Times.Once); - session.VerifySet(s => s.ClientProxy = null, Times.Once); + + Assert.IsNull(sessionContext.ClientProcess); + Assert.IsNull(sessionContext.ClientProxy); } [TestMethod] @@ -238,8 +173,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations sut.Revert(); process.Verify(p => p.Kill(), Times.AtLeastOnce); - session.VerifySet(s => s.ClientProcess = null, Times.Once); - session.VerifySet(s => s.ClientProxy = null, Times.Once); + + Assert.IsNull(sessionContext.ClientProcess); + Assert.IsNull(sessionContext.ClientProxy); } [TestMethod] @@ -249,12 +185,13 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations sut.Revert(); process.Verify(p => p.Kill(), Times.Exactly(5)); - session.VerifySet(s => s.ClientProcess = null, Times.Never); - session.VerifySet(s => s.ClientProxy = null, Times.Never); + + Assert.IsNotNull(sessionContext.ClientProcess); + Assert.IsNotNull(sessionContext.ClientProxy); } [TestMethod] - public void MustNotStopClientIfAlreadyTerminated() + public void MustNotStopClientOnRevertIfAlreadyTerminated() { process.SetupGet(p => p.HasTerminated).Returns(true); @@ -263,8 +200,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations proxy.Verify(p => p.InitiateShutdown(), Times.Never); proxy.Verify(p => p.Disconnect(), Times.Never); process.Verify(p => p.Kill(), Times.Never); - session.VerifySet(s => s.ClientProcess = null, Times.Never); - session.VerifySet(s => s.ClientProxy = null, Times.Never); + + Assert.IsNull(sessionContext.ClientProcess); + Assert.IsNull(sessionContext.ClientProxy); } private void PerformNormally() diff --git a/SafeExamBrowser.Runtime.UnitTests/Operations/ClientTerminationOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Operations/ClientTerminationOperationTests.cs new file mode 100644 index 00000000..db39b5f5 --- /dev/null +++ b/SafeExamBrowser.Runtime.UnitTests/Operations/ClientTerminationOperationTests.cs @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET) + * + * 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 Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using SafeExamBrowser.Contracts.Communication.Hosts; +using SafeExamBrowser.Contracts.Communication.Proxies; +using SafeExamBrowser.Contracts.Configuration; +using SafeExamBrowser.Contracts.Core.OperationModel; +using SafeExamBrowser.Contracts.Logging; +using SafeExamBrowser.Contracts.WindowsApi; +using SafeExamBrowser.Runtime.Operations; + +namespace SafeExamBrowser.Runtime.UnitTests.Operations +{ + [TestClass] + public class ClientTerminationOperationTests + { + private Action clientReady; + private Action terminated; + private AppConfig appConfig; + private Mock proxy; + private Mock logger; + private Mock process; + private Mock processFactory; + private Mock proxyFactory; + private Mock runtimeHost; + private Mock session; + private SessionContext sessionContext; + + private ClientTerminationOperation sut; + + [TestInitialize] + public void Initialize() + { + appConfig = new AppConfig(); + clientReady = new Action(() => runtimeHost.Raise(h => h.ClientReady += null)); + logger = new Mock(); + process = new Mock(); + processFactory = new Mock(); + proxy = new Mock(); + proxyFactory = new Mock(); + runtimeHost = new Mock(); + session = new Mock(); + sessionContext = new SessionContext(); + terminated = new Action(() => + { + runtimeHost.Raise(h => h.ClientDisconnected += null); + process.Raise(p => p.Terminated += null, 0); + }); + + session.SetupGet(s => s.AppConfig).Returns(appConfig); + sessionContext.ClientProcess = process.Object; + sessionContext.ClientProxy = proxy.Object; + sessionContext.Current = session.Object; + sessionContext.Next = session.Object; + proxyFactory.Setup(f => f.CreateClientProxy(It.IsAny())).Returns(proxy.Object); + + sut = new ClientTerminationOperation(logger.Object, processFactory.Object, proxyFactory.Object, runtimeHost.Object, sessionContext, 0); + } + + [TestMethod] + public void MustTerminateClientOnRepeat() + { + var terminated = new Action(() => + { + runtimeHost.Raise(h => h.ClientDisconnected += null); + process.Raise(p => p.Terminated += null, 0); + }); + + proxy.Setup(p => p.Disconnect()).Callback(terminated); + + var result = sut.Repeat(); + + proxy.Verify(p => p.InitiateShutdown(), Times.Once); + proxy.Verify(p => p.Disconnect(), Times.Once); + process.Verify(p => p.Kill(), Times.Never); + + Assert.IsNull(sessionContext.ClientProcess); + Assert.IsNull(sessionContext.ClientProxy); + Assert.AreEqual(OperationResult.Success, result); + } + + [TestMethod] + public void MustDoNothingOnRepeatIfNoClientRunning() + { + process.SetupGet(p => p.HasTerminated).Returns(true); + sessionContext.ClientProcess = process.Object; + + var result = sut.Repeat(); + + process.VerifyGet(p => p.HasTerminated, Times.Once); + + process.VerifyNoOtherCalls(); + processFactory.VerifyNoOtherCalls(); + proxy.VerifyNoOtherCalls(); + proxyFactory.VerifyNoOtherCalls(); + runtimeHost.VerifyNoOtherCalls(); + + Assert.AreEqual(OperationResult.Success, result); + } + } +} diff --git a/SafeExamBrowser.Runtime.UnitTests/Operations/ConfigurationOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Operations/ConfigurationOperationTests.cs index 20e45362..816c2f1b 100644 --- a/SafeExamBrowser.Runtime.UnitTests/Operations/ConfigurationOperationTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/Operations/ConfigurationOperationTests.cs @@ -11,7 +11,6 @@ using System.IO; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using SafeExamBrowser.Contracts.Communication.Data; -using SafeExamBrowser.Contracts.Communication.Proxies; using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration.Settings; using SafeExamBrowser.Contracts.Core.OperationModel; @@ -28,7 +27,10 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations private Mock logger; private Mock repository; private Mock resourceLoader; + private Mock session; + private SessionContext sessionContext; private Settings settings; + private ConfigurationOperation sut; [TestInitialize] @@ -38,32 +40,36 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations logger = new Mock(); repository = new Mock(); resourceLoader = new Mock(); + session = new Mock(); + sessionContext = new SessionContext(); settings = new Settings(); appConfig.AppDataFolder = @"C:\Not\Really\AppData"; appConfig.DefaultSettingsFileName = "SettingsDummy.txt"; appConfig.ProgramDataFolder = @"C:\Not\Really\ProgramData"; - - repository.SetupGet(r => r.CurrentSettings).Returns(settings); + session.SetupGet(s => s.AppConfig).Returns(appConfig); + session.SetupGet(s => s.Settings).Returns(settings); + sessionContext.Next = session.Object; } [TestMethod] public void MustUseCommandLineArgumentAs1stPrio() { + var settings = default(Settings); var url = @"http://www.safeexambrowser.org/whatever.seb"; var location = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations)); appConfig.ProgramDataFolder = location; appConfig.AppDataFolder = location; - repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.Success); + repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, null, null)).Returns(LoadStatus.Success); - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url }); + sut = new ConfigurationOperation(new[] { "blubb.exe", url }, repository.Object, logger.Object, resourceLoader.Object, sessionContext); sut.Perform(); var resource = new Uri(url); - repository.Verify(r => r.LoadSettings(It.Is(u => u.Equals(resource)), null, null), Times.Once); + repository.Verify(r => r.TryLoadSettings(It.Is(u => u.Equals(resource)), out settings, null, null), Times.Once); } [TestMethod] @@ -74,14 +80,14 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations appConfig.ProgramDataFolder = location; appConfig.AppDataFolder = $@"{location}\WRONG"; - repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.Success); + repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, null, null)).Returns(LoadStatus.Success); - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, null); + sut = new ConfigurationOperation(null, repository.Object, logger.Object, resourceLoader.Object, sessionContext); sut.Perform(); var resource = new Uri(Path.Combine(location, "SettingsDummy.txt")); - repository.Verify(r => r.LoadSettings(It.Is(u => u.Equals(resource)), null, null), Times.Once); + repository.Verify(r => r.TryLoadSettings(It.Is(u => u.Equals(resource)), out settings, null, null), Times.Once); } [TestMethod] @@ -91,20 +97,20 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations appConfig.AppDataFolder = location; - repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.Success); + repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, null, null)).Returns(LoadStatus.Success); - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, null); + sut = new ConfigurationOperation(null, repository.Object, logger.Object, resourceLoader.Object, sessionContext); sut.Perform(); var resource = new Uri(Path.Combine(location, "SettingsDummy.txt")); - repository.Verify(r => r.LoadSettings(It.Is(u => u.Equals(resource)), null, null), Times.Once); + repository.Verify(r => r.TryLoadSettings(It.Is(u => u.Equals(resource)), out settings, null, null), Times.Once); } [TestMethod] public void MustFallbackToDefaultsAsLastPrio() { - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, null); + sut = new ConfigurationOperation(null, repository.Object, logger.Object, resourceLoader.Object, sessionContext); sut.Perform(); repository.Verify(r => r.LoadDefaultSettings(), Times.Once); @@ -114,9 +120,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations public void MustAbortIfWishedByUser() { appConfig.ProgramDataFolder = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations)); - repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.Success); + repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, null, null)).Returns(LoadStatus.Success); - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, null); + sut = new ConfigurationOperation(null, repository.Object, logger.Object, resourceLoader.Object, sessionContext); sut.ActionRequired += args => { if (args is ConfigurationCompletedEventArgs c) @@ -133,9 +139,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations [TestMethod] public void MustNotAbortIfNotWishedByUser() { - repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.Success); + repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, null, null)).Returns(LoadStatus.Success); - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, null); + sut = new ConfigurationOperation(null, repository.Object, logger.Object, resourceLoader.Object, sessionContext); sut.ActionRequired += args => { if (args is ConfigurationCompletedEventArgs c) @@ -153,9 +159,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations public void MustNotAllowToAbortIfNotInConfigureClientMode() { settings.ConfigurationMode = ConfigurationMode.Exam; - repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.Success); + repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, null, null)).Returns(LoadStatus.Success); - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, null); + sut = new ConfigurationOperation(null, repository.Object, logger.Object, resourceLoader.Object, sessionContext); sut.ActionRequired += args => { if (args is ConfigurationCompletedEventArgs c) @@ -172,10 +178,10 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations { repository.Setup(r => r.LoadDefaultSettings()); - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, null); + sut = new ConfigurationOperation(null, repository.Object, logger.Object, resourceLoader.Object, sessionContext); sut.Perform(); - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new string[] { }); + sut = new ConfigurationOperation(new string[] { }, repository.Object, logger.Object, resourceLoader.Object, sessionContext); sut.Perform(); repository.Verify(r => r.LoadDefaultSettings(), Times.Exactly(2)); @@ -186,7 +192,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations { var uri = @"an/invalid\uri.'*%yolo/()你好"; - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", uri }); + sut = new ConfigurationOperation(new[] { "blubb.exe", uri }, repository.Object, logger.Object, resourceLoader.Object, sessionContext); sut.Perform(); } @@ -195,9 +201,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations { var url = @"http://www.safeexambrowser.org/whatever.seb"; - repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.AdminPasswordNeeded); + repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, null, null)).Returns(LoadStatus.AdminPasswordNeeded); - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url }); + sut = new ConfigurationOperation(new[] { "blubb.exe", url }, repository.Object, logger.Object, resourceLoader.Object, sessionContext); sut.ActionRequired += args => { if (args is PasswordRequiredEventArgs p) @@ -208,7 +214,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations sut.Perform(); - repository.Verify(r => r.LoadSettings(It.IsAny(), null, null), Times.Exactly(5)); + repository.Verify(r => r.TryLoadSettings(It.IsAny(), out settings, null, null), Times.Exactly(5)); } [TestMethod] @@ -216,9 +222,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations { var url = @"http://www.safeexambrowser.org/whatever.seb"; - repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded); + repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, null, null)).Returns(LoadStatus.SettingsPasswordNeeded); - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url }); + sut = new ConfigurationOperation(new[] { "blubb.exe", url }, repository.Object, logger.Object, resourceLoader.Object, sessionContext); sut.ActionRequired += args => { if (args is PasswordRequiredEventArgs p) @@ -229,7 +235,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations sut.Perform(); - repository.Verify(r => r.LoadSettings(It.IsAny(), null, null), Times.Exactly(5)); + repository.Verify(r => r.TryLoadSettings(It.IsAny(), out settings, null, null), Times.Exactly(5)); } [TestMethod] @@ -238,10 +244,10 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var password = "test"; var url = @"http://www.safeexambrowser.org/whatever.seb"; - repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.AdminPasswordNeeded); - repository.Setup(r => r.LoadSettings(It.IsAny(), password, null)).Returns(LoadStatus.Success); + repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, null, null)).Returns(LoadStatus.AdminPasswordNeeded); + repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, password, null)).Returns(LoadStatus.Success); - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url }); + sut = new ConfigurationOperation(new[] { "blubb.exe", url }, repository.Object, logger.Object, resourceLoader.Object, sessionContext); sut.ActionRequired += args => { if (args is PasswordRequiredEventArgs p) @@ -253,8 +259,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations sut.Perform(); - repository.Verify(r => r.LoadSettings(It.IsAny(), null, null), Times.Once); - repository.Verify(r => r.LoadSettings(It.IsAny(), password, null), Times.Once); + repository.Verify(r => r.TryLoadSettings(It.IsAny(), out settings, null, null), Times.Once); + repository.Verify(r => r.TryLoadSettings(It.IsAny(), out settings, password, null), Times.Once); } [TestMethod] @@ -263,10 +269,10 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var password = "test"; var url = @"http://www.safeexambrowser.org/whatever.seb"; - repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded); - repository.Setup(r => r.LoadSettings(It.IsAny(), null, password)).Returns(LoadStatus.Success); + repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, null, null)).Returns(LoadStatus.SettingsPasswordNeeded); + repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, null, password)).Returns(LoadStatus.Success); - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url }); + sut = new ConfigurationOperation(new[] { "blubb.exe", url }, repository.Object, logger.Object, resourceLoader.Object, sessionContext); sut.ActionRequired += args => { if (args is PasswordRequiredEventArgs p) @@ -278,8 +284,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations sut.Perform(); - repository.Verify(r => r.LoadSettings(It.IsAny(), null, null), Times.Once); - repository.Verify(r => r.LoadSettings(It.IsAny(), null, password), Times.Once); + repository.Verify(r => r.TryLoadSettings(It.IsAny(), out settings, null, null), Times.Once); + repository.Verify(r => r.TryLoadSettings(It.IsAny(), out settings, null, password), Times.Once); } [TestMethod] @@ -287,9 +293,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations { var url = @"http://www.safeexambrowser.org/whatever.seb"; - repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.AdminPasswordNeeded); + repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, null, null)).Returns(LoadStatus.AdminPasswordNeeded); - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url }); + sut = new ConfigurationOperation(new[] { "blubb.exe", url }, repository.Object, logger.Object, resourceLoader.Object, sessionContext); sut.ActionRequired += args => { if (args is PasswordRequiredEventArgs p) @@ -308,9 +314,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations { var url = @"http://www.safeexambrowser.org/whatever.seb"; - repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded); + repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, null, null)).Returns(LoadStatus.SettingsPasswordNeeded); - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url }); + sut = new ConfigurationOperation(new[] { "blubb.exe", url }, repository.Object, logger.Object, resourceLoader.Object, sessionContext); sut.ActionRequired += args => { if (args is PasswordRequiredEventArgs p) @@ -331,11 +337,11 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var settingsPassword = "abc"; var url = @"http://www.safeexambrowser.org/whatever.seb"; - repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded); - repository.Setup(r => r.LoadSettings(It.IsAny(), null, settingsPassword)).Returns(LoadStatus.AdminPasswordNeeded); - repository.Setup(r => r.LoadSettings(It.IsAny(), adminPassword, settingsPassword)).Returns(LoadStatus.Success); + repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, null, null)).Returns(LoadStatus.SettingsPasswordNeeded); + repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, null, settingsPassword)).Returns(LoadStatus.AdminPasswordNeeded); + repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, adminPassword, settingsPassword)).Returns(LoadStatus.Success); - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url }); + sut = new ConfigurationOperation(new[] { "blubb.exe", url }, repository.Object, logger.Object, resourceLoader.Object, sessionContext); sut.ActionRequired += args => { if (args is PasswordRequiredEventArgs p) @@ -347,30 +353,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations sut.Perform(); - repository.Verify(r => r.LoadSettings(It.IsAny(), null, null), Times.Once); - repository.Verify(r => r.LoadSettings(It.IsAny(), null, settingsPassword), Times.Once); - repository.Verify(r => r.LoadSettings(It.IsAny(), adminPassword, settingsPassword), Times.Once); - } - - [TestMethod] - public void MustNotWaitForPasswordViaClientIfCommunicationHasFailed() - { - var clientProxy = new Mock(); - var communication = new CommunicationResult(false); - var session = new Mock(); - var url = @"http://www.safeexambrowser.org/whatever.seb"; - - clientProxy.Setup(c => c.RequestPassword(It.IsAny(), It.IsAny())).Returns(communication); - repository.SetupGet(r => r.CurrentSession).Returns(session.Object); - repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded); - session.SetupGet(r => r.ClientProxy).Returns(clientProxy.Object); - settings.KioskMode = KioskMode.CreateNewDesktop; - - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url }); - - var result = sut.Perform(); - - Assert.AreEqual(OperationResult.Aborted, result); + repository.Verify(r => r.TryLoadSettings(It.IsAny(), out settings, null, null), Times.Once); + repository.Verify(r => r.TryLoadSettings(It.IsAny(), out settings, null, settingsPassword), Times.Once); + repository.Verify(r => r.TryLoadSettings(It.IsAny(), out settings, adminPassword, settingsPassword), Times.Once); } [TestMethod] @@ -379,9 +364,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var url = @"http://www.safeexambrowser.org/whatever.seb"; resourceLoader.Setup(r => r.IsHtmlResource(It.IsAny())).Returns(false); - repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.InvalidData); + repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, null, null)).Returns(LoadStatus.InvalidData); - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url }); + sut = new ConfigurationOperation(new[] { "blubb.exe", url }, repository.Object, logger.Object, resourceLoader.Object, sessionContext); var result = sut.Perform(); @@ -394,9 +379,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var url = "http://www.blubb.org/some/resource.html"; resourceLoader.Setup(r => r.IsHtmlResource(It.IsAny())).Returns(true); - repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.InvalidData); + repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, null, null)).Returns(LoadStatus.InvalidData); - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, new[] { "blubb.exe", url }); + sut = new ConfigurationOperation(new[] { "blubb.exe", url }, repository.Object, logger.Object, resourceLoader.Object, sessionContext); var result = sut.Perform(); @@ -410,14 +395,14 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var location = Path.GetDirectoryName(GetType().Assembly.Location); var resource = new Uri(Path.Combine(location, nameof(Operations), "SettingsDummy.txt")); - repository.SetupGet(r => r.ReconfigurationFilePath).Returns(resource.AbsolutePath); - repository.Setup(r => r.LoadSettings(It.Is(u => u.Equals(resource)), null, null)).Returns(LoadStatus.Success); + sessionContext.ReconfigurationFilePath = resource.AbsolutePath; + repository.Setup(r => r.TryLoadSettings(It.Is(u => u.Equals(resource)), out settings, null, null)).Returns(LoadStatus.Success); - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, null); + sut = new ConfigurationOperation(null, repository.Object, logger.Object, resourceLoader.Object, sessionContext); var result = sut.Repeat(); - repository.Verify(r => r.LoadSettings(It.Is(u => u.Equals(resource)), null, null), Times.Once); + repository.Verify(r => r.TryLoadSettings(It.Is(u => u.Equals(resource)), out settings, null, null), Times.Once); Assert.AreEqual(OperationResult.Success, result); } @@ -427,20 +412,20 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations { var resource = new Uri("file:///C:/does/not/exist.txt"); - repository.SetupGet(r => r.ReconfigurationFilePath).Returns(null as string); - repository.Setup(r => r.LoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.Success); + sessionContext.ReconfigurationFilePath = null; + repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, null, null)).Returns(LoadStatus.Success); - sut = new ConfigurationOperation(appConfig, repository.Object, logger.Object, resourceLoader.Object, null); + sut = new ConfigurationOperation(null, repository.Object, logger.Object, resourceLoader.Object, sessionContext); var result = sut.Repeat(); - repository.Verify(r => r.LoadSettings(It.Is(u => u.Equals(resource)), null, null), Times.Never); + repository.Verify(r => r.TryLoadSettings(It.Is(u => u.Equals(resource)), out settings, null, null), Times.Never); Assert.AreEqual(OperationResult.Failed, result); - repository.SetupGet(r => r.ReconfigurationFilePath).Returns(resource.AbsolutePath); + sessionContext.ReconfigurationFilePath = resource.AbsolutePath; result = sut.Repeat(); - repository.Verify(r => r.LoadSettings(It.Is(u => u.Equals(resource)), null, null), Times.Never); + repository.Verify(r => r.TryLoadSettings(It.Is(u => u.Equals(resource)), out settings, null, null), Times.Never); Assert.AreEqual(OperationResult.Failed, result); } } diff --git a/SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeOperationTests.cs index 889b4f96..6e140fd5 100644 --- a/SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeOperationTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeOperationTests.cs @@ -10,6 +10,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration.Settings; +using SafeExamBrowser.Contracts.Core.OperationModel; using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.WindowsApi; using SafeExamBrowser.Runtime.Operations; @@ -19,27 +20,37 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations [TestClass] public class KioskModeOperationTests { - private Mock configuration; + private Mock currentSession; + private Settings currentSettings; private Mock desktopFactory; private Mock explorerShell; private Mock logger; + private Mock nextSession; + private Settings nextSettings; private Mock processFactory; - private Settings settings; + private SessionContext sessionContext; + private KioskModeOperation sut; [TestInitialize] public void Initialize() { - configuration = new Mock(); + currentSession = new Mock(); + currentSettings = new Settings(); desktopFactory = new Mock(); explorerShell = new Mock(); logger = new Mock(); + nextSession = new Mock(); + nextSettings = new Settings(); processFactory = new Mock(); - settings = new Settings(); + sessionContext = new SessionContext(); - configuration.SetupGet(c => c.CurrentSettings).Returns(settings); + currentSession.SetupGet(s => s.Settings).Returns(currentSettings); + nextSession.SetupGet(s => s.Settings).Returns(nextSettings); + sessionContext.Current = currentSession.Object; + sessionContext.Next = nextSession.Object; - sut = new KioskModeOperation(configuration.Object, desktopFactory.Object, explorerShell.Object, logger.Object, processFactory.Object); + sut = new KioskModeOperation(desktopFactory.Object, explorerShell.Object, logger.Object, processFactory.Object, sessionContext); } [TestMethod] @@ -54,7 +65,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var setStartup = 0; var suspend = 0; - settings.KioskMode = KioskMode.CreateNewDesktop; + nextSettings.KioskMode = KioskMode.CreateNewDesktop; desktopFactory.Setup(f => f.GetCurrent()).Callback(() => getCurrrent = ++order).Returns(originalDesktop.Object); desktopFactory.Setup(f => f.CreateNew(It.IsAny())).Callback(() => createNew = ++order).Returns(newDesktop.Object); @@ -70,6 +81,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations processFactory.VerifySet(f => f.StartupDesktop = newDesktop.Object, Times.Once); explorerShell.Verify(s => s.Suspend(), Times.Once); + Assert.AreSame(sessionContext.NewDesktop, newDesktop.Object); + Assert.AreSame(sessionContext.OriginalDesktop, originalDesktop.Object); Assert.AreEqual(1, getCurrrent); Assert.AreEqual(2, createNew); Assert.AreEqual(3, activate); @@ -80,7 +93,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations [TestMethod] public void MustCorrectlyInitializeDisableExplorerShell() { - settings.KioskMode = KioskMode.DisableExplorerShell; + nextSettings.KioskMode = KioskMode.DisableExplorerShell; sut.Perform(); @@ -98,7 +111,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var close = 0; var resume = 0; - settings.KioskMode = KioskMode.CreateNewDesktop; + currentSettings.KioskMode = KioskMode.CreateNewDesktop; + nextSettings.KioskMode = KioskMode.CreateNewDesktop; desktopFactory.Setup(f => f.GetCurrent()).Returns(originalDesktop.Object); desktopFactory.Setup(f => f.CreateNew(It.IsAny())).Returns(newDesktop.Object); @@ -107,14 +121,16 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations newDesktop.Setup(d => d.Close()).Callback(() => close = ++order); explorerShell.Setup(s => s.Resume()).Callback(() => resume = ++order); - sut.Perform(); - sut.Revert(); + var performResult = sut.Perform(); + var revertResult = sut.Revert(); originalDesktop.Verify(d => d.Activate(), Times.Once); processFactory.VerifySet(f => f.StartupDesktop = originalDesktop.Object, Times.Once); newDesktop.Verify(d => d.Close(), Times.Once); explorerShell.Verify(s => s.Resume(), Times.Once); + Assert.AreEqual(OperationResult.Success, performResult); + Assert.AreEqual(OperationResult.Success, revertResult); Assert.AreEqual(1, activate); Assert.AreEqual(2, setStartup); Assert.AreEqual(3, close); @@ -124,25 +140,32 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations [TestMethod] public void MustCorrectlyRevertDisableExplorerShell() { - settings.KioskMode = KioskMode.DisableExplorerShell; + currentSettings.KioskMode = KioskMode.DisableExplorerShell; + nextSettings.KioskMode = KioskMode.DisableExplorerShell; - sut.Perform(); - sut.Revert(); + var performResult = sut.Perform(); + var revertResult = sut.Revert(); explorerShell.Verify(s => s.Start(), Times.Once); + + Assert.AreEqual(OperationResult.Success, performResult); + Assert.AreEqual(OperationResult.Success, revertResult); } [TestMethod] - public void MustCorrectlySwitchToOtherKioskModeWhenRepeating() + public void MustCorrectlyStartNewKioskModeWhenRepeating() { var newDesktop = new Mock(); var originalDesktop = new Mock(); + var result = default(OperationResult); desktopFactory.Setup(f => f.GetCurrent()).Returns(originalDesktop.Object); desktopFactory.Setup(f => f.CreateNew(It.IsAny())).Returns(newDesktop.Object); + nextSettings.KioskMode = KioskMode.CreateNewDesktop; - settings.KioskMode = KioskMode.CreateNewDesktop; - sut.Perform(); + result = sut.Perform(); + + Assert.AreEqual(OperationResult.Success, result); explorerShell.Verify(s => s.Terminate(), Times.Never); explorerShell.Verify(s => s.Start(), Times.Never); @@ -152,33 +175,43 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations newDesktop.Verify(d => d.Close(), Times.Never); originalDesktop.Verify(d => d.Activate(), Times.Never); - settings.KioskMode = KioskMode.DisableExplorerShell; - sut.Repeat(); + nextSettings.KioskMode = KioskMode.DisableExplorerShell; - explorerShell.Verify(s => s.Resume(), Times.Once); + result = sut.Repeat(); + + Assert.AreEqual(OperationResult.Success, result); + + explorerShell.Verify(s => s.Resume(), Times.Never); explorerShell.Verify(s => s.Terminate(), Times.Once); explorerShell.Verify(s => s.Suspend(), Times.Once); explorerShell.Verify(s => s.Start(), Times.Never); newDesktop.Verify(d => d.Activate(), Times.Once); - newDesktop.Verify(d => d.Close(), Times.Once); - originalDesktop.Verify(d => d.Activate(), Times.Once); + newDesktop.Verify(d => d.Close(), Times.Never); + originalDesktop.Verify(d => d.Activate(), Times.Never); - settings.KioskMode = KioskMode.CreateNewDesktop; - sut.Repeat(); + currentSettings.KioskMode = nextSettings.KioskMode; + nextSettings.KioskMode = KioskMode.CreateNewDesktop; - explorerShell.Verify(s => s.Resume(), Times.Once); + result = sut.Repeat(); + + Assert.AreEqual(OperationResult.Success, result); + + explorerShell.Verify(s => s.Resume(), Times.Never); explorerShell.Verify(s => s.Terminate(), Times.Once); explorerShell.Verify(s => s.Suspend(), Times.Exactly(2)); - explorerShell.Verify(s => s.Start(), Times.Once); + explorerShell.Verify(s => s.Start(), Times.Never); newDesktop.Verify(d => d.Activate(), Times.Exactly(2)); - newDesktop.Verify(d => d.Close(), Times.Once); - originalDesktop.Verify(d => d.Activate(), Times.Once); + newDesktop.Verify(d => d.Close(), Times.Never); + originalDesktop.Verify(d => d.Activate(), Times.Never); + + Assert.AreSame(sessionContext.NewDesktop, newDesktop.Object); + Assert.AreSame(sessionContext.OriginalDesktop, originalDesktop.Object); } [TestMethod] public void MustDoNothingWithoutKioskMode() { - settings.KioskMode = KioskMode.None; + nextSettings.KioskMode = KioskMode.None; sut.Perform(); sut.Repeat(); @@ -195,7 +228,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var newDesktop = new Mock(); var originalDesktop = new Mock(); - settings.KioskMode = KioskMode.CreateNewDesktop; + currentSettings.KioskMode = KioskMode.CreateNewDesktop; + nextSettings.KioskMode = KioskMode.CreateNewDesktop; desktopFactory.Setup(f => f.GetCurrent()).Returns(originalDesktop.Object); desktopFactory.Setup(f => f.CreateNew(It.IsAny())).Returns(newDesktop.Object); @@ -212,12 +246,16 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations newDesktop.Verify(d => d.Activate(), Times.Once); processFactory.VerifySet(f => f.StartupDesktop = newDesktop.Object, Times.Once); explorerShell.Verify(s => s.Suspend(), Times.Once); + + Assert.AreSame(sessionContext.NewDesktop, newDesktop.Object); + Assert.AreSame(sessionContext.OriginalDesktop, originalDesktop.Object); } [TestMethod] public void MustNotReinitializeDisableExplorerShellWhenRepeating() { - settings.KioskMode = KioskMode.DisableExplorerShell; + currentSettings.KioskMode = KioskMode.DisableExplorerShell; + nextSettings.KioskMode = KioskMode.DisableExplorerShell; sut.Perform(); sut.Repeat(); diff --git a/SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeTerminationOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeTerminationOperationTests.cs new file mode 100644 index 00000000..9fb83993 --- /dev/null +++ b/SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeTerminationOperationTests.cs @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET) + * + * 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 Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using SafeExamBrowser.Contracts.Configuration; +using SafeExamBrowser.Contracts.Configuration.Settings; +using SafeExamBrowser.Contracts.Core.OperationModel; +using SafeExamBrowser.Contracts.Logging; +using SafeExamBrowser.Contracts.WindowsApi; +using SafeExamBrowser.Runtime.Operations; + +namespace SafeExamBrowser.Runtime.UnitTests.Operations +{ + [TestClass] + public class KioskModeTerminationOperationTests + { + private Mock desktopFactory; + private Mock explorerShell; + private Mock logger; + private Mock nextSession; + private Settings nextSettings; + private Mock processFactory; + private SessionContext sessionContext; + + private KioskModeTerminationOperation sut; + private Mock currentSession; + private Settings currentSettings; + + [TestInitialize] + public void Initialize() + { + currentSession = new Mock(); + currentSettings = new Settings(); + desktopFactory = new Mock(); + explorerShell = new Mock(); + logger = new Mock(); + nextSession = new Mock(); + nextSettings = new Settings(); + processFactory = new Mock(); + sessionContext = new SessionContext(); + + currentSession.SetupGet(s => s.Settings).Returns(currentSettings); + nextSession.SetupGet(s => s.Settings).Returns(nextSettings); + sessionContext.Current = currentSession.Object; + sessionContext.Next = nextSession.Object; + + sut = new KioskModeTerminationOperation(desktopFactory.Object, explorerShell.Object, logger.Object, processFactory.Object, sessionContext); + } + + [TestMethod] + public void MustDoNothingOnPerform() + { + var result = sut.Perform(); + + currentSession.VerifyNoOtherCalls(); + desktopFactory.VerifyNoOtherCalls(); + explorerShell.VerifyNoOtherCalls(); + logger.VerifyNoOtherCalls(); + nextSession.VerifyNoOtherCalls(); + processFactory.VerifyNoOtherCalls(); + + Assert.AreEqual(OperationResult.Success, result); + } + + [TestMethod] + public void MustCorrectlyTerminateOldKioskModeWhenRepeating() + { + var newDesktop = new Mock(); + var originalDesktop = new Mock(); + var result = default(OperationResult); + + sessionContext.NewDesktop = newDesktop.Object; + sessionContext.OriginalDesktop = originalDesktop.Object; + sessionContext.ActiveMode = KioskMode.DisableExplorerShell; + nextSettings.KioskMode = KioskMode.CreateNewDesktop; + + result = sut.Repeat(); + + Assert.AreEqual(OperationResult.Success, result); + + explorerShell.Verify(s => s.Resume(), Times.Never); + explorerShell.Verify(s => s.Start(), Times.Once); + explorerShell.Verify(s => s.Suspend(), Times.Never); + explorerShell.Verify(s => s.Terminate(), Times.Never); + newDesktop.Verify(d => d.Activate(), Times.Never); + newDesktop.Verify(d => d.Close(), Times.Never); + originalDesktop.Verify(d => d.Activate(), Times.Never); + + sessionContext.ActiveMode = nextSettings.KioskMode; + nextSettings.KioskMode = KioskMode.DisableExplorerShell; + + result = sut.Repeat(); + + Assert.AreEqual(OperationResult.Success, result); + + explorerShell.Verify(s => s.Resume(), Times.Once); + explorerShell.Verify(s => s.Start(), Times.Once); + explorerShell.Verify(s => s.Suspend(), Times.Never); + explorerShell.Verify(s => s.Terminate(), Times.Never); + newDesktop.Verify(d => d.Activate(), Times.Never); + newDesktop.Verify(d => d.Close(), Times.Once); + originalDesktop.Verify(d => d.Activate(), Times.Once); + + sessionContext.ActiveMode = nextSettings.KioskMode; + nextSettings.KioskMode = KioskMode.CreateNewDesktop; + + result = sut.Repeat(); + + Assert.AreEqual(OperationResult.Success, result); + + explorerShell.Verify(s => s.Resume(), Times.Once); + explorerShell.Verify(s => s.Start(), Times.Exactly(2)); + explorerShell.Verify(s => s.Suspend(), Times.Never); + explorerShell.Verify(s => s.Terminate(), Times.Never); + newDesktop.Verify(d => d.Activate(), Times.Never); + newDesktop.Verify(d => d.Close(), Times.Once); + originalDesktop.Verify(d => d.Activate(), Times.Once); + } + + [TestMethod] + public void MustNotTerminateKioskModeIfSameInNextSesssion() + { + + } + + [TestMethod] + public void MustDoNothingOnRevert() + { + var result = sut.Revert(); + + currentSession.VerifyNoOtherCalls(); + desktopFactory.VerifyNoOtherCalls(); + explorerShell.VerifyNoOtherCalls(); + logger.VerifyNoOtherCalls(); + nextSession.VerifyNoOtherCalls(); + processFactory.VerifyNoOtherCalls(); + + Assert.AreEqual(OperationResult.Success, result); + } + } +} diff --git a/SafeExamBrowser.Runtime.UnitTests/Operations/ServiceOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Operations/ServiceOperationTests.cs index 7c122e1e..46e0336d 100644 --- a/SafeExamBrowser.Runtime.UnitTests/Operations/ServiceOperationTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/Operations/ServiceOperationTests.cs @@ -23,8 +23,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations { private Mock logger; private Mock service; - private Mock configuration; - private Mock session; + private Mock session; + private SessionContext sessionContext; private Settings settings; private ServiceOperation sut; @@ -33,26 +33,27 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations { logger = new Mock(); service = new Mock(); - configuration = new Mock(); - session = new Mock(); + session = new Mock(); + sessionContext = new SessionContext(); settings = new Settings(); - configuration.SetupGet(c => c.CurrentSession).Returns(session.Object); - configuration.SetupGet(c => c.CurrentSettings).Returns(settings); + sessionContext.Current = session.Object; + sessionContext.Next = session.Object; + session.SetupGet(s => s.Settings).Returns(settings); - sut = new ServiceOperation(configuration.Object, logger.Object, service.Object); + sut = new ServiceOperation(logger.Object, service.Object, sessionContext); } [TestMethod] public void MustConnectToService() { service.Setup(s => s.Connect(null, true)).Returns(true); - configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Mandatory }); + settings.ServicePolicy = ServicePolicy.Mandatory; sut.Perform(); service.Setup(s => s.Connect(null, true)).Returns(true); - configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Optional }); + settings.ServicePolicy = ServicePolicy.Optional; sut.Perform(); @@ -83,12 +84,12 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations public void MustNotFailIfServiceNotAvailable() { service.Setup(s => s.Connect(null, true)).Returns(false); - configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Mandatory }); + settings.ServicePolicy = ServicePolicy.Mandatory; sut.Perform(); service.Setup(s => s.Connect(null, true)).Returns(false); - configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Optional }); + settings.ServicePolicy = ServicePolicy.Optional; sut.Perform(); } @@ -97,7 +98,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations public void MustFailIfServiceMandatoryAndNotAvailable() { service.Setup(s => s.Connect(null, true)).Returns(false); - configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Mandatory }); + settings.ServicePolicy = ServicePolicy.Mandatory; var result = sut.Perform(); @@ -108,7 +109,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations public void MustNotFailIfServiceOptionalAndNotAvailable() { service.Setup(s => s.Connect(null, true)).Returns(false); - configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Optional }); + settings.ServicePolicy = ServicePolicy.Optional; var result = sut.Perform(); @@ -121,13 +122,13 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations public void MustDisconnectWhenReverting() { service.Setup(s => s.Connect(null, true)).Returns(true); - configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Mandatory }); + settings.ServicePolicy = ServicePolicy.Mandatory; sut.Perform(); sut.Revert(); service.Setup(s => s.Connect(null, true)).Returns(true); - configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Optional }); + settings.ServicePolicy = ServicePolicy.Optional; sut.Perform(); sut.Revert(); @@ -162,7 +163,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations { service.Setup(s => s.Connect(null, true)).Returns(true); service.Setup(s => s.Disconnect()).Returns(false); - configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Optional }); + settings.ServicePolicy = ServicePolicy.Optional; sut.Perform(); sut.Revert(); @@ -174,13 +175,13 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations public void MustNotDisconnnectIfNotAvailable() { service.Setup(s => s.Connect(null, true)).Returns(false); - configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Mandatory }); + settings.ServicePolicy = ServicePolicy.Mandatory; sut.Perform(); sut.Revert(); service.Setup(s => s.Connect(null, true)).Returns(false); - configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Optional }); + settings.ServicePolicy = ServicePolicy.Optional; sut.Perform(); sut.Revert(); diff --git a/SafeExamBrowser.Runtime.UnitTests/Operations/SessionActivationOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Operations/SessionActivationOperationTests.cs new file mode 100644 index 00000000..11bfbf1a --- /dev/null +++ b/SafeExamBrowser.Runtime.UnitTests/Operations/SessionActivationOperationTests.cs @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET) + * + * 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 Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using SafeExamBrowser.Contracts.Configuration; +using SafeExamBrowser.Contracts.Core.OperationModel; +using SafeExamBrowser.Contracts.Logging; +using SafeExamBrowser.Runtime.Operations; + +namespace SafeExamBrowser.Runtime.UnitTests.Operations +{ + [TestClass] + public class SessionActivationOperationTests + { + private Mock currentSession; + private Mock logger; + private Mock nextSession; + private SessionContext sessionContext; + + private SessionActivationOperation sut; + + [TestInitialize] + public void Initialize() + { + currentSession = new Mock(); + logger = new Mock(); + nextSession = new Mock(); + sessionContext = new SessionContext(); + + sessionContext.Current = currentSession.Object; + sessionContext.Next = nextSession.Object; + + sut = new SessionActivationOperation(logger.Object, sessionContext); + } + + [TestMethod] + public void MustCorrectlyActivateFirstSession() + { + sessionContext.Current = null; + + var result = sut.Perform(); + + currentSession.VerifyNoOtherCalls(); + nextSession.VerifyGet(s => s.Id); + + Assert.AreEqual(OperationResult.Success, result); + Assert.AreSame(sessionContext.Current, nextSession.Object); + Assert.IsNull(sessionContext.Next); + } + + [TestMethod] + public void MustCorrectlySwitchSession() + { + var result = sut.Repeat(); + + currentSession.VerifyGet(s => s.Id); + nextSession.VerifyGet(s => s.Id); + + Assert.AreEqual(OperationResult.Success, result); + Assert.AreSame(sessionContext.Current, nextSession.Object); + Assert.IsNull(sessionContext.Next); + } + + [TestMethod] + public void MustAlwaysRevertSuccessfully() + { + var result = sut.Revert(); + + currentSession.VerifyNoOtherCalls(); + nextSession.VerifyNoOtherCalls(); + + Assert.AreEqual(OperationResult.Success, result); + } + } +} diff --git a/SafeExamBrowser.Runtime.UnitTests/Operations/SessionInitializationOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Operations/SessionInitializationOperationTests.cs index 7ff8c536..e5ef8019 100644 --- a/SafeExamBrowser.Runtime.UnitTests/Operations/SessionInitializationOperationTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/Operations/SessionInitializationOperationTests.cs @@ -23,7 +23,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations private Mock configuration; private Mock logger; private Mock runtimeHost; - private Mock session; + private Mock session; + private SessionContext sessionContext; + private SessionInitializationOperation sut; [TestInitialize] @@ -33,12 +35,14 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations configuration = new Mock(); logger = new Mock(); runtimeHost = new Mock(); - session = new Mock(); + session = new Mock(); + sessionContext = new SessionContext(); - configuration.SetupGet(c => c.CurrentSession).Returns(session.Object); - configuration.SetupGet(c => c.AppConfig).Returns(appConfig); + configuration.Setup(c => c.InitializeSessionConfiguration()).Returns(session.Object); + session.SetupGet(s => s.AppConfig).Returns(appConfig); + sessionContext.Next = session.Object; - sut = new SessionInitializationOperation(configuration.Object, logger.Object, runtimeHost.Object); + sut = new SessionInitializationOperation(configuration.Object, logger.Object, runtimeHost.Object, sessionContext); } [TestMethod] diff --git a/SafeExamBrowser.Runtime.UnitTests/RuntimeControllerTests.cs b/SafeExamBrowser.Runtime.UnitTests/RuntimeControllerTests.cs index 447736d0..2649e622 100644 --- a/SafeExamBrowser.Runtime.UnitTests/RuntimeControllerTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/RuntimeControllerTests.cs @@ -91,5 +91,26 @@ namespace SafeExamBrowser.Runtime.UnitTests // Assert.AreEqual(OperationResult.Aborted, result); //} + + //[TestMethod] + //public void MustNotWaitForPasswordViaClientIfCommunicationHasFailed() + //{ + // var clientProxy = new Mock(); + // var communication = new CommunicationResult(false); + // var session = new Mock(); + // var url = @"http://www.safeexambrowser.org/whatever.seb"; + + // clientProxy.Setup(c => c.RequestPassword(It.IsAny(), It.IsAny())).Returns(communication); + // repository.SetupGet(r => r.CurrentSession).Returns(session.Object); + // repository.Setup(r => r.TryLoadSettings(It.IsAny(), null, null)).Returns(LoadStatus.SettingsPasswordNeeded); + // session.SetupGet(r => r.ClientProxy).Returns(clientProxy.Object); + // settings.KioskMode = KioskMode.CreateNewDesktop; + + // sut = new ConfigurationOperation(new[] { "blubb.exe", url }, repository.Object, logger.Object, resourceLoader.Object, sessionContext); + + // var result = sut.Perform(); + + // Assert.AreEqual(OperationResult.Aborted, result); + //} } } diff --git a/SafeExamBrowser.Runtime.UnitTests/SafeExamBrowser.Runtime.UnitTests.csproj b/SafeExamBrowser.Runtime.UnitTests/SafeExamBrowser.Runtime.UnitTests.csproj index 2a4f3ecc..db89bd65 100644 --- a/SafeExamBrowser.Runtime.UnitTests/SafeExamBrowser.Runtime.UnitTests.csproj +++ b/SafeExamBrowser.Runtime.UnitTests/SafeExamBrowser.Runtime.UnitTests.csproj @@ -79,10 +79,13 @@ + + + diff --git a/SafeExamBrowser.Runtime/Operations/ClientOperation.cs b/SafeExamBrowser.Runtime/Operations/ClientOperation.cs index 7def87c3..e21a5fdd 100644 --- a/SafeExamBrowser.Runtime/Operations/ClientOperation.cs +++ b/SafeExamBrowser.Runtime/Operations/ClientOperation.cs @@ -66,11 +66,11 @@ namespace SafeExamBrowser.Runtime.Operations if (success) { - logger.Info($"Successfully started new client instance."); + logger.Info("Successfully started new client instance."); } else { - logger.Error($"Failed to start new client instance! Aborting procedure..."); + logger.Error("Failed to start new client instance! Aborting procedure..."); } return success ? OperationResult.Success : OperationResult.Failed; diff --git a/SafeExamBrowser.Runtime/Operations/KioskModeOperation.cs b/SafeExamBrowser.Runtime/Operations/KioskModeOperation.cs index 024c017d..b80f3995 100644 --- a/SafeExamBrowser.Runtime/Operations/KioskModeOperation.cs +++ b/SafeExamBrowser.Runtime/Operations/KioskModeOperation.cs @@ -17,15 +17,33 @@ namespace SafeExamBrowser.Runtime.Operations { internal class KioskModeOperation : SessionOperation { - protected IDesktopFactory desktopFactory; - protected IExplorerShell explorerShell; + private IDesktopFactory desktopFactory; + private IExplorerShell explorerShell; + private IProcessFactory processFactory; + protected ILogger logger; - protected IProcessFactory processFactory; - private static IDesktop newDesktop; - private static IDesktop originalDesktop; + private IDesktop NewDesktop + { + get { return Context.NewDesktop; } + set { Context.NewDesktop = value; } + } - protected static KioskMode? ActiveMode { get; private set; } + private IDesktop OriginalDesktop + { + get { return Context.OriginalDesktop; } + set { Context.OriginalDesktop = value; } + } + + /// + /// TODO: This mechanism exposes the internal state of the operation! Find better solution which will keep the + /// state internal but still allow unit testing of both kiosk mode operations independently! + /// + protected KioskMode? ActiveMode + { + get { return Context.ActiveMode; } + set { Context.ActiveMode = value; } + } public override event ActionRequiredEventHandler ActionRequired { add { } remove { } } public override event StatusChangedEventHandler StatusChanged; @@ -97,14 +115,14 @@ namespace SafeExamBrowser.Runtime.Operations private void CreateNewDesktop() { - originalDesktop = desktopFactory.GetCurrent(); - logger.Info($"Current desktop is {originalDesktop}."); + OriginalDesktop = desktopFactory.GetCurrent(); + logger.Info($"Current desktop is {OriginalDesktop}."); - newDesktop = desktopFactory.CreateNew(nameof(SafeExamBrowser)); - logger.Info($"Created new desktop {newDesktop}."); + NewDesktop = desktopFactory.CreateNew(nameof(SafeExamBrowser)); + logger.Info($"Created new desktop {NewDesktop}."); - newDesktop.Activate(); - processFactory.StartupDesktop = newDesktop; + NewDesktop.Activate(); + processFactory.StartupDesktop = NewDesktop; logger.Info("Successfully activated new desktop."); explorerShell.Suspend(); @@ -112,21 +130,21 @@ namespace SafeExamBrowser.Runtime.Operations private void CloseNewDesktop() { - if (originalDesktop != null) + if (OriginalDesktop != null) { - originalDesktop.Activate(); - processFactory.StartupDesktop = originalDesktop; - logger.Info($"Switched back to original desktop {originalDesktop}."); + OriginalDesktop.Activate(); + processFactory.StartupDesktop = OriginalDesktop; + logger.Info($"Switched back to original desktop {OriginalDesktop}."); } else { logger.Warn($"No original desktop found when attempting to close new desktop!"); } - if (newDesktop != null) + if (NewDesktop != null) { - newDesktop.Close(); - logger.Info($"Closed new desktop {newDesktop}."); + NewDesktop.Close(); + logger.Info($"Closed new desktop {NewDesktop}."); } else { diff --git a/SafeExamBrowser.Runtime/SessionContext.cs b/SafeExamBrowser.Runtime/SessionContext.cs index ac66560e..c534f082 100644 --- a/SafeExamBrowser.Runtime/SessionContext.cs +++ b/SafeExamBrowser.Runtime/SessionContext.cs @@ -8,6 +8,7 @@ using SafeExamBrowser.Contracts.Communication.Proxies; using SafeExamBrowser.Contracts.Configuration; +using SafeExamBrowser.Contracts.Configuration.Settings; using SafeExamBrowser.Contracts.WindowsApi; namespace SafeExamBrowser.Runtime @@ -17,6 +18,11 @@ namespace SafeExamBrowser.Runtime /// internal class SessionContext { + /// + /// The currently active . + /// + public KioskMode? ActiveMode { get; set; } + /// /// The currently running client process. /// @@ -32,11 +38,21 @@ namespace SafeExamBrowser.Runtime /// public ISessionConfiguration Current { get; set; } + /// + /// The new desktop, if is currently active. + /// + public IDesktop NewDesktop { get; set; } + /// /// The configuration of the next session to be activated. /// public ISessionConfiguration Next { get; set; } + /// + /// The original desktop, if is currently active. + /// + public IDesktop OriginalDesktop { get; set; } + /// /// The path of the configuration file to be used for reconfiguration. ///