Skip to content

Commit b588764

Browse files
author
LoneWandererProductions
committed
add some final tests
1 parent cc698a4 commit b588764

4 files changed

Lines changed: 243 additions & 27 deletions

File tree

CommonExtendedObjectsTests/CommonExtendedObjectsTests.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
<TargetFramework>net5.0-windows</TargetFramework>
55

66
<IsPackable>false</IsPackable>
7+
8+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
79
</PropertyGroup>
810

911
<ItemGroup>
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
using ExtendedSystemObjects.Helper;
2+
using Microsoft.VisualStudio.TestTools.UnitTesting;
3+
using System;
4+
using System.Runtime.InteropServices;
5+
6+
namespace CommonExtendedObjectsTests
7+
{
8+
[TestClass]
9+
public unsafe class UnmanagedMemoryHelperTests
10+
{
11+
[TestMethod]
12+
public void Allocate_Reallocate_Free_Memory()
13+
{
14+
var count = 10;
15+
16+
var ptr = UnmanagedMemoryHelper.Allocate<int>(count);
17+
Assert.AreNotEqual(IntPtr.Zero, ptr);
18+
19+
try
20+
{
21+
// Write values to allocated memory
22+
var intPtr = (int*)ptr.ToPointer();
23+
for (var i = 0; i < count; i++)
24+
intPtr[i] = i;
25+
26+
// Reallocate to bigger size
27+
var newCount = 20;
28+
var newPtr = UnmanagedMemoryHelper.Reallocate<int>(ptr, newCount);
29+
Assert.AreNotEqual(IntPtr.Zero, newPtr);
30+
ptr = newPtr;
31+
32+
intPtr = (int*)ptr.ToPointer();
33+
34+
// Check old values still there
35+
for (var i = 0; i < count; i++)
36+
Assert.AreEqual(i, intPtr[i]);
37+
38+
// Write new values
39+
for (var i = count; i < newCount; i++)
40+
intPtr[i] = i * 2;
41+
42+
// Check new values
43+
for (var i = count; i < newCount; i++)
44+
Assert.AreEqual(i * 2, intPtr[i]);
45+
}
46+
finally
47+
{
48+
Marshal.FreeHGlobal(ptr);
49+
}
50+
}
51+
52+
[TestMethod]
53+
public void Clear_SetsMemoryToZero()
54+
{
55+
var count = 5;
56+
var ptr = UnmanagedMemoryHelper.Allocate<int>(count);
57+
try
58+
{
59+
var intPtr = (int*)ptr.ToPointer();
60+
for (var i = 0; i < count; i++)
61+
intPtr[i] = 123;
62+
63+
UnmanagedMemoryHelper.Clear<int>(ptr, count);
64+
65+
for (var i = 0; i < count; i++)
66+
Assert.AreEqual(0, intPtr[i]);
67+
}
68+
finally
69+
{
70+
Marshal.FreeHGlobal(ptr);
71+
}
72+
}
73+
74+
[TestMethod]
75+
public void ShiftRight_MovesElementsCorrectly()
76+
{
77+
var count = 5;
78+
var capacity = 10;
79+
var ptr = UnmanagedMemoryHelper.Allocate<int>(capacity);
80+
try
81+
{
82+
var intPtr = (int*)ptr.ToPointer();
83+
for (var i = 0; i < count; i++)
84+
intPtr[i] = i + 1; // 1,2,3,4,5
85+
86+
// Shift right at index 2 by 2 positions
87+
UnmanagedMemoryHelper.ShiftRight(intPtr, 2, 2, count, capacity);
88+
89+
// Now elements 3,4,5 moved right by 2: positions 4,5,6
90+
// Index 2 and 3 now free (undefined content)
91+
Assert.AreEqual(1, intPtr[0]);
92+
Assert.AreEqual(2, intPtr[1]);
93+
// We don't expect meaningful values at 2 and 3 since shifted right
94+
Assert.AreEqual(3, intPtr[4]);
95+
Assert.AreEqual(4, intPtr[5]);
96+
Assert.AreEqual(5, intPtr[6]);
97+
}
98+
finally
99+
{
100+
Marshal.FreeHGlobal(ptr);
101+
}
102+
}
103+
104+
[TestMethod]
105+
public void ShiftLeft_MovesElementsCorrectly()
106+
{
107+
var count = 5;
108+
var ptr = UnmanagedMemoryHelper.Allocate<int>(count);
109+
try
110+
{
111+
var intPtr = (int*)ptr.ToPointer();
112+
for (var i = 0; i < count; i++)
113+
intPtr[i] = i + 1; // 1,2,3,4,5
114+
115+
// Shift left at index 1 by 2 positions (delete 2 elements at index 1 and 2)
116+
UnmanagedMemoryHelper.ShiftLeft(intPtr, 1, 2, count);
117+
118+
// After shift left, elements at index 3,4 move to index 1,2
119+
Assert.AreEqual(1, intPtr[0]);
120+
Assert.AreEqual(4, intPtr[1]);
121+
Assert.AreEqual(5, intPtr[2]);
122+
// Index 3,4 undefined now, not tested
123+
}
124+
finally
125+
{
126+
Marshal.FreeHGlobal(ptr);
127+
}
128+
}
129+
130+
[TestMethod]
131+
public void Fill_FillsMemoryWithValue()
132+
{
133+
var count = 4;
134+
var ptr = UnmanagedMemoryHelper.Allocate<int>(count);
135+
try
136+
{
137+
var intPtr = (int*)ptr.ToPointer();
138+
UnmanagedMemoryHelper.Fill(intPtr, 42, count);
139+
140+
for (var i = 0; i < count; i++)
141+
Assert.AreEqual(42, intPtr[i]);
142+
}
143+
finally
144+
{
145+
Marshal.FreeHGlobal(ptr);
146+
}
147+
}
148+
149+
[TestMethod]
150+
public void IndexOf_FindsValueCorrectly()
151+
{
152+
var count = 5;
153+
var ptr = UnmanagedMemoryHelper.Allocate<int>(count);
154+
try
155+
{
156+
var intPtr = (int*)ptr.ToPointer();
157+
intPtr[0] = 10;
158+
intPtr[1] = 20;
159+
intPtr[2] = 30;
160+
intPtr[3] = 40;
161+
intPtr[4] = 50;
162+
163+
var idx = UnmanagedMemoryHelper.IndexOf(intPtr, 30, count);
164+
Assert.AreEqual(2, idx);
165+
166+
var notFound = UnmanagedMemoryHelper.IndexOf(intPtr, 99, count);
167+
Assert.AreEqual(-1, notFound);
168+
}
169+
finally
170+
{
171+
Marshal.FreeHGlobal(ptr);
172+
}
173+
}
174+
175+
[TestMethod]
176+
public void Swap_SwapsElementsCorrectly()
177+
{
178+
var count = 3;
179+
var ptr = UnmanagedMemoryHelper.Allocate<int>(count);
180+
try
181+
{
182+
var intPtr = (int*)ptr.ToPointer();
183+
intPtr[0] = 1;
184+
intPtr[1] = 2;
185+
intPtr[2] = 3;
186+
187+
UnmanagedMemoryHelper.Swap(intPtr, 0, 2);
188+
189+
Assert.AreEqual(3, intPtr[0]);
190+
Assert.AreEqual(2, intPtr[1]);
191+
Assert.AreEqual(1, intPtr[2]);
192+
}
193+
finally
194+
{
195+
Marshal.FreeHGlobal(ptr);
196+
}
197+
}
198+
}
199+
}

