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…
	
	Add table
		
		Reference in a new issue
	
	 dbuechel
						dbuechel