Skip to content

Commit

Permalink
Merge pull request #188 from Visionaid-International-Ltd/truncate-str…
Browse files Browse the repository at this point in the history
…eamdecorator-reads

Truncate StreamDecorator reads
  • Loading branch information
ironfede authored Oct 12, 2024
2 parents ceb409e + 6e712f4 commit 829cb82
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 50 deletions.
5 changes: 5 additions & 0 deletions sources/OpenMcdf.Extensions/StreamDecorator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ public override int Read(byte[] buffer, int offset, int count)
if (position >= cfStream.Size)
return 0;

int maxReadableLength = (int)Math.Min(int.MaxValue, Length - Position);
count = Math.Max(0, Math.Min(maxReadableLength, count));
if (count == 0)
return 0;

count = cfStream.Read(buffer, position, offset, count);
position += count;
return count;
Expand Down
44 changes: 35 additions & 9 deletions sources/Test/OpenMcdf.Extensions.Test/CFSStreamExtensionsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ public void Test_AS_IOSTREAM_MULTISECTOR_WRITE()
cf.SaveAs("$ACFFile2.cfs");
}

// Works
using (CompoundFile cf = new("$ACFFile2.cfs"))
{
using Stream s = cf.RootStorage.GetStream("ANewStream").AsIOStream();
Expand All @@ -102,15 +101,42 @@ public void Test_AS_IOSTREAM_MULTISECTOR_WRITE()
Assert.AreEqual(readData.Length, readCount);
CollectionAssert.AreEqual(data, readData);
}
}

// Won't work until #88 is fixed.
using (CompoundFile cf = new("$ACFFile2.cfs"))
{
using Stream readStream = cf.RootStorage.GetStream("ANewStream").AsIOStream();
using MemoryStream ms = new();
readStream.CopyTo(ms);
CollectionAssert.AreEqual(data, ms.ToArray());
}
[TestMethod]
[DataRow(CFSVersion.Ver_3, 0)]
[DataRow(CFSVersion.Ver_3, 63)]
[DataRow(CFSVersion.Ver_3, 64)]
[DataRow(CFSVersion.Ver_3, 65)]
[DataRow(CFSVersion.Ver_3, 511)]
[DataRow(CFSVersion.Ver_3, 512)]
[DataRow(CFSVersion.Ver_3, 513)]
[DataRow(CFSVersion.Ver_3, 4095)]
[DataRow(CFSVersion.Ver_3, 4096)]
[DataRow(CFSVersion.Ver_3, 409)]
[DataRow(CFSVersion.Ver_4, 0)]
[DataRow(CFSVersion.Ver_4, 63)]
[DataRow(CFSVersion.Ver_4, 64)]
[DataRow(CFSVersion.Ver_4, 65)]
[DataRow(CFSVersion.Ver_4, 511)]
[DataRow(CFSVersion.Ver_4, 512)]
[DataRow(CFSVersion.Ver_4, 513)]
[DataRow(CFSVersion.Ver_4, 4095)]
[DataRow(CFSVersion.Ver_4, 4096)]
[DataRow(CFSVersion.Ver_4, 4097)]
public void Test_STREAMDECORATOR_COPY(CFSVersion version, int length)
{
using CompoundFile cf = new(version, CFSConfiguration.Default);
CFStream cfStream = cf.RootStorage.AddStream("MyStream");
using StreamDecorator stream = new(cfStream);
var buffer = Helpers.GetBuffer(length);
stream.Write(buffer, 0, buffer.Length);
stream.Position = 0;
Assert.AreEqual(length, cfStream.Size);

using MemoryStream memoryStream = new();
stream.CopyTo(memoryStream);
CollectionAssert.AreEqual(buffer, memoryStream.ToArray());
}
}
}
110 changes: 69 additions & 41 deletions sources/Test/OpenMcdf.Test/CFStreamTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -448,51 +448,79 @@ public void Test_DELETE_STREAM_2()
}

[TestMethod]
public void Test_WRITE_AND_READ_CFS()
[DataRow(CFSVersion.Ver_3, 0)]
[DataRow(CFSVersion.Ver_3, 63)]
[DataRow(CFSVersion.Ver_3, 64)]
[DataRow(CFSVersion.Ver_3, 65)]
[DataRow(CFSVersion.Ver_3, 511)]
[DataRow(CFSVersion.Ver_3, 512)]
[DataRow(CFSVersion.Ver_3, 513)]
[DataRow(CFSVersion.Ver_3, 4095)]
[DataRow(CFSVersion.Ver_3, 4096)]
[DataRow(CFSVersion.Ver_3, 409)]
[DataRow(CFSVersion.Ver_4, 0)]
[DataRow(CFSVersion.Ver_4, 63)]
[DataRow(CFSVersion.Ver_4, 64)]
[DataRow(CFSVersion.Ver_4, 65)]
[DataRow(CFSVersion.Ver_4, 511)]
[DataRow(CFSVersion.Ver_4, 512)]
[DataRow(CFSVersion.Ver_4, 513)]
[DataRow(CFSVersion.Ver_4, 4095)]
[DataRow(CFSVersion.Ver_4, 4096)]
[DataRow(CFSVersion.Ver_4, 4097)]
public void Test_INCREMENTAL_SIZE_MULTIPLE_WRITE_AND_READ_CFS(CFSVersion version, int bufferSize)
{
string filename = "WRITE_AND_READ_CFS.cfs";

using CompoundFile cf = new();

CFStorage st = cf.RootStorage.AddStorage("MyStorage");
CFStream sm = st.AddStream("MyStream");
byte[] b = Helpers.GetBuffer(220, 0x0A);
sm.SetData(b);

cf.SaveAs(filename);
cf.Close();

using CompoundFile cf2 = new(filename);
CFStorage st2 = cf2.RootStorage.GetStorage("MyStorage");
CFStream sm2 = st2.GetStream("MyStream");
cf2.Close();

Assert.IsNotNull(sm2);
Assert.AreEqual(220, sm2.Size);

File.Delete(filename);
SingleWriteReadMatching(version, bufferSize);
}

