From c53a96f125c5b8d5f3cc04e2b9a9d41f934d23be Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Wed, 20 Apr 2022 10:59:20 -0700 Subject: [PATCH 1/2] Update TestHandleCollector() test Initialize local member in HandleCollector since it was the only one not initialized. Update test to wait for pending finalizers since that is when the HandleCollector API will trigger the GC. --- .../Runtime/InteropServices/HandleCollector.cs | 1 + .../InteropServices/HandleCollectorTests.cs | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/HandleCollector.cs b/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/HandleCollector.cs index a874251c5dbc41..7e83303a5bcbbf 100644 --- a/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/HandleCollector.cs +++ b/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/HandleCollector.cs @@ -40,6 +40,7 @@ public HandleCollector(string? name, int initialThreshold, int maximumThreshold) MaximumThreshold = maximumThreshold; _threshold = initialThreshold; _handleCount = 0; + _gcGeneration = 0; } public int Count => _handleCount; diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/HandleCollectorTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/HandleCollectorTests.cs index ce0ad62b912d56..c6b047d5229011 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/HandleCollectorTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/HandleCollectorTests.cs @@ -122,6 +122,7 @@ public static void Add_Overflows_ThrowsInvalidOperationException() public static void TestHandleCollector() { (int gen0, int gen1, int gen2) initialGcState = (GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2)); + int initSum = initialGcState.gen0 + initialGcState.gen1 + initialGcState.gen2; HandleCollector lowLimitCollector = new HandleCollector("LowLimit.Collector", LowLimitSize); for (int i = 0; i < LowLimitSize + 1; ++i) @@ -129,9 +130,13 @@ public static void TestHandleCollector() HandleLimitTester hlt = new HandleLimitTester(lowLimitCollector); } - (int gen0, int gen1, int gen2) postLowLimitState = (GC.CollectionCount(0),GC.CollectionCount(1), GC.CollectionCount(2)); + // Since all the tester does the HandleCollector decrement during finalization, wait for pending finalizers. + GC.WaitForPendingFinalizers(); - Assert.True(initialGcState.gen0 + initialGcState.gen1 + initialGcState.gen2 < postLowLimitState.gen0 + postLowLimitState.gen1 + postLowLimitState.gen2, "Low limit handle did not trigger a GC"); + (int gen0, int gen1, int gen2) postLowLimitState = (GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2)); + int postLowLimitSum = postLowLimitState.gen0 + postLowLimitState.gen1 + postLowLimitState.gen2; + + Assert.True(initSum < postLowLimitSum, $"Low limit handle did not trigger a GC: {initSum} < {postLowLimitSum}"); HandleCollector highLimitCollector = new HandleCollector("HighLimit.Collector", HighLimitSize); for (int i = 0; i < HighLimitSize + 10; ++i) @@ -139,9 +144,13 @@ public static void TestHandleCollector() HandleLimitTester hlt = new HandleLimitTester(highLimitCollector); } + // Since all the tester does the HandleCollector decrement during finalization, wait for pending finalizers. + GC.WaitForPendingFinalizers(); + (int gen0, int gen1, int gen2) postHighLimitState = (GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2)); + int postHighLimitSum = postHighLimitState.gen0 + postHighLimitState.gen1 + postHighLimitState.gen2; - Assert.True(postLowLimitState.gen0 + postLowLimitState.gen1 + postLowLimitState.gen2 < postHighLimitState.gen0 + postHighLimitState.gen1 + postHighLimitState.gen2, "High limit handle did not trigger a GC"); + Assert.True(postLowLimitSum < postHighLimitSum, $"High limit handle did not trigger a GC: {postLowLimitSum} < {postHighLimitSum}"); } private sealed class HandleLimitTester From ce348c161e61aa9641978007837ecaa2548a2f54 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Wed, 20 Apr 2022 15:04:39 -0700 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: Elinor Fung --- .../System/Runtime/InteropServices/HandleCollectorTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/HandleCollectorTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/HandleCollectorTests.cs index c6b047d5229011..471c8bf2a84fac 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/HandleCollectorTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/HandleCollectorTests.cs @@ -130,7 +130,7 @@ public static void TestHandleCollector() HandleLimitTester hlt = new HandleLimitTester(lowLimitCollector); } - // Since all the tester does the HandleCollector decrement during finalization, wait for pending finalizers. + // HandleLimitTester does the decrement on the HandleCollector during finalization, so we wait for pending finalizers. GC.WaitForPendingFinalizers(); (int gen0, int gen1, int gen2) postLowLimitState = (GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2)); @@ -144,7 +144,7 @@ public static void TestHandleCollector() HandleLimitTester hlt = new HandleLimitTester(highLimitCollector); } - // Since all the tester does the HandleCollector decrement during finalization, wait for pending finalizers. + // HandleLimitTester does the decrement on the HandleCollector during finalization, so we wait for pending finalizers. GC.WaitForPendingFinalizers(); (int gen0, int gen1, int gen2) postHighLimitState = (GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2));