From 38e145389e0e08cd0dcfb9d7b700a690fde6ea01 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Fri, 27 Jul 2018 12:03:30 -0700 Subject: [PATCH] Fix BackgroundDocumentGenerator flaky tests. - Some time spans were too aggressive for parsing a Razor file on a slow environment. - Fixed an obvious race where we'd expect 0 pending notifications when it was possible to be in the process of clearing notifications. #2506 --- .../BackgroundDocumentGenerator.cs | 13 +++++++++++++ .../BackgroundDocumentGeneratorTest.cs | 9 ++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.CodeAnalysis.Razor.Workspaces/DocumentGenerator/BackgroundDocumentGenerator.cs b/src/Microsoft.CodeAnalysis.Razor.Workspaces/DocumentGenerator/BackgroundDocumentGenerator.cs index 16d7f11959..122e577abe 100644 --- a/src/Microsoft.CodeAnalysis.Razor.Workspaces/DocumentGenerator/BackgroundDocumentGenerator.cs +++ b/src/Microsoft.CodeAnalysis.Razor.Workspaces/DocumentGenerator/BackgroundDocumentGenerator.cs @@ -56,6 +56,9 @@ namespace Microsoft.CodeAnalysis.Razor // Used in unit tests to ensure we can know when background work finishes. public ManualResetEventSlim NotifyBackgroundWorkStarting { get; set; } + // Used in unit tests to ensure we can know when background has captured its current workload. + public ManualResetEventSlim NotifyBackgroundCapturedWorkload { get; set; } + // Used in unit tests to ensure we can control when background work completes. public ManualResetEventSlim BlockBackgroundWorkCompleting { get; set; } @@ -93,6 +96,14 @@ namespace Microsoft.CodeAnalysis.Razor } } + private void OnBackgroundCapturedWorkload() + { + if (NotifyBackgroundCapturedWorkload != null) + { + NotifyBackgroundCapturedWorkload.Set(); + } + } + public override void Initialize(ProjectSnapshotManagerBase projectManager) { if (projectManager == null) @@ -161,6 +172,8 @@ namespace Microsoft.CodeAnalysis.Razor _files.Clear(); } + OnBackgroundCapturedWorkload(); + for (var i = 0; i < work.Length; i++) { var document = work[i]; diff --git a/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/DocumentGenerator/BackgroundDocumentGeneratorTest.cs b/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/DocumentGenerator/BackgroundDocumentGeneratorTest.cs index 546a0be79d..fdc6bd3698 100644 --- a/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/DocumentGenerator/BackgroundDocumentGeneratorTest.cs +++ b/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/DocumentGenerator/BackgroundDocumentGeneratorTest.cs @@ -95,7 +95,7 @@ namespace Microsoft.CodeAnalysis.Razor.ProjectSystem queue.BlockBackgroundWorkStart.Set(); queue.BlockBackgroundWorkCompleting.Set(); - await Task.Run(() => queue.NotifyBackgroundWorkCompleted.Wait(TimeSpan.FromSeconds(1))); + await Task.Run(() => queue.NotifyBackgroundWorkCompleted.Wait(TimeSpan.FromSeconds(3))); Assert.False(queue.IsScheduledOrRunning, "Queue should not have restarted"); Assert.False(queue.HasPendingNotifications, "Queue should have processed all notifications"); @@ -120,6 +120,7 @@ namespace Microsoft.CodeAnalysis.Razor.ProjectSystem Delay = TimeSpan.FromMilliseconds(1), BlockBackgroundWorkStart = new ManualResetEventSlim(initialState: false), NotifyBackgroundWorkStarting = new ManualResetEventSlim(initialState: false), + NotifyBackgroundCapturedWorkload = new ManualResetEventSlim(initialState: false), BlockBackgroundWorkCompleting = new ManualResetEventSlim(initialState: false), NotifyBackgroundWorkCompleted = new ManualResetEventSlim(initialState: false), }; @@ -136,6 +137,8 @@ namespace Microsoft.CodeAnalysis.Razor.ProjectSystem await Task.Run(() => queue.NotifyBackgroundWorkStarting.Wait(TimeSpan.FromSeconds(1))); Assert.True(queue.IsScheduledOrRunning, "Worker should be processing now"); + + await Task.Run(() => queue.NotifyBackgroundCapturedWorkload.Wait(TimeSpan.FromSeconds(1))); Assert.False(queue.HasPendingNotifications, "Worker should have taken all notifications"); queue.Enqueue(project, project.GetDocument(Documents[1].FilePath)); @@ -144,7 +147,7 @@ namespace Microsoft.CodeAnalysis.Razor.ProjectSystem // Allow work to complete, which should restart the timer. queue.BlockBackgroundWorkCompleting.Set(); - await Task.Run(() => queue.NotifyBackgroundWorkCompleted.Wait(TimeSpan.FromSeconds(1))); + await Task.Run(() => queue.NotifyBackgroundWorkCompleted.Wait(TimeSpan.FromSeconds(3))); queue.NotifyBackgroundWorkCompleted.Reset(); // It should start running again right away. @@ -155,7 +158,7 @@ namespace Microsoft.CodeAnalysis.Razor.ProjectSystem queue.BlockBackgroundWorkStart.Set(); queue.BlockBackgroundWorkCompleting.Set(); - await Task.Run(() => queue.NotifyBackgroundWorkCompleted.Wait(TimeSpan.FromSeconds(1))); + await Task.Run(() => queue.NotifyBackgroundWorkCompleted.Wait(TimeSpan.FromSeconds(3))); Assert.False(queue.IsScheduledOrRunning, "Queue should not have restarted"); Assert.False(queue.HasPendingNotifications, "Queue should have processed all notifications");