diff --git a/demo.md b/demo.md index 72f9f5e..1996256 100644 --- a/demo.md +++ b/demo.md @@ -2,6 +2,7 @@ hst imager - demo - gui: - download hst imager gui + - blank: 1gb image for testing and show .img vs .vhd - info - read from usb - write to usb diff --git a/src/Hst.Imager.Core.Tests/GivenReadCommand.cs b/src/Hst.Imager.Core.Tests/GivenReadCommand.cs index ed04195..e6c2547 100644 --- a/src/Hst.Imager.Core.Tests/GivenReadCommand.cs +++ b/src/Hst.Imager.Core.Tests/GivenReadCommand.cs @@ -1,3 +1,5 @@ +using Hst.Core.Extensions; + namespace Hst.Imager.Core.Tests { using System; @@ -15,7 +17,7 @@ namespace Hst.Imager.Core.Tests public class GivenReadCommand : CommandTestBase { [Fact] - public async Task WhenReadPhysicalDriveTToImgThenReadDataIsIdentical() + public async Task WhenReadPhysicalDriveToImgThenReadDataIsIdentical() { // arrange - paths and test command helper var sourcePath = TestCommandHelper.PhysicalDrivePath; @@ -204,7 +206,7 @@ public async Task WhenReadPhysicalDriveToVhdThenReadDataIsIdentical() // get source bytes var sourceBytes = await testCommandHelper.ReadMediaData(sourcePath); - // get destination bytes from vhd + // get destination bytes var destinationBytes = await ReadMediaBytes(testCommandHelper, destinationPath, ImageSize); var destinationPathSize = new FileInfo(destinationPath).Length; @@ -229,16 +231,16 @@ public async Task WhenReadPhysicalDriveToVhdWithSizeThenReadDataIsIdentical() var sourcePath = TestCommandHelper.PhysicalDrivePath; var destinationPath = $"{Guid.NewGuid()}.vhd"; var size = 16 * 512; - var fakeCommandHelper = new TestCommandHelper(); + var testCommandHelper = new TestCommandHelper(); try { // arrange - create source physical drive - fakeCommandHelper.AddTestMedia(sourcePath, ImageSize); + testCommandHelper.AddTestMedia(sourcePath, ImageSize); // arrange - read command var cancellationTokenSource = new CancellationTokenSource(); - var readCommand = new ReadCommand(new NullLogger(), fakeCommandHelper, + var readCommand = new ReadCommand(new NullLogger(), testCommandHelper, Enumerable.Empty(), sourcePath, destinationPath, new Size(size, Unit.Bytes), 0, false, false, 0); // act - read source physical drive to destination vhd @@ -246,15 +248,15 @@ public async Task WhenReadPhysicalDriveToVhdWithSizeThenReadDataIsIdentical() Assert.True(result.IsSuccess); // get source bytes - var sourceBytes = (await fakeCommandHelper.ReadMediaData(sourcePath)).Take(size).ToArray(); + var sourceBytes = (await testCommandHelper.ReadMediaData(sourcePath)).Take(size).ToArray(); Assert.Equal(size, sourceBytes.Length); - // get destination bytes from vhd - var destinationBytes = await fakeCommandHelper.ReadMediaData(destinationPath); - var destinationPathSize = new FileInfo(destinationPath).Length; + // get destination bytes + var destinationBytes = await testCommandHelper.ReadMediaData(destinationPath); - // assert length is not the same (vhd file format different than img) and bytes are the same - Assert.NotEqual(sourceBytes.Length, destinationPathSize); + // assert - source bytes are equal to destination bytes + destinationBytes = destinationBytes.Take(size).ToArray(); + Assert.Equal(sourceBytes.Length, destinationBytes.Length); Assert.Equal(sourceBytes, destinationBytes); } finally @@ -265,5 +267,56 @@ public async Task WhenReadPhysicalDriveToVhdWithSizeThenReadDataIsIdentical() } } } + + [Fact] + public async Task WhenReadPhysicalDriveToVhdWithSizeNotDividableBy512ThenReadDataIsIdentical() + { + // arrange - paths, size to read and test command helper + var srcPath = TestCommandHelper.PhysicalDrivePath; + var destPath = $"{Guid.NewGuid()}.vhd"; + var size = 1000000; + var testCommandHelper = new TestCommandHelper(); + + try + { + // arrange - create source physical drive + testCommandHelper.AddTestMedia(srcPath, 10.MB()); + + // arrange - read command + var cancellationTokenSource = new CancellationTokenSource(); + var readCommand = new ReadCommand(new NullLogger(), testCommandHelper, + Enumerable.Empty(), srcPath, destPath, new Size(size, Unit.Bytes), 0, false, false, 0); + + // act - read source physical drive to destination vhd + var result = await readCommand.Execute(cancellationTokenSource.Token); + Assert.True(result.IsSuccess); + + // get source bytes + var sourceBytes = (await testCommandHelper.ReadMediaData(srcPath)).Take(size).ToArray(); + Assert.Equal(size, sourceBytes.Length); + + // get destination bytes + var destinationBytes = await testCommandHelper.ReadMediaData(destPath); + + // assert - destination bytes are larger than size and dividable by 512 + Assert.True(destinationBytes.Length > size); + Assert.True(destinationBytes.Length % 512 == 0); + + // assert - destination bytes are equal to size rounded to next sector + Assert.Equal(size + (512 - size % 512), destinationBytes.Length); + + // assert - source bytes are equal to destination bytes + destinationBytes = destinationBytes.Take(size).ToArray(); + Assert.Equal(sourceBytes.Length, destinationBytes.Length); + Assert.Equal(sourceBytes, destinationBytes); + } + finally + { + if (File.Exists(destPath)) + { + File.Delete(destPath); + } + } + } } } \ No newline at end of file diff --git a/src/Hst.Imager.Core.Tests/StreamCopierTests/GivenStreamCopier.cs b/src/Hst.Imager.Core.Tests/StreamCopierTests/GivenStreamCopier.cs index 587c760..b06c964 100644 --- a/src/Hst.Imager.Core.Tests/StreamCopierTests/GivenStreamCopier.cs +++ b/src/Hst.Imager.Core.Tests/StreamCopierTests/GivenStreamCopier.cs @@ -190,4 +190,50 @@ public async Task WhenCopyAndDestinationOffsetIsLargerThanZeroSourceThenCopiedBy Assert.Equal(expectedDestinationBytes.Length, destinationBytes.Length); Assert.Equal(expectedDestinationBytes, destinationBytes); } + + public byte[] CreateTestData(long size) + { + var data = new byte[size]; + + for (var i = 0; i < data.Length; i++) + { + data[i] = (byte)(i % 256); + } + + return data; + } + + [Fact] + public async Task WhenCopy1MbFrom10MbSrcToDestWith1MbBufferThenDataIsEqual() + { + // arrange - test data + var data = CreateTestData(10.MB()); + + // arrange - source stream with test data + using var source = new MemoryStream(); + await source.WriteBytes(data); + + // arrange - destination stream + using var destination = new MemoryStream(); + + // arrange - stream copier + var streamCopier = new StreamCopier(1024 * 1024); + + // act - copy from source to destination + var size = (int)1.MB(); + var sourceOffset = 0; + var destinationOffset = 0; + var cancellationTokenSource = new CancellationTokenSource(); + await streamCopier.Copy(cancellationTokenSource.Token, source, destination, size, sourceOffset, destinationOffset, true); + + // get source bytes + var sourceBytes = data.Take(size).ToArray(); + + // get destination bytes + var destinationBytes = destination.ToArray(); + + // assert - source bytes are equal to destination bytes + Assert.Equal(sourceBytes.Length, destinationBytes.Length); + Assert.Equal(sourceBytes, destinationBytes); + } } \ No newline at end of file diff --git a/src/Hst.Imager.Core.Tests/TestCommandHelper.cs b/src/Hst.Imager.Core.Tests/TestCommandHelper.cs index cc5209f..2d3c4ad 100644 --- a/src/Hst.Imager.Core.Tests/TestCommandHelper.cs +++ b/src/Hst.Imager.Core.Tests/TestCommandHelper.cs @@ -132,6 +132,11 @@ public override Result GetWritableFileMedia(string path, long? size = nul return new Result(new Media(testMedia.Path, testMedia.Name, testMedia.Data.Length, Media.MediaType.Raw, false, new TestMediaStream(testMedia))); } + + if (size.HasValue) + { + size = GetVhdSize(size.Value); + } if (create && size == null) { diff --git a/src/Hst.Imager.Core/Commands/CommandHelper.cs b/src/Hst.Imager.Core/Commands/CommandHelper.cs index f813608..5aec9f9 100644 --- a/src/Hst.Imager.Core/Commands/CommandHelper.cs +++ b/src/Hst.Imager.Core/Commands/CommandHelper.cs @@ -1,7 +1,4 @@ -using DiscUtils.Fat; -using DiscUtils.Ntfs; - -namespace Hst.Imager.Core.Commands +namespace Hst.Imager.Core.Commands { using System; using System.Collections.Generic; @@ -267,8 +264,8 @@ public virtual Result GetWritableMedia(IEnumerable physic public virtual long GetVhdSize(long size) { - // vhd size dividable by 512 - return size % 512 != 0 ? size - (size % 512) : size; + // increase size to next sector size, if not dividable by 512 + return size % 512 != 0 ? size + (512 - size % 512) : size; } public bool IsVhd(string path) diff --git a/src/Hst.Imager.Core/StreamCopier.cs b/src/Hst.Imager.Core/StreamCopier.cs index 94d8515..01c61c6 100644 --- a/src/Hst.Imager.Core/StreamCopier.cs +++ b/src/Hst.Imager.Core/StreamCopier.cs @@ -105,7 +105,7 @@ public async Task Copy(CancellationToken token, Stream source, Stream de foreach (var dataSector in dataSectors) { var sectorSize = bytesProcessed + dataSector.Start + dataSector.Size > size - ? (int)(size - bytesProcessed + dataSector.Start) + ? (int)(size - (bytesProcessed + dataSector.Start)) : dataSector.Size; var sectorData = new byte[sectorSize];