SEBWIN-219: Completed provisional implementation of unit test for communication hosts.

This commit is contained in:
dbuechel 2018-03-20 09:21:10 +01:00
parent 3a4f189916
commit e750f870c0
6 changed files with 398 additions and 6 deletions

View file

@ -0,0 +1,163 @@
/*
* 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.Client.Communication;
using SafeExamBrowser.Contracts.Communication;
using SafeExamBrowser.Contracts.Communication.Data;
using SafeExamBrowser.Contracts.Communication.Hosts;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Client.UnitTests.Communication
{
[TestClass]
public class ClientHostTests
{
private const int PROCESS_ID = 1234;
private Mock<IConfigurationRepository> configuration;
private Mock<IHostObject> hostObject;
private Mock<IHostObjectFactory> hostObjectFactory;
private Mock<ILogger> logger;
private ClientHost sut;
[TestInitialize]
public void Initialize()
{
configuration = new Mock<IConfigurationRepository>();
hostObject = new Mock<IHostObject>();
hostObjectFactory = new Mock<IHostObjectFactory>();
logger = new Mock<ILogger>();
hostObjectFactory.Setup(f => f.CreateObject(It.IsAny<string>(), It.IsAny<ICommunication>())).Returns(hostObject.Object);
sut = new ClientHost("net:pipe://some/address", hostObjectFactory.Object, logger.Object, PROCESS_ID);
}
[TestMethod]
public void MustOnlyAllowConnectionIfTokenIsValid()
{
var token = Guid.NewGuid();
sut.StartupToken = token;
var response = sut.Connect(token);
Assert.IsNotNull(response);
Assert.IsTrue(response.ConnectionEstablished);
}
[TestMethod]
public void MustOnlyAllowOneConcurrentConnection()
{
var token = Guid.NewGuid();
sut.StartupToken = token;
var response1 = sut.Connect(token);
var response2 = sut.Connect(token);
var response3 = sut.Connect(token);
Assert.IsNotNull(response1);
Assert.IsNotNull(response2);
Assert.IsNotNull(response3);
Assert.IsNotNull(response1.CommunicationToken);
Assert.IsNull(response2.CommunicationToken);
Assert.IsNull(response3.CommunicationToken);
Assert.IsTrue(response1.ConnectionEstablished);
Assert.IsFalse(response2.ConnectionEstablished);
Assert.IsFalse(response3.ConnectionEstablished);
}
[TestMethod]
public void MustCorrectlyDisconnect()
{
var token = Guid.NewGuid();
sut.StartupToken = token;
var connectionResponse = sut.Connect(token);
var response = sut.Disconnect(new DisconnectionMessage { CommunicationToken = connectionResponse.CommunicationToken.Value });
Assert.IsNotNull(response);
Assert.IsTrue(response.ConnectionTerminated);
}
[TestMethod]
public void MustNotAllowReconnectionAfterDisconnection()
{
var token = sut.StartupToken = Guid.NewGuid();
var response = sut.Connect(token);
sut.Disconnect(new DisconnectionMessage { CommunicationToken = response.CommunicationToken.Value });
sut.StartupToken = token = Guid.NewGuid();
response = sut.Connect(token);
Assert.IsFalse(response.ConnectionEstablished);
}
[TestMethod]
public void MustHandleAuthenticationRequestCorrectly()
{
sut.StartupToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var message = new SimpleMessage(SimpleMessagePurport.Authenticate) { CommunicationToken = token };
var response = sut.Send(message);
Assert.IsNotNull(response);
Assert.IsInstanceOfType(response, typeof(AuthenticationResponse));
Assert.AreEqual(PROCESS_ID, (response as AuthenticationResponse)?.ProcessId);
}
[TestMethod]
public void MustHandleShutdownRequestCorrectly()
{
var shutdownRequested = false;
sut.Shutdown += () => shutdownRequested = true;
sut.StartupToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var message = new SimpleMessage(SimpleMessagePurport.Shutdown) { CommunicationToken = token };
var response = sut.Send(message);
Assert.IsTrue(shutdownRequested);
Assert.IsNotNull(response);
Assert.IsInstanceOfType(response, typeof(SimpleResponse));
Assert.AreEqual(SimpleResponsePurport.Acknowledged, (response as SimpleResponse)?.Purport);
}
[TestMethod]
public void MustReturnUnknownMessageAsDefault()
{
sut.StartupToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var message = new TestMessage { CommunicationToken = token } as Message;
var response = sut.Send(message);
Assert.IsNotNull(response);
Assert.IsInstanceOfType(response, typeof(SimpleResponse));
Assert.AreEqual(SimpleResponsePurport.UnknownMessage, (response as SimpleResponse)?.Purport);
message = new SimpleMessage(default(SimpleMessagePurport)) { CommunicationToken = token };
response = sut.Send(message);
Assert.IsNotNull(response);
Assert.IsInstanceOfType(response, typeof(SimpleResponse));
Assert.AreEqual(SimpleResponsePurport.UnknownMessage, (response as SimpleResponse)?.Purport);
}
private class TestMessage : Message { };
}
}

View file

@ -86,6 +86,7 @@
<Compile Include="Behaviour\Operations\ProcessMonitorOperationTests.cs" />
<Compile Include="Behaviour\Operations\TaskbarOperationTests.cs" />
<Compile Include="Behaviour\Operations\WindowMonitorOperationTests.cs" />
<Compile Include="Communication\ClientHostTests.cs" />
<Compile Include="Notifications\AboutNotificationControllerTests.cs" />
<Compile Include="Notifications\LogNotificationControllerTests.cs" />
<Compile Include="Notifications\NotificationButtonMock.cs" />
@ -105,6 +106,10 @@
<Project>{47DA5933-BEF8-4729-94E6-ABDE2DB12262}</Project>
<Name>SafeExamBrowser.Contracts</Name>
</ProjectReference>
<ProjectReference Include="..\SafeExamBrowser.Core\SafeExamBrowser.Core.csproj">
<Project>{3D6FDBB6-A4AF-4626-BB2B-BF329D44F9CC}</Project>
<Name>SafeExamBrowser.Core</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View file

@ -206,22 +206,71 @@ namespace SafeExamBrowser.Core.UnitTests.Communication.Hosts
[TestMethod]
public void MustCorrectlyHandlePingMessage()
{
// TODO
Assert.Fail();
var received = false;
var simpleReceived = false;
var message = new SimpleMessage(SimpleMessagePurport.Ping);
sut.OnReceiveStub = (m) => { received = true; return null; };
sut.OnReceiveSimpleMessageStub = (m) => { simpleReceived = true; return null; };
sut.OnConnectStub = (t) => { return true; };
sut.Connect();
message.CommunicationToken = sut.GetCommunicationToken().Value;
var response = sut.Send(message);
Assert.IsFalse(received);
Assert.IsFalse(simpleReceived);
Assert.IsInstanceOfType(response, typeof(SimpleResponse));
Assert.AreEqual(SimpleResponsePurport.Acknowledged, (response as SimpleResponse)?.Purport);
}
[TestMethod]
public void MustCorrectlyReceiveSimpleMessage()
{
// TODO
Assert.Fail();
var received = false;
var simpleReceived = false;
var purport = default(SimpleMessagePurport);
var message = new SimpleMessage(SimpleMessagePurport.ConfigurationNeeded);
var simpleResponse = new SimpleResponse(SimpleResponsePurport.UnknownMessage);
sut.OnReceiveStub = (m) => { received = true; return null; };
sut.OnReceiveSimpleMessageStub = (m) => { simpleReceived = true; purport = m; return simpleResponse; };
sut.OnConnectStub = (t) => { return true; };
sut.Connect();
message.CommunicationToken = sut.GetCommunicationToken().Value;
var response = sut.Send(message);
Assert.IsFalse(received);
Assert.IsTrue(simpleReceived);
Assert.IsInstanceOfType(response, typeof(SimpleResponse));
Assert.AreEqual(SimpleMessagePurport.ConfigurationNeeded, purport);
Assert.AreSame(simpleResponse, response);
}
[TestMethod]
public void MustCorrectlyReceiveMessage()
{
// TODO
Assert.Fail();
var received = false;
var simpleReceived = false;
var message = new ReconfigurationMessage(null);
var reconfigurationResponse = new ReconfigurationResponse();
sut.OnReceiveStub = (m) => { received = true; return reconfigurationResponse; };
sut.OnReceiveSimpleMessageStub = (m) => { simpleReceived = true; return null; };
sut.OnConnectStub = (t) => { return true; };
sut.Connect();
message.CommunicationToken = sut.GetCommunicationToken().Value;
var response = sut.Send(message);
Assert.IsTrue(received);
Assert.IsFalse(simpleReceived);
Assert.IsInstanceOfType(response, typeof(ReconfigurationResponse));
Assert.AreSame(reconfigurationResponse, response);
}
}
}

View file

@ -0,0 +1,168 @@
/*
* 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;
using SafeExamBrowser.Contracts.Communication.Data;
using SafeExamBrowser.Contracts.Communication.Hosts;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Runtime.Communication;
namespace SafeExamBrowser.Runtime.UnitTests.Communication
{
[TestClass]
public class RuntimeHostTests
{
private Mock<IConfigurationRepository> configuration;
private Mock<IHostObject> hostObject;
private Mock<IHostObjectFactory> hostObjectFactory;
private Mock<ILogger> logger;
private RuntimeHost sut;
[TestInitialize]
public void Initialize()
{
configuration = new Mock<IConfigurationRepository>();
hostObject = new Mock<IHostObject>();
hostObjectFactory = new Mock<IHostObjectFactory>();
logger = new Mock<ILogger>();
hostObjectFactory.Setup(f => f.CreateObject(It.IsAny<string>(), It.IsAny<ICommunication>())).Returns(hostObject.Object);
sut = new RuntimeHost("net:pipe://some/address", configuration.Object, hostObjectFactory.Object, logger.Object);
}
[TestMethod]
public void MustOnlyAllowConnectionIfTokenIsValid()
{
var token = Guid.NewGuid();
sut.StartupToken = token;
var response = sut.Connect(token);
Assert.IsNotNull(response);
Assert.IsTrue(response.ConnectionEstablished);
}
[TestMethod]
public void MustOnlyAllowOneConcurrentConnection()
{
var token = Guid.NewGuid();
sut.StartupToken = token;
var response1 = sut.Connect(token);
var response2 = sut.Connect(token);
var response3 = sut.Connect(token);
Assert.IsNotNull(response1);
Assert.IsNotNull(response2);
Assert.IsNotNull(response3);
Assert.IsNotNull(response1.CommunicationToken);
Assert.IsNull(response2.CommunicationToken);
Assert.IsNull(response3.CommunicationToken);
Assert.IsTrue(response1.ConnectionEstablished);
Assert.IsFalse(response2.ConnectionEstablished);
Assert.IsFalse(response3.ConnectionEstablished);
}
[TestMethod]
public void MustCorrectlyDisconnect()
{
var disconnected = false;
var token = Guid.NewGuid();
sut.StartupToken = token;
sut.ClientDisconnected += () => disconnected = true;
var connectionResponse = sut.Connect(token);
var response = sut.Disconnect(new DisconnectionMessage { CommunicationToken = connectionResponse.CommunicationToken.Value });
Assert.IsNotNull(response);
Assert.IsTrue(disconnected);
Assert.IsTrue(response.ConnectionTerminated);
}
[TestMethod]
public void MustAllowReconnectionAfterDisconnection()
{
var token = sut.StartupToken = Guid.NewGuid();
var response = sut.Connect(token);
sut.Disconnect(new DisconnectionMessage { CommunicationToken = response.CommunicationToken.Value });
sut.StartupToken = token = Guid.NewGuid();
response = sut.Connect(token);
Assert.IsTrue(response.ConnectionEstablished);
}
[TestMethod]
public void MustHandleClientReadyCorrectly()
{
var clientReady = false;
sut.ClientReady += () => clientReady = true;
sut.StartupToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var message = new SimpleMessage(SimpleMessagePurport.ClientIsReady) { CommunicationToken = token };
var response = sut.Send(message);
Assert.IsTrue(clientReady);
Assert.IsNotNull(response);
Assert.IsInstanceOfType(response, typeof(SimpleResponse));
Assert.AreEqual(SimpleResponsePurport.Acknowledged, (response as SimpleResponse)?.Purport);
}
[TestMethod]
public void MustHandleShutdownRequestCorrectly()
{
var shutdownRequested = false;
sut.ShutdownRequested += () => shutdownRequested = true;
sut.StartupToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var message = new SimpleMessage(SimpleMessagePurport.RequestShutdown) { CommunicationToken = token };
var response = sut.Send(message);
Assert.IsTrue(shutdownRequested);
Assert.IsNotNull(response);
Assert.IsInstanceOfType(response, typeof(SimpleResponse));
Assert.AreEqual(SimpleResponsePurport.Acknowledged, (response as SimpleResponse)?.Purport);
}
[TestMethod]
public void MustReturnUnknownMessageAsDefault()
{
sut.StartupToken = Guid.Empty;
var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var message = new TestMessage { CommunicationToken = token } as Message;
var response = sut.Send(message);
Assert.IsNotNull(response);
Assert.IsInstanceOfType(response, typeof(SimpleResponse));
Assert.AreEqual(SimpleResponsePurport.UnknownMessage, (response as SimpleResponse)?.Purport);
message = new SimpleMessage(default(SimpleMessagePurport)) { CommunicationToken = token };
response = sut.Send(message);
Assert.IsNotNull(response);
Assert.IsInstanceOfType(response, typeof(SimpleResponse));
Assert.AreEqual(SimpleResponsePurport.UnknownMessage, (response as SimpleResponse)?.Purport);
}
private class TestMessage : Message { };
}
}

View file

@ -85,6 +85,7 @@
<Compile Include="Behaviour\Operations\ServiceConnectionOperationTests.cs" />
<Compile Include="Behaviour\Operations\SessionSequenceOperationTests.cs" />
<Compile Include="Behaviour\RuntimeControllerTests.cs" />
<Compile Include="Communication\RuntimeHostTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
@ -96,6 +97,10 @@
<Project>{47DA5933-BEF8-4729-94E6-ABDE2DB12262}</Project>
<Name>SafeExamBrowser.Contracts</Name>
</ProjectReference>
<ProjectReference Include="..\SafeExamBrowser.Core\SafeExamBrowser.Core.csproj">
<Project>{3D6FDBB6-A4AF-4626-BB2B-BF329D44F9CC}</Project>
<Name>SafeExamBrowser.Core</Name>
</ProjectReference>
<ProjectReference Include="..\SafeExamBrowser.Runtime\SafeExamBrowser.Runtime.csproj">
<Project>{e3aed2f8-b5df-45d1-ac19-48066923d6d8}</Project>
<Name>SafeExamBrowser.Runtime</Name>

View file

@ -65,6 +65,7 @@ namespace SafeExamBrowser.Runtime.Communication
switch (message)
{
case ReconfigurationMessage reconfigurationMessage:
// TODO: Not the job of the host, fire event or alike!
return Handle(reconfigurationMessage);
}
@ -79,6 +80,7 @@ namespace SafeExamBrowser.Runtime.Communication
ClientReady?.Invoke();
return new SimpleResponse(SimpleResponsePurport.Acknowledged);
case SimpleMessagePurport.ConfigurationNeeded:
// TODO: Not the job of the host, fire event or alike!
return new ConfigurationResponse { Configuration = configuration.BuildClientConfiguration() };
case SimpleMessagePurport.RequestShutdown:
ShutdownRequested?.Invoke();