From 2960d57fc3daa3ead01a54be0eadeed9a7cfc4ac Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Thu, 24 Sep 2020 00:52:34 -0700 Subject: [PATCH] Extract helper class TestFixtureHelper --- .../AbstractCompletionProviderTests.cs | 15 +----- .../RefactoringHelpersTestBase.cs | 15 +----- .../AbstractSignatureHelpProviderTests.cs | 15 +----- .../TypeInferrer/TypeInferrerTestBase.cs | 15 +----- .../Utilities/TestFixtureHelper`1.cs | 54 +++++++++++++++++++ 5 files changed, 62 insertions(+), 52 deletions(-) create mode 100644 src/EditorFeatures/TestUtilities/Utilities/TestFixtureHelper`1.cs diff --git a/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs b/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs index 6f3a05c33d7..f79513a287a 100644 --- a/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs +++ b/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs @@ -38,8 +38,7 @@ public abstract class AbstractCompletionProviderTests : TestB { private static readonly TestComposition s_baseComposition = EditorTestCompositions.EditorFeatures.AddExcludedPartTypes(typeof(CompletionProvider)); - private readonly object _workspaceFixtureGate = new(); - private ReferenceCountedDisposable.WeakReference _weakWorkspaceFixture; + private readonly TestFixtureHelper _fixtureHelper = new(); protected readonly Mock MockCompletionSession; private ExportProvider _lazyExportProvider; @@ -56,17 +55,7 @@ protected virtual TestComposition GetComposition() => s_baseComposition.AddParts(GetCompletionProviderType()); private protected ReferenceCountedDisposable GetOrCreateWorkspaceFixture() - { - lock (_workspaceFixtureGate) - { - if (_weakWorkspaceFixture.TryAddReference() is { } workspaceFixture) - return workspaceFixture; - - var result = new ReferenceCountedDisposable(new TWorkspaceFixture()); - _weakWorkspaceFixture = new ReferenceCountedDisposable.WeakReference(result); - return result; - } - } + => _fixtureHelper.GetOrCreateFixture(); protected static async Task CanUseSpeculativeSemanticModelAsync(Document document, int position) { diff --git a/src/EditorFeatures/TestUtilities/RefactoringHelpers/RefactoringHelpersTestBase.cs b/src/EditorFeatures/TestUtilities/RefactoringHelpers/RefactoringHelpersTestBase.cs index 0d9af7a1ed4..d6518f17aff 100644 --- a/src/EditorFeatures/TestUtilities/RefactoringHelpers/RefactoringHelpersTestBase.cs +++ b/src/EditorFeatures/TestUtilities/RefactoringHelpers/RefactoringHelpersTestBase.cs @@ -22,21 +22,10 @@ namespace Microsoft.CodeAnalysis.Editor.UnitTests.RefactoringHelpers public abstract class RefactoringHelpersTestBase : TestBase where TWorkspaceFixture : TestWorkspaceFixture, new() { - private readonly object _workspaceFixtureGate = new(); - private ReferenceCountedDisposable.WeakReference _weakWorkspaceFixture; + private readonly TestFixtureHelper _fixtureHelper = new(); private protected ReferenceCountedDisposable GetOrCreateWorkspaceFixture() - { - lock (_workspaceFixtureGate) - { - if (_weakWorkspaceFixture.TryAddReference() is { } workspaceFixture) - return workspaceFixture; - - var result = new ReferenceCountedDisposable(new TWorkspaceFixture()); - _weakWorkspaceFixture = new ReferenceCountedDisposable.WeakReference(result); - return result; - } - } + => _fixtureHelper.GetOrCreateFixture(); protected Task TestAsync(string text) where TNode : SyntaxNode => TestAsync(text, Functions.True); diff --git a/src/EditorFeatures/TestUtilities/SignatureHelp/AbstractSignatureHelpProviderTests.cs b/src/EditorFeatures/TestUtilities/SignatureHelp/AbstractSignatureHelpProviderTests.cs index 94e1041277f..494b305dc85 100644 --- a/src/EditorFeatures/TestUtilities/SignatureHelp/AbstractSignatureHelpProviderTests.cs +++ b/src/EditorFeatures/TestUtilities/SignatureHelp/AbstractSignatureHelpProviderTests.cs @@ -28,23 +28,12 @@ namespace Microsoft.CodeAnalysis.Editor.UnitTests.SignatureHelp public abstract class AbstractSignatureHelpProviderTests : TestBase where TWorkspaceFixture : TestWorkspaceFixture, new() { - private readonly object _workspaceFixtureGate = new(); - private ReferenceCountedDisposable.WeakReference _weakWorkspaceFixture; + private readonly TestFixtureHelper _fixtureHelper = new(); internal abstract Type GetSignatureHelpProviderType(); private protected ReferenceCountedDisposable GetOrCreateWorkspaceFixture() - { - lock (_workspaceFixtureGate) - { - if (_weakWorkspaceFixture.TryAddReference() is { } workspaceFixture) - return workspaceFixture; - - var result = new ReferenceCountedDisposable(new TWorkspaceFixture()); - _weakWorkspaceFixture = new ReferenceCountedDisposable.WeakReference(result); - return result; - } - } + => _fixtureHelper.GetOrCreateFixture(); /// /// Verifies that sighelp comes up at the indicated location in markup ($$), with the indicated span [| ... |]. diff --git a/src/EditorFeatures/TestUtilities/TypeInferrer/TypeInferrerTestBase.cs b/src/EditorFeatures/TestUtilities/TypeInferrer/TypeInferrerTestBase.cs index 7d4f0ffa6ad..9f7017336fe 100644 --- a/src/EditorFeatures/TestUtilities/TypeInferrer/TypeInferrerTestBase.cs +++ b/src/EditorFeatures/TestUtilities/TypeInferrer/TypeInferrerTestBase.cs @@ -17,21 +17,10 @@ namespace Microsoft.CodeAnalysis.Editor.UnitTests.TypeInferrer public abstract class TypeInferrerTestBase : TestBase where TWorkspaceFixture : TestWorkspaceFixture, new() { - private readonly object _workspaceFixtureGate = new(); - private ReferenceCountedDisposable.WeakReference _weakWorkspaceFixture; + private readonly TestFixtureHelper _fixtureHelper = new(); private protected ReferenceCountedDisposable GetOrCreateWorkspaceFixture() - { - lock (_workspaceFixtureGate) - { - if (_weakWorkspaceFixture.TryAddReference() is { } workspaceFixture) - return workspaceFixture; - - var result = new ReferenceCountedDisposable(new TWorkspaceFixture()); - _weakWorkspaceFixture = new ReferenceCountedDisposable.WeakReference(result); - return result; - } - } + => _fixtureHelper.GetOrCreateFixture(); private static async Task CanUseSpeculativeSemanticModelAsync(Document document, int position) { diff --git a/src/EditorFeatures/TestUtilities/Utilities/TestFixtureHelper`1.cs b/src/EditorFeatures/TestUtilities/Utilities/TestFixtureHelper`1.cs new file mode 100644 index 00000000000..d1ceecde8b8 --- /dev/null +++ b/src/EditorFeatures/TestUtilities/Utilities/TestFixtureHelper`1.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.Editor.UnitTests +{ + internal sealed class TestFixtureHelper + where TFixture : class, IDisposable, new() + { + private readonly object _gate = new(); + + /// + /// Holds a weak reference to the current test fixture instance. This reference allows + /// to access and add a reference to the current test fixture if one exists, + /// but does not prevent the fixture from being disposed after the last reference to it is released. + /// + private ReferenceCountedDisposable.WeakReference _weakFixture; + + /// + /// Gets a reference to a test fixture, or creates it if one does not already exist. + /// + /// + /// The resulting test fixture will not be disposed until the last referencer disposes of its reference. + /// It is possible for more than one test fixture to be created during the life of any single test, but only one + /// test fixture will be live at any given point. + /// + /// The following shows how a block of test code can ensure a single test fixture is created and used + /// within any given block of code: + /// + /// + /// using (var fixture = GetOrCreateFixture()) + /// { + /// // The test fixture 'fixture' is guaranteed to not be released or replaced within this block + /// } + /// + /// + /// The test fixture instance. + internal ReferenceCountedDisposable GetOrCreateFixture() + { + lock (_gate) + { + if (_weakFixture.TryAddReference() is { } fixture) + return fixture; + + var result = new ReferenceCountedDisposable(new TFixture()); + _weakFixture = new ReferenceCountedDisposable.WeakReference(result); + return result; + } + } + } +} -- GitLab