diff --git a/SafeExamBrowser.Client.UnitTests/ClientControllerTests.cs b/SafeExamBrowser.Client.UnitTests/ClientControllerTests.cs index a7d611fd..571a9b6b 100644 --- a/SafeExamBrowser.Client.UnitTests/ClientControllerTests.cs +++ b/SafeExamBrowser.Client.UnitTests/ClientControllerTests.cs @@ -7,30 +7,30 @@ */ using Microsoft.VisualStudio.TestTools.UnitTesting; -using Moq; -using SafeExamBrowser.Client.Behaviour; -using SafeExamBrowser.Contracts.Behaviour.OperationModel; -using SafeExamBrowser.Contracts.Communication.Proxies; -using SafeExamBrowser.Contracts.Logging; -using SafeExamBrowser.Contracts.Monitoring; -using SafeExamBrowser.Contracts.UserInterface; -using SafeExamBrowser.Contracts.UserInterface.Taskbar; +//using Moq; +//using SafeExamBrowser.Client.Behaviour; +//using SafeExamBrowser.Contracts.Behaviour.OperationModel; +//using SafeExamBrowser.Contracts.Communication.Proxies; +//using SafeExamBrowser.Contracts.Logging; +//using SafeExamBrowser.Contracts.Monitoring; +//using SafeExamBrowser.Contracts.UserInterface; +//using SafeExamBrowser.Contracts.UserInterface.Taskbar; namespace SafeExamBrowser.Client.UnitTests { [TestClass] public class ClientControllerTests { - private Mock displayMonitorMock; - private Mock loggerMock; - private Mock processMonitorMock; - private Mock operationSequenceMock; - private Mock runtimeProxyMock; - private Mock taskbarMock; - private Mock uiFactoryMock; - private Mock windowMonitorMock; + //private Mock displayMonitorMock; + //private Mock loggerMock; + //private Mock processMonitorMock; + //private Mock operationSequenceMock; + //private Mock runtimeProxyMock; + //private Mock taskbarMock; + //private Mock uiFactoryMock; + //private Mock windowMonitorMock; - private ClientController sut; + //private ClientController sut; [TestMethod] public void TODO() diff --git a/SafeExamBrowser.Contracts/Behaviour/OperationModel/OperationResult.cs b/SafeExamBrowser.Contracts/Behaviour/OperationModel/OperationResult.cs index 37ce1b36..e8547b6e 100644 --- a/SafeExamBrowser.Contracts/Behaviour/OperationModel/OperationResult.cs +++ b/SafeExamBrowser.Contracts/Behaviour/OperationModel/OperationResult.cs @@ -16,7 +16,7 @@ namespace SafeExamBrowser.Contracts.Behaviour.OperationModel /// /// Indicates that the operation has been aborted due to an expected condition, e.g. as result of a user decision. /// - Aborted, + Aborted = 1, /// /// Indicates that the operation has failed due to an invalid or unexpected condition. diff --git a/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ClientOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ClientOperationTests.cs new file mode 100644 index 00000000..50bb559b --- /dev/null +++ b/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ClientOperationTests.cs @@ -0,0 +1,216 @@ +/* + * 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.Behaviour.OperationModel; +using SafeExamBrowser.Contracts.Communication.Data; +using SafeExamBrowser.Contracts.Communication.Hosts; +using SafeExamBrowser.Contracts.Communication.Proxies; +using SafeExamBrowser.Contracts.Configuration; +using SafeExamBrowser.Contracts.Logging; +using SafeExamBrowser.Contracts.WindowsApi; +using SafeExamBrowser.Runtime.Behaviour.Operations; + +namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations +{ + [TestClass] + public class ClientOperationTests + { + private Action clientReady; + private Action terminated; + private Mock configuration; + private Mock proxy; + private Mock logger; + private Mock process; + private Mock processFactory; + private Mock proxyFactory; + private Mock runtimeHost; + private RuntimeInfo runtimeInfo; + private Mock session; + private ClientOperation sut; + + [TestInitialize] + public void Initialize() + { + configuration = new Mock(); + 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(); + runtimeInfo = new RuntimeInfo(); + session = new Mock(); + 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.RuntimeInfo).Returns(runtimeInfo); + proxyFactory.Setup(f => f.CreateClientProxy(It.IsAny())).Returns(proxy.Object); + + sut = new ClientOperation(configuration.Object, logger.Object, processFactory.Object, proxyFactory.Object, runtimeHost.Object, 0); + } + + [TestMethod] + public void MustStartClientWhenPerforming() + { + var result = default(OperationResult); + var response = new AuthenticationResponse { ProcessId = 1234 }; + + process.SetupGet(p => p.Id).Returns(response.ProcessId); + processFactory.Setup(f => f.StartNew(It.IsAny(), It.IsAny())).Returns(process.Object).Callback(clientReady); + proxy.Setup(p => p.RequestAuthentication()).Returns(response); + proxy.Setup(p => p.Connect(It.IsAny(), true)).Returns(true); + + result = sut.Perform(); + + 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 MustStartClientWhenRepeating() + { + var result = default(OperationResult); + var response = new AuthenticationResponse { ProcessId = 1234 }; + + process.SetupGet(p => p.Id).Returns(response.ProcessId); + processFactory.Setup(f => f.StartNew(It.IsAny(), It.IsAny())).Returns(process.Object).Callback(clientReady); + proxy.Setup(p => p.RequestAuthentication()).Returns(response); + proxy.Setup(p => p.Connect(It.IsAny(), true)).Returns(true); + + 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 MustFailStartupIfClientNotStartedWithinTimeout() + { + var result = default(OperationResult); + + result = sut.Perform(); + + session.VerifySet(s => s.ClientProcess = process.Object, Times.Never); + session.VerifySet(s => s.ClientProxy = proxy.Object, Times.Never); + + Assert.AreEqual(OperationResult.Failed, result); + } + + [TestMethod] + public void MustFailStartupIfConnectionToClientNotEstablished() + { + var result = default(OperationResult); + + processFactory.Setup(f => f.StartNew(It.IsAny(), It.IsAny())).Returns(process.Object).Callback(clientReady); + proxy.Setup(p => p.Connect(It.IsAny(), true)).Returns(false); + + result = sut.Perform(); + + session.VerifySet(s => s.ClientProcess = process.Object, Times.Never); + session.VerifySet(s => s.ClientProxy = proxy.Object, Times.Never); + + Assert.AreEqual(OperationResult.Failed, result); + } + + [TestMethod] + public void MustFailStartupIfAuthenticationNotSuccessful() + { + var result = default(OperationResult); + var response = new AuthenticationResponse { ProcessId = -1 }; + + process.SetupGet(p => p.Id).Returns(1234); + processFactory.Setup(f => f.StartNew(It.IsAny(), It.IsAny())).Returns(process.Object).Callback(clientReady); + proxy.Setup(p => p.RequestAuthentication()).Returns(response); + proxy.Setup(p => p.Connect(It.IsAny(), true)).Returns(true); + + result = sut.Perform(); + + session.VerifySet(s => s.ClientProcess = process.Object, Times.Never); + session.VerifySet(s => s.ClientProxy = proxy.Object, Times.Never); + + Assert.AreEqual(OperationResult.Failed, result); + } + + [TestMethod] + public void MustStopClientWhenReverting() + { + proxy.Setup(p => p.Disconnect()).Callback(terminated); + + PerformNormally(); + sut.Revert(); + + 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); + } + + [TestMethod] + public void MustKillClientIfStoppingFailed() + { + process.Setup(p => p.Kill()).Callback(() => process.SetupGet(p => p.HasTerminated).Returns(true)); + + PerformNormally(); + 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); + } + + [TestMethod] + public void MustAttemptToKillFiveTimesThenAbort() + { + PerformNormally(); + 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); + } + + [TestMethod] + public void MustNotStopClientIfAlreadyTerminated() + { + process.SetupGet(p => p.HasTerminated).Returns(true); + + sut.Revert(); + + 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); + } + + private void PerformNormally() + { + var response = new AuthenticationResponse { ProcessId = 1234 }; + + process.SetupGet(p => p.Id).Returns(response.ProcessId); + processFactory.Setup(f => f.StartNew(It.IsAny(), It.IsAny())).Returns(process.Object).Callback(clientReady); + proxy.Setup(p => p.RequestAuthentication()).Returns(response); + proxy.Setup(p => p.Connect(It.IsAny(), true)).Returns(true); + + sut.Perform(); + } + } +} diff --git a/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ClientTerminationOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ClientTerminationOperationTests.cs new file mode 100644 index 00000000..5084ff68 --- /dev/null +++ b/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ClientTerminationOperationTests.cs @@ -0,0 +1,84 @@ +/* + * 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.Logging; +using SafeExamBrowser.Contracts.WindowsApi; +using SafeExamBrowser.Runtime.Behaviour.Operations; + +namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations +{ + [TestClass] + public class ClientTerminationOperationTests + { + private Action clientReady; + private Mock configuration; + private Mock proxy; + private Mock logger; + private Mock process; + private Mock processFactory; + private Mock proxyFactory; + private Mock runtimeHost; + private RuntimeInfo runtimeInfo; + private Mock session; + private ClientTerminationOperation sut; + + [TestInitialize] + public void Initialize() + { + configuration = new Mock(); + 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(); + runtimeInfo = new RuntimeInfo(); + session = new Mock(); + + configuration.SetupGet(c => c.CurrentSession).Returns(session.Object); + configuration.SetupGet(c => c.RuntimeInfo).Returns(runtimeInfo); + proxyFactory.Setup(f => f.CreateClientProxy(It.IsAny())).Returns(proxy.Object); + + sut = new ClientTerminationOperation(configuration.Object, logger.Object, processFactory.Object, proxyFactory.Object, runtimeHost.Object, 0); + } + + [TestMethod] + public void MustDoNothingOnPerform() + { + sut.Perform(); + + processFactory.VerifyNoOtherCalls(); + proxy.VerifyNoOtherCalls(); + proxyFactory.VerifyNoOtherCalls(); + } + + [TestMethod] + public void MustDoNothingOnRevert() + { + sut.Revert(); + + process.VerifyNoOtherCalls(); + proxy.VerifyNoOtherCalls(); + runtimeHost.VerifyNoOtherCalls(); + } + + [TestMethod] + public void MustStartClientOnRepeat() + { + // TODO: Extract static fields from operation -> allows unit testing of this requirement etc.! + Assert.Fail(); + } + } +} diff --git a/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ServiceConnectionOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ServiceOperationTests.cs similarity index 81% rename from SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ServiceConnectionOperationTests.cs rename to SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ServiceOperationTests.cs index b023e3e4..a1c04cdb 100644 --- a/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ServiceConnectionOperationTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ServiceOperationTests.cs @@ -21,11 +21,13 @@ using SafeExamBrowser.Runtime.Behaviour.Operations; namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations { [TestClass] - public class ServiceConnectionOperationTests + public class ServiceOperationTests { private Mock logger; private Mock service; private Mock configuration; + private Mock session; + private Settings settings; private Mock progressIndicator; private Mock text; private ServiceOperation sut; @@ -36,9 +38,14 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations logger = new Mock(); service = new Mock(); configuration = new Mock(); + session = new Mock(); + settings = new Settings(); progressIndicator = new Mock(); text = new Mock(); + configuration.SetupGet(c => c.CurrentSession).Returns(session.Object); + configuration.SetupGet(c => c.CurrentSettings).Returns(settings); + sut = new ServiceOperation(configuration.Object, logger.Object, service.Object, text.Object); } @@ -58,6 +65,26 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations service.Verify(s => s.Connect(null, true), Times.Exactly(2)); } + [TestMethod] + public void MustStartSessionIfConnected() + { + service.Setup(s => s.Connect(null, true)).Returns(true); + + sut.Perform(); + + service.Verify(s => s.StartSession(It.IsAny(), It.IsAny()), Times.Once); + } + + [TestMethod] + public void MustNotStartSessionIfNotConnected() + { + service.Setup(s => s.Connect(null, true)).Returns(false); + + sut.Perform(); + + service.Verify(s => s.StartSession(It.IsAny(), It.IsAny()), Times.Never); + } + [TestMethod] public void MustNotFailIfServiceNotAvailable() { @@ -124,6 +151,28 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations service.Verify(s => s.Disconnect(), Times.Exactly(2)); } + [TestMethod] + public void MustStopSessionWhenReverting() + { + service.Setup(s => s.Connect(null, true)).Returns(true); + + sut.Perform(); + sut.Revert(); + + service.Verify(s => s.StopSession(It.IsAny()), Times.Once); + } + + [TestMethod] + public void MustNotStopSessionWhenRevertingAndNotConnected() + { + service.Setup(s => s.Connect(null, true)).Returns(false); + + sut.Perform(); + sut.Revert(); + + service.Verify(s => s.StopSession(It.IsAny()), Times.Never); + } + [TestMethod] public void MustNotFailWhenDisconnecting() { diff --git a/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/SessionInitializationOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/SessionInitializationOperationTests.cs new file mode 100644 index 00000000..2fe62512 --- /dev/null +++ b/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/SessionInitializationOperationTests.cs @@ -0,0 +1,80 @@ +/* + * 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.Configuration; +using SafeExamBrowser.Contracts.Logging; +using SafeExamBrowser.Runtime.Behaviour.Operations; + +namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations +{ + [TestClass] + public class SessionInitializationOperationTests + { + private SessionInitializationOperation sut; + private Mock configuration; + private Mock logger; + private Mock runtimeHost; + private RuntimeInfo runtimeInfo; + private Mock session; + + [TestInitialize] + public void Initialize() + { + configuration = new Mock(); + logger = new Mock(); + runtimeHost = new Mock(); + runtimeInfo = new RuntimeInfo(); + session = new Mock(); + + configuration.SetupGet(c => c.CurrentSession).Returns(session.Object); + configuration.SetupGet(c => c.RuntimeInfo).Returns(runtimeInfo); + + sut = new SessionInitializationOperation(configuration.Object, logger.Object, runtimeHost.Object); + } + + [TestMethod] + public void MustInitializeConfigurationOnPerform() + { + var token = Guid.NewGuid(); + + session.SetupGet(s => s.StartupToken).Returns(token); + + sut.Perform(); + + configuration.Verify(c => c.InitializeSessionConfiguration(), Times.Once); + runtimeHost.VerifySet(r => r.StartupToken = token, Times.Once); + } + + [TestMethod] + public void MustInitializeConfigurationOnRepeat() + { + var token = Guid.NewGuid(); + + session.SetupGet(s => s.StartupToken).Returns(token); + + sut.Repeat(); + + configuration.Verify(c => c.InitializeSessionConfiguration(), Times.Once); + runtimeHost.VerifySet(r => r.StartupToken = token, Times.Once); + } + + [TestMethod] + public void MustDoNothingOnRevert() + { + sut.Revert(); + + configuration.VerifyNoOtherCalls(); + logger.VerifyNoOtherCalls(); + runtimeHost.VerifyNoOtherCalls(); + } + } +} diff --git a/SafeExamBrowser.Runtime.UnitTests/SafeExamBrowser.Runtime.UnitTests.csproj b/SafeExamBrowser.Runtime.UnitTests/SafeExamBrowser.Runtime.UnitTests.csproj index 796faa6a..c5e57a0f 100644 --- a/SafeExamBrowser.Runtime.UnitTests/SafeExamBrowser.Runtime.UnitTests.csproj +++ b/SafeExamBrowser.Runtime.UnitTests/SafeExamBrowser.Runtime.UnitTests.csproj @@ -82,7 +82,10 @@ - + + + + diff --git a/SafeExamBrowser.Runtime/Behaviour/Operations/ClientOperation.cs b/SafeExamBrowser.Runtime/Behaviour/Operations/ClientOperation.cs index f8e7d4b3..ba491e98 100644 --- a/SafeExamBrowser.Runtime/Behaviour/Operations/ClientOperation.cs +++ b/SafeExamBrowser.Runtime/Behaviour/Operations/ClientOperation.cs @@ -21,7 +21,7 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations { internal class ClientOperation : IOperation { - private const int TEN_SECONDS = 10000; + private readonly int timeout_ms; protected IConfigurationRepository configuration; protected ILogger logger; @@ -38,13 +38,15 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations ILogger logger, IProcessFactory processFactory, IProxyFactory proxyFactory, - IRuntimeHost runtimeHost) + IRuntimeHost runtimeHost, + int timeout_ms) { this.configuration = configuration; this.logger = logger; this.processFactory = processFactory; this.proxyFactory = proxyFactory; this.runtimeHost = runtimeHost; + this.timeout_ms = timeout_ms; } public virtual OperationResult Perform() @@ -84,6 +86,7 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations var clientReady = false; var clientReadyEvent = new AutoResetEvent(false); var clientReadyEventHandler = new CommunicationEventHandler(() => clientReadyEvent.Set()); + var clientExecutable = configuration.RuntimeInfo.ClientExecutablePath; var clientLogFile = $"{'"' + configuration.RuntimeInfo.ClientLogFile + '"'}"; var hostUri = configuration.RuntimeInfo.RuntimeAddress; @@ -94,12 +97,12 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations ClientProcess = processFactory.StartNew(clientExecutable, clientLogFile, hostUri, token); logger.Info("Waiting for client to complete initialization..."); - clientReady = clientReadyEvent.WaitOne(TEN_SECONDS); + clientReady = clientReadyEvent.WaitOne(timeout_ms); runtimeHost.ClientReady -= clientReadyEventHandler; if (!clientReady) { - logger.Error($"Failed to start client within {TEN_SECONDS / 1000} seconds!"); + logger.Error($"Failed to start client within {timeout_ms / 1000} seconds!"); return false; } @@ -155,19 +158,19 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations ClientProxy.Disconnect(); logger.Info("Waiting for client to disconnect from runtime communication host..."); - disconnected = disconnectedEvent.WaitOne(TEN_SECONDS); + disconnected = disconnectedEvent.WaitOne(timeout_ms); if (!disconnected) { - logger.Error($"Client failed to disconnect within {TEN_SECONDS / 1000} seconds!"); + logger.Error($"Client failed to disconnect within {timeout_ms / 1000} seconds!"); } logger.Info("Waiting for client process to terminate..."); - terminated = terminatedEvent.WaitOne(TEN_SECONDS); + terminated = terminatedEvent.WaitOne(timeout_ms); if (!terminated) { - logger.Error($"Client failed to terminate within {TEN_SECONDS / 1000} seconds!"); + logger.Error($"Client failed to terminate within {timeout_ms / 1000} seconds!"); } runtimeHost.ClientDisconnected -= disconnectedEventHandler; @@ -217,7 +220,7 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations { logger.Warn("Failed to kill client process. Trying again..."); - return TryKillClient(attempt++); + return TryKillClient(++attempt); } } } diff --git a/SafeExamBrowser.Runtime/Behaviour/Operations/ClientTerminationOperation.cs b/SafeExamBrowser.Runtime/Behaviour/Operations/ClientTerminationOperation.cs index 640ca109..5ca7265d 100644 --- a/SafeExamBrowser.Runtime/Behaviour/Operations/ClientTerminationOperation.cs +++ b/SafeExamBrowser.Runtime/Behaviour/Operations/ClientTerminationOperation.cs @@ -23,7 +23,8 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations ILogger logger, IProcessFactory processFactory, IProxyFactory proxyFactory, - IRuntimeHost runtimeHost) : base(configuration, logger, processFactory, proxyFactory, runtimeHost) + IRuntimeHost runtimeHost, + int timeout_ms) : base(configuration, logger, processFactory, proxyFactory, runtimeHost, timeout_ms) { } diff --git a/SafeExamBrowser.Runtime/CompositionRoot.cs b/SafeExamBrowser.Runtime/CompositionRoot.cs index 16720595..e029a90c 100644 --- a/SafeExamBrowser.Runtime/CompositionRoot.cs +++ b/SafeExamBrowser.Runtime/CompositionRoot.cs @@ -36,6 +36,8 @@ namespace SafeExamBrowser.Runtime internal void BuildObjectGraph(Action shutdown) { + const int TEN_SECONDS = 10000; + var args = Environment.GetCommandLineArgs(); var configuration = new ConfigurationRepository(); var nativeMethods = new NativeMethods(); @@ -64,9 +66,9 @@ namespace SafeExamBrowser.Runtime sessionOperations.Enqueue(new ConfigurationOperation(configuration, logger, messageBox, runtimeInfo, text, args)); sessionOperations.Enqueue(new SessionInitializationOperation(configuration, logger, runtimeHost)); sessionOperations.Enqueue(new ServiceOperation(configuration, logger, serviceProxy, text)); - sessionOperations.Enqueue(new ClientTerminationOperation(configuration, logger, processFactory, proxyFactory, runtimeHost)); + sessionOperations.Enqueue(new ClientTerminationOperation(configuration, logger, processFactory, proxyFactory, runtimeHost, TEN_SECONDS)); sessionOperations.Enqueue(new KioskModeOperation(logger, configuration)); - sessionOperations.Enqueue(new ClientOperation(configuration, logger, processFactory, proxyFactory, runtimeHost)); + sessionOperations.Enqueue(new ClientOperation(configuration, logger, processFactory, proxyFactory, runtimeHost, TEN_SECONDS)); var bootstrapSequence = new OperationSequence(logger, bootstrapOperations); var sessionSequence = new OperationSequence(logger, sessionOperations);