Skip to content

Commit 17fef3a

Browse files
authored
Merge pull request #15 from sharwell/integration-tests
Add tests
2 parents 9f2c39c + 1ede535 commit 17fef3a

File tree

59 files changed

+4341
-32
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+4341
-32
lines changed

Directory.Build.props

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project>
3+
4+
<PropertyGroup>
5+
<Company>Tunnel Vision Laboratories, LLC</Company>
6+
<Copyright>Copyright © Sam Harwell 2014</Copyright>
7+
<Version>4.2.0.0</Version>
8+
<FileVersion>4.2.0.0</FileVersion>
9+
<InformationalVersion>4.2.0-dev</InformationalVersion>
10+
</PropertyGroup>
11+
12+
<PropertyGroup>
13+
<DebugSymbols>true</DebugSymbols>
14+
<DebugType>portable</DebugType>
15+
</PropertyGroup>
16+
17+
<PropertyGroup>
18+
<SignAssembly>true</SignAssembly>
19+
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)Tvl.VisualStudio.MouseFastScroll\SharedKey.snk</AssemblyOriginatorKeyFile>
20+
</PropertyGroup>
21+
22+
<ItemGroup>
23+
<None Include="$(AssemblyOriginatorKeyFile)" Condition="'$(AssemblyOriginatorKeyFile)' != ''" Link="%(Filename)%(Extension)" />
24+
</ItemGroup>
25+
26+
<!-- StyleCop Analyzers configuration -->
27+
<PropertyGroup>
28+
<GenerateDocumentationFile>true</GenerateDocumentationFile>
29+
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)MouseFastScroll.ruleset</CodeAnalysisRuleSet>
30+
</PropertyGroup>
31+
32+
<ItemGroup>
33+
<PackageReference Include="StyleCop.Analyzers" Version="1.1.0-beta006" PrivateAssets="all" />
34+
<AdditionalFiles Include="$(MSBuildThisFileDirectory)stylecop.json" Link="stylecop.json" />
35+
<None Include="$(CodeAnalysisRuleSet)" Condition="'$(CodeAnalysisRuleSet)' != ''" Link="%(Filename)%(Extension)" />
36+
</ItemGroup>
37+
38+
</Project>

Directory.Build.targets

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project>
3+
</Project>

MouseFastScroll.ruleset

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<RuleSet Name="Rules for StyleCop.Analyzers" Description="Code analysis rules for StyleCop.Analyzers.csproj." ToolsVersion="15.0">
2+
<RuleSet Name="Rules for MouseFastScroll" Description="Code analysis rules for MouseFastScroll." ToolsVersion="15.0">
33
<Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
44
<Rule Id="CA1001" Action="Warning" />
55
<Rule Id="CA1009" Action="Warning" />
@@ -69,12 +69,24 @@
6969
<Rule Id="CS1591" Action="Hidden" />
7070
<Rule Id="CS1712" Action="Hidden" />
7171
</Rules>
72+
<Rules AnalyzerId="Microsoft.CodeAnalysis.CSharp.Features" RuleNamespace="Microsoft.CodeAnalysis.CSharp.Features">
73+
<!-- IDE0003 duplicates functionality provided by SX1101 -->
74+
<Rule Id="IDE0003" Action="None" />
75+
</Rules>
7276
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
7377
<Rule Id="SA1101" Action="None" />
74-
<Rule Id="SA1305" Action="Warning" />
78+
<Rule Id="SA1139" Action="None" /> <!-- https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2275 -->
79+
<Rule Id="SA1202" Action="None" />
80+
<Rule Id="SA1204" Action="None" />
81+
<Rule Id="SA1309" Action="None" />
7582
<Rule Id="SA1412" Action="Warning" />
7683
<Rule Id="SA1600" Action="None" />
77-
<Rule Id="SA1609" Action="Warning" />
84+
<Rule Id="SA1601" Action="None" />
85+
<Rule Id="SA1602" Action="None" />
86+
<Rule Id="SA1611" Action="None" />
87+
<Rule Id="SA1615" Action="None" />
7888
<Rule Id="SX1101" Action="Warning" />
89+
<Rule Id="SX1309" Action="Warning" />
90+
<Rule Id="SX1309S" Action="Warning" />
7991
</Rules>
8092
</RuleSet>

MouseFastScroll.sln

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,21 @@ MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7939456F-2CC6-4242-96AB-E1C8D75C0D79}"
77
ProjectSection(SolutionItems) = preProject
88
appveyor.yml = appveyor.yml
9+
Directory.Build.props = Directory.Build.props
10+
Directory.Build.targets = Directory.Build.targets
911
LICENSE.txt = LICENSE.txt
1012
README.md = README.md
13+
THIRD-PARTY-NOTICES.txt = THIRD-PARTY-NOTICES.txt
1114
EndProjectSection
1215
EndProject
1316
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tvl.VisualStudio.MouseFastScroll", "Tvl.VisualStudio.MouseFastScroll\Tvl.VisualStudio.MouseFastScroll.csproj", "{7DFA0DD1-8052-464D-9A1A-5EADC10A84B0}"
1417
EndProject
18+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tvl.VisualStudio.MouseFastScroll.IntegrationTests", "Tvl.VisualStudio.MouseFastScroll.IntegrationTests\Tvl.VisualStudio.MouseFastScroll.IntegrationTests.csproj", "{05BCF25F-BC5C-40AC-8A2C-66EB3969F0FB}"
19+
EndProject
20+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tvl.VisualStudio.MouseFastScroll.IntegrationTestService", "Tvl.VisualStudio.MouseFastScroll.IntegrationTestService\Tvl.VisualStudio.MouseFastScroll.IntegrationTestService.csproj", "{0366D6B8-8F75-47C2-A11E-1E69F1B9380C}"
21+
EndProject
22+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tvl.VisualStudio.MouseFastScroll.UnitTests", "Tvl.VisualStudio.MouseFastScroll.UnitTests\Tvl.VisualStudio.MouseFastScroll.UnitTests.csproj", "{5630A9D3-6B83-473B-BCE7-FFEB6D2E1063}"
23+
EndProject
1524
Global
1625
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1726
Debug|Any CPU = Debug|Any CPU
@@ -22,6 +31,18 @@ Global
2231
{7DFA0DD1-8052-464D-9A1A-5EADC10A84B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
2332
{7DFA0DD1-8052-464D-9A1A-5EADC10A84B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
2433
{7DFA0DD1-8052-464D-9A1A-5EADC10A84B0}.Release|Any CPU.Build.0 = Release|Any CPU
34+
{05BCF25F-BC5C-40AC-8A2C-66EB3969F0FB}.Debug|Any CPU.ActiveCfg = Debug|x86
35+
{05BCF25F-BC5C-40AC-8A2C-66EB3969F0FB}.Debug|Any CPU.Build.0 = Debug|x86
36+
{05BCF25F-BC5C-40AC-8A2C-66EB3969F0FB}.Release|Any CPU.ActiveCfg = Release|x86
37+
{05BCF25F-BC5C-40AC-8A2C-66EB3969F0FB}.Release|Any CPU.Build.0 = Release|x86
38+
{0366D6B8-8F75-47C2-A11E-1E69F1B9380C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39+
{0366D6B8-8F75-47C2-A11E-1E69F1B9380C}.Debug|Any CPU.Build.0 = Debug|Any CPU
40+
{0366D6B8-8F75-47C2-A11E-1E69F1B9380C}.Release|Any CPU.ActiveCfg = Release|Any CPU
41+
{0366D6B8-8F75-47C2-A11E-1E69F1B9380C}.Release|Any CPU.Build.0 = Release|Any CPU
42+
{5630A9D3-6B83-473B-BCE7-FFEB6D2E1063}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43+
{5630A9D3-6B83-473B-BCE7-FFEB6D2E1063}.Debug|Any CPU.Build.0 = Debug|Any CPU
44+
{5630A9D3-6B83-473B-BCE7-FFEB6D2E1063}.Release|Any CPU.ActiveCfg = Release|Any CPU
45+
{5630A9D3-6B83-473B-BCE7-FFEB6D2E1063}.Release|Any CPU.Build.0 = Release|Any CPU
2546
EndGlobalSection
2647
GlobalSection(SolutionProperties) = preSolution
2748
HideSolutionNode = FALSE

THIRD-PARTY-NOTICES.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Mouse Fast Scroll uses third-party libraries or other resources that may be
2+
distributed under licenses different than the Mouse Fast Scroll software.
3+
4+
In the event that we accidentally failed to list a required notice, please
5+
bring it to our attention by posting an issue.
6+
7+
The attached notices are provided for information only.
8+
9+
License notice for .NET Compiler Platform (Roslyn)
10+
--------------------------------------------------
11+
12+
Copyright Microsoft.
13+
14+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
15+
these files except in compliance with the License. You may obtain a copy of the
16+
License at
17+
18+
http://www.apache.org/licenses/LICENSE-2.0
19+
20+
Unless required by applicable law or agreed to in writing, software distributed
21+
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
22+
CONDITIONS OF ANY KIND, either express or implied. See the License for the
23+
specific language governing permissions and limitations under the License.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
2+
// Licensed under the Apache License, Version 2.0. See LICENSE.txt in the project root for license information.
3+
4+
namespace Tvl.VisualStudio.MouseFastScroll.IntegrationTestService
5+
{
6+
using System;
7+
using System.Collections.Concurrent;
8+
using System.Diagnostics;
9+
using System.Reflection;
10+
using System.Runtime.Remoting;
11+
12+
/// <summary>
13+
/// Provides a means of executing code in the Visual Studio host process.
14+
/// </summary>
15+
/// <remarks>
16+
/// This object exists in the Visual Studio host and is marhsalled across the process boundary.
17+
/// </remarks>
18+
public class IntegrationService : MarshalByRefObject
19+
{
20+
private readonly ConcurrentDictionary<string, ObjRef> _marshalledObjects = new ConcurrentDictionary<string, ObjRef>();
21+
22+
public IntegrationService()
23+
{
24+
PortName = GetPortName(Process.GetCurrentProcess().Id);
25+
BaseUri = "ipc://" + PortName;
26+
}
27+
28+
public string PortName
29+
{
30+
get;
31+
}
32+
33+
/// <summary>
34+
/// Gets the base Uri of the service. This resolves to a string such as <c>ipc://IntegrationService_{HostProcessId}"</c>
35+
/// </summary>
36+
public string BaseUri
37+
{
38+
get;
39+
}
40+
41+
private static string GetPortName(int hostProcessId)
42+
{
43+
// Make the channel name well-known by using a static base and appending the process ID of the host
44+
return $"{nameof(IntegrationService)}_{{{hostProcessId}}}";
45+
}
46+
47+
public static IntegrationService GetInstanceFromHostProcess(Process hostProcess)
48+
{
49+
var uri = $"ipc://{GetPortName(hostProcess.Id)}/{typeof(IntegrationService).FullName}";
50+
return (IntegrationService)Activator.GetObject(typeof(IntegrationService), uri);
51+
}
52+
53+
public string Execute(string assemblyFilePath, string typeFullName, string methodName)
54+
{
55+
var assembly = Assembly.LoadFrom(assemblyFilePath);
56+
var type = assembly.GetType(typeFullName);
57+
var methodInfo = type.GetMethod(methodName, BindingFlags.Public | BindingFlags.Static);
58+
var result = methodInfo.Invoke(null, null);
59+
60+
if (methodInfo.ReturnType == typeof(void))
61+
{
62+
return null;
63+
}
64+
65+
// Create a unique URL for each object returned, so that we can communicate with each object individually
66+
var resultType = result.GetType();
67+
var marshallableResult = (MarshalByRefObject)result;
68+
var objectUri = $"{resultType.FullName}_{Guid.NewGuid()}";
69+
var marshalledObject = RemotingServices.Marshal(marshallableResult, objectUri, resultType);
70+
71+
if (!_marshalledObjects.TryAdd(objectUri, marshalledObject))
72+
{
73+
throw new InvalidOperationException($"An object with the specified URI has already been marshalled. (URI: {objectUri})");
74+
}
75+
76+
return objectUri;
77+
}
78+
}
79+
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
2+
// Licensed under the Apache License, Version 2.0. See LICENSE.txt in the project root for license information.
3+
4+
namespace Tvl.VisualStudio.MouseFastScroll.IntegrationTestService
5+
{
6+
using System;
7+
using System.ComponentModel.Design;
8+
using System.Diagnostics;
9+
using System.Runtime.Remoting;
10+
using System.Runtime.Remoting.Channels;
11+
using System.Runtime.Remoting.Channels.Ipc;
12+
using System.Runtime.Serialization.Formatters;
13+
using Microsoft.VisualStudio.Shell;
14+
15+
internal sealed class IntegrationTestServiceCommands : IDisposable
16+
{
17+
public const int CmdIdStartIntegrationTestService = 0x5201;
18+
public const int CmdIdStopIntegrationTestService = 0x5204;
19+
20+
public static readonly Guid GuidIntegrationTestCmdSet = new Guid("F3505B05-AF1E-493A-A5A5-ECEB69C42714");
21+
22+
private static readonly BinaryServerFormatterSinkProvider DefaultSinkProvider = new BinaryServerFormatterSinkProvider()
23+
{
24+
TypeFilterLevel = TypeFilterLevel.Full,
25+
};
26+
27+
private readonly Package _package;
28+
29+
private readonly MenuCommand _startMenuCmd;
30+
private readonly MenuCommand _stopMenuCmd;
31+
32+
private IntegrationService _service;
33+
private IpcServerChannel _serviceChannel;
34+
private ObjRef _marshalledService;
35+
36+
private IntegrationTestServiceCommands(Package package)
37+
{
38+
_package = package ?? throw new ArgumentNullException(nameof(package));
39+
40+
if (ServiceProvider.GetService(typeof(IMenuCommandService)) is OleMenuCommandService menuCommandService)
41+
{
42+
var startMenuCmdId = new CommandID(GuidIntegrationTestCmdSet, CmdIdStartIntegrationTestService);
43+
_startMenuCmd = new MenuCommand(StartServiceCallback, startMenuCmdId)
44+
{
45+
Enabled = true,
46+
Visible = true,
47+
};
48+
menuCommandService.AddCommand(_startMenuCmd);
49+
50+
var stopMenuCmdId = new CommandID(GuidIntegrationTestCmdSet, CmdIdStopIntegrationTestService);
51+
_stopMenuCmd = new MenuCommand(StopServiceCallback, stopMenuCmdId)
52+
{
53+
Enabled = false,
54+
Visible = false,
55+
};
56+
menuCommandService.AddCommand(_stopMenuCmd);
57+
}
58+
}
59+
60+
public static IntegrationTestServiceCommands Instance
61+
{
62+
get; private set;
63+
}
64+
65+
private IServiceProvider ServiceProvider => _package;
66+
67+
public static void Initialize(Package package)
68+
{
69+
Instance = new IntegrationTestServiceCommands(package);
70+
}
71+
72+
public void Dispose()
73+
=> StopServiceCallback(this, EventArgs.Empty);
74+
75+
/// <summary>
76+
/// Starts the IPC server for the Integration Test service.
77+
/// </summary>
78+
private void StartServiceCallback(object sender, EventArgs e)
79+
{
80+
if (_startMenuCmd.Enabled)
81+
{
82+
_service = new IntegrationService();
83+
84+
_serviceChannel = new IpcServerChannel(
85+
name: $"Microsoft.VisualStudio.IntegrationTest.ServiceChannel_{Process.GetCurrentProcess().Id}",
86+
portName: _service.PortName,
87+
sinkProvider: DefaultSinkProvider);
88+
89+
var serviceType = typeof(IntegrationService);
90+
_marshalledService = RemotingServices.Marshal(_service, serviceType.FullName, serviceType);
91+
92+
_serviceChannel.StartListening(null);
93+
94+
SwapAvailableCommands(_startMenuCmd, _stopMenuCmd);
95+
}
96+
}
97+
98+
/// <summary>Stops the IPC server for the Integration Test service.</summary>
99+
private void StopServiceCallback(object sender, EventArgs e)
100+
{
101+
if (_stopMenuCmd.Enabled)
102+
{
103+
if (_serviceChannel != null)
104+
{
105+
_serviceChannel.StopListening(null);
106+
_serviceChannel = null;
107+
}
108+
109+
_marshalledService = null;
110+
_service = null;
111+
112+
SwapAvailableCommands(_stopMenuCmd, _startMenuCmd);
113+
}
114+
}
115+
116+
private void SwapAvailableCommands(MenuCommand commandToDisable, MenuCommand commandToEnable)
117+
{
118+
commandToDisable.Enabled = false;
119+
commandToDisable.Visible = false;
120+
121+
commandToEnable.Enabled = true;
122+
commandToEnable.Visible = true;
123+
}
124+
}
125+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<CommandTable xmlns="http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable" xmlns:xs="http://www.w3.org/2001/XMLSchema">
3+
<Commands package="guidIntegrationTestPackage">
4+
<Buttons>
5+
<Button guid="guidIntegrationTestCmdSet" id="cmdidIntegrationTestServiceStart" priority="0x0010" type="Button">
6+
<CommandFlag>DynamicVisibility</CommandFlag>
7+
<Strings>
8+
<ButtonText>Start</ButtonText>
9+
<CommandName>IntegrationTestService.Start</CommandName>
10+
<CanonicalName>IntegrationTestService.Start</CanonicalName>
11+
<LocCanonicalName>IntegrationTestService.Start</LocCanonicalName>
12+
</Strings>
13+
</Button>
14+
<Button guid="guidIntegrationTestCmdSet" id="cmdidIntegrationTestServiceStop" priority="0x0020" type="Button">
15+
<CommandFlag>DynamicVisibility</CommandFlag>
16+
<CommandFlag>DefaultDisabled</CommandFlag>
17+
<CommandFlag>DefaultInvisible</CommandFlag>
18+
<Strings>
19+
<ButtonText>Stop</ButtonText>
20+
<CommandName>IntegrationTestService.Stop</CommandName>
21+
<CanonicalName>IntegrationTestService.Stop</CanonicalName>
22+
<LocCanonicalName>IntegrationTestService.Stop</LocCanonicalName>
23+
</Strings>
24+
</Button>
25+
</Buttons>
26+
</Commands>
27+
28+
<Symbols>
29+
<GuidSymbol name="guidIntegrationTestPackage" value="{78D5A8B5-1634-434B-802D-E3E4A46B1AA6}" />
30+
31+
<GuidSymbol name="guidIntegrationTestCmdSet" value="{F3505B05-AF1E-493A-A5A5-ECEB69C42714}">
32+
<IDSymbol name="cmdidIntegrationTestServiceStart" value="0x5201" />
33+
<IDSymbol name="cmdidIntegrationTestServiceStop" value="0x5202" />
34+
</GuidSymbol>
35+
</Symbols>
36+
</CommandTable>

0 commit comments

Comments
 (0)