Skip to content

Commit

Permalink
Tests all passing again
Browse files Browse the repository at this point in the history
  • Loading branch information
jaredpar committed Jul 11, 2021
1 parent 39c049e commit c6702ae
Show file tree
Hide file tree
Showing 9 changed files with 259 additions and 193 deletions.
48 changes: 42 additions & 6 deletions Src/VimEditorHost/UnitTests/VimTestBase.cs
Expand Up @@ -45,7 +45,7 @@ public abstract class VimTestBase : IDisposable
/// Cache of composition containers. This is indexed on thread id as the underlying objects in the container
/// can, and often do, have thread affinity.
/// </summary>
private static readonly Dictionary<int, VimEditorHost> s_cachedVimEditorHostMap = new Dictionary<int, VimEditorHost>();
private static readonly Dictionary<(Type, int), VimEditorHost> s_cachedVimEditorHostMap = new Dictionary<(Type, int), VimEditorHost>();

public StaContext StaContext { get; }
public Dispatcher Dispatcher => StaContext.Dispatcher;
Expand Down Expand Up @@ -546,14 +546,50 @@ protected WpfTextViewDisplay CreateTextViewDisplay(IWpfTextView textView, bool s
lineChangeTracker);
}

private static VimEditorHost GetOrCreateVimEditorHost()
protected virtual Type GetVimHostExportType() => typeof(TestableVimHost);

public static Func<Type, bool> GetVimEditorHostTypeFilter(Type vimHostExportType)
{
// The unit test host exports several replacement components to facilitate
// better testing. For example it exports TestableClipboard which doesn't use
// the real clipboard (would make testing flaky). Have to exclude the real components
// here to avoid export conflicts
var iVimHostType = typeof(IVimHost);
Func<Type, bool> typeFilter = type =>
{
if (type == typeof(Vim.UI.Wpf.Implementation.Misc.ClipboardDevice) ||
type == typeof(Vim.UI.Wpf.Implementation.Misc.KeyboardDeviceImpl) ||
type == typeof(Vim.UI.Wpf.Implementation.Misc.MouseDeviceImpl))
{
return false;
}
if (iVimHostType.IsAssignableFrom(type) && type != vimHostExportType)
{
return false;
}
return true;
};

return typeFilter;
}

protected VimEditorHost CreateVimEditorHost(Type vimHostExportType)
{
var typeFilter = GetVimEditorHostTypeFilter(vimHostExportType);
var editorHostFactory = new VimEditorHostFactory(typeFilter);
var compositionContainer = editorHostFactory.CreateCompositionContainer();
return new VimEditorHost(compositionContainer);
}

