Skip to content
Draft
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .runsettings
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<!-- Configurations that affect the Test Framework -->
<RunConfiguration>
Expand All @@ -12,5 +12,6 @@
<Logging>Verbose</Logging>
<IsRealHardware>False</IsRealHardware>
<RunnerExtraArguments> --forcegc </RunnerExtraArguments>
<UsePreviewClr>True</UsePreviewClr>
</nanoFrameworkAdapter>
</RunSettings>
</RunSettings>
36 changes: 31 additions & 5 deletions Tests/NFUnitTestGC/TestGC.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.


using System;
using nanoFramework.TestFramework;

namespace NFUnitTestGC
Expand All @@ -15,16 +16,14 @@ public void TestGCStress()
int maxArraySize = 1024 * 32;
object[] arrays = new object[600];

// Starting TestGCStress

for (int loop = 0; loop < 100; loop++)
{
OutputHelper.WriteLine($"Running iteration {loop}");

for (int i = 0; i < arrays.Length - 1;)
{
OutputHelper.WriteLine($"Alloc array of {maxArraySize} bytes @ pos {i}");
arrays[i++] = new byte[maxArraySize]; ;
arrays[i++] = new byte[maxArraySize];

OutputHelper.WriteLine($"Alloc array of 64 bytes @ pos {i}");
arrays[i++] = new byte[64];
Expand All @@ -37,8 +36,35 @@ public void TestGCStress()
arrays[i] = null;
}
}
}

[TestMethod]
public void TestGetTotalMemory()
{
// create several objects
object[] objects = new object[100];

for (int i = 0; i < objects.Length; i++)
{
objects[i] = new object();
}

// get total memory
long totalMemory = GC.GetTotalMemory(false);
OutputHelper.WriteLine($"Total memory: {totalMemory} bytes");

// release objects
for (int i = 0; i < objects.Length; i++)
{
objects[i] = null;
}

// get total memory, forcing full collection
long totalMemoryAfterCollection = GC.GetTotalMemory(true);
OutputHelper.WriteLine($"Total memory: {totalMemoryAfterCollection} bytes");

// Completed TestGCStress
// check if memory was released
Assert.IsTrue(totalMemory > totalMemoryAfterCollection, "Memory was not released");
}
}
}
5 changes: 4 additions & 1 deletion Tests/NFUnitTestSystemLib/NFUnitTestSystemLib.nfproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@
<IsTestProject>true</IsTestProject>
<TestProjectType>UnitTest</TestProjectType>
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
<LangVersion>13.0</LangVersion>
</PropertyGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
<ItemGroup>
<Compile Include="RuntimeHelpersTests.cs" />
<Compile Include="UnitTestNullable.cs" />
<Compile Include="UnitTestUInt64.cs" />
<Compile Include="UnitTestUInt32.cs" />
<Compile Include="UnitTestSingle.cs" />
Expand Down Expand Up @@ -61,4 +64,4 @@
<ProjectConfigurationsDeclaredAsItems />
</ProjectCapabilities>
</ProjectExtensions>
</Project>
</Project>
68 changes: 68 additions & 0 deletions Tests/NFUnitTestSystemLib/RuntimeHelpersTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Runtime.CompilerServices;
using nanoFramework.TestFramework;