ExtendedSystemObjects/Helper/UnmanagedMemoryHelper.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,22 +83,21 @@ internal static unsafe void ShiftRight<T>(T* ptr, int index, int count, int leng
8383
where T : unmanaged
8484
{
8585
var elementsToShift = length - index;
86-
if (elementsToShift <= 0)
87-
{
86+
if (elementsToShift <= 0 || count <= 0)
8887
return;
89-
}
9088

89+
// Start copying from the end to avoid overwriting
9190
Buffer.MemoryCopy(
9291
ptr + index,
9392
ptr + index + count,
94-
(capacity - index - count) * sizeof(T),
93+
(capacity - index - count) * sizeof(T), // should be fine if debug check passes
9594
elementsToShift * sizeof(T));
9695
}
9796

9897
/// <summary>
9998
/// Shifts the left. Delete Element at index
10099
/// </summary>
101-
/// <typeparam name="T"></typeparam>
100+
/// <typeparam name="T">Generic Parameter</typeparam>
102101
/// <param name="ptr">The PTR.</param>
103102
/// <param name="index">The index.</param>
104103
/// <param name="count">The count.</param>
@@ -112,10 +111,12 @@ internal static unsafe void ShiftLeft<T>(T* ptr, int index, int count, int lengt
112111
return;
113112
}
114113

114+
var dstSize = (length - index) * sizeof(T); // full space after index
115+
115116
Buffer.MemoryCopy(
116117
ptr + index + count,
117118
ptr + index,
118-
elementsToShift * sizeof(T),
119+
dstSize,
119120
elementsToShift * sizeof(T));
120121
}
121122

