Skip to content

Commit 5a6ebe1

Browse files
committed
Add Unit Tests for GC (#206)
***NO_CI***
1 parent e0ceaab commit 5a6ebe1

9 files changed

+643
-0
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="Current" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup Label="Globals">
4+
<NanoFrameworkProjectSystemPath>$(MSBuildExtensionsPath)\nanoFramework\v1.0\</NanoFrameworkProjectSystemPath>
5+
</PropertyGroup>
6+
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props')" />
7+
<ItemGroup>
8+
<ProjectCapability Include="TestContainer" />
9+
</ItemGroup>
10+
<PropertyGroup>
11+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
12+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
13+
<ProjectTypeGuids>{11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
14+
<ProjectGuid>768be3b6-41c6-4dfb-8a2d-443b2113f5ad</ProjectGuid>
15+
<OutputType>Library</OutputType>
16+
<AppDesignerFolder>Properties</AppDesignerFolder>
17+
<FileAlignment>512</FileAlignment>
18+
<RootNamespace>NFUnitTestGC</RootNamespace>
19+
<AssemblyName>NFUnitTest</AssemblyName>
20+
<IsCodedUITest>False</IsCodedUITest>
21+
<IsTestProject>true</IsTestProject>
22+
<TestProjectType>UnitTest</TestProjectType>
23+
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
24+
</PropertyGroup>
25+
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
26+
<ItemGroup>
27+
<Compile Include="TestGCWithByteArrays.cs" />
28+
<Compile Include="TestGCWithTimeSpanArrays.cs" />
29+
<Compile Include="TestGCWithDateTimeArrays.cs" />
30+
<Compile Include="TestGCWithObjectArrays.cs" />
31+
<Compile Include="TestGC.cs" />
32+
<Compile Include="Properties\AssemblyInfo.cs" />
33+
</ItemGroup>
34+
<ItemGroup>
35+
<Reference Include="mscorlib">
36+
<HintPath>..\..\packages\nanoFramework.CoreLibrary.1.14.2\lib\mscorlib.dll</HintPath>
37+
</Reference>
38+
<Reference Include="nanoFramework.TestFramework">
39+
<HintPath>..\..\packages\nanoFramework.TestFramework.2.1.85\lib\nanoFramework.TestFramework.dll</HintPath>
40+
</Reference>
41+
<Reference Include="nanoFramework.UnitTestLauncher">
42+
<HintPath>..\..\packages\nanoFramework.TestFramework.2.1.85\lib\nanoFramework.UnitTestLauncher.exe</HintPath>
43+
</Reference>
44+
</ItemGroup>
45+
<ItemGroup>
46+
<None Include="packages.config" />
47+
</ItemGroup>
48+
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets')" />
49+
</Project>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System.Reflection;
2+
using System.Runtime.CompilerServices;
3+
using System.Runtime.InteropServices;
4+
5+
// General Information about an assembly is controlled through the following
6+
// set of attributes. Change these attribute values to modify the information
7+
// associated with an assembly.
8+
[assembly: AssemblyDescription("")]
9+
[assembly: AssemblyConfiguration("")]
10+
[assembly: AssemblyCompany("")]
11+
[assembly: AssemblyCopyright("Copyright (c) 2021 nanoFramework contributors")]
12+
[assembly: AssemblyTrademark("")]
13+
[assembly: AssemblyCulture("")]
14+
15+
// Setting ComVisible to false makes the types in this assembly not visible
16+
// to COM components. If you need to access a type in this assembly from
17+
// COM, set the ComVisible attribute to true on that type.
18+
[assembly: ComVisible(false)]
19+
20+
// Version information for an assembly consists of the following four values:
21+
//
22+
// Major Version
23+
// Minor Version
24+
// Build Number
25+
// Revision
26+
//
27+
// You can specify all the values or you can default the Build and Revision Numbers
28+
// by using the '*' as shown below:
29+
// [assembly: AssemblyVersion("1.0.*")]
30+
[assembly: AssemblyVersion("1.0.0.0")]
31+
[assembly: AssemblyFileVersion("1.0.0.0")]

Tests/NFUnitTestGC/TestGC.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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+
8+
using nanoFramework.TestFramework;
9+
using System;
10+
11+
namespace NFUnitTestGC
12+
{
13+
[TestClass]
14+
public class TestGC
15+
{
16+
[TestMethod]
17+
public void TestGCStress()
18+
{
19+
int maxArraySize = 1024 * 32;
20+
object[] arrays = new object[600];
21+
22+
OutputHelper.WriteLine("Starting TestGCStress");
23+
24+
for (int loop = 0; loop < 100; loop++)
25+
{
26+
OutputHelper.WriteLine($"Running iteration {loop}");
27+
28+
for (int i = 0; i < arrays.Length - 1;)
29+
{
30+
OutputHelper.WriteLine($"Alloc array of {maxArraySize} bytes @ pos {i}");
31+
arrays[i++] = new byte[maxArraySize]; ;
32+
33+
OutputHelper.WriteLine($"Alloc array of 64 bytes @ pos {i}");
34+
arrays[i++] = new byte[64];
35+
}
36+
37+
arrays[0] = new byte[maxArraySize];
38+
39+
for (int i = 0; i < arrays.Length; i++)
40+
{
41+
arrays[i] = null;
42+
}
43+
}
44+
45+
OutputHelper.WriteLine("Completed TestGCStress");
46+
}
47+
}
48+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
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 TestGCWithByteArrays
14+
{
15+
[TestMethod]
16+
public void TestCompactionForNotFixedArray()
17+
{
18+
OutputHelper.WriteLine("Starting TestCompactionForNotFixedArray");
19+
20+
for (int loop = 0; loop < 10; loop++)
21+
{
22+
OutputHelper.WriteLine($"Starting iteration {loop}");
23+
24+
// First we create byte and holes that keeps some space that could be used by compaction
25+
26+
// Small count so compaction does not happen
27+
byte[] arrayOfArrays = new byte[10];
28+
29+
RunAllocations(arrayOfArrays);
30+
31+
// This is the array that we expect to move in during compaction.
32+
byte[] testNativeBuffer = new byte[100];
33+
34+
// Fill it, so it is not optimized out
35+
Random random = new();
36+
var baseValue = random.Next(2);
37+
38+
for (int i = 0; i < testNativeBuffer.Length; i++)
39+
{
40+
testNativeBuffer[i] = (byte)(i * baseValue);
41+
}
42+
43+
// trigger compaction
44+
InitiateCompaction();
45+
46+
int index = 0;
47+
48+
// Check that array content is not corrupted
49+
foreach (var item in testNativeBuffer)
50+
{
51+
Assert.AreEqual(index * baseValue, item, $"Array content comparison failed at position {index}. Expecting {(index * baseValue)}, found {item}");
52+
index++;
53+
}
54+
55+
OutputHelper.WriteLine("No corruption detected in array");
56+
}
57+
58+
OutputHelper.WriteLine("Completed TestCompactionForNotFixedArray");
59+
}
60+
61+
void RunAllocations(byte[] arrObj)
62+
{
63+
for (int i = 1; i < arrObj.Length; i++)
64+
{
65+
// Creates referenced byte, which stays in memory until InitiateCompaction exits
66+
arrObj[i] = new byte();
67+
68+
// Tries to create larger object that would be later hole .
69+
// This object could be garbage collected on each "i" cycle.
70+
byte[] arr = new byte[50 * i];
71+
72+
// Creates some usage for arr, so it is not optimized out.
73+
arr[0] = 1;
74+
arr[1] = 2;
75+
76+
OutputHelper.WriteLine($"On Cycle {i:D3} Array of {arr[1]} was allocated");
77+
}
78+
}
79+
80+
// This method causes compaction to occur.
81+
// It is not so trivial as it need to fragment heap with referenced byte array.
82+
void InitiateCompaction()
83+
{
84+
// large count, so compaction happens during call to RunAllocations
85+
byte[] arrayOfArrays = new byte[1500];
86+
RunAllocations(arrayOfArrays);
87+
}
88+
}
89+
}

0 commit comments

Comments
 (0)