Skip to content

Commit ce71b7e

Browse files
committed
Added tests for the PublishToMarketplace build target.
1 parent 249c909 commit ce71b7e

File tree

9 files changed

+726
-0
lines changed

9 files changed

+726
-0
lines changed

Community.VisualStudio.Toolkit.sln

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "imports", "imports", "{544D
7979
src\toolkit\nuget\build\imports\PublishToMarketplace.targets = src\toolkit\nuget\build\imports\PublishToMarketplace.targets
8080
EndProjectSection
8181
EndProject
82+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MockVsixPublisher", "tools\MockVsixPublisher\MockVsixPublisher.csproj", "{C1BD4EBE-F43C-4A51-9801-A04E5C2C8B3E}"
83+
EndProject
8284
Global
8385
GlobalSection(SharedMSBuildProjectFiles) = preSolution
8486
src\toolkit\Community.VisualStudio.Toolkit.Shared\VSSDK.Helpers.Shared.projitems*{ff58bacd-16b0-4c73-ba03-4a255925153f}*SharedItemsImports = 5
@@ -154,6 +156,14 @@ Global
154156
{6AB57B05-4938-44BB-BBE4-38F3A55D1A54}.Release|Any CPU.Build.0 = Release|Any CPU
155157
{6AB57B05-4938-44BB-BBE4-38F3A55D1A54}.Release|x86.ActiveCfg = Release|Any CPU
156158
{6AB57B05-4938-44BB-BBE4-38F3A55D1A54}.Release|x86.Build.0 = Release|Any CPU
159+
{C1BD4EBE-F43C-4A51-9801-A04E5C2C8B3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
160+
{C1BD4EBE-F43C-4A51-9801-A04E5C2C8B3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
161+
{C1BD4EBE-F43C-4A51-9801-A04E5C2C8B3E}.Debug|x86.ActiveCfg = Debug|Any CPU
162+
{C1BD4EBE-F43C-4A51-9801-A04E5C2C8B3E}.Debug|x86.Build.0 = Debug|Any CPU
163+
{C1BD4EBE-F43C-4A51-9801-A04E5C2C8B3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
164+
{C1BD4EBE-F43C-4A51-9801-A04E5C2C8B3E}.Release|Any CPU.Build.0 = Release|Any CPU
165+
{C1BD4EBE-F43C-4A51-9801-A04E5C2C8B3E}.Release|x86.ActiveCfg = Release|Any CPU
166+
{C1BD4EBE-F43C-4A51-9801-A04E5C2C8B3E}.Release|x86.Build.0 = Release|Any CPU
157167
EndGlobalSection
158168
GlobalSection(SolutionProperties) = preSolution
159169
HideSolutionNode = FALSE
@@ -175,6 +185,7 @@ Global
175185
{2EC8051C-B422-4CEC-BA2F-BBD15551E6CB} = {6ED8D47D-D076-44C4-B0CE-B6CF944C71D3}
176186
{6ED8D47D-D076-44C4-B0CE-B6CF944C71D3} = {C27D922F-7897-4199-A2F9-6E1ED66C440A}
177187
{544DB8D0-6BAB-4739-B141-971AA59A494C} = {2EC8051C-B422-4CEC-BA2F-BBD15551E6CB}
188+
{C1BD4EBE-F43C-4A51-9801-A04E5C2C8B3E} = {3F2F4E99-C896-4C92-9F6D-66D2A8360168}
178189
EndGlobalSection
179190
GlobalSection(ExtensibilityGlobals) = postSolution
180191
SolutionGuid = {E0DD67C0-2617-498C-81F0-A5E4FF5831F1}

test/toolkit/Community.VisualStudio.Toolkit.UnitTests/Community.VisualStudio.Toolkit.UnitTests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<Import Project="..\..\..\src\toolkit\Community.VisualStudio.Toolkit.Shared\VSSDK.Helpers.Shared.projitems" Label="Shared" />
1717

1818
<ItemGroup>
19+
<PackageReference Include="Microsoft.Build.Locator" Version="1.4.1" />
1920
<PackageReference Include="Microsoft.VisualStudio.SDK" Version="17.0.31902.203" IncludeAssets="All" PrivateAssets="None" />
2021
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
2122
<PackageReference Include="Moq" Version="4.16.1" />
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System.Collections.Generic;
2+
3+
namespace Community.VisualStudio.Toolkit.UnitTests
4+
{
5+
internal class CompilationResult
6+
{
7+
public CompilationResult(int exitCode, IEnumerable<string> standardOutput, IEnumerable<string> standardError)
8+
{
9+
ExitCode = exitCode;
10+
StandardOutput = standardOutput;
11+
StandardError = standardError;
12+
}
13+
14+
public int ExitCode { get; }
15+
16+
public IEnumerable<string> StandardOutput { get; }
17+
18+
public IEnumerable<string> StandardError { get; }
19+
}
20+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
4+
namespace Community.VisualStudio.Toolkit.UnitTests
5+
{
6+
public class CompileOptions
7+
{
8+
public string Target { get; set; } = "Build";
9+
public object Properties { get; set; } = new object();
10+
public IEnumerable<string> Arguments { get; set; } = Enumerable.Empty<string>();
11+
public Dictionary<string, string> Environment { get; set; } = new Dictionary<string, string>();
12+
}
13+
}
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics;
4+
using System.IO;
5+
using System.Reflection;
6+
using System.Runtime.CompilerServices;
7+
using System.Text;
8+
using System.Threading.Tasks;
9+
using Microsoft.Build.Locator;
10+
using Xunit.Abstractions;
11+
12+
namespace Community.VisualStudio.Toolkit.UnitTests
13+
{
14+
internal class TestProject
15+
{
16+
private static readonly VisualStudioInstance _instance = MSBuildLocator.RegisterDefaults();
17+
18+
private readonly string _directory;
19+
private readonly List<string> _files = new();
20+
private readonly List<string> _props = new();
21+
private readonly List<string> _targets = new();
22+
23+
public TestProject(string directory)
24+
{
25+
_directory = directory;
26+
}
27+
28+
public void ImportTargets(string fileName)
29+
{
30+
string path = GetTargetsPath(fileName);
31+
_targets.Add($"<Import Project='{path}' />");
32+
}
33+
34+
private static string GetTargetsPath(string fileName, [CallerFilePath] string thisFilePath = "")
35+
{
36+
return Path.GetFullPath(
37+
Path.Combine(
38+
Path.GetDirectoryName(thisFilePath),
39+
$"../../../../src/toolkit/nuget/build/{fileName}"
40+
)
41+
);
42+
}
43+
44+
public void AddFile(string fileName, string contents)
45+
{
46+
string fullPath = Path.Combine(_directory, fileName);
47+
Directory.CreateDirectory(Path.GetDirectoryName(fullPath));
48+
File.WriteAllText(fullPath, contents);
49+
50+
_files.Add($"<Compile Include='{fileName}'/>");
51+
}
52+
53+
public async Task<CompilationResult> CompileAsync(CompileOptions options, ITestOutputHelper outputHelper)
54+
{
55+
WriteFiles();
56+
57+
using (Process process = new())
58+
{
59+
List<string> stdout = new();
60+
List<string> stderr = new();
61+
List<string> arguments = new();
62+
63+
arguments.Add("/Restore");
64+
arguments.Add($"/t:{options.Target}");
65+
arguments.Add("/nr:false"); // Disable node re-use.
66+
67+
foreach (PropertyInfo property in options.Properties.GetType().GetProperties())
68+
{
69+
object value = property.GetValue(options.Properties);
70+
if (value is not null)
71+
{
72+
arguments.Add($"/p:{property.Name}={value}");
73+
}
74+
}
75+
76+
foreach (string argument in options.Arguments)
77+
{
78+
arguments.Add(argument);
79+
}
80+
81+
process.StartInfo = new ProcessStartInfo
82+
{
83+
FileName = Path.Combine(_instance.MSBuildPath, "MSBuild.exe"),
84+
Arguments = string.Join(" ", arguments),
85+
WorkingDirectory = _directory,
86+
UseShellExecute = false,
87+
RedirectStandardOutput = true,
88+
RedirectStandardError = true,
89+
StandardOutputEncoding = Encoding.UTF8,
90+
StandardErrorEncoding = Encoding.UTF8
91+
};
92+
93+
foreach (KeyValuePair<string, string> entry in options.Environment)
94+
{
95+
process.StartInfo.Environment[entry.Key] = entry.Value;
96+
}
97+
98+
process.Start();
99+
100+
await Task.WhenAll(
101+
DrainReaderAsync(process.StandardOutput, (line) =>
102+
{
103+
stdout.Add(line);
104+
outputHelper.WriteLine(line);
105+
}),
106+
DrainReaderAsync(process.StandardError, (line) =>
107+
{
108+
stderr.Add(line);
109+
outputHelper.WriteLine(line);
110+
})
111+
);
112+
113+
process.WaitForExit();
114+
115+
return new CompilationResult(process.ExitCode, stdout, stderr);
116+
}
117+
}
118+
119+
private void WriteFiles()
120+
{
121+
WriteManifest();
122+
WriteProject();
123+
}
124+
125+
private void WriteProject()
126+
{
127+
string projectName = $"{Path.GetFileName(_directory)}.csproj";
128+
string projectFileName = Path.Combine(_directory, projectName);
129+
130+
File.WriteAllText(
131+
projectFileName,
132+
$@"
133+
<Project ToolsVersion='17.0' DefaultTargets='Build' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
134+
<PropertyGroup>
135+
<VSToolsPath Condition=""'$(VSToolsPath)' == ''"">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
136+
</PropertyGroup>
137+
<Import Project='$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props' Condition=""Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"" />
138+
{string.Join(Environment.NewLine, _props)}
139+
<PropertyGroup>
140+
<Configuration Condition="" '$(Configuration)' == '' "">Debug</Configuration>
141+
<Platform Condition="" '$(Platform)' == '' "">AnyCPU</Platform>
142+
<ProjectTypeGuids>{{82b43b9b-a64c-4715-b499-d71e9ca2bd60}};{{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}}</ProjectTypeGuids>
143+
<ProjectGuid>{{C313D707-2A74-4AD2-BB5D-0FD6C4942E08}}</ProjectGuid>
144+
<OutputType>Library</OutputType>
145+
<RootNamespace>Test.Extension</RootNamespace>
146+
<AssemblyName>Extension</AssemblyName>
147+
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
148+
<OutputPath>bin\$(Configuration)</OutputPath>
149+
<GeneratePkgDefFile>false</GeneratePkgDefFile>
150+
<DeployExtension>False</DeployExtension>
151+
</PropertyGroup>
152+
<ItemGroup>
153+
<None Include='source.extension.vsixmanifest'/>
154+
</ItemGroup>
155+
<ItemGroup>
156+
{string.Join(Environment.NewLine, _files)}
157+
</ItemGroup>
158+
<ItemGroup>
159+
<PackageReference Include='Microsoft.VSSDK.BuildTools' Version='17.0.5232'>
160+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
161+
<PrivateAssets>all</PrivateAssets>
162+
</PackageReference>
163+
</ItemGroup>
164+
{string.Join(Environment.NewLine, _targets)}
165+
<Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' />
166+
<Import Project='$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets' Condition=""'$(VSToolsPath)' != ''"" />
167+
</Project>");
168+
}
169+
170+
private void WriteManifest()
171+
{
172+
File.WriteAllText(
173+
Path.Combine(_directory, "source.extension.vsixmanifest"),
174+
@"<?xml version='1.0' encoding='utf-8'?>
175+
<PackageManifest Version='2.0.0' xmlns='http://schemas.microsoft.com/developer/vsx-schema/2011' xmlns:d='http://schemas.microsoft.com/developer/vsx-schema-design/2011'>
176+
<Metadata>
177+
<Identity Id='VSSDK.TestExtension.5a9a059d-5738-41dc-9075-250890b4ef6f' Version='1.0' Language='en-US' Publisher='Mads Kristensen' />
178+
<DisplayName>VSSDK.TestExtension</DisplayName>
179+
<Description>Empty VSIX Project.</Description>
180+
</Metadata>
181+
<Installation>
182+
<InstallationTarget Id='Microsoft.VisualStudio.Community' Version='[16.0, 17.0)' />
183+
</Installation>
184+
<Dependencies>
185+
<Dependency Id='Microsoft.Framework.NDP' DisplayName='Microsoft .NET Framework' d:Source='Manual' Version='[4.5,)' />
186+
</Dependencies>
187+
<Prerequisites>
188+
<Prerequisite Id='Microsoft.VisualStudio.Component.CoreEditor' Version='[16.0,17.0)' DisplayName='Visual Studio core editor' />
189+
</Prerequisites>
190+
<Assets>
191+
<Asset Type='Microsoft.VisualStudio.VsPackage' d:Source='Project' d:ProjectName='%CurrentProject%' Path='|%CurrentProject%;PkgdefProjectOutputGroup|' />
192+
<Asset Type='Microsoft.VisualStudio.MefComponent' d:Source='Project' d:ProjectName='%CurrentProject%' Path='|%CurrentProject%|' />
193+
</Assets>
194+
</PackageManifest>");
195+
}
196+
197+
private static async Task DrainReaderAsync(StreamReader reader, Action<string> output)
198+
{
199+
string line;
200+
while ((line = await reader.ReadLineAsync()) is not null)
201+
{
202+
output(line);
203+
}
204+
}
205+
}
206+
}

0 commit comments

Comments
 (0)