diff --git a/MatFileHandler.Tests/AbstractTestDataFactory.cs b/MatFileHandler.Tests/AbstractTestDataFactory.cs
index 082c81d..a7717d1 100755
--- a/MatFileHandler.Tests/AbstractTestDataFactory.cs
+++ b/MatFileHandler.Tests/AbstractTestDataFactory.cs
@@ -59,7 +59,7 @@ namespace MatFileHandler.Tests
private TTestData ReadTestData(string filename)
{
- using (var stream = new FileStream(filename, FileMode.Open))
+ using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
return ReadDataFromStream(stream);
}
diff --git a/MatFileHandler.Tests/MatFileReaderTests.cs b/MatFileHandler.Tests/MatFileReaderTests.cs
index 44e1e21..30ba7c2 100755
--- a/MatFileHandler.Tests/MatFileReaderTests.cs
+++ b/MatFileHandler.Tests/MatFileReaderTests.cs
@@ -18,12 +18,10 @@ namespace MatFileHandler.Tests
///
/// Test reading all files in a given test set.
///
- /// Name of the set.
- [Theory]
- [InlineData("good")]
- public void TestReader(string testSet)
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestReader(AbstractTestDataFactory testFactory)
{
- foreach (var matFile in GetTests(testSet).GetAllTestData())
+ foreach (var matFile in testFactory.GetAllTestData())
{
Assert.NotEmpty(matFile.Variables);
}
@@ -32,10 +30,10 @@ namespace MatFileHandler.Tests
///
/// Test reading lower and upper limits of integer data types.
///
- [Fact]
- public void TestLimits()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestLimits(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["limits"];
+ var matFile = testFactory["limits"];
IArray array;
array = matFile["int8_"].Value;
CheckLimits(array as IArrayOf, CommonData.Int8Limits);
@@ -66,10 +64,10 @@ namespace MatFileHandler.Tests
///
/// Test writing lower and upper limits of integer-based complex data types.
///
- [Fact]
- public void TestComplexLimits()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestComplexLimits(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["limits_complex"];
+ var matFile = testFactory["limits_complex"];
IArray array;
array = matFile["int8_complex"].Value;
CheckComplexLimits(array as IArrayOf>, CommonData.Int8Limits);
@@ -102,10 +100,10 @@ namespace MatFileHandler.Tests
///
/// Test reading an ASCII-encoded string.
///
- [Fact]
- public void TestAscii()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestAscii(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["ascii"];
+ var matFile = testFactory["ascii"];
var arrayAscii = matFile["s"].Value as ICharArray;
Assert.NotNull(arrayAscii);
Assert.Equal(new[] { 1, 3 }, arrayAscii.Dimensions);
@@ -116,10 +114,10 @@ namespace MatFileHandler.Tests
///
/// Test reading a Unicode string.
///
- [Fact]
- public void TestUnicode()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestUnicode(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["unicode"];
+ var matFile = testFactory["unicode"];
var arrayUnicode = matFile["s"].Value as ICharArray;
Assert.NotNull(arrayUnicode);
Assert.Equal(new[] { 1, 2 }, arrayUnicode.Dimensions);
@@ -131,10 +129,10 @@ namespace MatFileHandler.Tests
///
/// Test reading a wide Unicode string.
///
- [Fact]
- public void TestUnicodeWide()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestUnicodeWide(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["unicode-wide"];
+ var matFile = testFactory["unicode-wide"];
var arrayUnicodeWide = matFile["s"].Value as ICharArray;
Assert.NotNull(arrayUnicodeWide);
Assert.Equal(new[] { 1, 2 }, arrayUnicodeWide.Dimensions);
@@ -144,10 +142,10 @@ namespace MatFileHandler.Tests
///
/// Test converting a structure array to a Double array.
///
- [Fact]
- public void TestConvertToDoubleArray()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestConvertToDoubleArray(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["struct"];
+ var matFile = testFactory["struct"];
var array = matFile.Variables[0].Value;
Assert.Null(array.ConvertToDoubleArray());
}
@@ -156,10 +154,10 @@ namespace MatFileHandler.Tests
/// Test converting a structure array to a Complex array.
///
/// Should return null.
- [Fact]
- public void TestConvertToComplexArray()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestConvertToComplexArray(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["struct"];
+ var matFile = testFactory["struct"];
var array = matFile.Variables[0].Value;
Assert.Null(array.ConvertToComplexArray());
}
@@ -167,10 +165,10 @@ namespace MatFileHandler.Tests
///
/// Test reading an enumeration.
///
- [Fact]
- public void TestEnum()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestEnum(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["enum"];
+ var matFile = testFactory["enum"];
var days = matFile["days"].Value;
var enumeration = new EnumAdapter(days);
Assert.Equal(5, enumeration.Values.Count);
@@ -184,10 +182,10 @@ namespace MatFileHandler.Tests
///
/// Test reading a structure array.
///
- [Fact]
- public void TestStruct()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestStruct(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["struct"];
+ var matFile = testFactory["struct"];
var structure = matFile["struct_"].Value as IStructureArray;
Assert.NotNull(structure);
Assert.Equal(new[] { "x", "y" }, structure.FieldNames);
@@ -238,10 +236,10 @@ namespace MatFileHandler.Tests
///
/// Test reading a sparse array.
///
- [Fact]
- public void TestSparse()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestSparse(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["sparse"];
+ var matFile = testFactory["sparse"];
var sparseArray = matFile["sparse_"].Value as ISparseArrayOf;
Assert.NotNull(sparseArray);
Assert.Equal(new[] { 4, 5 }, sparseArray.Dimensions);
@@ -268,10 +266,10 @@ namespace MatFileHandler.Tests
///
/// Test reading a logical array.
///
- [Fact]
- public void TestLogical()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestLogical(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["logical"];
+ var matFile = testFactory["logical"];
var array = matFile["logical_"].Value;
var logicalArray = array as IArrayOf;
Assert.NotNull(logicalArray);
@@ -286,10 +284,10 @@ namespace MatFileHandler.Tests
///
/// Test reading a sparse logical array.
///
- [Fact]
- public void TestSparseLogical()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestSparseLogical(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["sparse_logical"];
+ var matFile = testFactory["sparse_logical"];
var array = matFile["sparse_logical"].Value;
var sparseArray = array as ISparseArrayOf;
Assert.NotNull (sparseArray);
@@ -305,10 +303,10 @@ namespace MatFileHandler.Tests
///
/// Test reading a global variable.
///
- [Fact]
- public void TestGlobal()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestGlobal(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["global"];
+ var matFile = testFactory["global"];
var variable = matFile.Variables.First();
Assert.True(variable.IsGlobal);
}
@@ -316,10 +314,10 @@ namespace MatFileHandler.Tests
///
/// Test reading a sparse complex array.
///
- [Fact]
- public void TextSparseComplex()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TextSparseComplex(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["sparse_complex"];
+ var matFile = testFactory["sparse_complex"];
var array = matFile["sparse_complex"].Value;
var sparseArray = array as ISparseArrayOf;
Assert.NotNull(sparseArray);
@@ -332,10 +330,10 @@ namespace MatFileHandler.Tests
///
/// Test reading an object.
///
- [Fact]
- public void TestObject()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestObject(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["object"];
+ var matFile = testFactory["object"];
var obj = matFile["object_"].Value as IMatObject;
Assert.NotNull(obj);
Assert.Equal("Point", obj.ClassName);
@@ -349,10 +347,10 @@ namespace MatFileHandler.Tests
///
/// Test reading another object.
///
- [Fact]
- public void TestObject2()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestObject2(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["object2"];
+ var matFile = testFactory["object2"];
var obj = matFile["object2"].Value as IMatObject;
Assert.NotNull(obj);
Assert.Equal("Point", obj.ClassName);
@@ -372,10 +370,10 @@ namespace MatFileHandler.Tests
///
/// Test reading a table.
///
- [Fact]
- public void TestTable()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestTable(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["table"];
+ var matFile = testFactory["table"];
var obj = matFile["table_"].Value as IMatObject;
var table = new TableAdapter(obj);
Assert.Equal(3, table.NumberOfRows);
@@ -393,10 +391,10 @@ namespace MatFileHandler.Tests
///
/// Test reading a table with strings
///
- [Fact]
- public void TestTableWithStrings()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestTableWithStrings(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["table-with-strings"];
+ var matFile = testFactory["table-with-strings"];
var obj = matFile["t"].Value as IMatObject;
var table = new TableAdapter(obj);
Assert.Equal(5, table.NumberOfRows);
@@ -418,10 +416,10 @@ namespace MatFileHandler.Tests
///
/// Test subobjects within objects.
///
- [Fact]
- public void TestSubobjects()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestSubobjects(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["pointWithSubpoints"];
+ var matFile = testFactory["pointWithSubpoints"];
var p = matFile["p"].Value as IMatObject;
Assert.Equal("Point", p.ClassName);
var x = p["x"] as IMatObject;
@@ -441,10 +439,10 @@ namespace MatFileHandler.Tests
///
/// Test nested objects.
///
- [Fact]
- public void TestNestedObjects()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestNestedObjects(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["subsubPoint"];
+ var matFile = testFactory["subsubPoint"];
var p = matFile["p"].Value as IMatObject;
Assert.Equal("Point", p.ClassName);
Assert.Equal(new[] { 1.0 }, p["x"].ConvertToDoubleArray());
@@ -459,10 +457,10 @@ namespace MatFileHandler.Tests
///
/// Test datetime objects.
///
- [Fact]
- public void TestDatetime()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestDatetime(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["datetime"];
+ var matFile = testFactory["datetime"];
var d = matFile["d"].Value as IMatObject;
var datetime = new DatetimeAdapter(d);
Assert.Equal(new[] { 1, 2 }, datetime.Dimensions);
@@ -473,10 +471,10 @@ namespace MatFileHandler.Tests
///
/// Another test for datetime objects.
///
- [Fact]
- public void TestDatetime2()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestDatetime2(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["datetime2"];
+ var matFile = testFactory["datetime2"];
var d = matFile["d"].Value as IMatObject;
var datetime = new DatetimeAdapter(d);
Assert.Equal(new[] { 1, 1 }, datetime.Dimensions);
@@ -488,10 +486,10 @@ namespace MatFileHandler.Tests
///
/// Test string objects.
///
- [Fact]
- public void TestString()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestString(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["string"];
+ var matFile = testFactory["string"];
var s = matFile["s"].Value as IMatObject;
var str = new StringAdapter(s);
Assert.Equal(new[] { 4, 1 }, str.Dimensions);
@@ -504,10 +502,10 @@ namespace MatFileHandler.Tests
///
/// Test duration objects.
///
- [Fact]
- public void TestDuration()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestDuration(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["duration"];
+ var matFile = testFactory["duration"];
var d = matFile["d"].Value as IMatObject;
var duration = new DurationAdapter(d);
Assert.Equal(new[] { 1, 3 }, duration.Dimensions);
@@ -519,10 +517,10 @@ namespace MatFileHandler.Tests
///
/// Test unrepresentable datetime.
///
- [Fact]
- public void TestDatetime_Unrepresentable()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void TestDatetime_Unrepresentable(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["datetime-unrepresentable"];
+ var matFile = testFactory["datetime-unrepresentable"];
var obj = matFile["d"].Value as IMatObject;
var datetime = new DatetimeAdapter(obj);
var d0 = datetime[0];
@@ -532,10 +530,10 @@ namespace MatFileHandler.Tests
///
/// Test 3-dimensional arrays.
///
- [Fact]
- public void Test_3DArrays()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void Test_3DArrays(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["issue20.mat"];
+ var matFile = testFactory["issue20.mat"];
var obj = matFile["a3d"].Value;
var values = obj.ConvertToDoubleArray();
Assert.Equal(Enumerable.Range(1, 24).Select(x => (double)x).ToArray(), values);
@@ -563,21 +561,34 @@ namespace MatFileHandler.Tests
Assert.Equal(expected, obj.ConvertToMultidimensionalDoubleArray());
Assert.Null(obj.ConvertTo2dDoubleArray());
}
-
+
///
/// Test four-dimensional arrays.
///
- [Fact]
- public void Test_4DArrays()
+ [Theory, MemberData(nameof(TestDataFactories))]
+ public void Test_4DArrays(AbstractTestDataFactory testFactory)
{
- var matFile = GetTests("good")["issue20.mat"];
+ var matFile = testFactory["issue20.mat"];
var obj = matFile["a4d"].Value;
Assert.Equal(Enumerable.Range(1, 120).Select(x => (double)x).ToArray(), obj.ConvertToDoubleArray());
Assert.Null(obj.ConvertTo2dDoubleArray());
}
- private static AbstractTestDataFactory GetTests(string factoryName) =>
- new PartialReadMatTestDataFactory(Path.Combine(TestDirectory, factoryName));
+ ///
+ /// Returns the factories that provide test data in various configurations.
+ ///
+ public static TheoryData> TestDataFactories
+ {
+ get
+ {
+ return new TheoryData>
+ {
+ new MatTestDataFactory(Path.Combine(TestDirectory, "good")),
+ new PartialReadMatTestDataFactory(Path.Combine(TestDirectory, "good")),
+ new UnalignedMatTestDataFactory(Path.Combine(TestDirectory, "good")),
+ };
+ }
+ }
private static void CheckLimits(IArrayOf array, T[] limits)
where T : struct
diff --git a/MatFileHandler.Tests/PartialReadMatTestDataFactory.cs b/MatFileHandler.Tests/PartialReadMatTestDataFactory.cs
index f77f7f1..1c277b6 100644
--- a/MatFileHandler.Tests/PartialReadMatTestDataFactory.cs
+++ b/MatFileHandler.Tests/PartialReadMatTestDataFactory.cs
@@ -6,7 +6,7 @@ namespace MatFileHandler.Tests
{
///
/// Factory providing the parsed contents of .mat files,
- /// wrapped in a .
+ /// wrapped in a .
///
public class PartialReadMatTestDataFactory : MatTestDataFactory
{
@@ -26,7 +26,7 @@ namespace MatFileHandler.Tests
/// Parsed contents of the file.
protected override IMatFile ReadDataFromStream(Stream stream)
{
- using (var wrapper = new PartialReadStream(stream))
+ using (var wrapper = new PartialUnseekableReadStream(stream))
{
return base.ReadDataFromStream(wrapper);
}
diff --git a/MatFileHandler.Tests/PartialReadStream.cs b/MatFileHandler.Tests/PartialUnseekableReadStream.cs
similarity index 81%
rename from MatFileHandler.Tests/PartialReadStream.cs
rename to MatFileHandler.Tests/PartialUnseekableReadStream.cs
index b056457..ce828a0 100644
--- a/MatFileHandler.Tests/PartialReadStream.cs
+++ b/MatFileHandler.Tests/PartialUnseekableReadStream.cs
@@ -8,15 +8,15 @@ namespace MatFileHandler.Tests
///
/// A stream which wraps another stream and only reads one byte at a time.
///
- internal class PartialReadStream : Stream
+ internal class PartialUnseekableReadStream : Stream
{
private readonly Stream _baseStream;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The stream to wrap.
- public PartialReadStream(Stream baseStream)
+ public PartialUnseekableReadStream(Stream baseStream)
{
_baseStream = baseStream;
}
@@ -25,7 +25,7 @@ namespace MatFileHandler.Tests
public override bool CanRead => _baseStream.CanRead;
///
- public override bool CanSeek => _baseStream.CanSeek;
+ public override bool CanSeek => false;
///
public override bool CanWrite => false;
@@ -36,8 +36,8 @@ namespace MatFileHandler.Tests
///
public override long Position
{
- get => _baseStream.Position;
- set => _baseStream.Position = value;
+ get => throw new NotSupportedException();
+ set => throw new NotSupportedException();
}
///
@@ -55,13 +55,13 @@ namespace MatFileHandler.Tests
///
public override long Seek(long offset, SeekOrigin origin)
{
- return _baseStream.Seek(offset, origin);
+ throw new NotSupportedException();
}
///
public override void SetLength(long value)
{
- _baseStream.SetLength(value);
+ throw new NotSupportedException();
}
///
diff --git a/MatFileHandler.Tests/UnalignedMatTestDataFactory.cs b/MatFileHandler.Tests/UnalignedMatTestDataFactory.cs
new file mode 100644
index 0000000..8cf2f48
--- /dev/null
+++ b/MatFileHandler.Tests/UnalignedMatTestDataFactory.cs
@@ -0,0 +1,37 @@
+// Copyright 2017-2018 Alexander Luzgarev
+
+using System.IO;
+
+namespace MatFileHandler.Tests
+{
+ ///
+ /// Factory providing the parsed contents of .mat files,
+ /// which start at a non-8 byte-aligned offset in the stream.
+ ///
+ public class UnalignedMatTestDataFactory : MatTestDataFactory
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Directory containing test files.
+ public UnalignedMatTestDataFactory(string testDirectory)
+ : base(testDirectory)
+ {
+ }
+
+ ///
+ protected override IMatFile ReadDataFromStream(Stream stream)
+ {
+ using (var ms = new MemoryStream())
+ {
+ ms.Seek(3, SeekOrigin.Begin);
+
+ stream.CopyTo(ms);
+
+ ms.Seek(3, SeekOrigin.Begin);
+
+ return base.ReadDataFromStream(ms);
+ }
+ }
+ }
+}
diff --git a/MatFileHandler/MatFileReader.cs b/MatFileHandler/MatFileReader.cs
index a4e3ae6..adc29ac 100755
--- a/MatFileHandler/MatFileReader.cs
+++ b/MatFileHandler/MatFileReader.cs
@@ -28,7 +28,7 @@ namespace MatFileHandler
/// Contents of the file.
public IMatFile Read()
{
- using (var reader = new BinaryReader(Stream))
+ using (var reader = new BinaryReader(new PositionTrackingStream(Stream)))
{
return Read(reader);
}
diff --git a/MatFileHandler/PositionTrackingStream.cs b/MatFileHandler/PositionTrackingStream.cs
new file mode 100644
index 0000000..f62b931
--- /dev/null
+++ b/MatFileHandler/PositionTrackingStream.cs
@@ -0,0 +1,77 @@
+// Copyright 2017-2018 Alexander Luzgarev
+
+using System;
+using System.IO;
+
+namespace MatFileHandler;
+
+///
+/// A stream which wraps another stream and tracks the number of bytes read
+/// for the purpose of adjusting for padding.
+///
+internal sealed class PositionTrackingStream : Stream
+{
+ private readonly Stream _baseStream;
+ private long _position;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The stream to wrap.
+ public PositionTrackingStream(Stream baseStream)
+ {
+ _baseStream = baseStream;
+ }
+
+ ///
+ public override bool CanRead => _baseStream.CanRead;
+
+ ///
+ public override bool CanSeek => false;
+
+ ///
+ public override bool CanWrite => false;
+
+ ///
+ public override long Length => _baseStream.Length;
+
+ ///
+ public override long Position
+ {
+ get => _position;
+ set => throw new NotSupportedException();
+ }
+
+ ///
+ public override void Flush() => _baseStream.Flush();
+
+ ///
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ int bytesRead = _baseStream.Read(buffer, offset, count);
+
+ _position += bytesRead;
+
+ return bytesRead;
+ }
+
+ ///
+ public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
+
+ ///
+ public override void SetLength(long value) => throw new NotSupportedException();
+
+ ///
+ public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
+
+ ///
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ _baseStream.Dispose();
+ }
+
+ base.Dispose(disposing);
+ }
+}