diff options
-rw-r--r-- | lib/Utils/src/Memory/VnTable.cs | 42 | ||||
-rw-r--r-- | lib/Utils/tests/Memory/VnTableTests.cs | 71 |
2 files changed, 53 insertions, 60 deletions
diff --git a/lib/Utils/src/Memory/VnTable.cs b/lib/Utils/src/Memory/VnTable.cs index ce105f9..43e2c02 100644 --- a/lib/Utils/src/Memory/VnTable.cs +++ b/lib/Utils/src/Memory/VnTable.cs @@ -40,7 +40,7 @@ namespace VNLib.Utils.Memory /// <summary> /// A value that indicates if the table does not contain any values /// </summary> - public bool Empty { get; } + public bool Empty => Rows == 0 && Cols == 0; /// <summary> /// The number of rows in the table @@ -74,16 +74,12 @@ namespace VNLib.Utils.Memory public VnTable(IUnmangedHeap heap, uint rows, uint cols) { //empty table - if (rows == 0 && cols == 0) - { - Empty = true; - } - else + if (rows != 0 || cols != 0) { ulong tableSize = checked((ulong)rows * (ulong)cols); ArgumentNullException.ThrowIfNull(heap); - ArgumentOutOfRangeException.ThrowIfGreaterThan(tableSize, nuint.MinValue); + ArgumentOutOfRangeException.ThrowIfGreaterThan(tableSize, nuint.MaxValue); ArgumentOutOfRangeException.ThrowIfGreaterThan(MemoryUtil.ByteCount<T>((nuint)tableSize), nuint.MaxValue, nameof(rows)); Rows = rows; @@ -107,6 +103,8 @@ namespace VNLib.Utils.Memory { ValidateArgs(row, col); + Debug.Assert(BufferHandle != null, nameof(BufferHandle) + " != null"); + //Calculate the address in memory for the item //Calc row offset ulong address = checked(row * Cols); @@ -135,6 +133,8 @@ namespace VNLib.Utils.Memory { ValidateArgs(row, col); + Debug.Assert(BufferHandle != null, nameof(BufferHandle) + " != null"); + //Calculate the address in memory for the item //Calc row offset @@ -153,17 +153,8 @@ namespace VNLib.Utils.Memory private void ValidateArgs(uint row, uint col) { Check(); - - if (Empty) - { - throw new InvalidOperationException("Table is empty"); - } - - //If not empty expect a non-null handle - Debug.Assert(BufferHandle != null, nameof(BufferHandle) + " != null"); - - ArgumentOutOfRangeException.ThrowIfGreaterThan(row, Rows); - ArgumentOutOfRangeException.ThrowIfGreaterThan(col, Cols); + ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(row, Rows); + ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(col, Cols); } /// <summary> @@ -191,16 +182,14 @@ namespace VNLib.Utils.Memory get { Check(); - return !Empty ? *(BufferHandle!.GetOffset(index)) : throw new InvalidOperationException("Cannot index an empty table"); + ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(index, (ulong)Rows * (ulong)Cols); + return *(BufferHandle!.GetOffset(index)); } set { Check(); - if (Empty) - { - throw new InvalidOperationException("Cannot index an empty table"); - } + ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(index, (ulong)Rows * (ulong)Cols); *(BufferHandle!.GetOffset(index)) = value; } } @@ -208,11 +197,8 @@ namespace VNLib.Utils.Memory ///<inheritdoc/> protected override void Free() { - if (!Empty) - { - //Dispose the buffer - BufferHandle!.Dispose(); - } + //Dispose the buffer + BufferHandle?.Dispose(); } } }
\ No newline at end of file diff --git a/lib/Utils/tests/Memory/VnTableTests.cs b/lib/Utils/tests/Memory/VnTableTests.cs index cb8ea91..832ef26 100644 --- a/lib/Utils/tests/Memory/VnTableTests.cs +++ b/lib/Utils/tests/Memory/VnTableTests.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023 Vaughn Nugent +* Copyright (c) 2024 Vaughn Nugent * * Library: VNLib * Package: VNLib.UtilsTests @@ -41,6 +41,12 @@ namespace VNLib.Utils.Memory.Tests //Test 0 rows/cols Assert.IsTrue(0 == empty.Rows); Assert.IsTrue(0 == empty.Cols); + + //Test that empty table throws on access + Assert.ThrowsException<ArgumentOutOfRangeException>(() => _ = empty[0, 0]); + Assert.ThrowsException<ArgumentOutOfRangeException>(() => _ = empty.Get(0, 0)); + Assert.ThrowsException<ArgumentOutOfRangeException>(() => empty.Set(0, 0, 10)); + Assert.ThrowsException<ArgumentOutOfRangeException>(() => empty[0, 0] = 10); } using (VnTable<int> table = new(40000, 10000)) @@ -52,6 +58,16 @@ namespace VNLib.Utils.Memory.Tests Assert.IsTrue(10000 == table.Cols); } + //Test params + Assert.ThrowsException<ArgumentNullException>(() => _ = new VnTable<int>(null!, 1, 1)); + + /* + * Try-catch is used because underlying heaps + * may cause different OOM exceptions to be raised + * but still have a base class of OutOfMemoryException. + * So catch covers all OOM exceptions. + */ + try { using VnTable<int> table = new(uint.MaxValue, 20); @@ -67,20 +83,6 @@ namespace VNLib.Utils.Memory.Tests } [TestMethod()] - public void VnTableTest1() - { - //No throw if empty - using VnTable<int> table = new(null!,0, 0); - - //Throw if table is not empty - Assert.ThrowsException<ArgumentNullException>(() => - { - using VnTable<int> table = new(null!,1, 1); - }); - - } - - [TestMethod()] public void GetSetTest() { static void TestIndexAt(VnTable<int> table, uint row, uint col, int value) @@ -119,28 +121,33 @@ namespace VNLib.Utils.Memory.Tests Assert.IsTrue(value == table[row, col]); Assert.IsTrue(value == table.Get(row, col)); } - - using (VnTable<int> table = new(11, 11)) - { - //Test index at 10,10 - TestIndexAt(table, 10, 10, 11); - //Test same index with different value using the .set() method - TestSetAt(table, 10, 10, 25); - //Test direct access - TestSetDirectAccess(table, 10, 10, 50); + using VnTable<int> table = new(11, 11); + + //Test index at 10,10 + TestIndexAt(table, 10, 10, 11); + //Test same index with different value using the .set() method + TestSetAt(table, 10, 10, 25); + + //Test direct access + TestSetDirectAccess(table, 10, 10, 50); - TestGetDirectAccess(table, 10, 10, 37); + TestGetDirectAccess(table, 10, 10, 37); - //Test index at 0,0 - TestIndexAt(table, 0, 0, 13); - TestSetAt(table, 0, 0, 85); + //Test index at 0,0 + TestIndexAt(table, 0, 0, 13); + TestSetAt(table, 0, 0, 85); - //Test at 0,0 - TestSetDirectAccess(table, 0, 0, 100); - TestGetDirectAccess(table, 0, 0, 86); - } + //Test at 0,0 + TestSetDirectAccess(table, 0, 0, 100); + TestGetDirectAccess(table, 0, 0, 86); + + Assert.ThrowsException<ArgumentOutOfRangeException>(() => _ = table[11, 11]); + Assert.ThrowsException<ArgumentOutOfRangeException>(() => _ = table.Get(11, 11)); + + Assert.ThrowsException<ArgumentOutOfRangeException>(() => table.Set(11, 11, 10)); + Assert.ThrowsException<ArgumentOutOfRangeException>(() => table[11, 11] = 10); } [TestMethod()] |