From e110b279d1088b31b09ecff9f480b60ba6fca837 Mon Sep 17 00:00:00 2001 From: Heejae Chang Date: Wed, 10 Jun 2015 16:15:23 -0700 Subject: [PATCH] fix flaky unit test sometimes, instance are kept alive by stack. give it a bit more timeout and clear object in other method. --- ...CacheServiceFactory.ProjectCacheService.cs | 6 +-- ...ojectCacheServiceFactory.SimpleMRUCache.cs | 22 +++++------ .../ProjectCacheHostServiceFactoryTests.cs | 38 +++++++++++++++---- 3 files changed, 45 insertions(+), 21 deletions(-) diff --git a/src/EditorFeatures/Core/Implementation/Workspaces/ProjectCacheServiceFactory.ProjectCacheService.cs b/src/EditorFeatures/Core/Implementation/Workspaces/ProjectCacheServiceFactory.ProjectCacheService.cs index 442ed8a9b35..b82b77bb8ea 100644 --- a/src/EditorFeatures/Core/Implementation/Workspaces/ProjectCacheServiceFactory.ProjectCacheService.cs +++ b/src/EditorFeatures/Core/Implementation/Workspaces/ProjectCacheServiceFactory.ProjectCacheService.cs @@ -54,11 +54,11 @@ public void ClearImplicitCache() } } - public void ClearExpiredImplicitCache(int expirationTimeInMS) + public void ClearExpiredImplicitCache(DateTime expirationTime) { lock (_gate) { - _implicitCache.ClearExpiredItems(expirationTimeInMS); + _implicitCache.ClearExpiredItems(expirationTime); } } @@ -89,8 +89,8 @@ public IDisposable EnableCaching(ProjectId key) } else if (!PartOfP2PReferences(key)) { - _implicitCacheMonitor?.Touch(); _implicitCache.Touch(instance); + _implicitCacheMonitor?.Touch(); } return instance; diff --git a/src/EditorFeatures/Core/Implementation/Workspaces/ProjectCacheServiceFactory.SimpleMRUCache.cs b/src/EditorFeatures/Core/Implementation/Workspaces/ProjectCacheServiceFactory.SimpleMRUCache.cs index 00d1324cd0a..67c363ee33b 100644 --- a/src/EditorFeatures/Core/Implementation/Workspaces/ProjectCacheServiceFactory.SimpleMRUCache.cs +++ b/src/EditorFeatures/Core/Implementation/Workspaces/ProjectCacheServiceFactory.SimpleMRUCache.cs @@ -40,32 +40,32 @@ public bool Empty public void Touch(object instance) { var oldIndex = -1; - var oldTime = Environment.TickCount; + var oldTime = DateTime.UtcNow; for (var i = 0; i < nodes.Length; i++) { if (instance == nodes[i].Data) { - nodes[i].LastTouchedInMS = Environment.TickCount; + nodes[i].LastTouched = DateTime.UtcNow; return; } - if (oldTime >= nodes[i].LastTouchedInMS) + if (oldTime >= nodes[i].LastTouched) { - oldTime = nodes[i].LastTouchedInMS; + oldTime = nodes[i].LastTouched; oldIndex = i; } } Contract.Requires(oldIndex >= 0); - nodes[oldIndex] = new Node(instance, Environment.TickCount); + nodes[oldIndex] = new Node(instance, DateTime.UtcNow); } - public void ClearExpiredItems(int expirationTimeInMS) + public void ClearExpiredItems(DateTime expirationTime) { for (var i = 0; i < nodes.Length; i++) { - if (nodes[i].Data != null && nodes[i].LastTouchedInMS < expirationTimeInMS) + if (nodes[i].Data != null && nodes[i].LastTouched < expirationTime) { nodes[i] = default(Node); } @@ -80,12 +80,12 @@ public void Clear() private struct Node { public readonly object Data; - public int LastTouchedInMS; + public DateTime LastTouched; - public Node(object data, int lastTouchedInMS) + public Node(object data, DateTime lastTouched) { Data = data; - LastTouchedInMS = lastTouchedInMS; + LastTouched = lastTouched; } } } @@ -108,7 +108,7 @@ private class ImplicitCacheMonitor : IdleProcessor protected override Task ExecuteAsync() { - _owner.ClearExpiredImplicitCache(Environment.TickCount - BackOffTimeSpanInMS); + _owner.ClearExpiredImplicitCache(DateTime.UtcNow - TimeSpan.FromMilliseconds(BackOffTimeSpanInMS)); return SpecializedTasks.EmptyTask; } diff --git a/src/EditorFeatures/Test/Workspaces/ProjectCacheHostServiceFactoryTests.cs b/src/EditorFeatures/Test/Workspaces/ProjectCacheHostServiceFactoryTests.cs index 4a728e8b1f5..236ff0a32e6 100644 --- a/src/EditorFeatures/Test/Workspaces/ProjectCacheHostServiceFactoryTests.cs +++ b/src/EditorFeatures/Test/Workspaces/ProjectCacheHostServiceFactoryTests.cs @@ -120,14 +120,35 @@ public void TestImplicitCacheKeepsObjectAlive1() public void TestImplicitCacheMonitoring() { var cacheService = new ProjectCacheHostServiceFactory.ProjectCacheService(null, 10, forceCleanup: true); + var weak = PutObjectInImplicitCache(cacheService); + + var timeout = TimeSpan.FromSeconds(10); + var current = DateTime.UtcNow; + do + { + Thread.Sleep(100); + CollectGarbage(); + + if (DateTime.UtcNow - current > timeout) + { + break; + } + } + while (weak.IsAlive); + + Assert.False(weak.IsAlive); + GC.KeepAlive(cacheService); + } + + private static WeakReference PutObjectInImplicitCache(ProjectCacheHostServiceFactory.ProjectCacheService cacheService) + { var instance = new object(); var weak = new WeakReference(instance); + cacheService.CacheObjectIfCachingEnabledForKey(ProjectId.CreateNewId(), (object)null, instance); instance = null; - Thread.Sleep(100); - CollectGarbage(); - Assert.False(weak.IsAlive); - GC.KeepAlive(cacheService); + + return weak; } [Fact] @@ -224,9 +245,12 @@ private class Owner : ICachedObjectOwner private static void CollectGarbage() { - GC.Collect(); - GC.WaitForPendingFinalizers(); - GC.Collect(); + for (var i = 0; i < 10; i++) + { + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); + } } } } -- GitLab