private VimEditorHost GetOrCreateVimEditorHost()
{
var key = Thread.CurrentThread.ManagedThreadId;
var vimHostExportType = GetVimHostExportType();
var key = (vimHostExportType, Thread.CurrentThread.ManagedThreadId);
if (!s_cachedVimEditorHostMap.TryGetValue(key, out VimEditorHost host))
{
var editorHostFactory = new VimEditorHostFactory();
var compositionContainer = editorHostFactory.CreateCompositionContainer();
host = new VimEditorHost(compositionContainer);
host = CreateVimEditorHost(vimHostExportType);
s_cachedVimEditorHostMap[key] = host;
}

Expand Down
15 changes: 0 additions & 15 deletions Src/VimEditorHost/VimEditorHostFactory.cs
Expand Up @@ -93,21 +93,6 @@ public VimEditorHost CreateVimEditorHost()

private void BuildCatalog(Func<Type, bool> typeFilter)
{
#if VS_UNIT_TEST_HOST
// The unit test host exports several replacement components to facilitate
// better testing. For example it exports TestableClipboard which doesn't use
// the real clipboard (would make testing flaky). Have to exclude the real components
// here to avoid export conflicts
Func<Type, bool> unitTestTypeFilter = type =>
type != typeof(Vim.UI.Wpf.Implementation.Misc.ClipboardDevice) &&
type != typeof(Vim.UI.Wpf.Implementation.Misc.KeyboardDeviceImpl) &&
type != typeof(Vim.UI.Wpf.Implementation.Misc.MouseDeviceImpl) &&
type.FullName != "Vim.VisualStudio.VsVimHost";
var originalTypeFilter = typeFilter;

typeFilter = type => originalTypeFilter(type) && unitTestTypeFilter(type);
#endif

// https://github.com/VsVim/VsVim/issues/2905
// Once VimEditorUtils is broken up correctly the composition code here should be
// reconsidered: particularly all of the ad-hoc exports below. Really need to move
Expand Down
8 changes: 5 additions & 3 deletions Src/VimTestUtils/VimTestUtils.csproj
Expand Up @@ -7,6 +7,11 @@
<AssemblyName>Vim.UnitTest.Utils</AssemblyName>
<TargetFramework>net472</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Exports\**" />
<EmbeddedResource Remove="Exports\**" />
<None Remove="Exports\**" />
</ItemGroup>
<ItemGroup>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
Expand All @@ -32,7 +37,4 @@
<ItemGroup>
<ProjectReference Include="..\VimCore\VimCore.fsproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Exports\" />
</ItemGroup>
</Project>
3 changes: 0 additions & 3 deletions Test/VimWpfTest/VimWpfTest.projitems
Expand Up @@ -26,7 +26,4 @@
<Compile Include="$(MSBuildThisFileDirectory)VimMouseProcessorTest.cs" />
<Compile Include="$(MSBuildThisFileDirectory)WpfIntegrationTest.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="$(MSBuildThisFileDirectory)Properties\" />
</ItemGroup>
</Project>
@@ -0,0 +1,95 @@
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Editor;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.TextManager.Interop;
using Moq;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Text;

namespace VsVimSharedTest.Implementation
{
[Export(typeof(IVsEditorAdaptersFactoryService))]
[Export(typeof(TestableEditorAdaptersFactoryService))]
internal sealed class TestableEditorAdaptersFactoryService : IVsEditorAdaptersFactoryService
{
private MockRepository _factory = new MockRepository(MockBehavior.Loose);

public IVsCodeWindow CreateVsCodeWindowAdapter(Microsoft.VisualStudio.OLE.Interop.IServiceProvider serviceProvider)
{
throw new NotImplementedException();
}

public IVsTextBuffer CreateVsTextBufferAdapter(Microsoft.VisualStudio.OLE.Interop.IServiceProvider serviceProvider, Microsoft.VisualStudio.Utilities.IContentType contentType)
{
throw new NotImplementedException();
}

public IVsTextBuffer CreateVsTextBufferAdapter(Microsoft.VisualStudio.OLE.Interop.IServiceProvider serviceProvider)
{
throw new NotImplementedException();
}

public IVsTextBuffer CreateVsTextBufferAdapterForSecondaryBuffer(Microsoft.VisualStudio.OLE.Interop.IServiceProvider serviceProvider, Microsoft.VisualStudio.Text.ITextBuffer secondaryBuffer)
{
throw new NotImplementedException();
}

public IVsTextBufferCoordinator CreateVsTextBufferCoordinatorAdapter()
{
throw new NotImplementedException();
}

public IVsTextView CreateVsTextViewAdapter(Microsoft.VisualStudio.OLE.Interop.IServiceProvider serviceProvider, ITextViewRoleSet roles)
{
throw new NotImplementedException();
}

public IVsTextView CreateVsTextViewAdapter(Microsoft.VisualStudio.OLE.Interop.IServiceProvider serviceProvider)
{
throw new NotImplementedException();
}

public IVsTextBuffer GetBufferAdapter(ITextBuffer textBuffer)
{
var lines = _factory.Create<IVsTextLines>();
IVsEnumLineMarkers markers;
lines
.Setup(x => x.EnumMarkers(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<uint>(), out markers))
.Returns(VSConstants.E_FAIL);
return lines.Object;
}

public Microsoft.VisualStudio.Text.ITextBuffer GetDataBuffer(IVsTextBuffer bufferAdapter)
{
throw new NotImplementedException();
}

public Microsoft.VisualStudio.Text.ITextBuffer GetDocumentBuffer(IVsTextBuffer bufferAdapter)
{
throw new NotImplementedException();
}

public IVsTextView GetViewAdapter(ITextView textView)
{
return null;
}

public IWpfTextView GetWpfTextView(IVsTextView viewAdapter)
{
throw new NotImplementedException();
}

public IWpfTextViewHost GetWpfTextViewHost(IVsTextView viewAdapter)
{
throw new NotImplementedException();
}

public void SetDataBuffer(IVsTextBuffer bufferAdapter, Microsoft.VisualStudio.Text.ITextBuffer dataBuffer)
{
throw new NotImplementedException();
}
}
}
86 changes: 86 additions & 0 deletions Test/VsVimSharedTest/Implementation/TestableServiceProvider.cs
@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Windows.Threading;
using Vim.EditorHost;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Editor;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.TextManager.Interop;
using Moq;
using Vim;
using Vim.Extensions;
using Vim.UI.Wpf;
using Vim.UnitTest;
using Vim.VisualStudio.UnitTest.Mock;
using Xunit;
using System.Threading;
using EnvDTE;
using Thread = System.Threading.Thread;

namespace Vim.VisualStudio.UnitTest
{
[Export(typeof(SVsServiceProvider))]
[Export(typeof(TestableServiceProvider))]
internal sealed class TestableServiceProvider : SVsServiceProvider
{
/// <summary>
/// This smooths out the nonsense type equality problems that come with having NoPia
/// enabled on only some of the assemblies.
/// </summary>
private sealed class TypeEqualityComparer : IEqualityComparer<Type>
{
public bool Equals(Type x, Type y)
{
return
x.FullName == y.FullName &&
x.GUID == y.GUID;
}

public int GetHashCode(Type obj)
{
return obj != null ? obj.GUID.GetHashCode() : 0;
}
}

private MockRepository _factory = new MockRepository(MockBehavior.Loose);
private readonly Dictionary<Type, object> _serviceMap = new Dictionary<Type, object>(new TypeEqualityComparer());

public TestableServiceProvider()
{
_serviceMap[typeof(SVsShell)] = _factory.Create<IVsShell>().Object;
_serviceMap[typeof(SVsTextManager)] = _factory.Create<IVsTextManager>().Object;
_serviceMap[typeof(SVsRunningDocumentTable)] = _factory.Create<IVsRunningDocumentTable>().Object;
_serviceMap[typeof(SVsUIShell)] = MockObjectFactory.CreateVsUIShell4(MockBehavior.Strict).Object;
_serviceMap[typeof(SVsShellMonitorSelection)] = _factory.Create<IVsMonitorSelection>().Object;
_serviceMap[typeof(IVsExtensibility)] = _factory.Create<IVsExtensibility>().Object;
var dte = MockObjectFactory.CreateDteWithCommands();
_serviceMap[typeof(_DTE)] = dte.Object;
_serviceMap[typeof(SVsStatusbar)] = _factory.Create<IVsStatusbar>().Object;
_serviceMap[typeof(SDTE)] = dte.Object;
_serviceMap[typeof(SVsSettingsManager)] = CreateSettingsManager().Object;
_serviceMap[typeof(SVsFindManager)] = _factory.Create<IVsFindManager>().Object;
}

private Mock<IVsSettingsManager> CreateSettingsManager()
{
var settingsManager = _factory.Create<IVsSettingsManager>();

var writableSettingsStore = _factory.Create<IVsWritableSettingsStore>();
var local = writableSettingsStore.Object;
settingsManager.Setup(x => x.GetWritableSettingsStore(It.IsAny<uint>(), out local)).Returns(VSConstants.S_OK);

return settingsManager;
}

public object GetService(Type serviceType)
{
return _serviceMap[serviceType];
}
}
}

0 comments on commit c6702ae

Please sign in to comment.