Added tests for unaligned reads
This commit is contained in:
@@ -202,6 +202,197 @@ namespace Duplicati.UnitTest.DiskImage
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
#region IRawDisk Unaligned Read Tests
|
||||
|
||||
}
|
||||
[Test]
|
||||
public async Task Test_RawDisk_ReadUnalignedOffset_ReturnsCorrectData()
|
||||
{
|
||||
// First write aligned data, then read at an unaligned offset
|
||||
var sectorSize = _rawDisk.SectorSize;
|
||||
|
||||
// Write known pattern at sector 1
|
||||
var writeBuffer = new byte[sectorSize];
|
||||
for (int i = 0; i < sectorSize; i++)
|
||||
writeBuffer[i] = (byte)(i & 0xFF);
|
||||
|
||||
await _rawDisk.WriteSectorsAsync(1, writeBuffer, CancellationToken.None);
|
||||
|
||||
// Read at offset = sector_size + 1 (unaligned)
|
||||
// The implementation should handle this by padding to sector boundaries
|
||||
var offset = sectorSize + 1;
|
||||
var length = sectorSize - 2;
|
||||
|
||||
using var stream = await _rawDisk.ReadBytesAsync(offset, length, CancellationToken.None);
|
||||
var readBuffer = new byte[length];
|
||||
var bytesRead = await stream.ReadAsync(readBuffer.AsMemory(), CancellationToken.None);
|
||||
|
||||
// Should return the data we wrote at sector 1, starting from byte offset 1
|
||||
Assert.AreEqual(length, bytesRead, "Should have read the requested length.");
|
||||
for (int i = 0; i < length; i++)
|
||||
Assert.AreEqual((byte)((i + 1) & 0xFF), readBuffer[i], $"Byte at position {i} should match.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_RawDisk_ReadUnalignedLength_ReturnsCorrectData()
|
||||
{
|
||||
// Test reading with a length that's not a multiple of sector size
|
||||
var sectorSize = _rawDisk.SectorSize;
|
||||
|
||||
// Write known pattern at sector 0
|
||||
var writeBuffer = new byte[sectorSize];
|
||||
for (int i = 0; i < sectorSize; i++)
|
||||
writeBuffer[i] = (byte)(i & 0xFF);
|
||||
|
||||
await _rawDisk.WriteSectorsAsync(0, writeBuffer, CancellationToken.None);
|
||||
|
||||
// Read with unaligned length (sectorSize - 1)
|
||||
var length = sectorSize - 1;
|
||||
using var stream = await _rawDisk.ReadBytesAsync(0, length, CancellationToken.None);
|
||||
var readBuffer = new byte[length];
|
||||
var bytesRead = await stream.ReadAsync(readBuffer.AsMemory(), CancellationToken.None);
|
||||
|
||||
Assert.AreEqual(length, bytesRead, "Should have read the requested length.");
|
||||
for (int i = 0; i < length; i++)
|
||||
Assert.AreEqual((byte)(i & 0xFF), readBuffer[i], $"Byte at position {i} should match.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_RawDisk_ReadShortLength_ReturnsCorrectData()
|
||||
{
|
||||
// Read at offset 0 with length = sector_size - 1 (short read)
|
||||
var sectorSize = _rawDisk.SectorSize;
|
||||
|
||||
// Write known pattern at sector 0
|
||||
var writeBuffer = new byte[sectorSize];
|
||||
for (int i = 0; i < sectorSize; i++)
|
||||
writeBuffer[i] = (byte)(i & 0xFF);
|
||||
|
||||
await _rawDisk.WriteSectorsAsync(0, writeBuffer, CancellationToken.None);
|
||||
|
||||
// Read short length
|
||||
var length = sectorSize - 1;
|
||||
using var stream = await _rawDisk.ReadBytesAsync(0, length, CancellationToken.None);
|
||||
var readBuffer = new byte[length];
|
||||
var bytesRead = await stream.ReadAsync(readBuffer.AsMemory(), CancellationToken.None);
|
||||
|
||||
Assert.AreEqual(length, bytesRead, "Should have read the requested short length.");
|
||||
for (int i = 0; i < length; i++)
|
||||
Assert.AreEqual((byte)(i & 0xFF), readBuffer[i], $"Byte at position {i} should match.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_RawDisk_ReadStraddlingSectors_ReturnsCorrectData()
|
||||
{
|
||||
// Read at offset = sector_size / 2 with length = sector_size (straddles two sectors)
|
||||
var sectorSize = _rawDisk.SectorSize;
|
||||
|
||||
// Write different patterns at sectors 0 and 1
|
||||
var sector0Data = new byte[sectorSize];
|
||||
var sector1Data = new byte[sectorSize];
|
||||
for (int i = 0; i < sectorSize; i++)
|
||||
{
|
||||
sector0Data[i] = (byte)(i | 0xF0); // Pattern 0xF0-0xFF
|
||||
sector1Data[i] = (byte)(i | 0x0F); // Pattern 0x0F-0x1E
|
||||
}
|
||||
|
||||
await _rawDisk.WriteSectorsAsync(0, sector0Data, CancellationToken.None);
|
||||
await _rawDisk.WriteSectorsAsync(1, sector1Data, CancellationToken.None);
|
||||
|
||||
// Read at half-sector offset with full sector length
|
||||
var offset = sectorSize / 2;
|
||||
using var stream = await _rawDisk.ReadBytesAsync(offset, sectorSize, CancellationToken.None);
|
||||
var readBuffer = new byte[sectorSize];
|
||||
var bytesRead = await stream.ReadAsync(readBuffer.AsMemory(), CancellationToken.None);
|
||||
|
||||
Assert.AreEqual(sectorSize, bytesRead, "Should have read one sector.");
|
||||
|
||||
// First half should be from end of sector 0
|
||||
for (int i = 0; i < sectorSize / 2; i++)
|
||||
{
|
||||
var expected = (byte)((sectorSize / 2 + i) | 0xF0);
|
||||
Assert.AreEqual(expected, readBuffer[i], $"Byte at position {i} should match sector 0 data.");
|
||||
}
|
||||
|
||||
// Second half should be from start of sector 1
|
||||
for (int i = sectorSize / 2; i < sectorSize; i++)
|
||||
{
|
||||
var expected = (byte)((i - sectorSize / 2) | 0x0F);
|
||||
Assert.AreEqual(expected, readBuffer[i], $"Byte at position {i} should match sector 1 data.");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_RawDisk_ReadNearEndOfDisk_ReturnsCorrectData()
|
||||
{
|
||||
// Read at the very end of the disk where remaining bytes < sector_size
|
||||
var sectorSize = _rawDisk.SectorSize;
|
||||
var diskSize = _rawDisk.Size;
|
||||
|
||||
// Calculate the last sector and write data there
|
||||
var lastSector = (diskSize / sectorSize) - 1;
|
||||
var writeBuffer = new byte[sectorSize];
|
||||
new Random().NextBytes(writeBuffer);
|
||||
|
||||
await _rawDisk.WriteSectorsAsync(lastSector, writeBuffer, CancellationToken.None);
|
||||
|
||||
// Read from near the end
|
||||
var offset = diskSize - sectorSize;
|
||||
using var stream = await _rawDisk.ReadBytesAsync(offset, sectorSize, CancellationToken.None);
|
||||
var readBuffer = new byte[sectorSize];
|
||||
var bytesRead = await stream.ReadAsync(readBuffer.AsMemory(), CancellationToken.None);
|
||||
|
||||
Assert.AreEqual(sectorSize, bytesRead, "Should have read a full sector.");
|
||||
Assert.AreEqual(writeBuffer, readBuffer, "Data should match what was written.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_RawDisk_ReadUnalignedOffsetWithMemory_ReturnsCorrectData()
|
||||
{
|
||||
// Test the Memory-based ReadBytesAsync with unaligned offset
|
||||
var sectorSize = _rawDisk.SectorSize;
|
||||
|
||||
// Write known pattern at sector 1
|
||||
var writeBuffer = new byte[sectorSize];
|
||||
for (int i = 0; i < sectorSize; i++)
|
||||
writeBuffer[i] = (byte)((i * 2) & 0xFF);
|
||||
|
||||
await _rawDisk.WriteSectorsAsync(1, writeBuffer, CancellationToken.None);
|
||||
|
||||
// Read at unaligned offset
|
||||
var offset = sectorSize + 4;
|
||||
var length = sectorSize - 8;
|
||||
var readBuffer = new byte[length];
|
||||
var bytesRead = await _rawDisk.ReadBytesAsync(offset, readBuffer.AsMemory(), CancellationToken.None);
|
||||
|
||||
Assert.AreEqual(length, bytesRead, "Should have read the requested length.");
|
||||
for (int i = 0; i < length; i++)
|
||||
Assert.AreEqual((byte)(((i + 4) * 2) & 0xFF), readBuffer[i], $"Byte at position {i} should match.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_RawDisk_ReadUnalignedLengthWithMemory_ReturnsCorrectData()
|
||||
{
|
||||
// Test the Memory-based ReadBytesAsync with unaligned length
|
||||
var sectorSize = _rawDisk.SectorSize;
|
||||
|
||||
// Write known pattern at sector 0
|
||||
var writeBuffer = new byte[sectorSize];
|
||||
for (int i = 0; i < sectorSize; i++)
|
||||
writeBuffer[i] = (byte)((i + 100) & 0xFF);
|
||||
|
||||
await _rawDisk.WriteSectorsAsync(0, writeBuffer, CancellationToken.None);
|
||||
|
||||
// Read with unaligned length
|
||||
var length = sectorSize - 5;
|
||||
var readBuffer = new byte[length];
|
||||
var bytesRead = await _rawDisk.ReadBytesAsync(0, readBuffer.AsMemory(), CancellationToken.None);
|
||||
|
||||
Assert.AreEqual(length, bytesRead, "Should have read the requested length.");
|
||||
for (int i = 0; i < length; i++)
|
||||
Assert.AreEqual((byte)((i + 100) & 0xFF), readBuffer[i], $"Byte at position {i} should match.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user