From e942fdbd0cdafa77c35954dd14dfe1cc887b69ad Mon Sep 17 00:00:00 2001 From: Inga Lovinde <52715130+inga-lovinde@users.noreply.github.com> Date: Mon, 17 Jul 2017 13:23:13 +0300 Subject: [PATCH] Contracts refactored --- .../IContentEncryptor.cs | 11 -------- .../ContentTransformations/IContentHasher.cs | 2 +- .../IContentTransformer.cs | 11 ++++++++ Source/Contracts/ReportStorage/IFileInfo.cs | 13 ++++++++++ Source/Contracts/ReportStorage/IReportInfo.cs | 21 ++++++++++++++++ .../Contracts/ReportStorage/IReportStorage.cs | 18 +++++++++++++ .../TargetBinaryStorage/IBlobInfo.cs | 13 ++++++++++ .../ITargetBinaryStorage.cs | 13 ++++++++++ .../TargetMetadataStorage/ITargetDirectory.cs | 13 ++++++++++ .../TargetMetadataStorage/ITargetFile.cs | 10 ++++++++ .../ITargetFileVersion.cs | 15 +++++++++++ .../ITargetMetadataStorage.cs | 9 +++++++ .../ITargetMetadataStorageForRecovery.cs | 13 ++++++++++ .../TargetStorage/ITargetDirectory.cs | 13 ---------- Source/Contracts/TargetStorage/ITargetFile.cs | 18 ------------- .../Contracts/TargetStorage/ITargetStorage.cs | 9 ------- .../ITargetStorageForRecovery.cs | 10 -------- .../ClearTextContentEncryptor.cs | 25 +++++++++++++------ Source/Hasher.SHA1/SHA1ContentHasher.cs | 3 ++- .../EncryptorAndHasherTests.cs | 8 +++--- Tests/Hasher.SHA1/HasherTests.cs | 24 ++++++++++++------ 21 files changed, 189 insertions(+), 83 deletions(-) delete mode 100644 Source/Contracts/ContentTransformations/IContentEncryptor.cs create mode 100644 Source/Contracts/ContentTransformations/IContentTransformer.cs create mode 100644 Source/Contracts/ReportStorage/IFileInfo.cs create mode 100644 Source/Contracts/ReportStorage/IReportInfo.cs create mode 100644 Source/Contracts/ReportStorage/IReportStorage.cs create mode 100644 Source/Contracts/TargetBinaryStorage/IBlobInfo.cs create mode 100644 Source/Contracts/TargetBinaryStorage/ITargetBinaryStorage.cs create mode 100644 Source/Contracts/TargetMetadataStorage/ITargetDirectory.cs create mode 100644 Source/Contracts/TargetMetadataStorage/ITargetFile.cs create mode 100644 Source/Contracts/TargetMetadataStorage/ITargetFileVersion.cs create mode 100644 Source/Contracts/TargetMetadataStorage/ITargetMetadataStorage.cs create mode 100644 Source/Contracts/TargetMetadataStorage/ITargetMetadataStorageForRecovery.cs delete mode 100644 Source/Contracts/TargetStorage/ITargetDirectory.cs delete mode 100644 Source/Contracts/TargetStorage/ITargetFile.cs delete mode 100644 Source/Contracts/TargetStorage/ITargetStorage.cs delete mode 100644 Source/Contracts/TargetStorage/ITargetStorageForRecovery.cs diff --git a/Source/Contracts/ContentTransformations/IContentEncryptor.cs b/Source/Contracts/ContentTransformations/IContentEncryptor.cs deleted file mode 100644 index 41d1dd0..0000000 --- a/Source/Contracts/ContentTransformations/IContentEncryptor.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace EternalArrowBackup.Contracts.ContentTransformations -{ - using System.Threading.Tasks; - - public interface IContentEncryptor - { - Task Encrypt(byte[] originalData); - - Task Decrypt(byte[] encryptedData); - } -} diff --git a/Source/Contracts/ContentTransformations/IContentHasher.cs b/Source/Contracts/ContentTransformations/IContentHasher.cs index 0c255c3..392b8cc 100644 --- a/Source/Contracts/ContentTransformations/IContentHasher.cs +++ b/Source/Contracts/ContentTransformations/IContentHasher.cs @@ -5,6 +5,6 @@ public interface IContentHasher { - Task ComputeHash(byte[] content); + Task ComputeHash(Stream content); } } diff --git a/Source/Contracts/ContentTransformations/IContentTransformer.cs b/Source/Contracts/ContentTransformations/IContentTransformer.cs new file mode 100644 index 0000000..26430cd --- /dev/null +++ b/Source/Contracts/ContentTransformations/IContentTransformer.cs @@ -0,0 +1,11 @@ +namespace EternalArrowBackup.Contracts.ContentTransformations +{ + using System.Threading.Tasks; + + public interface IContentTransformer + { + Task TransformData(byte[] originalData); + + Task GetOriginalData(byte[] transformedData); + } +} diff --git a/Source/Contracts/ReportStorage/IFileInfo.cs b/Source/Contracts/ReportStorage/IFileInfo.cs new file mode 100644 index 0000000..77b0b4b --- /dev/null +++ b/Source/Contracts/ReportStorage/IFileInfo.cs @@ -0,0 +1,13 @@ +namespace EternalArrowBackup.Contracts.ReportStorage +{ + public interface IFileInfo + { + string DirectoryPath { get; } + + string Filename { get; } + + string Hash { get; } + + long Size { get; } + } +} diff --git a/Source/Contracts/ReportStorage/IReportInfo.cs b/Source/Contracts/ReportStorage/IReportInfo.cs new file mode 100644 index 0000000..d9ff01c --- /dev/null +++ b/Source/Contracts/ReportStorage/IReportInfo.cs @@ -0,0 +1,21 @@ +namespace EternalArrowBackup.Contracts.ReportStorage +{ + using System; + + public interface IReportInfo + { + string ReportId { get; } + + DateTime DateTime { get; } + + bool IsCompleted { get; } + + bool IsEmpty { get; } + + bool HasErrors { get; } + + IObservable GetAllErrors(); + + IObservable GetAllFiles(); + } +} diff --git a/Source/Contracts/ReportStorage/IReportStorage.cs b/Source/Contracts/ReportStorage/IReportStorage.cs new file mode 100644 index 0000000..2c6375c --- /dev/null +++ b/Source/Contracts/ReportStorage/IReportStorage.cs @@ -0,0 +1,18 @@ +namespace EternalArrowBackup.Contracts.ReportStorage +{ + using System; + using System.Threading.Tasks; + + public interface IReportStorage + { + Task InitReport(string reportId); + + Task CompleteReport(string reportId, bool isEmpty, bool hasErrors); + + Task AddError(string reportId, string errorMessage); + + Task AddFileInfo(string reportId, string directoryPath, string fileName, string hash, long size); + + IObservable GetAllReports(bool includeEmpty); + } +} diff --git a/Source/Contracts/TargetBinaryStorage/IBlobInfo.cs b/Source/Contracts/TargetBinaryStorage/IBlobInfo.cs new file mode 100644 index 0000000..75e6f3c --- /dev/null +++ b/Source/Contracts/TargetBinaryStorage/IBlobInfo.cs @@ -0,0 +1,13 @@ +namespace EternalArrowBackup.Contracts.TargetBinaryStorage +{ + using System; + + public interface IBlobInfo + { + DateTime UploadDate { get; } + + long OriginalSize { get; } + + string[] BlockKeys { get; } + } +} diff --git a/Source/Contracts/TargetBinaryStorage/ITargetBinaryStorage.cs b/Source/Contracts/TargetBinaryStorage/ITargetBinaryStorage.cs new file mode 100644 index 0000000..76a229b --- /dev/null +++ b/Source/Contracts/TargetBinaryStorage/ITargetBinaryStorage.cs @@ -0,0 +1,13 @@ +namespace EternalArrowBackup.Contracts.TargetBinaryStorage +{ + using System.Threading.Tasks; + + public interface ITargetBinaryStorage + { + Task WriteBlock(byte[] block, string blobId, int partNumber, string blockKey); + + Task WriteBlob(string blobId, long originalSize, string[] blockKeys); + + Task GetBlobIfExists(string blobId); + } +} diff --git a/Source/Contracts/TargetMetadataStorage/ITargetDirectory.cs b/Source/Contracts/TargetMetadataStorage/ITargetDirectory.cs new file mode 100644 index 0000000..53269ef --- /dev/null +++ b/Source/Contracts/TargetMetadataStorage/ITargetDirectory.cs @@ -0,0 +1,13 @@ +namespace EternalArrowBackup.Contracts.TargetMetadataStorage +{ + using System; + using System.Threading; + using System.Threading.Tasks; + + public interface ITargetDirectory + { + Task UploadFile(string filename, string originalHash, long originalSize); + + IObservable GetAllLatestFileVersions(CancellationToken ct); + } +} diff --git a/Source/Contracts/TargetMetadataStorage/ITargetFile.cs b/Source/Contracts/TargetMetadataStorage/ITargetFile.cs new file mode 100644 index 0000000..e8037db --- /dev/null +++ b/Source/Contracts/TargetMetadataStorage/ITargetFile.cs @@ -0,0 +1,10 @@ +namespace EternalArrowBackup.Contracts.TargetMetadataStorage +{ + using System; + using System.Threading; + + public interface ITargetFile + { + IObservable GetAllVersions(CancellationToken ct); + } +} diff --git a/Source/Contracts/TargetMetadataStorage/ITargetFileVersion.cs b/Source/Contracts/TargetMetadataStorage/ITargetFileVersion.cs new file mode 100644 index 0000000..40a7f45 --- /dev/null +++ b/Source/Contracts/TargetMetadataStorage/ITargetFileVersion.cs @@ -0,0 +1,15 @@ +namespace EternalArrowBackup.Contracts.TargetMetadataStorage +{ + using System; + + public interface ITargetFileVersion + { + string Filename { get; } + + string Hash { get; } + + DateTime UploadDate { get; } + + long Size { get; } + } +} diff --git a/Source/Contracts/TargetMetadataStorage/ITargetMetadataStorage.cs b/Source/Contracts/TargetMetadataStorage/ITargetMetadataStorage.cs new file mode 100644 index 0000000..369a2c6 --- /dev/null +++ b/Source/Contracts/TargetMetadataStorage/ITargetMetadataStorage.cs @@ -0,0 +1,9 @@ +namespace EternalArrowBackup.Contracts.TargetMetadataStorage +{ + using System.Threading.Tasks; + + public interface ITargetMetadataStorage + { + Task GetDirectory(string normalizedRelativeDirectoryPath); + } +} diff --git a/Source/Contracts/TargetMetadataStorage/ITargetMetadataStorageForRecovery.cs b/Source/Contracts/TargetMetadataStorage/ITargetMetadataStorageForRecovery.cs new file mode 100644 index 0000000..8f189e3 --- /dev/null +++ b/Source/Contracts/TargetMetadataStorage/ITargetMetadataStorageForRecovery.cs @@ -0,0 +1,13 @@ +namespace EternalArrowBackup.Contracts.TargetMetadataStorage +{ + using System; + using System.Threading; + using System.Threading.Tasks; + + public interface ITargetMetadataStorageForRecovery + { + IObservable GetAllDirectories(CancellationToken ct); + + Task GetFile(string normalizedRelativeDirectoryPath, string filename); + } +} diff --git a/Source/Contracts/TargetStorage/ITargetDirectory.cs b/Source/Contracts/TargetStorage/ITargetDirectory.cs deleted file mode 100644 index f0ad6ef..0000000 --- a/Source/Contracts/TargetStorage/ITargetDirectory.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace EternalArrowBackup.Contracts.TargetStorage -{ - using System; - using System.Threading; - using System.Threading.Tasks; - - public interface ITargetDirectory - { - Task UploadFile(string filename, byte[] data, string originalHash, long originalSize); - - IObservable GetAllFiles(CancellationToken ct); - } -} diff --git a/Source/Contracts/TargetStorage/ITargetFile.cs b/Source/Contracts/TargetStorage/ITargetFile.cs deleted file mode 100644 index c3d4eac..0000000 --- a/Source/Contracts/TargetStorage/ITargetFile.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace EternalArrowBackup.Contracts.TargetStorage -{ - using System; - using System.Threading.Tasks; - - public interface ITargetFile - { - string Filename { get; } - - string Hash { get; } - - DateTime UploadDate { get; } - - long Size { get; } - - Task RetrieveContents(); - } -} diff --git a/Source/Contracts/TargetStorage/ITargetStorage.cs b/Source/Contracts/TargetStorage/ITargetStorage.cs deleted file mode 100644 index 74fdcef..0000000 --- a/Source/Contracts/TargetStorage/ITargetStorage.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace EternalArrowBackup.Contracts.TargetStorage -{ - using System.Threading.Tasks; - - public interface ITargetStorage - { - Task GetDirectory(string normalizedRelativePath); - } -} diff --git a/Source/Contracts/TargetStorage/ITargetStorageForRecovery.cs b/Source/Contracts/TargetStorage/ITargetStorageForRecovery.cs deleted file mode 100644 index 36b51b1..0000000 --- a/Source/Contracts/TargetStorage/ITargetStorageForRecovery.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace EternalArrowBackup.Contracts.TargetStorage -{ - using System; - using System.Threading; - - public interface ITargetStorageForRecovery - { - IObservable GetAllDirectories(CancellationToken ct); - } -} diff --git a/Source/Encryptor.ClearText/ClearTextContentEncryptor.cs b/Source/Encryptor.ClearText/ClearTextContentEncryptor.cs index 2c2cb35..e56e18f 100644 --- a/Source/Encryptor.ClearText/ClearTextContentEncryptor.cs +++ b/Source/Encryptor.ClearText/ClearTextContentEncryptor.cs @@ -1,11 +1,12 @@ namespace EternalArrowBackup.Encryptor.ClearText { using System; + using System.IO; using System.Text; using System.Threading.Tasks; using Contracts.ContentTransformations; - public class ClearTextContentEncryptor : IContentEncryptor + public class ClearTextContentEncryptor : IContentTransformer { public ClearTextContentEncryptor(IContentHasher hasher) { @@ -14,7 +15,7 @@ private IContentHasher Hasher { get; } - public async Task Decrypt(byte[] encryptedData) + public async Task GetOriginalData(byte[] encryptedData) { var hashLength = encryptedData[encryptedData.Length - 1]; @@ -25,19 +26,27 @@ Buffer.BlockCopy(encryptedData, originalData.Length, hashBytes, 0, hashBytes.Length); var expectedHash = Encoding.UTF8.GetString(hashBytes); - var actualHash = await this.Hasher.ComputeHash(originalData); - - if (expectedHash != actualHash) + using (var stream = new MemoryStream(originalData)) { - return new FailedDecryptionResult(); + var actualHash = await this.Hasher.ComputeHash(stream); + + if (expectedHash != actualHash) + { + return new FailedDecryptionResult(); + } } return new SuccessfulDecryptionResult(originalData); } - public async Task Encrypt(byte[] originalData) + public async Task TransformData(byte[] originalData) { - var hash = await this.Hasher.ComputeHash(originalData); + string hash; + using (var stream = new MemoryStream(originalData)) + { + hash = await this.Hasher.ComputeHash(stream); + } + var hashBytes = Encoding.UTF8.GetBytes(hash); if (hashBytes.Length >= 256) { diff --git a/Source/Hasher.SHA1/SHA1ContentHasher.cs b/Source/Hasher.SHA1/SHA1ContentHasher.cs index f21ac69..218d867 100644 --- a/Source/Hasher.SHA1/SHA1ContentHasher.cs +++ b/Source/Hasher.SHA1/SHA1ContentHasher.cs @@ -1,12 +1,13 @@ namespace EternalArrowBackup.Hasher.SHA1 { + using System.IO; using System.Linq; using System.Threading.Tasks; using Contracts.ContentTransformations; public class SHA1ContentHasher : IContentHasher { - public Task ComputeHash(byte[] content) + public Task ComputeHash(Stream content) { return Task.Run(() => { diff --git a/Tests/Encryptor.ClearText/EncryptorAndHasherTests.cs b/Tests/Encryptor.ClearText/EncryptorAndHasherTests.cs index 3f97318..a0ff000 100644 --- a/Tests/Encryptor.ClearText/EncryptorAndHasherTests.cs +++ b/Tests/Encryptor.ClearText/EncryptorAndHasherTests.cs @@ -16,19 +16,19 @@ var messageBytes = Encoding.ASCII.GetBytes(message); var hasher = new SHA1ContentHasher(); var encryptor = new ClearTextContentEncryptor(hasher); - var encrypted = await encryptor.Encrypt(messageBytes); + var encrypted = await encryptor.TransformData(messageBytes); - var decryptionResult = await encryptor.Decrypt(encrypted); + var decryptionResult = await encryptor.GetOriginalData(encrypted); Assert.True(decryptionResult.IsSuccessful); Assert.Equal(messageBytes, decryptionResult.Data); encrypted[0]++; - decryptionResult = await encryptor.Decrypt(encrypted); + decryptionResult = await encryptor.GetOriginalData(encrypted); Assert.False(decryptionResult.IsSuccessful); encrypted[0]--; encrypted[encrypted.Length - 1]--; - decryptionResult = await encryptor.Decrypt(encrypted); + decryptionResult = await encryptor.GetOriginalData(encrypted); Assert.False(decryptionResult.IsSuccessful); } } diff --git a/Tests/Hasher.SHA1/HasherTests.cs b/Tests/Hasher.SHA1/HasherTests.cs index 4ce6781..0787312 100644 --- a/Tests/Hasher.SHA1/HasherTests.cs +++ b/Tests/Hasher.SHA1/HasherTests.cs @@ -2,6 +2,7 @@ { using System; using System.Diagnostics; + using System.IO; using System.Text; using System.Threading.Tasks; using Xunit; @@ -21,8 +22,11 @@ var expectedHashFormatted = expectedHash.Replace(" ", string.Empty).ToLowerInvariant(); var hasher = new SHA1ContentHasher(); var messageBytes = Encoding.ASCII.GetBytes(inputMessage); - var actualHash = await hasher.ComputeHash(messageBytes); - Assert.Equal(expectedHashFormatted, actualHash); + using (var stream = new MemoryStream(messageBytes)) + { + var actualHash = await hasher.ComputeHash(stream); + Assert.Equal(expectedHashFormatted, actualHash); + } } // Single-threaded SHA1 performance on i5-6500 is around 500MB/s @@ -46,12 +50,16 @@ var expectedTimeHigh = 1 + length / (MegabytesPerSecondLowSpeed * 1000); var hasher = new SHA1ContentHasher(); - var stopwatch = new Stopwatch(); - stopwatch.Start(); - await hasher.ComputeHash(messageBytes); - stopwatch.Stop(); - - Assert.InRange(stopwatch.ElapsedMilliseconds, expectedTimeLow, expectedTimeHigh); + using (var stream = new MemoryStream(messageBytes)) + { + await hasher.ComputeHash(stream); + stream.Seek(0, SeekOrigin.Begin); + var stopwatch = new Stopwatch(); + stopwatch.Start(); + await hasher.ComputeHash(stream); + stopwatch.Stop(); + Assert.InRange(stopwatch.ElapsedMilliseconds, expectedTimeLow, expectedTimeHigh); + } } } }