[TestMethod]
public void Test_INCREMENTAL_SIZE_MULTIPLE_WRITE_AND_READ_CFS()
[DataRow(CFSVersion.Ver_3, 0)]
[DataRow(CFSVersion.Ver_3, 63)]
[DataRow(CFSVersion.Ver_3, 64)]
[DataRow(CFSVersion.Ver_3, 65)]
[DataRow(CFSVersion.Ver_3, 511)]
[DataRow(CFSVersion.Ver_3, 512)]
[DataRow(CFSVersion.Ver_3, 513)]
[DataRow(CFSVersion.Ver_3, 4095)]
[DataRow(CFSVersion.Ver_3, 4096)]
[DataRow(CFSVersion.Ver_3, 409)]
[DataRow(CFSVersion.Ver_4, 0)]
[DataRow(CFSVersion.Ver_4, 63)]
[DataRow(CFSVersion.Ver_4, 64)]
[DataRow(CFSVersion.Ver_4, 65)]
[DataRow(CFSVersion.Ver_4, 511)]
[DataRow(CFSVersion.Ver_4, 512)]
[DataRow(CFSVersion.Ver_4, 513)]
[DataRow(CFSVersion.Ver_4, 4095)]
[DataRow(CFSVersion.Ver_4, 4096)]
[DataRow(CFSVersion.Ver_4, 4097)]
public void Test_INCREMENTAL_SIZE_MULTIPLE_WRITE_AND_READ_CFS_STREAM(CFSVersion version, int bufferLength)
{
Random r = new Random();
SingleWriteReadMatchingSTREAMED(version, bufferLength);
}

for (int i = r.Next(1, 100); i < 1024 * 1024 * 70; i = i << 1)
static IEnumerable<object[]> FuzzyBufferLengths
{
get
{
SingleWriteReadMatching(i + r.Next(0, 3));
Random r = new Random();

foreach (CFSVersion version in Enum.GetValues(typeof(CFSVersion)))
{
for (int i = r.Next(1, 100); i < 1024 * 1024 * 70; i = i << 1)
{
yield return new object[] { version, i + r.Next(0, 3) };
}
}
}
}

[TestMethod]
public void Test_INCREMENTAL_SIZE_MULTIPLE_WRITE_AND_READ_CFS_STREAM()
[Ignore("Run fuzzing tests manually")]
[DynamicData(nameof(FuzzyBufferLengths), DynamicDataSourceType.Property)]
public void Test_INCREMENTAL_SIZE_MULTIPLE_WRITE_AND_READ_CFS_STREAM_FUZZING(CFSVersion version, int bufferLength)
{
Random r = new Random();

for (int i = r.Next(1, 100); i < 1024 * 1024 * 70; i = i << 1)
{
SingleWriteReadMatchingSTREAMED(i + r.Next(0, 3));
}
SingleWriteReadMatchingSTREAMED(version, bufferLength);
}

[TestMethod]
Expand Down Expand Up @@ -554,13 +582,13 @@ public static void SingleTransactedChange(int size)
CollectionAssert.AreEqual(b, sm2.GetData());
}

private static void SingleWriteReadMatching(int size)
private static void SingleWriteReadMatching(CFSVersion version, int bufferLength)
{
string filename = "INCREMENTAL_SIZE_MULTIPLE_WRITE_AND_READ_CFS.cfs";
string filename = $"{nameof(SingleWriteReadMatching)}_{version}_{bufferLength}.cfs";

File.Delete(filename);

byte[] b = Helpers.GetBuffer(size);
byte[] b = Helpers.GetBuffer(bufferLength);

using (CompoundFile cf = new())
{
Expand All @@ -576,17 +604,17 @@ private static void SingleWriteReadMatching(int size)
CFStream sm2 = st2.GetStream("MyStream");

Assert.IsNotNull(sm2);
Assert.AreEqual(size, sm2.Size);
Assert.AreEqual(bufferLength, sm2.Size);
CollectionAssert.AreEqual(b, sm2.GetData());
}

private static void SingleWriteReadMatchingSTREAMED(int size)
private static void SingleWriteReadMatchingSTREAMED(CFSVersion version, int bufferLength)
{
byte[] b = Helpers.GetBuffer(size);
byte[] b = Helpers.GetBuffer(bufferLength);

using MemoryStream ms = new(size);
using MemoryStream ms = new(bufferLength);

using (CompoundFile cf = new())
using (CompoundFile cf = new(version, CFSConfiguration.Default))
{
CFStorage st = cf.RootStorage.AddStorage("MyStorage");
CFStream sm = st.AddStream("MyStream");
Expand Down

0 comments on commit 829cb82

Please sign in to comment.