Skip to content

Commit 971ed70

Browse files
committed
Add Unit Tests for GC and strings (#209)
***NO_CI***
1 parent 0defde4 commit 971ed70

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed

Tests/NFUnitTestGC/NFUnitTestGC.nfproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
2626
<ItemGroup>
2727
<Compile Include="TestGCWithByteArrays.cs" />
28+
<Compile Include="TestGCWithStringArrays.cs" />
2829
<Compile Include="TestGCWithTimeSpanArrays.cs" />
2930
<Compile Include="TestGCWithDateTimeArrays.cs" />
3031
<Compile Include="TestGCWithObjectArrays.cs" />
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//
2+
// Copyright (c) .NET Foundation and Contributors
3+
// Portions Copyright (c) Microsoft Corporation. All rights reserved.
4+
// See LICENSE file in the project root for full license information.
5+
//
6+
7+
using nanoFramework.TestFramework;
8+
using System;
9+
10+
namespace NFUnitTestGC
11+
{
12+
[TestClass]
13+
public class TestGCWithStringArrays
14+
{
15+
[TestMethod]
16+
public void TestCompactionForNotFixedStringArray()
17+
{
18+
OutputHelper.WriteLine("Starting TestCompactionForNotFixedStringArray");
19+
20+
for (int loop = 0; loop < 10; loop++)
21+
{
22+
OutputHelper.WriteLine($"Starting iteration {loop}");
23+
24+
// First we create objects and holes that keeps some space that could be used by compaction.
25+
26+
// Small count so compaction does not happen.
27+
HolderForString[] arrayOfStrings = new HolderForString[10];
28+
RunStringAllocations(arrayOfStrings);
29+
30+
// This is the array that we expect to move in during compaction.
31+
HolderForString[] testNativeBuffer = new HolderForString[100];
32+
// Fill it, so it is not optimized out
33+
for (int i = 0; i < testNativeBuffer.Length; i++)
34+
{
35+
testNativeBuffer[i] = new HolderForString(Guid.NewGuid().ToString());
36+
}
37+
38+
OutputHelper.WriteLine("Large HolderForString array created");
39+
OutputHelper.WriteLine("Forcing compaction to occurr");
40+
41+
// Causes compaction
42+
InitiateStringCompaction();
43+
44+
OutputHelper.WriteLine("Compaction occurred");
45+
OutputHelper.WriteLine("Checking arrays for corrupted data...");
46+
47+
int index = 0;
48+
49+
// Check that array content is not corrupted
50+
foreach (HolderForString holder in testNativeBuffer)
51+
{
52+
Assert.AreEqual(
53+
holder.StringHash,
54+
holder.StringContent.GetHashCode(),
55+
$"Array content comparison failed at position {index}. Expecting {holder.StringHash}, found {holder.StringContent.GetHashCode()}");
56+
57+
index++;
58+
}
59+
60+
OutputHelper.WriteLine("No corruption detected in array");
61+
}
62+
63+
OutputHelper.WriteLine("Completed TestCompactionForNotFixedArray");
64+
}
65+
66+
// This function cause compaction to occur.
67+
// It is not so trivial as it need to fragment heap with referenced objects.
68+
void InitiateStringCompaction()
69+
{
70+
// Large count, so compaction happens during RunAllocations.
71+
HolderForString[] arrayOfArrays = new HolderForString[400];
72+
RunStringAllocations(arrayOfArrays);
73+
}
74+
75+
private void RunStringAllocations(HolderForString[] arrObj)
76+
{
77+
for (int i = 1; i < arrObj.Length; i++)
78+
{
79+
// Creates referenced object, which stays in memory until InitiateCompaction exits
80+
arrObj[i] = new HolderForString(Guid.NewGuid().ToString());
81+
82+
// Tries to create larger object that would be later hole
83+
// This object could be garbage collected on each "i" cycle
84+
HolderForString[] arr = new HolderForString[50 * i];
85+
86+
// Creates some usage for array elements, so it is not optimized out
87+
arr[0] = new HolderForString(Guid.NewGuid().ToString());
88+
}
89+
}
90+
91+
private class HolderForString
92+
{
93+
public int StringHash { get; }
94+
public string StringContent { get; }
95+
96+
public HolderForString(string value)
97+
{
98+
StringContent = value;
99+
StringHash = value.GetHashCode();
100+
}
101+
}
102+
}
103+
}

0 commit comments

Comments
 (0)