SEBWIN-296: Implemented unit tests for binary serializer.
This commit is contained in:
parent
f86615c77d
commit
817d9eaefc
4 changed files with 156 additions and 26 deletions
|
@ -6,17 +6,148 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* 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 Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using Moq;
|
||||||
|
using SafeExamBrowser.Configuration.DataFormats;
|
||||||
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
|
using SafeExamBrowser.Contracts.Configuration.Cryptography;
|
||||||
|
using SafeExamBrowser.Contracts.Configuration.DataCompression;
|
||||||
|
using SafeExamBrowser.Contracts.Configuration.DataFormats;
|
||||||
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Configuration.UnitTests.DataFormats
|
namespace SafeExamBrowser.Configuration.UnitTests.DataFormats
|
||||||
{
|
{
|
||||||
[TestClass]
|
[TestClass]
|
||||||
public class BinarySerializerTests
|
public class BinarySerializerTests
|
||||||
{
|
{
|
||||||
|
private Mock<IDataCompressor> compressor;
|
||||||
|
private Mock<ILogger> logger;
|
||||||
|
private Mock<IPasswordEncryption> passwordEncryption;
|
||||||
|
private Mock<IPublicKeyEncryption> publicKeyEncryption;
|
||||||
|
private Mock<IPublicKeyEncryption> symmetricEncryption;
|
||||||
|
private Mock<IDataSerializer> xmlSerializer;
|
||||||
|
private SerializeResult xmlResult;
|
||||||
|
|
||||||
|
private BinarySerializer sut;
|
||||||
|
|
||||||
[TestInitialize]
|
[TestInitialize]
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
|
compressor = new Mock<IDataCompressor>();
|
||||||
|
logger = new Mock<ILogger>();
|
||||||
|
passwordEncryption = new Mock<IPasswordEncryption>();
|
||||||
|
publicKeyEncryption = new Mock<IPublicKeyEncryption>();
|
||||||
|
symmetricEncryption = new Mock<IPublicKeyEncryption>();
|
||||||
|
xmlResult = new SerializeResult { Data = new MemoryStream(), Status = SaveStatus.Success };
|
||||||
|
xmlSerializer = new Mock<IDataSerializer>();
|
||||||
|
|
||||||
|
compressor.Setup(c => c.Compress(It.IsAny<Stream>())).Returns(new MemoryStream());
|
||||||
|
xmlSerializer.Setup(x => x.TrySerialize(It.IsAny<IDictionary<string, object>>(), It.IsAny<EncryptionParameters>())).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<string, object>();
|
||||||
|
var result = sut.TrySerialize(data);
|
||||||
|
|
||||||
|
compressor.Verify(c => c.Compress(It.IsAny<Stream>()), Times.Exactly(2));
|
||||||
|
xmlSerializer.Verify(x => x.TrySerialize(It.Is<IDictionary<string, object>>(d => d == data), It.Is<EncryptionParameters>(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<string, object>();
|
||||||
|
var encryption = new PasswordParameters { Password = "blubb" };
|
||||||
|
|
||||||
|
passwordEncryption.Setup(p => p.Encrypt(It.IsAny<Stream>(), It.IsAny<string>(), out encrypted)).Returns(SaveStatus.Success);
|
||||||
|
|
||||||
|
var result = sut.TrySerialize(data, encryption);
|
||||||
|
|
||||||
|
compressor.Verify(c => c.Compress(It.IsAny<Stream>()), Times.Exactly(2));
|
||||||
|
passwordEncryption.Verify(p => p.Encrypt(It.IsAny<Stream>(), It.Is<string>(s => s == encryption.Password), out encrypted), Times.Once);
|
||||||
|
xmlSerializer.Verify(x => x.TrySerialize(It.Is<IDictionary<string, object>>(d => d == data), It.Is<EncryptionParameters>(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<string, object>();
|
||||||
|
var encryption = new PublicKeyParameters
|
||||||
|
{
|
||||||
|
InnerEncryption = new PasswordParameters { Password = "test" },
|
||||||
|
SymmetricEncryption = false
|
||||||
|
};
|
||||||
|
|
||||||
|
passwordEncryption.Setup(p => p.Encrypt(It.IsAny<Stream>(), It.IsAny<string>(), out encrypted)).Returns(SaveStatus.Success);
|
||||||
|
publicKeyEncryption.Setup(p => p.Encrypt(It.IsAny<Stream>(), It.IsAny<X509Certificate2>(), out encrypted)).Returns(SaveStatus.Success);
|
||||||
|
|
||||||
|
var result = sut.TrySerialize(data, encryption);
|
||||||
|
|
||||||
|
compressor.Verify(c => c.Compress(It.IsAny<Stream>()), Times.Exactly(2));
|
||||||
|
passwordEncryption.Verify(p => p.Encrypt(It.IsAny<Stream>(), It.Is<string>(s => s == encryption.InnerEncryption.Password), out encrypted), Times.Once);
|
||||||
|
publicKeyEncryption.Verify(p => p.Encrypt(It.IsAny<Stream>(), It.IsAny<X509Certificate2>(), out encrypted), Times.Once);
|
||||||
|
xmlSerializer.Verify(x => x.TrySerialize(It.Is<IDictionary<string, object>>(d => d == data), It.Is<EncryptionParameters>(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<string, object>();
|
||||||
|
var encryption = new PublicKeyParameters
|
||||||
|
{
|
||||||
|
SymmetricEncryption = true
|
||||||
|
};
|
||||||
|
|
||||||
|
symmetricEncryption.Setup(p => p.Encrypt(It.IsAny<Stream>(), It.IsAny<X509Certificate2>(), out encrypted)).Returns(SaveStatus.Success);
|
||||||
|
|
||||||
|
var result = sut.TrySerialize(data, encryption);
|
||||||
|
|
||||||
|
compressor.Verify(c => c.Compress(It.IsAny<Stream>()), Times.Exactly(2));
|
||||||
|
symmetricEncryption.Verify(p => p.Encrypt(It.IsAny<Stream>(), It.IsAny<X509Certificate2>(), out encrypted), Times.Once);
|
||||||
|
xmlSerializer.Verify(x => x.TrySerialize(It.Is<IDictionary<string, object>>(d => d == data), It.Is<EncryptionParameters>(e => e == null)), Times.Once);
|
||||||
|
passwordEncryption.VerifyNoOtherCalls();
|
||||||
|
publicKeyEncryption.VerifyNoOtherCalls();
|
||||||
|
|
||||||
|
Assert.AreEqual(SaveStatus.Success, result.Status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,19 +181,19 @@ namespace SafeExamBrowser.Configuration.DataFormats
|
||||||
|
|
||||||
private string ReadPrefix(Stream data)
|
private string ReadPrefix(Stream data)
|
||||||
{
|
{
|
||||||
var prefixData = new byte[PREFIX_LENGTH];
|
var prefix = new byte[PREFIX_LENGTH];
|
||||||
|
|
||||||
if (compressor.IsCompressed(data))
|
if (compressor.IsCompressed(data))
|
||||||
{
|
{
|
||||||
prefixData = compressor.Peek(data, PREFIX_LENGTH);
|
prefix = compressor.Peek(data, PREFIX_LENGTH);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
data.Seek(0, SeekOrigin.Begin);
|
data.Seek(0, SeekOrigin.Begin);
|
||||||
data.Read(prefixData, 0, PREFIX_LENGTH);
|
data.Read(prefix, 0, PREFIX_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Encoding.UTF8.GetString(prefixData);
|
return Encoding.UTF8.GetString(prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsValid(string prefix)
|
private bool IsValid(string prefix)
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using SafeExamBrowser.Configuration.Cryptography;
|
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
using SafeExamBrowser.Contracts.Configuration.Cryptography;
|
using SafeExamBrowser.Contracts.Configuration.Cryptography;
|
||||||
using SafeExamBrowser.Contracts.Configuration.DataCompression;
|
using SafeExamBrowser.Contracts.Configuration.DataCompression;
|
||||||
|
@ -21,12 +20,26 @@ namespace SafeExamBrowser.Configuration.DataFormats
|
||||||
public class BinarySerializer : IDataSerializer
|
public class BinarySerializer : IDataSerializer
|
||||||
{
|
{
|
||||||
private IDataCompressor compressor;
|
private IDataCompressor compressor;
|
||||||
private IModuleLogger logger;
|
private ILogger logger;
|
||||||
|
private IPasswordEncryption passwordEncryption;
|
||||||
|
private IPublicKeyEncryption publicKeyEncryption;
|
||||||
|
private IPublicKeyEncryption symmetricEncryption;
|
||||||
|
private IDataSerializer xmlSerializer;
|
||||||
|
|
||||||
public BinarySerializer(IDataCompressor compressor, IModuleLogger logger)
|
public BinarySerializer(
|
||||||
|
IDataCompressor compressor,
|
||||||
|
ILogger logger,
|
||||||
|
IPasswordEncryption passwordEncryption,
|
||||||
|
IPublicKeyEncryption publicKeyEncryption,
|
||||||
|
IPublicKeyEncryption symmetricEncryption,
|
||||||
|
IDataSerializer xmlSerializer)
|
||||||
{
|
{
|
||||||
this.compressor = compressor;
|
this.compressor = compressor;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
|
this.passwordEncryption = passwordEncryption;
|
||||||
|
this.publicKeyEncryption = publicKeyEncryption;
|
||||||
|
this.symmetricEncryption = symmetricEncryption;
|
||||||
|
this.xmlSerializer = xmlSerializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanSerialize(FormatType format)
|
public bool CanSerialize(FormatType format)
|
||||||
|
@ -65,12 +78,11 @@ namespace SafeExamBrowser.Configuration.DataFormats
|
||||||
|
|
||||||
if (result.Status == SaveStatus.Success)
|
if (result.Status == SaveStatus.Success)
|
||||||
{
|
{
|
||||||
var encryption = new PasswordEncryption(logger.CloneFor(nameof(PasswordEncryption)));
|
|
||||||
var prefix = password.IsHash ? BinaryBlock.PasswordConfigureClient : BinaryBlock.Password;
|
var prefix = password.IsHash ? BinaryBlock.PasswordConfigureClient : BinaryBlock.Password;
|
||||||
|
|
||||||
logger.Debug("Attempting to serialize password block...");
|
logger.Debug("Attempting to serialize password block...");
|
||||||
|
|
||||||
var status = encryption.Encrypt(result.Data, password.Password, out var encrypted);
|
var status = passwordEncryption.Encrypt(result.Data, password.Password, out var encrypted);
|
||||||
|
|
||||||
if (status == SaveStatus.Success)
|
if (status == SaveStatus.Success)
|
||||||
{
|
{
|
||||||
|
@ -87,7 +99,6 @@ namespace SafeExamBrowser.Configuration.DataFormats
|
||||||
{
|
{
|
||||||
logger.Debug("Attempting to serialize plain data block...");
|
logger.Debug("Attempting to serialize plain data block...");
|
||||||
|
|
||||||
var xmlSerializer = new XmlSerializer(logger.CloneFor(nameof(XmlSerializer)));
|
|
||||||
var result = xmlSerializer.TrySerialize(data);
|
var result = xmlSerializer.TrySerialize(data);
|
||||||
|
|
||||||
if (result.Status == SaveStatus.Success)
|
if (result.Status == SaveStatus.Success)
|
||||||
|
@ -109,7 +120,7 @@ namespace SafeExamBrowser.Configuration.DataFormats
|
||||||
|
|
||||||
if (result.Status == SaveStatus.Success)
|
if (result.Status == SaveStatus.Success)
|
||||||
{
|
{
|
||||||
var encryption = DetermineEncryptionForPublicKeyHashBlock(parameters);
|
var encryption = parameters.SymmetricEncryption ? symmetricEncryption : publicKeyEncryption;
|
||||||
var prefix = parameters.SymmetricEncryption ? BinaryBlock.PublicKeySymmetric : BinaryBlock.PublicKey;
|
var prefix = parameters.SymmetricEncryption ? BinaryBlock.PublicKeySymmetric : BinaryBlock.PublicKey;
|
||||||
|
|
||||||
logger.Debug("Attempting to serialize public key hash block...");
|
logger.Debug("Attempting to serialize public key hash block...");
|
||||||
|
@ -135,18 +146,6 @@ namespace SafeExamBrowser.Configuration.DataFormats
|
||||||
return SerializePlainDataBlock(data, true);
|
return SerializePlainDataBlock(data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PublicKeyEncryption DetermineEncryptionForPublicKeyHashBlock(PublicKeyParameters parameters)
|
|
||||||
{
|
|
||||||
var passwordEncryption = new PasswordEncryption(logger.CloneFor(nameof(PasswordEncryption)));
|
|
||||||
|
|
||||||
if (parameters.SymmetricEncryption)
|
|
||||||
{
|
|
||||||
return new PublicKeySymmetricEncryption(new CertificateStore(), logger.CloneFor(nameof(PublicKeySymmetricEncryption)), passwordEncryption);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PublicKeyEncryption(new CertificateStore(), logger.CloneFor(nameof(PublicKeyEncryption)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Stream WritePrefix(string prefix, Stream data)
|
private Stream WritePrefix(string prefix, Stream data)
|
||||||
{
|
{
|
||||||
var prefixBytes = Encoding.UTF8.GetBytes(prefix);
|
var prefixBytes = Encoding.UTF8.GetBytes(prefix);
|
||||||
|
|
|
@ -119,16 +119,16 @@ namespace SafeExamBrowser.Runtime
|
||||||
var compressor = new GZipCompressor(ModuleLogger(nameof(GZipCompressor)));
|
var compressor = new GZipCompressor(ModuleLogger(nameof(GZipCompressor)));
|
||||||
var passwordEncryption = new PasswordEncryption(ModuleLogger(nameof(PasswordEncryption)));
|
var passwordEncryption = new PasswordEncryption(ModuleLogger(nameof(PasswordEncryption)));
|
||||||
var publicKeyEncryption = new PublicKeyEncryption(new CertificateStore(), ModuleLogger(nameof(PublicKeyEncryption)));
|
var publicKeyEncryption = new PublicKeyEncryption(new CertificateStore(), ModuleLogger(nameof(PublicKeyEncryption)));
|
||||||
var symmetricInnerEncryption = new PasswordEncryption(ModuleLogger(nameof(PasswordEncryption)));
|
var symmetricEncryption = new PublicKeySymmetricEncryption(new CertificateStore(), ModuleLogger(nameof(PublicKeySymmetricEncryption)), passwordEncryption);
|
||||||
var symmetricEncryption = new PublicKeySymmetricEncryption(new CertificateStore(), ModuleLogger(nameof(PublicKeySymmetricEncryption)), symmetricInnerEncryption);
|
|
||||||
var repositoryLogger = ModuleLogger(nameof(ConfigurationRepository));
|
var repositoryLogger = ModuleLogger(nameof(ConfigurationRepository));
|
||||||
var xmlParser = new XmlParser(ModuleLogger(nameof(XmlParser)));
|
var xmlParser = new XmlParser(ModuleLogger(nameof(XmlParser)));
|
||||||
|
var xmlSerializer = new XmlSerializer(ModuleLogger(nameof(XmlSerializer)));
|
||||||
|
|
||||||
configuration = new ConfigurationRepository(new HashAlgorithm(), repositoryLogger, executable.Location, programCopyright, programTitle, programVersion);
|
configuration = new ConfigurationRepository(new HashAlgorithm(), repositoryLogger, executable.Location, programCopyright, programTitle, programVersion);
|
||||||
appConfig = configuration.InitializeAppConfig();
|
appConfig = configuration.InitializeAppConfig();
|
||||||
|
|
||||||
configuration.Register(new BinaryParser(compressor, new HashAlgorithm(), ModuleLogger(nameof(BinaryParser)), passwordEncryption, publicKeyEncryption, symmetricEncryption, xmlParser));
|
configuration.Register(new BinaryParser(compressor, new HashAlgorithm(), ModuleLogger(nameof(BinaryParser)), passwordEncryption, publicKeyEncryption, symmetricEncryption, xmlParser));
|
||||||
configuration.Register(new BinarySerializer(compressor, ModuleLogger(nameof(BinarySerializer))));
|
configuration.Register(new BinarySerializer(compressor, ModuleLogger(nameof(BinarySerializer)), passwordEncryption, publicKeyEncryption, symmetricEncryption, xmlSerializer));
|
||||||
configuration.Register(new XmlParser(ModuleLogger(nameof(XmlParser))));
|
configuration.Register(new XmlParser(ModuleLogger(nameof(XmlParser))));
|
||||||
configuration.Register(new XmlSerializer(ModuleLogger(nameof(XmlSerializer))));
|
configuration.Register(new XmlSerializer(ModuleLogger(nameof(XmlSerializer))));
|
||||||
configuration.Register(new FileResourceLoader(ModuleLogger(nameof(FileResourceLoader))));
|
configuration.Register(new FileResourceLoader(ModuleLogger(nameof(FileResourceLoader))));
|
||||||
|
|
Loading…
Reference in a new issue