SEBWIN-219: Extended unit test coverage of runtime operations.
This commit is contained in:
parent
6efa7bed81
commit
eb5fc50fea
10 changed files with 470 additions and 32 deletions
|
@ -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<IDisplayMonitor> displayMonitorMock;
|
||||
private Mock<ILogger> loggerMock;
|
||||
private Mock<IProcessMonitor> processMonitorMock;
|
||||
private Mock<IOperationSequence> operationSequenceMock;
|
||||
private Mock<IRuntimeProxy> runtimeProxyMock;
|
||||
private Mock<ITaskbar> taskbarMock;
|
||||
private Mock<IUserInterfaceFactory> uiFactoryMock;
|
||||
private Mock<IWindowMonitor> windowMonitorMock;
|
||||
//private Mock<IDisplayMonitor> displayMonitorMock;
|
||||
//private Mock<ILogger> loggerMock;
|
||||
//private Mock<IProcessMonitor> processMonitorMock;
|
||||
//private Mock<IOperationSequence> operationSequenceMock;
|
||||
//private Mock<IRuntimeProxy> runtimeProxyMock;
|
||||
//private Mock<ITaskbar> taskbarMock;
|
||||
//private Mock<IUserInterfaceFactory> uiFactoryMock;
|
||||
//private Mock<IWindowMonitor> windowMonitorMock;
|
||||
|
||||
private ClientController sut;
|
||||
//private ClientController sut;
|
||||
|
||||
[TestMethod]
|
||||
public void TODO()
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace SafeExamBrowser.Contracts.Behaviour.OperationModel
|
|||
/// <summary>
|
||||
/// Indicates that the operation has been aborted due to an expected condition, e.g. as result of a user decision.
|
||||
/// </summary>
|
||||
Aborted,
|
||||
Aborted = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the operation has failed due to an invalid or unexpected condition.
|
||||
|
|
|
@ -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<IConfigurationRepository> configuration;
|
||||
private Mock<IClientProxy> proxy;
|
||||
private Mock<ILogger> logger;
|
||||
private Mock<IProcess> process;
|
||||
private Mock<IProcessFactory> processFactory;
|
||||
private Mock<IProxyFactory> proxyFactory;
|
||||
private Mock<IRuntimeHost> runtimeHost;
|
||||
private RuntimeInfo runtimeInfo;
|
||||
private Mock<ISessionData> session;
|
||||
private ClientOperation sut;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
configuration = new Mock<IConfigurationRepository>();
|
||||
clientReady = new Action(() => runtimeHost.Raise(h => h.ClientReady += null));
|
||||
logger = new Mock<ILogger>();
|
||||
process = new Mock<IProcess>();
|
||||
processFactory = new Mock<IProcessFactory>();
|
||||
proxy = new Mock<IClientProxy>();
|
||||
proxyFactory = new Mock<IProxyFactory>();
|
||||
runtimeHost = new Mock<IRuntimeHost>();
|
||||
runtimeInfo = new RuntimeInfo();
|
||||
session = new Mock<ISessionData>();
|
||||
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<string>())).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<string>(), It.IsAny<string[]>())).Returns(process.Object).Callback(clientReady);
|
||||
proxy.Setup(p => p.RequestAuthentication()).Returns(response);
|
||||
proxy.Setup(p => p.Connect(It.IsAny<Guid>(), 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<string>(), It.IsAny<string[]>())).Returns(process.Object).Callback(clientReady);
|
||||
proxy.Setup(p => p.RequestAuthentication()).Returns(response);
|
||||
proxy.Setup(p => p.Connect(It.IsAny<Guid>(), 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<string>(), It.IsAny<string[]>())).Returns(process.Object).Callback(clientReady);
|
||||
proxy.Setup(p => p.Connect(It.IsAny<Guid>(), 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<string>(), It.IsAny<string[]>())).Returns(process.Object).Callback(clientReady);
|
||||
proxy.Setup(p => p.RequestAuthentication()).Returns(response);
|
||||
proxy.Setup(p => p.Connect(It.IsAny<Guid>(), 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<string>(), It.IsAny<string[]>())).Returns(process.Object).Callback(clientReady);
|
||||
proxy.Setup(p => p.RequestAuthentication()).Returns(response);
|
||||
proxy.Setup(p => p.Connect(It.IsAny<Guid>(), true)).Returns(true);
|
||||
|
||||
sut.Perform();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<IConfigurationRepository> configuration;
|
||||
private Mock<IClientProxy> proxy;
|
||||
private Mock<ILogger> logger;
|
||||
private Mock<IProcess> process;
|
||||
private Mock<IProcessFactory> processFactory;
|
||||
private Mock<IProxyFactory> proxyFactory;
|
||||
private Mock<IRuntimeHost> runtimeHost;
|
||||
private RuntimeInfo runtimeInfo;
|
||||
private Mock<ISessionData> session;
|
||||
private ClientTerminationOperation sut;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
configuration = new Mock<IConfigurationRepository>();
|
||||
clientReady = new Action(() => runtimeHost.Raise(h => h.ClientReady += null));
|
||||
logger = new Mock<ILogger>();
|
||||
process = new Mock<IProcess>();
|
||||
processFactory = new Mock<IProcessFactory>();
|
||||
proxy = new Mock<IClientProxy>();
|
||||
proxyFactory = new Mock<IProxyFactory>();
|
||||
runtimeHost = new Mock<IRuntimeHost>();
|
||||
runtimeInfo = new RuntimeInfo();
|
||||
session = new Mock<ISessionData>();
|
||||
|
||||
configuration.SetupGet(c => c.CurrentSession).Returns(session.Object);
|
||||
configuration.SetupGet(c => c.RuntimeInfo).Returns(runtimeInfo);
|
||||
proxyFactory.Setup(f => f.CreateClientProxy(It.IsAny<string>())).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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,11 +21,13 @@ using SafeExamBrowser.Runtime.Behaviour.Operations;
|
|||
namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
||||
{
|
||||
[TestClass]
|
||||
public class ServiceConnectionOperationTests
|
||||
public class ServiceOperationTests
|
||||
{
|
||||
private Mock<ILogger> logger;
|
||||
private Mock<IServiceProxy> service;
|
||||
private Mock<IConfigurationRepository> configuration;
|
||||
private Mock<ISessionData> session;
|
||||
private Settings settings;
|
||||
private Mock<IProgressIndicator> progressIndicator;
|
||||
private Mock<IText> text;
|
||||
private ServiceOperation sut;
|
||||
|
@ -36,9 +38,14 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
|
|||
logger = new Mock<ILogger>();
|
||||
service = new Mock<IServiceProxy>();
|
||||
configuration = new Mock<IConfigurationRepository>();
|
||||
session = new Mock<ISessionData>();
|
||||
settings = new Settings();
|
||||
progressIndicator = new Mock<IProgressIndicator>();
|
||||
text = new Mock<IText>();
|
||||
|
||||
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<Guid>(), It.IsAny<Settings>()), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MustNotStartSessionIfNotConnected()
|
||||
{
|
||||
service.Setup(s => s.Connect(null, true)).Returns(false);
|
||||
|
||||
sut.Perform();
|
||||
|
||||
service.Verify(s => s.StartSession(It.IsAny<Guid>(), It.IsAny<Settings>()), 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<Guid>()), 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<Guid>()), Times.Never);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MustNotFailWhenDisconnecting()
|
||||
{
|
|
@ -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<IConfigurationRepository> configuration;
|
||||
private Mock<ILogger> logger;
|
||||
private Mock<IRuntimeHost> runtimeHost;
|
||||
private RuntimeInfo runtimeInfo;
|
||||
private Mock<ISessionData> session;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
configuration = new Mock<IConfigurationRepository>();
|
||||
logger = new Mock<ILogger>();
|
||||
runtimeHost = new Mock<IRuntimeHost>();
|
||||
runtimeInfo = new RuntimeInfo();
|
||||
session = new Mock<ISessionData>();
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -82,7 +82,10 @@
|
|||
<ItemGroup>
|
||||
<Compile Include="Behaviour\Operations\ConfigurationOperationTests.cs" />
|
||||
<Compile Include="Behaviour\Operations\KioskModeOperationTests.cs" />
|
||||
<Compile Include="Behaviour\Operations\ServiceConnectionOperationTests.cs" />
|
||||
<Compile Include="Behaviour\Operations\ServiceOperationTests.cs" />
|
||||
<Compile Include="Behaviour\Operations\ClientOperationTests.cs" />
|
||||
<Compile Include="Behaviour\Operations\ClientTerminationOperationTests.cs" />
|
||||
<Compile Include="Behaviour\Operations\SessionInitializationOperationTests.cs" />
|
||||
<Compile Include="Behaviour\RuntimeControllerTests.cs" />
|
||||
<Compile Include="Communication\RuntimeHostTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue