Merge pull request #11 from Microsoft/develop
Create release for VS2017
This commit is contained in:
Коммит
846bcd07c7
|
@ -53,13 +53,28 @@ It's also recommended that, if your machine supports it, you install [Docker for
|
|||
|
||||
```batch
|
||||
REM You only need to build once unless updating the Dockerfile or files it copies.
|
||||
test\docker\build
|
||||
docker\build
|
||||
|
||||
REM This will automatically map build output. Defaults to Debug configuration. Pass -? for options.
|
||||
test\docker\test
|
||||
docker\test
|
||||
```
|
||||
|
||||
You can also run `test\docker\run.cmd` to start an interactive shell for exploratory testing.
|
||||
For a faster development process, you can run `docker\run -detach`, copy the container ID printed to the window, then subsequently run `docker\test -on <container id>` replacing `<container id>` with the container ID you copied previously. You can make changes to the test data and even rebuild the module and run this command again as frequently as you need. This is especially handy for quick turn around when debugging and fixing a problem.
|
||||
|
||||
To stop the container, run `docker stop <container id>`. If you did not pass `-keep` when you started the container it will be removed automatically.
|
||||
|
||||
### Debugging
|
||||
|
||||
You can also run `docker\run.cmd` to start an interactive shell for exploratory testing. If no other commands are passed when starting the container, the Visual Studio Remote Debugger will launch by default. Remote debugging services are discoverable on your private network.
|
||||
|
||||
1. Click *Debug -> Attach to Process*
|
||||
2. Change *Transport* to "Remote (no authentication)"
|
||||
3. Click *Find*
|
||||
4. Click *Select* on the container (host name will be the container name)
|
||||
5. Select "powershell" under *Available Processes*
|
||||
6. Click *Attach*
|
||||
|
||||
If you know the host name or IP address (depending on your network configuration for the container), you can type it into the *Qualifier* directory along with port 4020, e.g. "172.22.0.1:4020".
|
||||
|
||||
## Pull Requests
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ To install for all users, pass `AllUsers` instead of `CurrentUser`, or just leav
|
|||
You can also download the ZIP package from the [Releases][releases] page on this project site and extract to a directory named _VSSetup_ under a directory in your `$env:PSMODULEPATH`.
|
||||
|
||||
```powershell
|
||||
Expand-Archive VSSetup.zip "${env:USERPROFILE}\Documents\WindowsPowerShell\Modules\VSSetup"
|
||||
Expand-Archive VSSetup.zip "$([Environment]::GetFolderPath("MyDocuments"))\WindowsPowerShell\Modules\VSSetup"
|
||||
```
|
||||
|
||||
## Using
|
||||
|
|
|
@ -4,11 +4,24 @@
|
|||
# Require .NET Framework
|
||||
FROM microsoft/windowsservercore
|
||||
|
||||
# Download and register current query APIs
|
||||
# Download and install Remote Debugger
|
||||
SHELL ["powershell.exe", "-ExecutionPolicy", "Bypass", "-Command"]
|
||||
ENV API_VERSION="1.5.125-rc"
|
||||
RUN $ErrorActionPreference = 'Stop' ; \
|
||||
$VerbosePreference = 'Continue' ; \
|
||||
New-Item -Path C:\Downloads -Type Directory | Out-Null ; \
|
||||
Invoke-WebRequest -Uri 'https://go.microsoft.com/fwlink/?LinkId=615470&clcid=0x409' -OutFile C:\Downloads\rtools_setup_x64.exe ; \
|
||||
Start-Process -Wait -FilePath C:\Downloads\rtools_setup_x64.exe -ArgumentList '-q'
|
||||
|
||||
# Configure Remote Debugger
|
||||
EXPOSE 3702 4020 4021
|
||||
RUN $ErrorActionPreference = 'Stop' ; \
|
||||
$VerbosePreference = 'Continue' ; \
|
||||
Start-Process -Wait -FilePath 'C:\Program Files\Microsoft Visual Studio 14.0\Common7\IDE\Remote Debugger\x64\msvsmon.exe' -ArgumentList '/prepcomputer', '/private', '/quiet'
|
||||
|
||||
# Download and register current query APIs
|
||||
ENV API_VERSION="1.8.24"
|
||||
RUN $ErrorActionPreference = 'Stop' ; \
|
||||
$VerbosePreference = 'Continue' ; \
|
||||
Invoke-WebRequest -Uri "https://www.nuget.org/api/v2/package/Microsoft.VisualStudio.Setup.Configuration.Native/${env:API_VERSION}" -OutFile C:\Downloads\Microsoft.VisualStudio.Setup.Configuration.Native.zip ; \
|
||||
Expand-Archive -Path C:\Downloads\Microsoft.VisualStudio.Setup.Configuration.Native.zip -DestinationPath C:\Downloads\Microsoft.VisualStudio.Setup.Configuration.Native ; \
|
||||
C:\Windows\System32\regsvr32.exe /s C:\Downloads\Microsoft.VisualStudio.Setup.Configuration.Native\tools\x64\Microsoft.VisualStudio.Setup.Configuration.Native.dll ; \
|
||||
|
@ -16,7 +29,10 @@ RUN $ErrorActionPreference = 'Stop' ; \
|
|||
|
||||
# Install latest version of Pester for integration testing
|
||||
RUN $ErrorActionPreference = 'Stop' ; \
|
||||
$VerbosePreference = 'Continue' ; \
|
||||
Install-PackageProvider -Name nuget -MinimumVersion 2.8.5.201 -Force ; \
|
||||
Install-Module -Name Pester -Scope CurrentUser -SkipPublisherCheck -Force
|
||||
|
||||
# Start Remote Debugger if no other command is passed to PowerShell
|
||||
ENTRYPOINT ["powershell.exe", "-ExecutionPolicy", "Unrestricted"]
|
||||
CMD ["-NoExit", "-Command", "& 'C:\\Program Files\\Microsoft Visual Studio 14.0\\Common7\\IDE\\Remote Debugger\\x64\\msvsmon.exe' /silent /noauth /anyuser"]
|
|
@ -73,6 +73,13 @@
|
|||
"logFilePath": "C:\\TEMP\\dd_setup_201601180315_003_Microsoft.VisualStudio.Workload.Office_errors.log",
|
||||
"description": "Failed to install Microsoft.VisualStudio.Workload.Office"
|
||||
}
|
||||
],
|
||||
"skippedPackages": [
|
||||
{
|
||||
"id": "Microsoft.VisualStudio.Component.Sharepoint.Tools",
|
||||
"version": "15.0.260009.0",
|
||||
"type": "Component"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -62,6 +62,13 @@ Describe 'Get-VSSetupInstance' {
|
|||
$instance.InstanceId | Should Be 1
|
||||
$instance.InstallationVersion | Should Be '15.0.26116.0'
|
||||
}
|
||||
|
||||
It 'Does not contain errors' {
|
||||
$instance = Get-VSSetupInstance 'C:\VS\Community'
|
||||
|
||||
$instance.State -band 'NoErrors' | Should Be 'NoErrors'
|
||||
$instance.Errors | Should Be $null
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Contains custom properties' {
|
||||
|
@ -86,4 +93,23 @@ Describe 'Get-VSSetupInstance' {
|
|||
$instance.Properties.Count | Should Be 0
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Contains errors' {
|
||||
$instance = Get-VSSetupInstance C:\VS\Enterprise
|
||||
|
||||
It 'Contains errors' {
|
||||
$instance.State -band 'NoErrors' | Should Be 0
|
||||
$instance.Errors | Should Not Be $null
|
||||
}
|
||||
|
||||
It 'Contains failed packages' {
|
||||
$instance.Errors.FailedPackages.Count | Should Be 1
|
||||
$instance.Errors.FailedPackages[0].Id | Should Be 'Microsoft.VisualStudio.Workload.Office'
|
||||
}
|
||||
|
||||
It 'Contains skipped packages' {
|
||||
$instance.Errors.SkippedPackages.Count | Should Be 1
|
||||
$instance.Errors.SkippedPackages[0].Id | Should Be 'Microsoft.VisualStudio.Component.Sharepoint.Tools'
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,10 +8,11 @@ setlocal
|
|||
if "%script%"=="" set script=%~nx0
|
||||
|
||||
set projectDir=%~dp0
|
||||
set solutionDir=%projectDir:~0,-12%
|
||||
set solutionDir=%projectDir:~0,-7%
|
||||
|
||||
set configuration=Debug
|
||||
set name=vssetup/test
|
||||
set mode=-it
|
||||
|
||||
:parse
|
||||
if "%1"=="" goto :parse_end
|
||||
|
@ -20,6 +21,10 @@ if /i "%1"=="-name" set name=%2& shift& shift& goto :parse
|
|||
if /i "%1"=="/name" set name=%2& shift& shift& goto :parse
|
||||
if /i "%1"=="-configuration" set configuration=%2& shift& shift& goto :parse
|
||||
if /i "%1"=="/configuration" set configuration=%2& shift& shift& goto :parse
|
||||
if /i "%1"=="-detach" set mode=-d& shift& goto :parse
|
||||
if /i "%1"=="/detach" set mode=-d& shift& goto :parse
|
||||
if /i "%1"=="-on" set id=%2& shift& shift& goto :parse
|
||||
if /i "%1"=="/on" set id=%2& shift& shift& goto :parse
|
||||
if /i "%1"=="-network" set params=%params% --network "%2"& shift& shift& goto :parse
|
||||
if /i "%1"=="/network" set params=%params% --network "%2"& shift& shift& goto :parse
|
||||
if /i "%1"=="-keep" set keep=1& shift& goto :parse
|
||||
|
@ -38,19 +43,26 @@ goto :help
|
|||
if "%keep%"=="" set params=%params% --rm
|
||||
|
||||
set outputPath=%solutionDir%src\VSSetup.PowerShell\bin\%configuration%
|
||||
set volumes=-v "%projectDir%Instances:C:\ProgramData\Microsoft\VisualStudio\Packages\_Instances"
|
||||
set volumes=-v "%outputPath%:C:\Users\ContainerAdministrator\Documents\WindowsPowerShell\Modules\VSSetup:ro"
|
||||
set volumes=%volumes% -v "%projectDir%Instances:C:\ProgramData\Microsoft\VisualStudio\Packages\_Instances:ro"
|
||||
set volumes=%volumes% -v C:\VS\Community
|
||||
set volumes=%volumes% -v C:\VS\Professional
|
||||
set volumes=%volumes% -v C:\VS\Enterprise
|
||||
set volumes=%volumes% -v C:\BuildTools
|
||||
set volumes=%volumes% -v "%projectDir%Tests:C:\Tests"
|
||||
set volumes=%volumes% -v "%outputPath%:C:\Users\ContainerAdministrator\Documents\WindowsPowerShell\Modules\VSSetup"
|
||||
|
||||
@echo on
|
||||
docker run -it %volumes%%params% %name% %args%
|
||||
if "%id%"=="" (
|
||||
REM Uses the ENTRYPOINT declaration in the Dockerfile
|
||||
set cmd=docker run %mode% %volumes%%params% %name% %args%
|
||||
) else (
|
||||
REM Keep in sync with the ENTRYPOINT in the Dockerfile
|
||||
set cmd=docker exec %mode% %id% powershell.exe -ExecutionPolicy Unrestricted %args%
|
||||
)
|
||||
|
||||
echo %cmd%
|
||||
call %cmd%
|
||||
@if errorlevel 1 exit /b %ERRORLEVEL%
|
||||
|
||||
@echo off
|
||||
echo.
|
||||
goto :EOF
|
||||
|
||||
|
@ -63,11 +75,13 @@ echo.
|
|||
echo %usage%
|
||||
echo.
|
||||
echo Options:
|
||||
echo -name Image name. Defaults to vssetup/test.
|
||||
echo -configuration The build configuration to map. Defaults to Debug.
|
||||
echo -network External network name. Defaults to discovered transparent network.
|
||||
echo -keep Do not delete the container after exiting.
|
||||
echo -? Displays this help message.
|
||||
echo -name value Image name. Defaults to vssetup/test.
|
||||
echo -configuration value The build configuration to map. Defaults to Debug.
|
||||
echo -detach Detach from the container and show the ID.
|
||||
echo -on value Run command on specified container ID.
|
||||
echo -network value External network name. Defaults to discovered transparent network.
|
||||
echo -keep Do not delete the container after exiting.
|
||||
echo -? Displays this help message.
|
||||
echo.
|
||||
if "%noargs%"=="" (
|
||||
echo Arguments:
|
|
@ -0,0 +1,38 @@
|
|||
// <copyright file="Errors.cs" company="Microsoft Corporation">
|
||||
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE.txt in the project root for license information.
|
||||
// </copyright>
|
||||
|
||||
namespace Microsoft.VisualStudio.Setup
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using Configuration;
|
||||
|
||||
/// <summary>
|
||||
/// Represents errors that occurred during the last install operation.
|
||||
/// </summary>
|
||||
public class Errors
|
||||
{
|
||||
private readonly IList<FailedPackageReference> failedPackages;
|
||||
private readonly IList<PackageReference> skippedPackages;
|
||||
|
||||
internal Errors(ISetupErrorState errors)
|
||||
{
|
||||
Validate.NotNull(errors, nameof(errors));
|
||||
|
||||
FailedPackages = Utilities.TrySetCollection(ref failedPackages, nameof(FailedPackages), errors.GetFailedPackages, PackageReferenceFactory.Create);
|
||||
SkippedPackages = Utilities.TrySetCollection(ref skippedPackages, nameof(SkippedPackages), errors.GetSkippedPackages, PackageReferenceFactory.Create);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of references to packages that failed to install.
|
||||
/// </summary>
|
||||
public ReadOnlyCollection<FailedPackageReference> FailedPackages { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of references to packages skipped because other packages in their parent workload or components failed.
|
||||
/// </summary>
|
||||
public ReadOnlyCollection<PackageReference> SkippedPackages { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
// <copyright file="FailedPackageReference.cs" company="Microsoft Corporation">
|
||||
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE.txt in the project root for license information.
|
||||
// </copyright>
|
||||
|
||||
namespace Microsoft.VisualStudio.Setup
|
||||
{
|
||||
using Configuration;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a failed package reference.
|
||||
/// </summary>
|
||||
public class FailedPackageReference : PackageReference
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FailedPackageReference"/> class.
|
||||
/// </summary>
|
||||
/// <param name="reference">The <see cref="ISetupFailedPackageReference"/> to adapt.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="reference"/> is null.</exception>
|
||||
internal FailedPackageReference(ISetupFailedPackageReference reference)
|
||||
: base(reference)
|
||||
{
|
||||
Validate.NotNull(reference, nameof(reference));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,6 @@ namespace Microsoft.VisualStudio.Setup
|
|||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using Configuration;
|
||||
|
||||
/// <summary>
|
||||
|
@ -58,75 +57,101 @@ namespace Microsoft.VisualStudio.Setup
|
|||
// The instance ID is required, but then try to set other properties to release the COM object and its resources ASAP.
|
||||
InstanceId = instance.GetInstanceId();
|
||||
|
||||
TrySet(ref installationName, nameof(InstallationName), instance.GetInstallationName);
|
||||
TrySet(ref installationPath, nameof(InstallationPath), instance.GetInstallationPath);
|
||||
TrySet(ref installationVersion, nameof(InstallationVersion), () =>
|
||||
{
|
||||
Version version;
|
||||
|
||||
var versionString = instance.GetInstallationVersion();
|
||||
if (Version.TryParse(versionString, out version))
|
||||
Utilities.TrySet(ref installationName, nameof(InstallationName), instance.GetInstallationName, OnError);
|
||||
Utilities.TrySet(ref installationPath, nameof(InstallationPath), instance.GetInstallationPath, OnError);
|
||||
Utilities.TrySet(
|
||||
ref installationVersion,
|
||||
nameof(InstallationVersion),
|
||||
() =>
|
||||
{
|
||||
return version.Normalize();
|
||||
}
|
||||
Version version;
|
||||
|
||||
return null;
|
||||
});
|
||||
var versionString = instance.GetInstallationVersion();
|
||||
if (Version.TryParse(versionString, out version))
|
||||
{
|
||||
return version.Normalize();
|
||||
}
|
||||
|
||||
TrySet(ref installDate, nameof(InstallDate), () =>
|
||||
{
|
||||
var ft = instance.GetInstallDate();
|
||||
var l = ((long)ft.dwHighDateTime << 32) + ft.dwLowDateTime;
|
||||
return null;
|
||||
},
|
||||
OnError);
|
||||
|
||||
return DateTime.FromFileTime(l);
|
||||
});
|
||||
Utilities.TrySet(
|
||||
ref installDate,
|
||||
nameof(InstallDate),
|
||||
() =>
|
||||
{
|
||||
var ft = instance.GetInstallDate();
|
||||
var l = ((long)ft.dwHighDateTime << 32) + ft.dwLowDateTime;
|
||||
|
||||
TrySet(ref state, nameof(State), instance.GetState);
|
||||
return DateTime.FromFileTime(l);
|
||||
},
|
||||
OnError);
|
||||
|
||||
Utilities.TrySet(ref state, nameof(State), instance.GetState, OnError);
|
||||
|
||||
var lcid = CultureInfo.CurrentUICulture.LCID;
|
||||
TrySet(ref displayName, nameof(DisplayName), () =>
|
||||
{
|
||||
return instance.GetDisplayName(lcid);
|
||||
});
|
||||
|
||||
TrySet(ref description, nameof(Description), () =>
|
||||
{
|
||||
return instance.GetDescription(lcid);
|
||||
});
|
||||
|
||||
TrySet(ref productPath, nameof(ProductPath), () =>
|
||||
{
|
||||
var path = instance.GetProductPath();
|
||||
return instance.ResolvePath(path);
|
||||
});
|
||||
|
||||
TrySet(ref product, nameof(Product), () =>
|
||||
{
|
||||
var reference = instance.GetProduct();
|
||||
if (reference != null)
|
||||
Utilities.TrySet(
|
||||
ref displayName,
|
||||
nameof(DisplayName),
|
||||
() =>
|
||||
{
|
||||
return new PackageReference(reference);
|
||||
}
|
||||
return instance.GetDisplayName(lcid);
|
||||
},
|
||||
OnError);
|
||||
|
||||
return null;
|
||||
});
|
||||
Utilities.TrySet(
|
||||
ref description,
|
||||
nameof(Description),
|
||||
() =>
|
||||
{
|
||||
return instance.GetDescription(lcid);
|
||||
},
|
||||
OnError);
|
||||
|
||||
TrySet(ref packages, nameof(Packages), () =>
|
||||
Utilities.TrySet(
|
||||
ref productPath,
|
||||
nameof(ProductPath),
|
||||
() =>
|
||||
{
|
||||
var path = instance.GetProductPath();
|
||||
return instance.ResolvePath(path);
|
||||
},
|
||||
OnError);
|
||||
|
||||
Utilities.TrySet(
|
||||
ref product,
|
||||
nameof(Product),
|
||||
() =>
|
||||
{
|
||||
var reference = instance.GetProduct();
|
||||
if (reference != null)
|
||||
{
|
||||
return new PackageReference(reference);
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
OnError);
|
||||
|
||||
Packages = Utilities.TrySetCollection(ref packages, nameof(Packages), instance.GetPackages, PackageReferenceFactory.Create, OnError);
|
||||
|
||||
var errors = instance.GetErrors();
|
||||
if (errors != null)
|
||||
{
|
||||
return new List<PackageReference>(GetPackages(instance));
|
||||
});
|
||||
|
||||
if (packages != null && packages.Any())
|
||||
{
|
||||
Packages = new ReadOnlyCollection<PackageReference>(packages);
|
||||
Errors = new Errors(errors);
|
||||
}
|
||||
|
||||
TrySet(ref properties, nameof(Properties), () =>
|
||||
{
|
||||
var properties = instance.GetProperties();
|
||||
return properties?.GetNames()
|
||||
.ToDictionary(name => name.ToPascalCase(), name => properties.GetValue(name), StringComparer.OrdinalIgnoreCase);
|
||||
});
|
||||
Utilities.TrySet(
|
||||
ref properties,
|
||||
nameof(Properties),
|
||||
() =>
|
||||
{
|
||||
var properties = instance.GetProperties();
|
||||
return properties?.GetNames()
|
||||
.ToDictionary(name => name.ToPascalCase(), name => properties.GetValue(name), StringComparer.OrdinalIgnoreCase);
|
||||
},
|
||||
OnError);
|
||||
|
||||
if (properties != null)
|
||||
{
|
||||
|
@ -138,9 +163,9 @@ namespace Microsoft.VisualStudio.Setup
|
|||
Properties = ReadOnlyDictionary<string, object>.Empty;
|
||||
}
|
||||
|
||||
TrySet(ref enginePath, nameof(EnginePath), instance.GetEnginePath);
|
||||
TrySet(ref isComplete, nameof(IsComplete), instance.IsComplete);
|
||||
TrySet(ref isLaunchable, nameof(IsLaunchable), instance.IsLaunchable);
|
||||
Utilities.TrySet(ref enginePath, nameof(EnginePath), instance.GetEnginePath, OnError);
|
||||
Utilities.TrySet(ref isComplete, nameof(IsComplete), instance.IsComplete, OnError);
|
||||
Utilities.TrySet(ref isLaunchable, nameof(IsLaunchable), instance.IsLaunchable, OnError);
|
||||
|
||||
// Get all properties of the instance not explicitly declared.
|
||||
var store = (ISetupPropertyStore)instance;
|
||||
|
@ -209,6 +234,11 @@ namespace Microsoft.VisualStudio.Setup
|
|||
/// </summary>
|
||||
public IDictionary<string, object> Properties { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets errors that occurred during the last install (if any).
|
||||
/// </summary>
|
||||
public Errors Errors { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the engine that installed the instance.
|
||||
/// </summary>
|
||||
|
@ -229,31 +259,9 @@ namespace Microsoft.VisualStudio.Setup
|
|||
/// </summary>
|
||||
internal IDictionary<string, object> AdditionalProperties { get; }
|
||||
|
||||
private static IEnumerable<PackageReference> GetPackages(ISetupInstance2 instance)
|
||||
private void OnError(string propertyName)
|
||||
{
|
||||
var references = instance.GetPackages();
|
||||
if (references != null)
|
||||
{
|
||||
foreach (var reference in instance.GetPackages())
|
||||
{
|
||||
if (reference != null)
|
||||
{
|
||||
yield return new PackageReference(reference);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void TrySet<T>(ref T property, string propertyName, Func<T> action)
|
||||
{
|
||||
try
|
||||
{
|
||||
property = action.Invoke();
|
||||
}
|
||||
catch (COMException ex) when (ex.ErrorCode == NativeMethods.E_NOTFOUND)
|
||||
{
|
||||
Trace.WriteLine($@"Instance: property ""{propertyName}"" not found on instance ""{InstanceId}"".");
|
||||
}
|
||||
Trace.WriteLine($@"Instance: property ""{propertyName}"" not found on instance ""{InstanceId}"".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
namespace Microsoft.VisualStudio.Setup
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using Configuration;
|
||||
|
||||
/// <summary>
|
||||
|
@ -34,7 +32,7 @@ namespace Microsoft.VisualStudio.Setup
|
|||
// The package reference ID is required, but then try to set other properties to release the COM object and its resources ASAP.
|
||||
Id = reference.GetId();
|
||||
|
||||
TrySet(ref version, nameof(Version), () =>
|
||||
Utilities.TrySet(ref version, nameof(Version), () =>
|
||||
{
|
||||
Version version;
|
||||
|
||||
|
@ -47,11 +45,11 @@ namespace Microsoft.VisualStudio.Setup
|
|||
return null;
|
||||
});
|
||||
|
||||
TrySet(ref chip, nameof(Chip), reference.GetChip);
|
||||
TrySet(ref branch, nameof(Branch), reference.GetBranch);
|
||||
TrySet(ref type, nameof(Type), reference.GetType);
|
||||
TrySet(ref isExtension, nameof(IsExtension), reference.GetIsExtension);
|
||||
TrySet(ref uniqueId, nameof(UniqueId), reference.GetUniqueId);
|
||||
Utilities.TrySet(ref chip, nameof(Chip), reference.GetChip);
|
||||
Utilities.TrySet(ref branch, nameof(Branch), reference.GetBranch);
|
||||
Utilities.TrySet(ref type, nameof(Type), reference.GetType);
|
||||
Utilities.TrySet(ref isExtension, nameof(IsExtension), reference.GetIsExtension);
|
||||
Utilities.TrySet(ref uniqueId, nameof(UniqueId), reference.GetUniqueId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -97,17 +95,5 @@ namespace Microsoft.VisualStudio.Setup
|
|||
{
|
||||
return uniqueId ?? base.ToString();
|
||||
}
|
||||
|
||||
private void TrySet<T>(ref T property, string propertyName, Func<T> action)
|
||||
{
|
||||
try
|
||||
{
|
||||
property = action.Invoke();
|
||||
}
|
||||
catch (COMException ex) when (ex.ErrorCode == NativeMethods.E_NOTFOUND)
|
||||
{
|
||||
Trace.WriteLine($@"Instance: property ""{propertyName}"" not found on package reference ""{Id}"".");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
// <copyright file="PackageReferenceFactory.cs" company="Microsoft Corporation">
|
||||
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE.txt in the project root for license information.
|
||||
// </copyright>
|
||||
|
||||
namespace Microsoft.VisualStudio.Setup
|
||||
{
|
||||
using Configuration;
|
||||
|
||||
/// <summary>
|
||||
/// Creates <see cref="PackageReference"/> or derivative classes.
|
||||
/// </summary>
|
||||
internal static class PackageReferenceFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="PackageReference"/> from an <see cref="ISetupPackageReference"/>.
|
||||
/// </summary>
|
||||
/// <param name="package">The <see cref="ISetupPackageReference"/> to wrap.</param>
|
||||
/// <returns>A <see cref="PackageReference"/> that wraps the <see cref="ISetupPackageReference"/>.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="package"/> is null.</exception>
|
||||
public static PackageReference Create(ISetupPackageReference package)
|
||||
{
|
||||
Validate.NotNull(package, nameof(package));
|
||||
|
||||
return new PackageReference(package);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="FailedPackageReference"/> from an <see cref="ISetupFailedPackageReference"/>.
|
||||
/// </summary>
|
||||
/// <param name="package">The <see cref="ISetupFailedPackageReference"/> to wrap.</param>
|
||||
/// <returns>A <see cref="FailedPackageReference"/> that wraps the <see cref="ISetupFailedPackageReference"/>.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="package"/> is null.</exception>
|
||||
public static FailedPackageReference Create(ISetupFailedPackageReference package)
|
||||
{
|
||||
Validate.NotNull(package, nameof(package));
|
||||
|
||||
return new FailedPackageReference(package);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
// <copyright file="Utilities.cs" company="Microsoft Corporation">
|
||||
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE.txt in the project root for license information.
|
||||
// </copyright>
|
||||
|
||||
namespace Microsoft.VisualStudio.Setup
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using Configuration;
|
||||
|
||||
/// <summary>
|
||||
/// Utility methods.
|
||||
/// </summary>
|
||||
internal static class Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets an empty <see cref="ReadOnlyCollection{T}"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of element.</typeparam>
|
||||
/// <returns>An empty <see cref="ReadOnlyCollection{T}"/>.</returns>
|
||||
public static ReadOnlyCollection<T> EmptyReadOnlyCollection<T>()
|
||||
{
|
||||
return EmptyReadOnlyCollectionContainer<T>.Instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an <see cref="IEnumerable{T}"/> of adapted packages from type <typeparamref name="T"/> to type <typeparamref name="R"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the package reference to adapt.</typeparam>
|
||||
/// <typeparam name="R">The adapted type of the package reference.</typeparam>
|
||||
/// <param name="action">A method that gets an <see cref="IEnumerable{T}"/> of package reference of type <typeparamref name="T"/>.</param>
|
||||
/// <param name="creator">A method that creates an adapted reference of type <typeparamref name="R"/>.</param>
|
||||
/// <returns>An <see cref="IEnumerable{T}"/> of adapted packages. This enumeration may yield zero results.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="action"/> or <paramref name="creator"/> is null.</exception>
|
||||
public static IEnumerable<R> GetAdaptedPackages<T, R>(Func<IEnumerable<T>> action, Func<T, R> creator)
|
||||
where T : ISetupPackageReference
|
||||
where R : PackageReference
|
||||
{
|
||||
Validate.NotNull(action, nameof(action));
|
||||
Validate.NotNull(creator, nameof(creator));
|
||||
|
||||
return YieldAdaptedPackages(action, creator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the given <paramref name="property"/> if the <paramref name="action"/> does not throw a <see cref="COMException"/> for 0x80070490.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the property to set.</typeparam>
|
||||
/// <param name="property">A reference to the property to set.</param>
|
||||
/// <param name="propertyName">The name of the property for diagnostic purposes.</param>
|
||||
/// <param name="action">A method that returns the value of the property to set.</param>
|
||||
/// <param name="error">Optional error handler that accepts the name of the property.</param>
|
||||
/// <exception cref="ArgumentException"><paramref name="propertyName"/> is an empty string.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="propertyName"/> or <paramref name="action"/> is null.</exception>
|
||||
public static void TrySet<T>(ref T property, string propertyName, Func<T> action, Action<string> error = null)
|
||||
{
|
||||
Validate.NotNullOrEmpty(propertyName, nameof(propertyName));
|
||||
Validate.NotNull(action, nameof(action));
|
||||
|
||||
try
|
||||
{
|
||||
property = action.Invoke();
|
||||
}
|
||||
catch (COMException ex) when (ex.ErrorCode == NativeMethods.E_NOTFOUND)
|
||||
{
|
||||
error?.Invoke(propertyName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the given package reference collection <paramref name="property"/> if the <paramref name="action"/> does not throw a <see cref="COMException"/> for 0x80070490.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the package reference to adapt.</typeparam>
|
||||
/// <typeparam name="R">The adapted type of the package reference.</typeparam>
|
||||
/// <param name="property">A reference to the property to set.</param>
|
||||
/// <param name="propertyName">The name of the property for diagnostic purposes.</param>
|
||||
/// <param name="action">A method that returns the value of the property to set.</param>
|
||||
/// <param name="creator">A method that creates the adapted reference type.</param>
|
||||
/// <param name="error">Optional error handler that accepts the name of the property.</param>
|
||||
/// <returns>A <see cref="ReadOnlyCollection{T}"/> containing the adapted package references. This collection may be empty.</returns>
|
||||
/// <exception cref="ArgumentException"><paramref name="propertyName"/> is an empty string.</exception>
|
||||
/// <exception cref="ArgumentNullException">One or more parameters is null.</exception>
|
||||
public static ReadOnlyCollection<R> TrySetCollection<T, R>(
|
||||
ref IList<R> property,
|
||||
string propertyName,
|
||||
Func<IEnumerable<T>> action,
|
||||
Func<T, R> creator,
|
||||
Action<string> error = null)
|
||||
where T : ISetupPackageReference
|
||||
where R : PackageReference
|
||||
{
|
||||
Validate.NotNullOrEmpty(propertyName, nameof(propertyName));
|
||||
Validate.NotNull(action, nameof(action));
|
||||
Validate.NotNull(creator, nameof(creator));
|
||||
|
||||
var packages = GetAdaptedPackages(action, creator);
|
||||
TrySet(ref property, propertyName, packages.ToList, error);
|
||||
|
||||
if (property != null && property.Any())
|
||||
{
|
||||
return new ReadOnlyCollection<R>(property);
|
||||
}
|
||||
|
||||
return EmptyReadOnlyCollection<R>();
|
||||
}
|
||||
|
||||
private static IEnumerable<R> YieldAdaptedPackages<T, R>(Func<IEnumerable<T>> action, Func<T, R> creator)
|
||||
{
|
||||
var references = action?.Invoke();
|
||||
if (references != null)
|
||||
{
|
||||
foreach (var reference in references)
|
||||
{
|
||||
if (reference != null)
|
||||
{
|
||||
yield return creator(reference);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class EmptyReadOnlyCollectionContainer<T>
|
||||
{
|
||||
public static readonly ReadOnlyCollection<T> Instance = new ReadOnlyCollection<T>(new T[0]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,7 +35,7 @@
|
|||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.Setup.Configuration.Interop, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Interop.1.5.125-rc\lib\net35\Microsoft.VisualStudio.Setup.Configuration.Interop.dll</HintPath>
|
||||
<HintPath>..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Interop.1.8.24\lib\net35\Microsoft.VisualStudio.Setup.Configuration.Interop.dll</HintPath>
|
||||
<EmbedInteropTypes>True</EmbedInteropTypes>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
|
@ -47,10 +47,13 @@
|
|||
<Reference Include="Microsoft.CSharp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Errors.cs" />
|
||||
<Compile Include="Extensions.cs" />
|
||||
<Compile Include="FailedPackageReference.cs" />
|
||||
<Compile Include="Instance.cs" />
|
||||
<Compile Include="NativeMethods.cs" />
|
||||
<Compile Include="PackageReference.cs" />
|
||||
<Compile Include="PackageReferenceFactory.cs" />
|
||||
<Compile Include="QueryFactory.cs" />
|
||||
<Compile Include="PowerShell\Extensions.cs" />
|
||||
<Compile Include="PowerShell\GetInstanceCommand.cs" />
|
||||
|
@ -64,6 +67,7 @@
|
|||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ReadOnlyDictionary.cs" />
|
||||
<Compile Include="Utilities.cs" />
|
||||
<Compile Include="Validate.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.PowerShell.3.ReferenceAssemblies" version="1.0.0" targetFramework="net40-client" />
|
||||
<package id="Microsoft.VisualStudio.Setup.Configuration.Interop" version="1.5.125-rc" targetFramework="net40-client" developmentDependency="true" />
|
||||
<package id="Microsoft.VisualStudio.Setup.Configuration.Interop" version="1.8.24" targetFramework="net40-client" developmentDependency="true" />
|
||||
<package id="Nerdbank.GitVersioning" version="1.5.62" targetFramework="net40-client" developmentDependency="true" />
|
||||
<package id="NuProj.Common" version="0.11.14-beta" targetFramework="net40-client" developmentDependency="true" />
|
||||
<package id="StyleCop.Analyzers" version="1.0.0" targetFramework="net40-client" developmentDependency="true" />
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
// <copyright file="ErrorsTests.cs" company="Microsoft Corporation">
|
||||
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE.txt in the project root for license information.
|
||||
// </copyright>
|
||||
|
||||
namespace Microsoft.VisualStudio.Setup
|
||||
{
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Configuration;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
public class ErrorsTests
|
||||
{
|
||||
[Fact]
|
||||
public void New_Errors_Null_Throws()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>("errors", () => new Errors(null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void New_Missing_FailedPackages()
|
||||
{
|
||||
var errors = new Mock<ISetupErrorState>();
|
||||
errors.Setup(x => x.GetFailedPackages()).Throws(new COMException("Not found", NativeMethods.E_NOTFOUND));
|
||||
|
||||
var sut = new Errors(errors.Object);
|
||||
|
||||
Assert.Empty(sut.FailedPackages);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void New_FailedPackages()
|
||||
{
|
||||
var a = new Mock<ISetupFailedPackageReference>();
|
||||
a.As<ISetupPackageReference>().Setup(x => x.GetId()).Returns("a");
|
||||
|
||||
var b = new Mock<ISetupFailedPackageReference>();
|
||||
b.As<ISetupPackageReference>().Setup(x => x.GetId()).Returns("b");
|
||||
|
||||
var errors = new Mock<ISetupErrorState>();
|
||||
errors.Setup(x => x.GetFailedPackages()).Returns(new[] { a.Object, b.Object });
|
||||
|
||||
var sut = new Errors(errors.Object);
|
||||
|
||||
Assert.NotNull(sut.FailedPackages);
|
||||
Assert.Collection(
|
||||
sut.FailedPackages,
|
||||
x => Assert.Equal("a", x.Id),
|
||||
x => Assert.Equal("b", x.Id));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void New_Missing_SkippedPackages()
|
||||
{
|
||||
var errors = new Mock<ISetupErrorState>();
|
||||
errors.Setup(x => x.GetSkippedPackages()).Throws(new COMException("Not found", NativeMethods.E_NOTFOUND));
|
||||
|
||||
var sut = new Errors(errors.Object);
|
||||
|
||||
Assert.Empty(sut.SkippedPackages);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void New_SkippedPackages()
|
||||
{
|
||||
var skippedPackages = new[]
|
||||
{
|
||||
Mock.Of<ISetupPackageReference>(x => x.GetId() == "a"),
|
||||
Mock.Of<ISetupPackageReference>(x => x.GetId() == "b"),
|
||||
};
|
||||
|
||||
var errors = new Mock<ISetupErrorState>();
|
||||
errors.Setup(x => x.GetSkippedPackages()).Returns(skippedPackages);
|
||||
|
||||
var sut = new Errors(errors.Object);
|
||||
|
||||
Assert.NotNull(sut.SkippedPackages);
|
||||
Assert.Collection(
|
||||
sut.SkippedPackages,
|
||||
x => Assert.Equal("a", x.Id),
|
||||
x => Assert.Equal("b", x.Id));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
// <copyright file="FailedPackageReferenceTests.cs" company="Microsoft Corporation">
|
||||
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE.txt in the project root for license information.
|
||||
// </copyright>
|
||||
|
||||
namespace Microsoft.VisualStudio.Setup
|
||||
{
|
||||
using System;
|
||||
using Configuration;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
public class FailedPackageReferenceTests
|
||||
{
|
||||
[Fact]
|
||||
public void New_Reference_Null_Throws()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>("reference", () => new FailedPackageReference(null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void New_Valid()
|
||||
{
|
||||
var reference = new Mock<ISetupFailedPackageReference>();
|
||||
reference.As<ISetupPackageReference>().Setup(x => x.GetId()).Returns("a");
|
||||
|
||||
var sut = new FailedPackageReference(reference.Object);
|
||||
Assert.Equal("a", sut.Id);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -106,7 +106,7 @@ namespace Microsoft.VisualStudio.Setup
|
|||
instance.Setup(x => x.GetInstanceId()).Returns("test");
|
||||
|
||||
var sut = new Instance(instance.Object);
|
||||
Assert.Null(sut.Packages);
|
||||
Assert.Empty(sut.Packages);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -116,7 +116,7 @@ namespace Microsoft.VisualStudio.Setup
|
|||
instance.Setup(x => x.GetPackages()).Returns(Enumerable.Empty<ISetupPackageReference>().ToArray());
|
||||
|
||||
var sut = new Instance(instance.Object);
|
||||
Assert.Null(sut.Packages);
|
||||
Assert.Empty(sut.Packages);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -152,5 +152,63 @@ namespace Microsoft.VisualStudio.Setup
|
|||
Assert.Equal(2, sut.AdditionalProperties["B"]);
|
||||
Assert.Equal(2, sut.AdditionalProperties["b"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void New_No_Errors()
|
||||
{
|
||||
instance.Setup(x => x.GetInstanceId()).Returns("test");
|
||||
|
||||
var sut = new Instance(instance.Object);
|
||||
|
||||
Assert.Null(sut.Errors);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void New_FailedPackages()
|
||||
{
|
||||
var a = new Mock<ISetupFailedPackageReference>();
|
||||
a.As<ISetupPackageReference>().Setup(x => x.GetId()).Returns("a");
|
||||
|
||||
var b = new Mock<ISetupFailedPackageReference>();
|
||||
b.As<ISetupPackageReference>().Setup(x => x.GetId()).Returns("b");
|
||||
|
||||
var errors = new Mock<ISetupErrorState>();
|
||||
errors.Setup(x => x.GetFailedPackages()).Returns(new[] { a.Object, b.Object });
|
||||
|
||||
instance.Setup(x => x.GetInstanceId()).Returns("test");
|
||||
instance.Setup(x => x.GetErrors()).Returns(errors.Object);
|
||||
|
||||
var sut = new Instance(instance.Object);
|
||||
|
||||
Assert.NotNull(sut.Errors);
|
||||
Assert.Collection(
|
||||
sut.Errors.FailedPackages,
|
||||
x => Assert.Equal("a", x.Id),
|
||||
x => Assert.Equal("b", x.Id));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void New_SkippedPackages()
|
||||
{
|
||||
var skippedPackages = new[]
|
||||
{
|
||||
Mock.Of<ISetupPackageReference>(x => x.GetId() == "a"),
|
||||
Mock.Of<ISetupPackageReference>(x => x.GetId() == "b"),
|
||||
};
|
||||
|
||||
var errors = new Mock<ISetupErrorState>();
|
||||
errors.Setup(x => x.GetSkippedPackages()).Returns(skippedPackages);
|
||||
|
||||
instance.Setup(x => x.GetInstanceId()).Returns("test");
|
||||
instance.Setup(x => x.GetErrors()).Returns(errors.Object);
|
||||
|
||||
var sut = new Instance(instance.Object);
|
||||
|
||||
Assert.NotNull(sut.Errors);
|
||||
Assert.Collection(
|
||||
sut.Errors.SkippedPackages,
|
||||
x => Assert.Equal("a", x.Id),
|
||||
x => Assert.Equal("b", x.Id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
// <copyright file="PackageReferenceFactoryTests.cs" company="Microsoft Corporation">
|
||||
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE.txt in the project root for license information.
|
||||
// </copyright>
|
||||
|
||||
namespace Microsoft.VisualStudio.Setup
|
||||
{
|
||||
using System;
|
||||
using Configuration;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
public class PackageReferenceFactoryTests
|
||||
{
|
||||
[Fact]
|
||||
public void Create_PackageReference_Null_Throws()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>("package", () => PackageReferenceFactory.Create((ISetupPackageReference)null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Create_PackageReference()
|
||||
{
|
||||
var reference = Mock.Of<ISetupPackageReference>(x => x.GetId() == "a");
|
||||
var actual = PackageReferenceFactory.Create(reference);
|
||||
|
||||
Assert.IsType<PackageReference>(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Create_FailedPackageReference_Null_Throws()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>("package", () => PackageReferenceFactory.Create((ISetupFailedPackageReference)null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Create_FailedPackageReference()
|
||||
{
|
||||
var reference = new Mock<ISetupFailedPackageReference>();
|
||||
reference.As<ISetupPackageReference>().Setup(x => x.GetId()).Returns("a");
|
||||
|
||||
var actual = PackageReferenceFactory.Create(reference.Object);
|
||||
|
||||
Assert.IsType<FailedPackageReference>(actual);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,233 @@
|
|||
// <copyright file="UtilitiesTests.cs" company="Microsoft Corporation">
|
||||
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE.txt in the project root for license information.
|
||||
// </copyright>
|
||||
|
||||
namespace Microsoft.VisualStudio.Setup
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using Configuration;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
public class UtilitiesTests
|
||||
{
|
||||
[Fact]
|
||||
public void EmptyReadOnlyCollection_Empty()
|
||||
{
|
||||
Assert.Empty(Utilities.EmptyReadOnlyCollection<PackageReference>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyReadOnlyCollection_Singleton()
|
||||
{
|
||||
Assert.Same(Utilities.EmptyReadOnlyCollection<PackageReference>(), Utilities.EmptyReadOnlyCollection<PackageReference>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetAdaptedProperties_Action_Null_Throws()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>("action", () => Utilities.GetAdaptedPackages<ISetupPackageReference, PackageReference>(null, null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetAdaptedProperties_Creator_Null_Throws()
|
||||
{
|
||||
var references = new[]
|
||||
{
|
||||
Mock.Of<ISetupPackageReference>(x => x.GetId() == "a"),
|
||||
Mock.Of<ISetupPackageReference>(x => x.GetId() == "b"),
|
||||
};
|
||||
|
||||
Assert.Throws<ArgumentNullException>("creator", () => Utilities.GetAdaptedPackages<ISetupPackageReference, PackageReference>(() => references, null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetAdaptedProperties_Empty()
|
||||
{
|
||||
var references = new ISetupPackageReference[0];
|
||||
Func<ISetupPackageReference, PackageReference> creator = reference => PackageReferenceFactory.Create(reference);
|
||||
|
||||
var packages = Utilities.GetAdaptedPackages(() => references, creator).ToList();
|
||||
|
||||
Assert.Empty(packages);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetAdaptedProperties()
|
||||
{
|
||||
var references = new[]
|
||||
{
|
||||
Mock.Of<ISetupPackageReference>(x => x.GetId() == "a"),
|
||||
Mock.Of<ISetupPackageReference>(x => x.GetId() == "b"),
|
||||
};
|
||||
|
||||
Func<ISetupPackageReference, PackageReference> creator = reference => PackageReferenceFactory.Create(reference);
|
||||
|
||||
var packages = Utilities.GetAdaptedPackages(() => references, creator).ToList();
|
||||
|
||||
Assert.Collection(
|
||||
packages,
|
||||
x => Assert.Equal("a", x.Id),
|
||||
x => Assert.Equal("b", x.Id));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TrySet_PropertyName_Null_Throws()
|
||||
{
|
||||
string property = null;
|
||||
Assert.Throws<ArgumentNullException>("propertyName", () => Utilities.TrySet(ref property, null, null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TrySet_PropertyName_Empty_Throws()
|
||||
{
|
||||
string property = null;
|
||||
Assert.Throws<ArgumentException>("propertyName", () => Utilities.TrySet(ref property, string.Empty, null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TrySet_Action_Null_Throws()
|
||||
{
|
||||
string property = null;
|
||||
Assert.Throws<ArgumentNullException>("action", () => Utilities.TrySet(ref property, nameof(property), null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TrySet_COMException_E_NOTFOUND()
|
||||
{
|
||||
string property = null;
|
||||
Utilities.TrySet(ref property, nameof(property), () => { throw new COMException("Not found", NativeMethods.E_NOTFOUND); });
|
||||
|
||||
Assert.Null(property);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TrySet_COMException_REGDB_E_CLASSNOTREG()
|
||||
{
|
||||
string property = null;
|
||||
var ex = Assert.Throws<COMException>(() => Utilities.TrySet(ref property, nameof(property), () => { throw new COMException("Not registered", NativeMethods.REGDB_E_CLASSNOTREG); }));
|
||||
|
||||
Assert.Equal(NativeMethods.REGDB_E_CLASSNOTREG, ex.ErrorCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TrySet()
|
||||
{
|
||||
string property = null;
|
||||
Utilities.TrySet(ref property, nameof(property), () => { return "test"; });
|
||||
|
||||
Assert.Equal("test", property);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TrySet_Error_Callback()
|
||||
{
|
||||
string property = null;
|
||||
var called = false;
|
||||
|
||||
Utilities.TrySet(
|
||||
ref property,
|
||||
nameof(property),
|
||||
() => { throw new COMException("Not found", NativeMethods.E_NOTFOUND); },
|
||||
propertyName => called = true);
|
||||
|
||||
Assert.Null(property);
|
||||
Assert.True(called);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TrySetCollection_PropertyName_Null_Throws()
|
||||
{
|
||||
IList<PackageReference> property = null;
|
||||
Assert.Throws<ArgumentNullException>("propertyName", () => Utilities.TrySetCollection<ISetupPackageReference, PackageReference>(ref property, null, null, null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TrySetCollection_PropertyName_Empty_Throws()
|
||||
{
|
||||
IList<PackageReference> property = null;
|
||||
Assert.Throws<ArgumentException>("propertyName", () => Utilities.TrySetCollection<ISetupPackageReference, PackageReference>(ref property, string.Empty, null, null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TrySetCollection_Action_Null_Throws()
|
||||
{
|
||||
IList<PackageReference> property = null;
|
||||
Assert.Throws<ArgumentNullException>("action", () => Utilities.TrySetCollection<ISetupPackageReference, PackageReference>(ref property, nameof(property), null, null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TrySetCollection_Creator_Null_Throws()
|
||||
{
|
||||
IList<PackageReference> property = null;
|
||||
var references = new[]
|
||||
{
|
||||
Mock.Of<ISetupPackageReference>(x => x.GetId() == "a"),
|
||||
Mock.Of<ISetupPackageReference>(x => x.GetId() == "b"),
|
||||
};
|
||||
|
||||
Assert.Throws<ArgumentNullException>("creator", () => Utilities.TrySetCollection(ref property, nameof(property), () => references, null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TrySetCollection_Empty()
|
||||
{
|
||||
IList<PackageReference> property = null;
|
||||
var references = new ISetupPackageReference[0];
|
||||
Func<ISetupPackageReference, PackageReference> creator = reference => PackageReferenceFactory.Create(reference);
|
||||
|
||||
var packages = Utilities.TrySetCollection(ref property, nameof(property), () => references, creator);
|
||||
|
||||
Assert.Empty(packages);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TrySetCollection()
|
||||
{
|
||||
IList<PackageReference> property = null;
|
||||
var references = new[]
|
||||
{
|
||||
Mock.Of<ISetupPackageReference>(x => x.GetId() == "a"),
|
||||
Mock.Of<ISetupPackageReference>(x => x.GetId() == "b"),
|
||||
};
|
||||
|
||||
Func<ISetupPackageReference, PackageReference> creator = reference => PackageReferenceFactory.Create(reference);
|
||||
|
||||
var packages = Utilities.TrySetCollection(ref property, nameof(property), () => references, creator);
|
||||
|
||||
Assert.Collection(
|
||||
packages,
|
||||
x => Assert.Equal("a", x.Id),
|
||||
x => Assert.Equal("b", x.Id));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TrySetCollection_Error_Callback()
|
||||
{
|
||||
IList<PackageReference> property = null;
|
||||
var called = false;
|
||||
var references = new[]
|
||||
{
|
||||
Mock.Of<ISetupPackageReference>(x => x.GetId() == "a"),
|
||||
Mock.Of<ISetupPackageReference>(x => x.GetId() == "b"),
|
||||
};
|
||||
|
||||
Func<ISetupPackageReference, PackageReference> creator = reference => PackageReferenceFactory.Create(reference);
|
||||
|
||||
var packages = Utilities.TrySetCollection(
|
||||
ref property,
|
||||
nameof(property),
|
||||
() => { throw new COMException("Not found", NativeMethods.E_NOTFOUND); },
|
||||
creator,
|
||||
propertyName => called = true);
|
||||
|
||||
Assert.Null(property);
|
||||
Assert.Empty(packages);
|
||||
Assert.True(called);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -46,7 +46,7 @@
|
|||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.Setup.Configuration.Interop, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Interop.1.5.125-rc\lib\net35\Microsoft.VisualStudio.Setup.Configuration.Interop.dll</HintPath>
|
||||
<HintPath>..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Interop.1.8.24\lib\net35\Microsoft.VisualStudio.Setup.Configuration.Interop.dll</HintPath>
|
||||
<EmbedInteropTypes>False</EmbedInteropTypes>
|
||||
</Reference>
|
||||
<Reference Include="Moq, Version=4.5.30.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
|
||||
|
@ -78,13 +78,17 @@
|
|||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ErrorsTests.cs" />
|
||||
<Compile Include="ExtensionsTests.cs" />
|
||||
<Compile Include="FailedPackageReferenceTests.cs" />
|
||||
<Compile Include="InstanceTests.cs" />
|
||||
<Compile Include="PackageReferenceFactoryTests.cs" />
|
||||
<Compile Include="PackageReferenceTests.cs" />
|
||||
<Compile Include="PowerShell\ExtensionsTests.cs" />
|
||||
<Compile Include="PowerShell\SelectInstanceCommandTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ReadOnlyDictionaryTests.cs" />
|
||||
<Compile Include="UtilitiesTests.cs" />
|
||||
<Compile Include="ValidateTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<packages>
|
||||
<package id="Castle.Core" version="3.3.3" targetFramework="net45" />
|
||||
<package id="Microsoft.PowerShell.3.ReferenceAssemblies" version="1.0.0" targetFramework="net45" />
|
||||
<package id="Microsoft.VisualStudio.Setup.Configuration.Interop" version="1.5.125-rc" targetFramework="net45" />
|
||||
<package id="Microsoft.VisualStudio.Setup.Configuration.Interop" version="1.8.24" targetFramework="net45" />
|
||||
<package id="Moq" version="4.5.30" targetFramework="net45" />
|
||||
<package id="Nerdbank.GitVersioning" version="1.5.62" targetFramework="net40-client" developmentDependency="true" requireReinstallation="true" />
|
||||
<package id="StyleCop.Analyzers" version="1.0.0" targetFramework="net40-client" developmentDependency="true" />
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
|
||||
"version": "1.0.0-rc",
|
||||
"version": "1.0.0",
|
||||
"publicReleaseRefSpec": [
|
||||
"^refs/heads/master$",
|
||||
"^refs/tags/v\\d\\.\\d"
|
||||
|
|
Загрузка…
Ссылка в новой задаче