/* * Copyright (c) 2024 ETH Zürich, IT Services * * 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 System.Collections.Generic; using System.IO; using System.Security.Cryptography.X509Certificates; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using SafeExamBrowser.Configuration.DataFormats; using SafeExamBrowser.Configuration.Contracts; using SafeExamBrowser.Configuration.Contracts.Cryptography; using SafeExamBrowser.Configuration.Contracts.DataCompression; using SafeExamBrowser.Configuration.Contracts.DataFormats; using SafeExamBrowser.Logging.Contracts; namespace SafeExamBrowser.Configuration.UnitTests.DataFormats { [TestClass] public class BinarySerializerTests { private Mock compressor; private Mock logger; private Mock passwordEncryption; private Mock publicKeyEncryption; private Mock symmetricEncryption; private Mock xmlSerializer; private SerializeResult xmlResult; private BinarySerializer sut; [TestInitialize] public void Initialize() { compressor = new Mock(); logger = new Mock(); passwordEncryption = new Mock(); publicKeyEncryption = new Mock(); symmetricEncryption = new Mock(); xmlResult = new SerializeResult { Data = new MemoryStream(), Status = SaveStatus.Success }; xmlSerializer = new Mock(); compressor.Setup(c => c.Compress(It.IsAny())).Returns(new MemoryStream()); xmlSerializer.Setup(x => x.TrySerialize(It.IsAny>(), It.IsAny())).Returns(xmlResult); sut = new BinarySerializer(compressor.Object, logger.Object, passwordEncryption.Object, publicKeyEncryption.Object, symmetricEncryption.Object, xmlSerializer.Object); } [TestMethod] public void MustOnlySupportBinaryFormat() { var values = Enum.GetValues(typeof(FormatType)); foreach (var value in values) { if (value is FormatType format && format != FormatType.Binary) { Assert.IsFalse(sut.CanSerialize(format)); } } Assert.IsTrue(sut.CanSerialize(FormatType.Binary)); } [TestMethod] public void MustCorrectlySerializePlainDataBlock() { var data = new Dictionary(); var result = sut.TrySerialize(data); compressor.Verify(c => c.Compress(It.IsAny()), Times.Exactly(2)); xmlSerializer.Verify(x => x.TrySerialize(It.Is>(d => d == data), It.Is(e => e == null)), Times.Once); passwordEncryption.VerifyNoOtherCalls(); publicKeyEncryption.VerifyNoOtherCalls(); symmetricEncryption.VerifyNoOtherCalls(); Assert.AreEqual(SaveStatus.Success, result.Status); } [TestMethod] public void MustCorrectlySerializePasswordBlock() { var encrypted = new MemoryStream() as Stream; var data = new Dictionary(); var encryption = new PasswordParameters { Password = "blubb" }; passwordEncryption.Setup(p => p.Encrypt(It.IsAny(), It.IsAny(), out encrypted)).Returns(SaveStatus.Success); var result = sut.TrySerialize(data, encryption); compressor.Verify(c => c.Compress(It.IsAny()), Times.Exactly(2)); passwordEncryption.Verify(p => p.Encrypt(It.IsAny(), It.Is(s => s == encryption.Password), out encrypted), Times.Once); xmlSerializer.Verify(x => x.TrySerialize(It.Is>(d => d == data), It.Is(e => e == null)), Times.Once); publicKeyEncryption.VerifyNoOtherCalls(); symmetricEncryption.VerifyNoOtherCalls(); Assert.AreEqual(SaveStatus.Success, result.Status); } [TestMethod] public void MustCorrectlySerializePublicKeyBlock() { var encrypted = new MemoryStream() as Stream; var data = new Dictionary(); var encryption = new PublicKeyParameters { InnerEncryption = new PasswordParameters { Password = "test" }, SymmetricEncryption = false }; passwordEncryption.Setup(p => p.Encrypt(It.IsAny(), It.IsAny(), out encrypted)).Returns(SaveStatus.Success); publicKeyEncryption.Setup(p => p.Encrypt(It.IsAny(), It.IsAny(), out encrypted)).Returns(SaveStatus.Success); var result = sut.TrySerialize(data, encryption); compressor.Verify(c => c.Compress(It.IsAny()), Times.Exactly(2)); passwordEncryption.Verify(p => p.Encrypt(It.IsAny(), It.Is(s => s == encryption.InnerEncryption.Password), out encrypted), Times.Once); publicKeyEncryption.Verify(p => p.Encrypt(It.IsAny(), It.IsAny(), out encrypted), Times.Once); xmlSerializer.Verify(x => x.TrySerialize(It.Is>(d => d == data), It.Is(e => e == null)), Times.Once); symmetricEncryption.VerifyNoOtherCalls(); Assert.AreEqual(SaveStatus.Success, result.Status); } [TestMethod] public void MustCorrectlySerializePublicKeySymmetricBlock() { var encrypted = new MemoryStream() as Stream; var data = new Dictionary(); var encryption = new PublicKeyParameters { SymmetricEncryption = true }; symmetricEncryption.Setup(p => p.Encrypt(It.IsAny(), It.IsAny(), out encrypted)).Returns(SaveStatus.Success); var result = sut.TrySerialize(data, encryption); compressor.Verify(c => c.Compress(It.IsAny()), Times.Exactly(2)); symmetricEncryption.Verify(p => p.Encrypt(It.IsAny(), It.IsAny(), out encrypted), Times.Once); xmlSerializer.Verify(x => x.TrySerialize(It.Is>(d => d == data), It.Is(e => e == null)), Times.Once); passwordEncryption.VerifyNoOtherCalls(); publicKeyEncryption.VerifyNoOtherCalls(); Assert.AreEqual(SaveStatus.Success, result.Status); } } }