diff --git a/SafeExamBrowser.Applications.UnitTests/ApplicationFactoryTests.cs b/SafeExamBrowser.Applications.UnitTests/ApplicationFactoryTests.cs new file mode 100644 index 00000000..3215b9ba --- /dev/null +++ b/SafeExamBrowser.Applications.UnitTests/ApplicationFactoryTests.cs @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2023 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.Applications.Contracts; +using SafeExamBrowser.Logging.Contracts; +using SafeExamBrowser.Monitoring.Contracts.Applications; +using SafeExamBrowser.Settings.Applications; +using SafeExamBrowser.WindowsApi.Contracts; + +namespace SafeExamBrowser.Applications.UnitTests +{ + [TestClass] + public class ApplicationFactoryTests + { + private Mock applicationMonitor; + private Mock logger; + private Mock nativeMethods; + private Mock processFactory; + + private ApplicationFactory sut; + + [TestInitialize] + public void Initialize() + { + applicationMonitor = new Mock(); + logger = new Mock(); + nativeMethods = new Mock(); + processFactory = new Mock(); + + sut = new ApplicationFactory(applicationMonitor.Object, logger.Object, nativeMethods.Object, processFactory.Object); + } + + [TestMethod] + public void MustCorrectlyCreateApplication() + { + var settings = new WhitelistApplication + { + DisplayName = "Windows Command Prompt", + ExecutableName = "cmd.exe", + }; + + var result = sut.TryCreate(settings, out var application); + + Assert.AreEqual(FactoryResult.Success, result); + Assert.IsNotNull(application); + Assert.IsInstanceOfType(application); + } + + [TestMethod] + public void MustIndicateIfApplicationNotFound() + { + var settings = new WhitelistApplication + { + ExecutableName = "some_random_application_which_does_not_exist_on_a_normal_system.exe" + }; + + var result = sut.TryCreate(settings, out var application); + + Assert.AreEqual(FactoryResult.NotFound, result); + Assert.IsNull(application); + } + + [TestMethod] + public void MustFailGracefullyAndIndicateThatErrorOccurred() + { + var settings = new WhitelistApplication + { + DisplayName = "Windows Command Prompt", + ExecutableName = "cmd.exe", + }; + + logger.Setup(l => l.CloneFor(It.IsAny())).Throws(); + + var result = sut.TryCreate(settings, out var application); + + Assert.AreEqual(FactoryResult.Error, result); + } + } +} diff --git a/SafeExamBrowser.Applications.UnitTests/Properties/AssemblyInfo.cs b/SafeExamBrowser.Applications.UnitTests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..4fe90ba7 --- /dev/null +++ b/SafeExamBrowser.Applications.UnitTests/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("SafeExamBrowser.Applications.UnitTests")] +[assembly: AssemblyDescription("Safe Exam Browser")] +[assembly: AssemblyCompany("ETH Zürich")] +[assembly: AssemblyProduct("SafeExamBrowser.Applications.UnitTests")] +[assembly: AssemblyCopyright("Copyright © 2023 ETH Zürich, Educational Development and Technology (LET)")] + +[assembly: ComVisible(false)] + +[assembly: Guid("fc6d80ec-8611-4287-87e2-17c028a10858")] + +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyInformationalVersion("1.0.0.0")] diff --git a/SafeExamBrowser.Applications.UnitTests/SafeExamBrowser.Applications.UnitTests.csproj b/SafeExamBrowser.Applications.UnitTests/SafeExamBrowser.Applications.UnitTests.csproj new file mode 100644 index 00000000..65f35445 --- /dev/null +++ b/SafeExamBrowser.Applications.UnitTests/SafeExamBrowser.Applications.UnitTests.csproj @@ -0,0 +1,131 @@ + + + + + + Debug + AnyCPU + {FC6D80EC-8611-4287-87E2-17C028A10858} + Library + Properties + SafeExamBrowser.Applications.UnitTests + SafeExamBrowser.Applications.UnitTests + v4.7.2 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 15.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + 7.3 + prompt + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + 7.3 + prompt + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + 7.3 + prompt + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + 7.3 + prompt + + + + ..\packages\Castle.Core.5.1.1\lib\net462\Castle.Core.dll + + + ..\packages\MSTest.TestFramework.3.0.2\lib\net462\Microsoft.VisualStudio.TestPlatform.TestFramework.dll + + + ..\packages\MSTest.TestFramework.3.0.2\lib\net462\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll + + + ..\packages\Moq.4.18.4\lib\net462\Moq.dll + + + + + + ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + + + + + + + + + + + + + {ac77745d-3b41-43e2-8e84-d40e5a4ee77f} + SafeExamBrowser.Applications.Contracts + + + {a113e68f-1209-4689-981a-15c554b2df4e} + SafeExamBrowser.Applications + + + {fe0e1224-b447-4b14-81e7-ed7d84822aa0} + SafeExamBrowser.Core.Contracts + + + {64ea30fb-11d4-436a-9c2b-88566285363e} + SafeExamBrowser.Logging.Contracts + + + {6d563a30-366d-4c35-815b-2c9e6872278b} + SafeExamBrowser.Monitoring.Contracts + + + {30b2d907-5861-4f39-abad-c4abf1b3470e} + SafeExamBrowser.Settings + + + {7016f080-9aa5-41b2-a225-385ad877c171} + SafeExamBrowser.WindowsApi.Contracts + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + \ No newline at end of file diff --git a/SafeExamBrowser.Applications.UnitTests/app.config b/SafeExamBrowser.Applications.UnitTests/app.config new file mode 100644 index 00000000..1696df66 --- /dev/null +++ b/SafeExamBrowser.Applications.UnitTests/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/SafeExamBrowser.Applications.UnitTests/packages.config b/SafeExamBrowser.Applications.UnitTests/packages.config new file mode 100644 index 00000000..83be390d --- /dev/null +++ b/SafeExamBrowser.Applications.UnitTests/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/SafeExamBrowser.Applications/ApplicationFactory.cs b/SafeExamBrowser.Applications/ApplicationFactory.cs index aff41939..69cef224 100644 --- a/SafeExamBrowser.Applications/ApplicationFactory.cs +++ b/SafeExamBrowser.Applications/ApplicationFactory.cs @@ -20,10 +20,10 @@ namespace SafeExamBrowser.Applications { public class ApplicationFactory : IApplicationFactory { - private IApplicationMonitor applicationMonitor; - private IModuleLogger logger; - private INativeMethods nativeMethods; - private IProcessFactory processFactory; + private readonly IApplicationMonitor applicationMonitor; + private readonly IModuleLogger logger; + private readonly INativeMethods nativeMethods; + private readonly IProcessFactory processFactory; public ApplicationFactory( IApplicationMonitor applicationMonitor, @@ -39,9 +39,9 @@ namespace SafeExamBrowser.Applications public FactoryResult TryCreate(WhitelistApplication settings, out IApplication application) { - var name = $"'{settings.DisplayName}' ({ settings.ExecutableName})"; + var name = $"'{settings.DisplayName}' ({settings.ExecutableName})"; - application = default(IApplication); + application = default; try { @@ -82,14 +82,14 @@ namespace SafeExamBrowser.Applications var paths = new List(); var registryPath = QueryPathFromRegistry(settings); - mainExecutable = default(string); + mainExecutable = default; paths.Add(new[] { Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), settings.ExecutableName }); paths.Add(new[] { Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), settings.ExecutableName }); paths.Add(new[] { Environment.GetFolderPath(Environment.SpecialFolder.System), settings.ExecutableName }); paths.Add(new[] { Environment.GetFolderPath(Environment.SpecialFolder.SystemX86), settings.ExecutableName }); - if (settings.ExecutablePath != default(string)) + if (settings.ExecutablePath != default) { paths.Add(new[] { settings.ExecutablePath, settings.ExecutableName }); paths.Add(new[] { Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), settings.ExecutablePath, settings.ExecutableName }); @@ -98,11 +98,11 @@ namespace SafeExamBrowser.Applications paths.Add(new[] { Environment.GetFolderPath(Environment.SpecialFolder.SystemX86), settings.ExecutablePath, settings.ExecutableName }); } - if (registryPath != default(string)) + if (registryPath != default) { paths.Add(new[] { registryPath, settings.ExecutableName }); - if (settings.ExecutablePath != default(string)) + if (settings.ExecutablePath != default) { paths.Add(new[] { registryPath, settings.ExecutablePath, settings.ExecutableName }); } @@ -146,7 +146,7 @@ namespace SafeExamBrowser.Applications logger.Error($"Failed to query path in registry for '{settings.ExecutableName}'!", e); } - return default(string); + return default; } } } diff --git a/SafeExamBrowser.Applications/Properties/AssemblyInfo.cs b/SafeExamBrowser.Applications/Properties/AssemblyInfo.cs index f1be4b1b..90b3253b 100644 --- a/SafeExamBrowser.Applications/Properties/AssemblyInfo.cs +++ b/SafeExamBrowser.Applications/Properties/AssemblyInfo.cs @@ -1,4 +1,5 @@ using System.Reflection; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following @@ -14,6 +15,7 @@ using System.Runtime.InteropServices; // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] +[assembly: InternalsVisibleTo("SafeExamBrowser.Applications.UnitTests")] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("a113e68f-1209-4689-981a-15c554b2df4e")] diff --git a/SafeExamBrowser.Browser.UnitTests/Handlers/ResourceHandlerTests.cs b/SafeExamBrowser.Browser.UnitTests/Handlers/ResourceHandlerTests.cs index e4cf2808..06441071 100644 --- a/SafeExamBrowser.Browser.UnitTests/Handlers/ResourceHandlerTests.cs +++ b/SafeExamBrowser.Browser.UnitTests/Handlers/ResourceHandlerTests.cs @@ -80,13 +80,41 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers } [TestMethod] - public void MustNotAppendCustomHeadersForCrossDomain() + public void MustAppendCustomHeadersForCrossDomainResourceRequestAndMainFrame() { var browser = new Mock(); var headers = new NameValueCollection(); var request = new Mock(); browser.SetupGet(b => b.Address).Returns("http://www.otherhost.org"); + keyGenerator.Setup(g => g.CalculateBrowserExamKeyHash(It.IsAny(), It.IsAny(), It.IsAny())).Returns(new Random().Next().ToString()); + keyGenerator.Setup(g => g.CalculateConfigurationKeyHash(It.IsAny(), It.IsAny())).Returns(new Random().Next().ToString()); + request.SetupGet(r => r.ResourceType).Returns(ResourceType.MainFrame); + request.SetupGet(r => r.Headers).Returns(new NameValueCollection()); + request.SetupGet(r => r.Url).Returns("http://www.host.org"); + request.SetupSet(r => r.Headers = It.IsAny()).Callback((h) => headers = h); + settings.SendConfigurationKey = true; + settings.SendBrowserExamKey = true; + + var result = sut.OnBeforeResourceLoad(browser.Object, Mock.Of(), Mock.Of