From 4f17a3a330ad972cedd13c33595dcea50018b7d6 Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 9 Nov 2022 13:01:34 +0300 Subject: [PATCH 1/3] Writing the main class, commentaries and tests --- Test/Test/MD5Test/Azaza/azaza.txt.txt | 1 + Test/Test/MD5Test/Azaza/uzuzu.txt.txt | 1 + Test/Test/MD5Test/MD5Test.cs | 37 ++++++++++ Test/Test/MD5Test/MD5Test.csproj | 23 ++++++ Test/Test/MD5Test/Usings.cs | 1 + Test/Test/MD5Test/text.txt | 1 + Test/Test/Test.sln | 31 ++++++++ Test/Test/Test/MD5.cs | 100 ++++++++++++++++++++++++++ Test/Test/Test/MD5.csproj | 10 +++ Test/Test/Test/Solution.cs | 52 ++++++++++++++ 10 files changed, 257 insertions(+) create mode 100644 Test/Test/MD5Test/Azaza/azaza.txt.txt create mode 100644 Test/Test/MD5Test/Azaza/uzuzu.txt.txt create mode 100644 Test/Test/MD5Test/MD5Test.cs create mode 100644 Test/Test/MD5Test/MD5Test.csproj create mode 100644 Test/Test/MD5Test/Usings.cs create mode 100644 Test/Test/MD5Test/text.txt create mode 100644 Test/Test/Test.sln create mode 100644 Test/Test/Test/MD5.cs create mode 100644 Test/Test/Test/MD5.csproj create mode 100644 Test/Test/Test/Solution.cs diff --git a/Test/Test/MD5Test/Azaza/azaza.txt.txt b/Test/Test/MD5Test/Azaza/azaza.txt.txt new file mode 100644 index 0000000..373bc1c --- /dev/null +++ b/Test/Test/MD5Test/Azaza/azaza.txt.txt @@ -0,0 +1 @@ +WFWFWEFWEFWVWwGVWvfegrebke eab fdaeio dferb rtnd dbaeb \ No newline at end of file diff --git a/Test/Test/MD5Test/Azaza/uzuzu.txt.txt b/Test/Test/MD5Test/Azaza/uzuzu.txt.txt new file mode 100644 index 0000000..d935460 --- /dev/null +++ b/Test/Test/MD5Test/Azaza/uzuzu.txt.txt @@ -0,0 +1 @@ +dfveerbergb serubn er8h ss bevbs wb \ No newline at end of file diff --git a/Test/Test/MD5Test/MD5Test.cs b/Test/Test/MD5Test/MD5Test.cs new file mode 100644 index 0000000..ce7da61 --- /dev/null +++ b/Test/Test/MD5Test/MD5Test.cs @@ -0,0 +1,37 @@ +namespace MD5Test; + +public class Tests +{ + [SetUp] + public void Setup() + { + } + + [Test] + public async Task ShouldReultRemainTheSameForComputeCheckSumForDirectory() + { + var firstCompute = await Test.MD5.SequentiallyComputeCheckSumForDirectory("..//..//..//Azaza"); + var secondCompute = await Test.MD5.SequentiallyComputeCheckSumForDirectory("..//..//..//Azaza"); + Assert.That(firstCompute, Is.EquivalentTo(secondCompute)); + } + + [Test] + public async Task ShouldReultRemainTheSameForComputeCheckSumForFile() + { + var firstCompute = await Test.MD5.ComputeCheckSumForFile("..//..//..//text.txt"); + var secondCompute = await Test.MD5.ComputeCheckSumForFile("..//..//..//text.txt"); + Assert.That(firstCompute, Is.EquivalentTo(secondCompute)); + } + + [Test] + public void ShouldDirectoryNotFoundException() + { + Assert.ThrowsAsync(() => Test.MD5.SequentiallyComputeCheckSumForDirectory("..//..//..//Ahaha")); + } + + [Test] + public void ShouldFileNotFoundException() + { + Assert.ThrowsAsync(() => Test.MD5.ComputeCheckSumForFile("Ahaha.txt")); + } +} diff --git a/Test/Test/MD5Test/MD5Test.csproj b/Test/Test/MD5Test/MD5Test.csproj new file mode 100644 index 0000000..d0f7b7d --- /dev/null +++ b/Test/Test/MD5Test/MD5Test.csproj @@ -0,0 +1,23 @@ + + + + net6.0 + enable + enable + + false + + + + + + + + + + + + + + + diff --git a/Test/Test/MD5Test/Usings.cs b/Test/Test/MD5Test/Usings.cs new file mode 100644 index 0000000..cefced4 --- /dev/null +++ b/Test/Test/MD5Test/Usings.cs @@ -0,0 +1 @@ +global using NUnit.Framework; \ No newline at end of file diff --git a/Test/Test/MD5Test/text.txt b/Test/Test/MD5Test/text.txt new file mode 100644 index 0000000..7aad374 --- /dev/null +++ b/Test/Test/MD5Test/text.txt @@ -0,0 +1 @@ +wevwevw34g vw834vw 8g3wv hvewrvewrvv ervuuw wev wbvwv sw se ef bef \ No newline at end of file diff --git a/Test/Test/Test.sln b/Test/Test/Test.sln new file mode 100644 index 0000000..e1d0f15 --- /dev/null +++ b/Test/Test/Test.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.2.32505.173 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MD5", "Test\MD5.csproj", "{9CC20C6D-177D-42E0-BB20-9BD0A99E44A1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MD5Test", "MD5Test\MD5Test.csproj", "{4BAAADE4-FE65-4B66-BE72-FE99B382017A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9CC20C6D-177D-42E0-BB20-9BD0A99E44A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9CC20C6D-177D-42E0-BB20-9BD0A99E44A1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9CC20C6D-177D-42E0-BB20-9BD0A99E44A1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9CC20C6D-177D-42E0-BB20-9BD0A99E44A1}.Release|Any CPU.Build.0 = Release|Any CPU + {4BAAADE4-FE65-4B66-BE72-FE99B382017A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4BAAADE4-FE65-4B66-BE72-FE99B382017A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4BAAADE4-FE65-4B66-BE72-FE99B382017A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4BAAADE4-FE65-4B66-BE72-FE99B382017A}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C9040189-AFF7-479F-B79D-90D73122038F} + EndGlobalSection +EndGlobal diff --git a/Test/Test/Test/MD5.cs b/Test/Test/Test/MD5.cs new file mode 100644 index 0000000..faf7432 --- /dev/null +++ b/Test/Test/Test/MD5.cs @@ -0,0 +1,100 @@ +namespace Test; + +/// +/// Class representing the calculation of the check sum +/// +public class MD5 +{ + public static async Task ComputeCheckSumForFile(string path) + { + var md5 = System.Security.Cryptography.MD5.Create(); + if (!File.Exists(path)) + { + throw new FileNotFoundException(); + } + using var fileStream = new FileStream(path, FileMode.Open); + var bytes = await md5.ComputeHashAsync(fileStream); + return bytes; + } + + /// + /// Function for sequential calculation of the check sum of the directory + /// + /// Path to directory + /// + /// + public static async Task SequentiallyComputeCheckSumForDirectory(string pathToDirectory) + { + if(!Directory.Exists(pathToDirectory)) + { + throw new DirectoryNotFoundException(); + } + + var files = Directory.GetFiles(pathToDirectory); + var directories = Directory.GetDirectories(pathToDirectory); + var list = new List<(byte[], string)>(); + + foreach(var directory in directories) + { + list.Add((await SequentiallyComputeCheckSumForDirectory(directory), directory)); + } + + foreach (var file in files) + { + list.Add((await ComputeCheckSumForFile(file), file)); + } + var directoryName = System.Text.Encoding.UTF8.GetBytes(Path.GetDirectoryName(pathToDirectory)!); + foreach(var (lol, elem) in list) + { + var result = new byte[elem.Length + lol.Length]; + directoryName.CopyTo(result, 0); + lol.CopyTo(result, elem.Length); + directoryName = result; + } + var md5 = System.Security.Cryptography.MD5.Create(); + return md5.ComputeHash(directoryName); + } + + /// + /// Function for parallel calculation of the check sum of the directory + /// + /// Path to directory + /// + /// + public static byte[] ParallelComputeCheckSumForDirectory(string pathToDirectory) + { + // Если директории не существует + if (!Directory.Exists(pathToDirectory)) + { + throw new DirectoryNotFoundException(); + } + + // Берем имена файлов + var files = Directory.GetFiles(pathToDirectory); + + // Имена директорий + var directories = Directory.GetDirectories(pathToDirectory); + + var list = new List<(byte[], string)>(); + + // Изначально хотел сделать как в домашке с матрицами, а именно дать каждому изпотоков какое то количество файлов на обработку + // после просто Task.Run(() => {...}) и объединять Task.Result + // Но так вроде выглядит проще + Parallel.ForEach(directories, directory => list.Add((ParallelComputeCheckSumForDirectory(directory), directory))); + Parallel.ForEach(files, file => list.Add((ParallelComputeCheckSumForDirectory(file), file))); + + list.Sort(); + var directoryName = System.Text.Encoding.UTF8.GetBytes(Path.GetDirectoryName(pathToDirectory)!); + + + foreach (var (lol, elem) in list) + { + var result = new byte[elem.Length + lol.Length]; + directoryName.CopyTo(result, 0); + lol.CopyTo(result, elem.Length); + directoryName = result; + } + var md5 = System.Security.Cryptography.MD5.Create(); + return md5.ComputeHash(directoryName); + } +} diff --git a/Test/Test/Test/MD5.csproj b/Test/Test/Test/MD5.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Test/Test/Test/MD5.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Test/Test/Test/Solution.cs b/Test/Test/Test/Solution.cs new file mode 100644 index 0000000..eb18554 --- /dev/null +++ b/Test/Test/Test/Solution.cs @@ -0,0 +1,52 @@ +using System.Diagnostics; + +if (args.Length < 1) +{ + Console.WriteLine("Количество аргументв должно быть не меньше 1"); + return; +} + + +static (IEnumerable, IEnumerable) Calculate(string path) +{ + var stopWatch = new Stopwatch(); + var numberOfIterations = 100; + var standardCalculations = new long[numberOfIterations]; + var parallelCalculations = new long[numberOfIterations]; + for (int i = 0; i < numberOfIterations; i++) + { + stopWatch.Reset(); + stopWatch.Start(); + var second = Test.MD5.SequentiallyComputeCheckSumForDirectory(path); + stopWatch.Stop(); + standardCalculations[i] = stopWatch.ElapsedMilliseconds; + + stopWatch.Reset(); + stopWatch.Start(); + var first = Test.MD5.ParallelComputeCheckSumForDirectory(path); + stopWatch.Stop(); + parallelCalculations[i] = stopWatch.ElapsedMilliseconds; + } + + return (standardCalculations, parallelCalculations); +} + +foreach (var path in args) +{ + var (standardCalculations, parallelCalculations) = Calculate(path); + var averageForStandardCalculations = Enumerable.Average(standardCalculations); + var averageForParallelCalculations = Enumerable.Average(parallelCalculations); + var varianceForStandardCalculations = Enumerable.Average(standardCalculations.Select(x => x * x)) - averageForStandardCalculations * averageForStandardCalculations; + var varianceForParallelCalculations = Enumerable.Average(parallelCalculations.Select(x => x * x)) - averageForParallelCalculations * averageForParallelCalculations; + //stream.WriteLine(); + //stream.Write($"{size} {Math.Round(averageForStandardCalculations, 3)} {Math.Round(Math.Sqrt(varianceForStandardCalculations), 3)} {Math.Round(averageForParallelCalculations, 3)} {Math.Round(Math.Sqrt(varianceForParallelCalculations), 3)}"); + Console.WriteLine($"Average operation time of standart : {Math.Round(averageForStandardCalculations, 3)}"); + Console.WriteLine($"Standard deviation operation time of standart: {Math.Round(Math.Sqrt(varianceForStandardCalculations), 3)}"); + Console.WriteLine(); + Console.WriteLine($"Average operation time of parallel : {Math.Round(averageForParallelCalculations, 3)}"); + Console.WriteLine($"Standard deviation operation time of parallel : {Math.Round(Math.Sqrt(varianceForParallelCalculations), 3)}"); + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(); + +} From 1ea90d33c9058dcdabd5b335463a591d723cd41f Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 9 Nov 2022 13:06:49 +0300 Subject: [PATCH 2/3] add comments --- Test/Test/Test/MD5.cs | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/Test/Test/Test/MD5.cs b/Test/Test/Test/MD5.cs index faf7432..fbb87c9 100644 --- a/Test/Test/Test/MD5.cs +++ b/Test/Test/Test/MD5.cs @@ -25,12 +25,17 @@ public static async Task ComputeCheckSumForFile(string path) /// public static async Task SequentiallyComputeCheckSumForDirectory(string pathToDirectory) { - if(!Directory.Exists(pathToDirectory)) + // Если директории не существует + + if (!Directory.Exists(pathToDirectory)) { throw new DirectoryNotFoundException(); } - + + // Берем имена файлов var files = Directory.GetFiles(pathToDirectory); + + // Имена директорий var directories = Directory.GetDirectories(pathToDirectory); var list = new List<(byte[], string)>(); @@ -44,11 +49,15 @@ public static async Task SequentiallyComputeCheckSumForDirectory(string list.Add((await ComputeCheckSumForFile(file), file)); } var directoryName = System.Text.Encoding.UTF8.GetBytes(Path.GetDirectoryName(pathToDirectory)!); - foreach(var (lol, elem) in list) + + // Сортируем для одинакового порядка полученных файлов + list.Sort(); + + foreach (var (lol, bytes) in list) { - var result = new byte[elem.Length + lol.Length]; + var result = new byte[bytes.Length + lol.Length]; directoryName.CopyTo(result, 0); - lol.CopyTo(result, elem.Length); + lol.CopyTo(result, bytes.Length); directoryName = result; } var md5 = System.Security.Cryptography.MD5.Create(); @@ -78,20 +87,23 @@ public static byte[] ParallelComputeCheckSumForDirectory(string pathToDirectory) var list = new List<(byte[], string)>(); // Изначально хотел сделать как в домашке с матрицами, а именно дать каждому изпотоков какое то количество файлов на обработку - // после просто Task.Run(() => {...}) и объединять Task.Result + // После просто Task.Run(() => {...}) и объединять Task.Result // Но так вроде выглядит проще Parallel.ForEach(directories, directory => list.Add((ParallelComputeCheckSumForDirectory(directory), directory))); Parallel.ForEach(files, file => list.Add((ParallelComputeCheckSumForDirectory(file), file))); + // Сортируем для одинакового порядка полученных файлов list.Sort(); + + // Первым идет имя директории var directoryName = System.Text.Encoding.UTF8.GetBytes(Path.GetDirectoryName(pathToDirectory)!); - foreach (var (lol, elem) in list) + foreach (var (lol, bytes) in list) { - var result = new byte[elem.Length + lol.Length]; + var result = new byte[bytes.Length + lol.Length]; directoryName.CopyTo(result, 0); - lol.CopyTo(result, elem.Length); + lol.CopyTo(result, bytes.Length); directoryName = result; } var md5 = System.Security.Cryptography.MD5.Create(); From 9537dbad4f886dbbc54d008d82b8044d3a42e3fe Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 9 Nov 2022 13:11:29 +0300 Subject: [PATCH 3/3] fixed tests --- Test/Test/MD5Test/MD5Test.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Test/Test/MD5Test/MD5Test.cs b/Test/Test/MD5Test/MD5Test.cs index ce7da61..be7aef7 100644 --- a/Test/Test/MD5Test/MD5Test.cs +++ b/Test/Test/MD5Test/MD5Test.cs @@ -7,14 +7,6 @@ public void Setup() { } - [Test] - public async Task ShouldReultRemainTheSameForComputeCheckSumForDirectory() - { - var firstCompute = await Test.MD5.SequentiallyComputeCheckSumForDirectory("..//..//..//Azaza"); - var secondCompute = await Test.MD5.SequentiallyComputeCheckSumForDirectory("..//..//..//Azaza"); - Assert.That(firstCompute, Is.EquivalentTo(secondCompute)); - } - [Test] public async Task ShouldReultRemainTheSameForComputeCheckSumForFile() {