namespace NFUnitTestSystemLib
{
[TestClass]
class RuntimeHelpersTests
{
[TestMethod]
public static void IsReferenceOrContainsReferences()
{
Assert.IsFalse(RuntimeHelpers.IsReferenceOrContainsReferences<int>());
Assert.IsTrue(RuntimeHelpers.IsReferenceOrContainsReferences<string>());
Assert.IsFalse(RuntimeHelpers.IsReferenceOrContainsReferences<Guid>());
Assert.IsFalse(RuntimeHelpers.IsReferenceOrContainsReferences<StructWithoutReferences>());
Assert.IsTrue(RuntimeHelpers.IsReferenceOrContainsReferences<StructWithReferences>());
Assert.IsFalse(RuntimeHelpers.IsReferenceOrContainsReferences<RefStructWithoutReferences>());
Assert.IsTrue(RuntimeHelpers.IsReferenceOrContainsReferences<RefStructWithReferences>());
Assert.IsTrue(RuntimeHelpers.IsReferenceOrContainsReferences<Span<char>>());
Assert.IsTrue(RuntimeHelpers.IsReferenceOrContainsReferences<ReadOnlySpan<char>>());
//Assert.IsTrue(RuntimeHelpers.IsReferenceOrContainsReferences<RefStructWithRef>());
//Assert.IsTrue(RuntimeHelpers.IsReferenceOrContainsReferences<RefStructWithNestedRef>());
}

private struct StructWithoutReferences
{
public int a, b, c;
}

private struct StructWithReferences
{
public int a, b, c;
public object d;
}

private ref struct RefStructWithoutReferences
{
public int a;
public long b;
}

private ref struct RefStructWithReferences
{
public int a;
public object b;
}

// TODO: add after checking viability of ref fields in ref structs
//private ref struct RefStructWithRef
//{
// public ref int a;

// internal RefStructWithRef(ref int aVal)
// {
// a = ref aVal;
// }
//}

//private ref struct RefStructWithNestedRef
//{
// public Span<char> a;
//}
}
}
85 changes: 35 additions & 50 deletions Tests/NFUnitTestSystemLib/UnitTestGCTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ namespace NFUnitTestSystemLib
[TestClass]
public class UnitTestGCTest
{
#pragma warning disable S1215 // this is intended to test the GC
#pragma warning disable S1854 // this is intended to test the GC
#pragma warning disable S2696 // this is intended to test the GC
#pragma warning disable S3971 // this is intended to test the GC

internal class FinalizeObject
{
public static FinalizeObject m_currentInstance = null;
Expand Down Expand Up @@ -54,17 +59,20 @@ public void SystemGC1_Test()
/// 6. Verify that object has been collected
/// </summary>
///
// Tests ReRegisterForFinalize
// Create a FinalizeObject.

OutputHelper.WriteLine("Tests ReRegisterForFinalize");
OutputHelper.WriteLine("Create a FinalizeObject.");

FinalizeObject mfo = new FinalizeObject();
m_hasFinalized1 = false;
m_hasFinalized2 = false;

// Release reference
OutputHelper.WriteLine("Release reference");
mfo = null;

// Allow GC
GC.WaitForPendingFinalizers();
OutputHelper.WriteLine("Allow GC");
GC.Collect();

int sleepTime = 1000;
int slept = 0;
Expand All @@ -85,10 +93,10 @@ public void SystemGC1_Test()
// FinalizeObject.m_currentInstance field. Setting this value
// to null and forcing another garbage collection will now
// cause the object to Finalize permanently.
// Reregister and allow for GC
FinalizeObject.m_currentInstance = null;

GC.WaitForPendingFinalizers();
OutputHelper.WriteLine("Reregister and allow for GC");
FinalizeObject.m_currentInstance = null;
GC.Collect();

sleepTime = 1000;
slept = 0;
Expand Down Expand Up @@ -119,26 +127,27 @@ public void SystemGC2_Test()
/// 6. Verify that object has not been collected
/// </summary>
///
// Tests SuppressFinalize
// Create a FinalizeObject.

OutputHelper.WriteLine("Tests SuppressFinalize");
OutputHelper.WriteLine("Create a FinalizeObject");
FinalizeObject mfo = new FinalizeObject();
m_hasFinalized1 = false;
m_hasFinalized2 = false;

// Releasing
OutputHelper.WriteLine("Releasing");
GC.SuppressFinalize(mfo);
mfo = null;

// Allow GC
GC.WaitForPendingFinalizers();
OutputHelper.WriteLine("Allow GC");
GC.Collect();

int sleepTime = 1000;
int slept = 0;

while (!m_hasFinalized1 && slept < sleepTime)
{
// force GC run caused by memory allocation
var dummyArray = new byte[1024 * 1024 * 1];
_ = new byte[1024 * 1024 * 1];

System.Threading.Thread.Sleep(10);
slept += 10;
Expand All @@ -161,59 +170,35 @@ public void SystemGC3_Test()
/// </summary>
///

// Tests WaitForPendingFinalizers, dependant on test 1
// will auto-fail if test 1 fails.
OutputHelper.Write("Tests WaitForPendingFinalizers, dependant on test 1");
OutputHelper.WriteLine("will auto-fail if test 1 fails.");
OutputHelper.WriteLine("will fail if test 1 fails.");

Assert.IsTrue(m_Test1Result);
Assert.IsTrue(m_Test1Result, "Can't run this test as SystemGC1_Test has failed.");

// Create a FinalizeObject.
OutputHelper.WriteLine("Create a FinalizeObject");
FinalizeObject mfo = new FinalizeObject();
m_hasFinalized1 = false;
m_hasFinalized2 = false;

// Releasing
OutputHelper.WriteLine("Releasing");
mfo = null;

int sleepTime = 1000;
int slept = 0;

while (!m_hasFinalized1 && slept < sleepTime)
{
// force GC run caused by memory allocation
var dummyArray = new byte[1024 * 1024 * 1];

System.Threading.Thread.Sleep(10);
slept += 10;
}

OutputHelper.WriteLine($"GC took {slept}");

// Wait for GC
OutputHelper.WriteLine("Wait for GC");
GC.Collect();
GC.WaitForPendingFinalizers();

// Releasing again
OutputHelper.WriteLine("Releasing again");
FinalizeObject.m_currentInstance = null;

sleepTime = 1000;
slept = 0;

while (!m_hasFinalized2 && slept < sleepTime)
{
// force GC run caused by memory allocation
var dummyArray = new byte[1024 * 1024 * 1];

System.Threading.Thread.Sleep(10);
slept += 10;
}

OutputHelper.WriteLine($"GC took {slept}");

// Wait for GC
OutputHelper.WriteLine("Wait for GC");
GC.Collect();
GC.WaitForPendingFinalizers();

Assert.IsTrue(m_hasFinalized2);
}
}
#pragma warning restore S1215 // "GC.Collect" should not be called
#pragma warning restore S1854 // Unused assignments should be removed
#pragma warning restore S2696 // Instance members should not write to "static" fields
#pragma warning restore S3971 // "GC.SuppressFinalize" should not be called
}
Loading
Loading