提交 ff7264f0 编写于 作者: K Kevin Pilch-Bisson

Attempt to diagnose the flakiness in TestTagsChangesForEntireFile

I'm unable to figure out what is going wrong here. My best guess is that
a second workspace event happens before the text changes that causes
classification to refresh while still on the original snapshot.

This adds some additional diagnostics to our test to try to identify that.

Also changes CheckPoint.Release to CheckPoint.TryRelease, so that it's
possible to observe if someone else already caused the checkpoint task to
complete.

Related to #9723.
上级 a42fae6f
...@@ -35,21 +35,35 @@ public async Task TestTagsChangedForEntireFile() ...@@ -35,21 +35,35 @@ public async Task TestTagsChangedForEntireFile()
null, null,
new SyntacticClassificationTaggerProvider(null, null, null)); new SyntacticClassificationTaggerProvider(null, null, null));
SnapshotSpan span = default(SnapshotSpan); var expectedLength = subjectBuffer.CurrentSnapshot.Length;
var actualVersionNumber = int.MaxValue;
var actualLength = int.MaxValue;
var didRelease = false;
tagComputer.TagsChanged += (s, e) => tagComputer.TagsChanged += (s, e) =>
{ {
span = e.Span; actualVersionNumber = e.Span.Snapshot.Version.VersionNumber;
checkpoint.Release(); actualLength = e.Span.Length;
didRelease = checkpoint.TryRelease();
}; };
await checkpoint.Task; await checkpoint.Task;
Assert.Equal(1, actualVersionNumber);
Assert.Equal(expectedLength, actualLength);
Assert.True(didRelease);
checkpoint = new Checkpoint(); checkpoint = new Checkpoint();
// Now apply an edit that require us to reclassify more that just the current line // Now apply an edit that require us to reclassify more that just the current line
subjectBuffer.Insert(document.CursorPosition.Value, "\""); var snapshot = subjectBuffer.Insert(document.CursorPosition.Value, "\"");
expectedLength = snapshot.Length;
// NOTE: TagsChanged is raised on the UI thread, so there is no race between
// assigning expected here and verifying in the event handler, because the
// event handler can't run until we await.
await checkpoint.Task; await checkpoint.Task;
Assert.Equal(subjectBuffer.CurrentSnapshot.Length, span.Length); Assert.Equal(2, actualVersionNumber);
Assert.Equal(expectedLength, actualLength);
Assert.True(didRelease);
} }
} }
} }
......
...@@ -1466,7 +1466,7 @@ class C ...@@ -1466,7 +1466,7 @@ class C
' before the model computation has finished. Then, allow the ' before the model computation has finished. Then, allow the
' computation to complete. There should still be no session. ' computation to complete. There should still be no session.
state.SendBackspace() state.SendBackspace()
slowProvider.checkpoint.Release() slowProvider.checkpoint.TryRelease()
Await state.AssertNoCompletionSession() Await state.AssertNoCompletionSession()
End Using End Using
End Function End Function
......
...@@ -92,17 +92,17 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense ...@@ -92,17 +92,17 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense
Dim checkpoint2 = New Checkpoint Dim checkpoint2 = New Checkpoint
Dim checkpoint3 = New Checkpoint Dim checkpoint3 = New Checkpoint
token.Setup(Sub(t) t.Dispose()).Callback(Sub() checkpoint3.Release()) token.Setup(Sub(t) t.Dispose()).Callback(Sub() checkpoint3.TryRelease())
modelComputation.ChainTaskAndNotifyControllerWhenFinished(Function(m, c) modelComputation.ChainTaskAndNotifyControllerWhenFinished(Function(m, c)
checkpoint1.Release() checkpoint1.TryRelease()
checkpoint2.Task.Wait() checkpoint2.Task.Wait()
c.ThrowIfCancellationRequested() c.ThrowIfCancellationRequested()
Return Task.FromResult(model) Return Task.FromResult(model)
End Function) End Function)
Await checkpoint1.Task Await checkpoint1.Task
modelComputation.Stop() modelComputation.Stop()
checkpoint2.Release() checkpoint2.TryRelease()
Await checkpoint3.Task Await checkpoint3.Task
controller.Verify(Sub(c) c.OnModelUpdated(model), Times.Never) controller.Verify(Sub(c) c.OnModelUpdated(model), Times.Never)
......
...@@ -153,7 +153,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense ...@@ -153,7 +153,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense
Sub() GetMocks(controller).Buffer.Insert(0, " "))) Sub() GetMocks(controller).Buffer.Insert(0, " ")))
Dim handled = dispatcher.InvokeAsync(Function() controller.TryHandleUpKey()) ' Send the controller an up key, which should block on the computation Dim handled = dispatcher.InvokeAsync(Function() controller.TryHandleUpKey()) ' Send the controller an up key, which should block on the computation
checkpoint.Release() ' Allow slowprovider to finish checkpoint.TryRelease() ' Allow slowprovider to finish
Await handled.Task.ConfigureAwait(False) Await handled.Task.ConfigureAwait(False)
' We expect 2 calls to the presenter (because we had an existing presentation session when we started the second computation). ' We expect 2 calls to the presenter (because we had an existing presentation session when we started the second computation).
......
...@@ -11,11 +11,9 @@ namespace Roslyn.Test.Utilities ...@@ -11,11 +11,9 @@ namespace Roslyn.Test.Utilities
public class Checkpoint public class Checkpoint
{ {
private readonly TaskCompletionSource<object> _tcs = new TaskCompletionSource<object>(); private readonly TaskCompletionSource<object> _tcs = new TaskCompletionSource<object>();
public Task Task { get { return _tcs.Task; } }
public void Release() public Task Task => _tcs.Task;
{
_tcs.TrySetResult(null); public bool TryRelease() => _tcs.TrySetResult(null);
}
} }
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册