-
Notifications
You must be signed in to change notification settings - Fork 0
к/р 1 #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
к/р 1 #5
Changes from all commits
cdea628
e1a9db3
e09ca4f
53541e3
18819f3
09c5f19
addb198
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| // Copyright (c) Alexander Bugaev 2024 | ||
| // | ||
| // Use of this source code is governed by an MIT license | ||
| // that can be found in the LICENSE file or at | ||
| // https://opensource.org/licenses/MIT. | ||
|
|
||
| namespace CheckSum.Tests; | ||
|
|
||
| public static class CheckSumUtilsTest | ||
| { | ||
| private const string TestFilesPath = "TestFiles/"; | ||
|
|
||
| public static IEnumerable<TestCaseData> TestCases() | ||
| { | ||
| foreach (var testFile in Directory.GetFileSystemEntries(TestFilesPath)) | ||
| { | ||
| yield return new TestCaseData(testFile); | ||
| } | ||
| } | ||
|
|
||
| [TestCaseSource(nameof(TestCases))] | ||
| public static async Task TestCheckSumEvaluation_CorrectCases_CheckSumsAreEqual(string path) | ||
| { | ||
| var hash1 = CheckSumUtils.GetCheckSumSequentially(path); | ||
| var hash2 = await CheckSumUtils.GetCheckSumConcurrently(path); | ||
| Assert.That(hash1, Is.EqualTo(hash2)); | ||
| } | ||
|
|
||
| [Test] | ||
| public static void TestCheckSumEvaluation_UnexistentFile_ThrowException() | ||
| { | ||
| Assert.Throws<FileNotFoundException>( | ||
| () => CheckSumUtils.GetCheckSumSequentially("agsgdffdghgf")); | ||
| Assert.ThrowsAsync<FileNotFoundException>( | ||
| async () => await CheckSumUtils.GetCheckSumConcurrently("agsgdffdghgf")); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| // Copyright (c) Alexander Bugaev 2024 | ||
| // | ||
| // Use of this source code is governed by an MIT license | ||
| // that can be found in the LICENSE file or at | ||
| // https://opensource.org/licenses/MIT. | ||
|
|
||
| global using NUnit.Framework; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <TargetFramework>net9.0</TargetFramework> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
|
|
||
| <IsPackable>false</IsPackable> | ||
| <IsTestProject>true</IsTestProject> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" /> | ||
| <PackageReference Include="NUnit" Version="3.13.3" /> | ||
| <PackageReference Include="NUnit3TestAdapter" Version="4.2.1" /> | ||
| <PackageReference Include="NUnit.Analyzers" Version="3.6.1" /> | ||
| <PackageReference Include="coverlet.collector" Version="6.0.0" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <ProjectReference Include="..\Test1\Test1.csproj" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <Content Include="TestFiles/**"> | ||
| <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||
| </Content> | ||
| </ItemGroup> | ||
|
|
||
| </Project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| yvuyvuyvyuyyyuvyuvyuuyvyvyvuyvuyvyuyyyuvyuvyuuyvyvyvuyvuyvyuyyyuvyu | ||
| vyuuyvyvyvuyvuyvyuyyyuvyuvyuuyvyvyvuyvuyvyuyyyuvyuvyuuyvyvyvuyvuyvyuyyy | ||
| uvyuvyuuyvyvyvuyvuyvyuyyyuvyuvyuuyvyvyvuyvuyvyuyyyuvyuvyuuyvyv |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| qqqqqqqqwqwqwqqqqqqqqqwqwqwqqqqqqqqqwqwqwqqqqqqqqqwqwqwqqqqqqqqqwqwqwq | ||
| qqqqqqqqwqwqwqqqqqqqqqwqwqwqqqqqqqqqwqwqwqqqqqqqqqwqwqwqqqqqqqqqwqwqwq | ||
| qqqqqqqqwqwqwqqqqqqqqqwqwqwqqqqqqqqqwqwqwqqqqqqqqqwqwqwqqqqqqqqqwqwqwqqqqqqqqqwqwqwq |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| qqqqqqqqwqwqwq2131313131 | ||
| qqqqqqqqwqwqwq2131313131 | ||
| qqqqqqqqwqwqwq2131313131 | ||
| qqqqqqqqwqwqwq2131313131 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 90090090302131312900900903021313129009009030213131290090090302131312 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 11111111111111222222222222aaaaaaaaaaa |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 11111111111111222222222222aaaaaaaaaaa11111111111111222222222222aaaaaaaaaaa1211 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 00000000111111111111111111111111111112222222222222211111111111111222222222222aaaaaaaaaaa |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| fasgagasasgassg049203209-05034958034 | ||
| 32313 | ||
| 321312 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| | ||
| Microsoft Visual Studio Solution File, Format Version 12.00 | ||
| # Visual Studio Version 17 | ||
| VisualStudioVersion = 17.0.31903.59 | ||
| MinimumVisualStudioVersion = 10.0.40219.1 | ||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test1", "Test1\Test1.csproj", "{E17B3681-8DCA-4F5D-BCF6-B941B2A3C896}" | ||
| EndProject | ||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test1.Tests", "Test1.Tests\Test1.Tests.csproj", "{F9AFFFD2-F330-491C-8C88-A114CE9EBC22}" | ||
| EndProject | ||
| Global | ||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
| Debug|Any CPU = Debug|Any CPU | ||
| Release|Any CPU = Release|Any CPU | ||
| EndGlobalSection | ||
| GlobalSection(SolutionProperties) = preSolution | ||
| HideSolutionNode = FALSE | ||
| EndGlobalSection | ||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
| {E17B3681-8DCA-4F5D-BCF6-B941B2A3C896}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| {E17B3681-8DCA-4F5D-BCF6-B941B2A3C896}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| {E17B3681-8DCA-4F5D-BCF6-B941B2A3C896}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| {E17B3681-8DCA-4F5D-BCF6-B941B2A3C896}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| {7F25481E-3621-4545-95FA-ACF6A3C42F70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| {7F25481E-3621-4545-95FA-ACF6A3C42F70}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| {7F25481E-3621-4545-95FA-ACF6A3C42F70}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| {7F25481E-3621-4545-95FA-ACF6A3C42F70}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| {F9AFFFD2-F330-491C-8C88-A114CE9EBC22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| {F9AFFFD2-F330-491C-8C88-A114CE9EBC22}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| {F9AFFFD2-F330-491C-8C88-A114CE9EBC22}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| {F9AFFFD2-F330-491C-8C88-A114CE9EBC22}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| EndGlobalSection | ||
| EndGlobal |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| // Copyright (c) Alexander Bugaev 2024 | ||
| // | ||
| // Use of this source code is governed by an MIT license | ||
| // that can be found in the LICENSE file or at | ||
| // https://opensource.org/licenses/MIT. | ||
|
|
||
| using System.Security.Cryptography; | ||
| using System.Text; | ||
|
|
||
| namespace CheckSum; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. namespace лучше перед using |
||
|
|
||
| /// <summary> | ||
| /// Class for evaluating file check sums. | ||
| /// </summary> | ||
| public static class CheckSumUtils | ||
| { | ||
| /// <summary> | ||
| /// Evaluate the check sum of given file sequentially. | ||
| /// </summary> | ||
| /// <param name="path">Path of the file to get check sum of.</param> | ||
| /// <returns>An array of bytes: evaluated check sum.</returns> | ||
| /// <exception cref="FileNotFoundException">File was not found.</exception> | ||
| public static byte[] GetCheckSumSequentially(string path) | ||
| { | ||
| if (File.Exists(path)) | ||
| { | ||
| return GetFileCheckSumSequentially(path); | ||
| } | ||
|
|
||
| if (Directory.Exists(path)) | ||
| { | ||
| return GetDirectoryCheckSumSequentially(path); | ||
| } | ||
|
|
||
| throw new FileNotFoundException(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Evaluate the check sum of given file concurrently. | ||
| /// </summary> | ||
| /// <param name="path">Path of the file to get check sum of.</param> | ||
| /// <returns>A task with result as an array of bytes: evaluated check sum.</returns> | ||
| /// <exception cref="FileNotFoundException">File was not found.</exception> | ||
| public static async Task<byte[]> GetCheckSumConcurrently(string path) | ||
| { | ||
| if (File.Exists(path)) | ||
| { | ||
| return await GetFileCheckSumConcurrently(path); | ||
| } | ||
|
|
||
| if (Directory.Exists(path)) | ||
| { | ||
| return GetDirectoryCheckSumConcurrently(path); | ||
| } | ||
|
|
||
| throw new FileNotFoundException(); | ||
| } | ||
|
|
||
| private static byte[] GetFileCheckSumSequentially(string path) | ||
| { | ||
| var content = File.ReadAllBytes(path); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Если файл в память не лезет, быть беде |
||
| return MD5.HashData(content); | ||
| } | ||
|
|
||
| private static byte[] GetDirectoryCheckSumSequentially(string path) | ||
| { | ||
| var result = new List<byte>(); | ||
| var name = Path.GetFileName(path); | ||
| var nameHash = MD5.HashData(Encoding.Unicode.GetBytes(name)); | ||
| result.AddRange(nameHash); | ||
|
|
||
| var entries = Directory.GetFileSystemEntries(path); | ||
| Array.Sort(entries); | ||
| foreach (var entry in entries) | ||
| { | ||
| result.AddRange(GetCheckSumSequentially(entry)); | ||
| } | ||
|
|
||
| return result.ToArray(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Так это не чексумма, а конкатенированный набор чексумм. Надо было это ещё в MD5 запихать. |
||
| } | ||
|
|
||
| private static async Task<byte[]> GetFileCheckSumConcurrently(string path) | ||
| { | ||
| var content = await File.ReadAllBytesAsync(path); | ||
| return MD5.HashData(content); | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Вы не поверите, но и в однопоточном случае стоило так с файлом и поступать. Синхронный ввод-вывод в современном мире, я бы сказал, вообще не нужен. Тут оно асинхронное, но не параллельное, так что не противоречит условию. |
||
|
|
||
| private static byte[] GetDirectoryCheckSumConcurrently(string path) | ||
| { | ||
| var tasks = new List<Task<byte[]>>(); | ||
| var name = Path.GetFileName(path); | ||
| var nameHash = MD5.HashData(Encoding.Unicode.GetBytes(name)); | ||
| tasks.Add(Task.Run(() => nameHash)); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Он же уже посчитан. Task.Result? |
||
|
|
||
| var entries = Directory.GetFileSystemEntries(path); | ||
| Array.Sort(entries); | ||
| foreach (var entry in entries) | ||
| { | ||
| tasks.Add(GetCheckSumConcurrently(entry)); | ||
| } | ||
|
|
||
| var resultSize = 0; | ||
| foreach (var task in tasks) | ||
| { | ||
| resultSize += task.Result.Length; | ||
| } | ||
|
|
||
| var result = new byte[resultSize]; | ||
| var currentIndex = 0; | ||
| foreach (var task in tasks) | ||
| { | ||
| for (int i = 0; i < task.Result.Length; ++i) | ||
| { | ||
| result[currentIndex] = task.Result[i]; | ||
| ++currentIndex; | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Процесс можно было немного автоматизировать через Array.Copy |
||
| } | ||
|
|
||
| return result; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. И тоже, ожидался 128-битный хеш, вернули что попало |
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| // Copyright (c) Alexander Bugaev 2024 | ||
| // | ||
| // Use of this source code is governed by an MIT license | ||
| // that can be found in the LICENSE file or at | ||
| // https://opensource.org/licenses/MIT. | ||
|
|
||
| namespace CheckSum; | ||
|
|
||
| using System.Diagnostics; | ||
|
|
||
| /// <summary> | ||
| /// Program that compares the time of sequential and | ||
| /// concurrent check sum evaluation variations. | ||
| /// </summary> | ||
| public static class Program | ||
| { | ||
| /// <summary> | ||
| /// Main entry point of the program. | ||
| /// </summary> | ||
| /// <param name="args">First argument is the path of | ||
| /// the file to evaluate the check sum of.</param> | ||
| public static void Main(string[] args) | ||
|
Comment on lines
+15
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Это не нужно, используйте top-level statements |
||
| { | ||
| if (args.Length != 1) | ||
| { | ||
| throw new ArgumentException("Invalid arguments.\nExpected: Path of the file"); | ||
| } | ||
|
|
||
| var path = args[0]; | ||
| var stopWatch = new Stopwatch(); | ||
|
|
||
| try | ||
| { | ||
| stopWatch.Restart(); | ||
| CheckSumUtils.GetCheckSumSequentially(path); | ||
| stopWatch.Stop(); | ||
| Console.WriteLine($"Time of the sequential evaluation: {stopWatch.Elapsed}"); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Указывайте единицы измерения всегда |
||
|
|
||
| stopWatch.Restart(); | ||
| CheckSumUtils.GetCheckSumConcurrently(path).Wait(); | ||
| stopWatch.Stop(); | ||
| Console.WriteLine($"Time of the concurrent evaluation: {stopWatch.Elapsed}"); | ||
| } | ||
| catch (FileNotFoundException e) | ||
| { | ||
| Console.WriteLine($"Error: {e.Message}"); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
| <PropertyGroup> | ||
| <OutputType>Exe</OutputType> | ||
| <TargetFramework>net9.0</TargetFramework> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
| </PropertyGroup> | ||
| <ItemGroup> | ||
| <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all"/> | ||
| </ItemGroup> | ||
| </Project> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Если проходите по коллекции, чтобы сделать yield, это сразу знак, что делаете что-то не так, коллекция ведь и так коллекция, а yield нужен, чтобы по набору значений коллекцию сделать