ExtendedSystemObjects/UnmanagedIntList.cs

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -177,30 +177,22 @@ public void Resize(int newSize)
177177
Length = newSize;
178178
}
179179

180-
/// <inheritdoc />
181-
/// <summary>
182-
/// Removes all elements from the list. The capacity remains unchanged.
183-
/// </summary>
184-
public void Clear()
185-
{
186-
Length = 0;
187-
188-
// Clear the entire allocated capacity, not just Length items
189-
UnmanagedMemoryHelper.Clear<int>(_buffer, Capacity);
190-
}
191-
192-
/// <inheritdoc />
193180
/// <summary>
194-
/// Frees unmanaged resources used by the <see cref="T:ExtendedSystemObjects.IntList" />.
195-
/// After calling this method, the instance should not be used.
181+
/// Creates a deep copy of the current <see cref="UnmanagedIntList"/> instance,
182+
/// including its unmanaged buffer contents.
196183
/// </summary>
197-
public void Dispose()
184+
/// <returns>A new <see cref="UnmanagedIntList"/> instance with the same values.</returns>
185+
public UnmanagedIntList Clone()
198186
{
199-
Dispose(true);
200-
GC.SuppressFinalize(this);
187+
var clone = new UnmanagedIntList(Length);
188+
for (int i = 0; i < Length; i++)
189+
{
190+
clone._ptr[i] = _ptr[i];
191+
}
192+
clone.Length = Length;
193+
return clone;
201194
}
202195

203-
204196
/// <summary>
205197
/// Binaries the search.
206198
/// </summary>
@@ -423,11 +415,33 @@ public void CopyTo(Span<int> target)
423415
AsSpan().Slice(0, Length).CopyTo(target);
424416
}
425417

418+
/// <inheritdoc />
419+
/// <summary>
420+
/// Removes all elements from the list. The capacity remains unchanged.
421+
/// </summary>
422+
public void Clear()
423+
{
424+
Length = 0;
425+
426+
// Clear the entire allocated capacity, not just Length items
427+
UnmanagedMemoryHelper.Clear<int>(_buffer, Capacity);
428+
}
429+
430+
/// <inheritdoc />
426431
/// <summary>
427-
/// Releases the unmanaged resources used by the list.
428-
/// After disposal, the instance should not be used.
432+
/// Frees unmanaged resources used by the <see cref="T:ExtendedSystemObjects.IntList" />.
433+
/// After calling this method, the instance should not be used.
429434
/// </summary>
435+
public void Dispose()
436+
{
437+
Dispose(true);
438+
GC.SuppressFinalize(this);
439+
}
430440

441+
/// <summary>
442+
/// Releases the unmanaged resources used by the list.
443+
/// After disposal, the instance should not be used.
444+
/// </summary>
431445
~UnmanagedIntList()
432446
{
433447
Dispose(false);

0 commit comments

Comments
 (0)