2018-03-27 20:26:55 -07:00
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
using FluentAssertions ;
using Microsoft.DotNet.BuildServer ;
using Microsoft.DotNet.Cli ;
using Microsoft.DotNet.Cli.CommandLine ;
using Microsoft.DotNet.Cli.Utils ;
2018-04-26 17:04:37 -07:00
using Microsoft.DotNet.TestFramework ;
2018-03-27 20:26:55 -07:00
using Microsoft.DotNet.Tools.BuildServer ;
using Microsoft.DotNet.Tools.BuildServer.Shutdown ;
using Microsoft.DotNet.Tools.Test.Utilities ;
2018-04-26 17:04:37 -07:00
using Microsoft.Extensions.EnvironmentAbstractions ;
2018-03-27 20:26:55 -07:00
using Moq ;
using Xunit ;
using Parser = Microsoft . DotNet . Cli . Parser ;
2018-04-26 17:04:37 -07:00
using CommandLocalizableStrings = Microsoft . DotNet . BuildServer . LocalizableStrings ;
2018-03-27 20:26:55 -07:00
using LocalizableStrings = Microsoft . DotNet . Tools . BuildServer . Shutdown . LocalizableStrings ;
2018-04-26 17:04:37 -07:00
using TestBuildServerCommand = Microsoft . DotNet . Tools . Test . Utilities . BuildServerCommand ;
2018-03-27 20:26:55 -07:00
namespace Microsoft.DotNet.Tests.Commands
{
2018-04-26 17:04:37 -07:00
public class BuildServerShutdownCommandTests : TestBase
2018-03-27 20:26:55 -07:00
{
private readonly BufferedReporter _reporter = new BufferedReporter ( ) ;
[Fact]
2018-04-15 00:50:32 -07:00
public void GivenNoOptionsItEnumeratesAllServers ( )
2018-03-27 20:26:55 -07:00
{
2018-04-15 00:50:32 -07:00
var provider = new Mock < IBuildServerProvider > ( MockBehavior . Strict ) ;
2018-03-27 20:26:55 -07:00
2018-04-15 00:50:32 -07:00
provider
. Setup ( p = > p . EnumerateBuildServers ( ServerEnumerationFlags . All ) )
. Returns ( Array . Empty < IBuildServer > ( ) ) ;
2018-03-27 20:26:55 -07:00
2018-04-15 00:50:32 -07:00
var command = CreateCommand ( serverProvider : provider . Object ) ;
2018-03-27 20:26:55 -07:00
2018-04-15 00:50:32 -07:00
command . Execute ( ) . Should ( ) . Be ( 0 ) ;
2018-03-27 20:26:55 -07:00
2018-04-15 00:50:32 -07:00
_reporter . Lines . Should ( ) . Equal ( LocalizableStrings . NoServersToShutdown . Green ( ) ) ;
2018-03-27 20:26:55 -07:00
2018-04-15 00:50:32 -07:00
provider . Verify ( p = > p . EnumerateBuildServers ( ServerEnumerationFlags . All ) , Times . Once ) ;
2018-03-27 20:26:55 -07:00
}
[Fact]
2018-04-15 00:50:32 -07:00
public void GivenMSBuildOptionOnlyItEnumeratesOnlyMSBuildServers ( )
2018-03-27 20:26:55 -07:00
{
2018-04-15 00:50:32 -07:00
var provider = new Mock < IBuildServerProvider > ( MockBehavior . Strict ) ;
provider
. Setup ( p = > p . EnumerateBuildServers ( ServerEnumerationFlags . MSBuild ) )
. Returns ( Array . Empty < IBuildServer > ( ) ) ;
2018-03-27 20:26:55 -07:00
2018-04-15 00:50:32 -07:00
var command = CreateCommand ( options : "--msbuild" , serverProvider : provider . Object ) ;
command . Execute ( ) . Should ( ) . Be ( 0 ) ;
_reporter . Lines . Should ( ) . Equal ( LocalizableStrings . NoServersToShutdown . Green ( ) ) ;
provider . Verify ( p = > p . EnumerateBuildServers ( ServerEnumerationFlags . MSBuild ) , Times . Once ) ;
2018-03-27 20:26:55 -07:00
}
[Fact]
2018-04-15 00:50:32 -07:00
public void GivenVBCSCompilerOptionOnlyItEnumeratesOnlyVBCSCompilers ( )
2018-03-27 20:26:55 -07:00
{
2018-04-15 00:50:32 -07:00
var provider = new Mock < IBuildServerProvider > ( MockBehavior . Strict ) ;
2018-03-27 20:26:55 -07:00
2018-04-15 00:50:32 -07:00
provider
. Setup ( p = > p . EnumerateBuildServers ( ServerEnumerationFlags . VBCSCompiler ) )
. Returns ( Array . Empty < IBuildServer > ( ) ) ;
var command = CreateCommand ( options : "--vbcscompiler" , serverProvider : provider . Object ) ;
2018-03-27 20:26:55 -07:00
command . Execute ( ) . Should ( ) . Be ( 0 ) ;
2018-04-15 00:50:32 -07:00
_reporter . Lines . Should ( ) . Equal ( LocalizableStrings . NoServersToShutdown . Green ( ) ) ;
2018-03-27 20:26:55 -07:00
2018-04-15 00:50:32 -07:00
provider . Verify ( p = > p . EnumerateBuildServers ( ServerEnumerationFlags . VBCSCompiler ) , Times . Once ) ;
2018-03-27 20:26:55 -07:00
}
[Fact]
2018-04-15 00:50:32 -07:00
public void GivenRazorOptionOnlyItEnumeratesOnlyRazorServers ( )
2018-03-27 20:26:55 -07:00
{
2018-04-15 00:50:32 -07:00
var provider = new Mock < IBuildServerProvider > ( MockBehavior . Strict ) ;
2018-03-27 20:26:55 -07:00
2018-04-15 00:50:32 -07:00
provider
. Setup ( p = > p . EnumerateBuildServers ( ServerEnumerationFlags . Razor ) )
. Returns ( Array . Empty < IBuildServer > ( ) ) ;
2018-03-27 20:26:55 -07:00
2018-04-15 00:50:32 -07:00
var command = CreateCommand ( options : "--razor" , serverProvider : provider . Object ) ;
2018-03-27 20:26:55 -07:00
2018-04-15 00:50:32 -07:00
command . Execute ( ) . Should ( ) . Be ( 0 ) ;
2018-03-27 20:26:55 -07:00
2018-04-15 00:50:32 -07:00
_reporter . Lines . Should ( ) . Equal ( LocalizableStrings . NoServersToShutdown . Green ( ) ) ;
2018-03-27 20:26:55 -07:00
2018-04-15 00:50:32 -07:00
provider . Verify ( p = > p . EnumerateBuildServers ( ServerEnumerationFlags . Razor ) , Times . Once ) ;
2018-03-27 20:26:55 -07:00
}
[Fact]
2018-04-15 00:50:32 -07:00
public void GivenSuccessfulShutdownsItPrintsSuccess ( )
2018-03-27 20:26:55 -07:00
{
var mocks = new [ ] {
2018-04-15 00:50:32 -07:00
CreateServerMock ( "first" ) ,
CreateServerMock ( "second" ) ,
CreateServerMock ( "third" )
2018-03-27 20:26:55 -07:00
} ;
2018-04-15 00:50:32 -07:00
var provider = new Mock < IBuildServerProvider > ( MockBehavior . Strict ) ;
provider
. Setup ( p = > p . EnumerateBuildServers ( ServerEnumerationFlags . All ) )
. Returns ( mocks . Select ( m = > m . Object ) ) ;
var command = CreateCommand ( serverProvider : provider . Object ) ;
2018-03-27 20:26:55 -07:00
command . Execute ( ) . Should ( ) . Be ( 0 ) ;
_reporter . Lines . Should ( ) . Equal (
FormatShuttingDownMessage ( mocks [ 0 ] . Object ) ,
FormatShuttingDownMessage ( mocks [ 1 ] . Object ) ,
FormatShuttingDownMessage ( mocks [ 2 ] . Object ) ,
FormatSuccessMessage ( mocks [ 0 ] . Object ) ,
FormatSuccessMessage ( mocks [ 1 ] . Object ) ,
2018-04-15 00:50:32 -07:00
FormatSuccessMessage ( mocks [ 2 ] . Object ) ) ;
2018-03-27 20:26:55 -07:00
VerifyShutdownCalls ( mocks ) ;
}
[Fact]
2018-04-15 00:50:32 -07:00
public void GivenAFailingShutdownItPrintsFailureMessage ( )
2018-03-27 20:26:55 -07:00
{
2018-04-15 00:50:32 -07:00
const string FirstFailureMessage = "first failed!" ;
const string ThirdFailureMessage = "third failed!" ;
2018-03-27 20:26:55 -07:00
var mocks = new [ ] {
2018-04-15 00:50:32 -07:00
CreateServerMock ( "first" , exceptionMessage : FirstFailureMessage ) ,
CreateServerMock ( "second" ) ,
CreateServerMock ( "third" , exceptionMessage : ThirdFailureMessage )
2018-03-27 20:26:55 -07:00
} ;
2018-04-15 00:50:32 -07:00
var provider = new Mock < IBuildServerProvider > ( MockBehavior . Strict ) ;
provider
. Setup ( p = > p . EnumerateBuildServers ( ServerEnumerationFlags . All ) )
. Returns ( mocks . Select ( m = > m . Object ) ) ;
var command = CreateCommand ( serverProvider : provider . Object ) ;
2018-03-27 20:26:55 -07:00
command . Execute ( ) . Should ( ) . Be ( 1 ) ;
_reporter . Lines . Should ( ) . Equal (
FormatShuttingDownMessage ( mocks [ 0 ] . Object ) ,
FormatShuttingDownMessage ( mocks [ 1 ] . Object ) ,
FormatShuttingDownMessage ( mocks [ 2 ] . Object ) ,
2018-04-15 00:50:32 -07:00
FormatFailureMessage ( mocks [ 0 ] . Object , FirstFailureMessage ) ,
FormatSuccessMessage ( mocks [ 1 ] . Object ) ,
FormatFailureMessage ( mocks [ 2 ] . Object , ThirdFailureMessage ) ) ;
2018-03-27 20:26:55 -07:00
VerifyShutdownCalls ( mocks ) ;
}
2018-04-26 17:04:37 -07:00
[Fact]
public void GivenARunningRazorServerItShutsDownSuccessfully ( )
{
var pipeName = Path . GetRandomFileName ( ) ;
var pidDirectory = Path . GetFullPath ( Path . Combine ( TempRoot . Root , Path . GetRandomFileName ( ) ) ) ;
var testInstance = TestAssets . Get ( "TestRazorApp" )
. CreateInstance ( )
. WithSourceFiles ( ) ;
new BuildCommand ( )
. WithWorkingDirectory ( testInstance . Root )
. WithEnvironmentVariable ( BuildServerProvider . PidFileDirectoryVariableName , pidDirectory )
. Execute ( $"/p:_RazorBuildServerPipeName={pipeName}" )
. Should ( )
. Pass ( ) ;
var files = Directory . GetFiles ( pidDirectory , RazorPidFile . FilePrefix + "*" ) ;
files . Length . Should ( ) . Be ( 1 ) ;
var pidFile = RazorPidFile . Read ( new FilePath ( files . First ( ) ) ) ;
pidFile . PipeName . Should ( ) . Be ( pipeName ) ;
new TestBuildServerCommand ( )
. WithWorkingDirectory ( testInstance . Root )
. WithEnvironmentVariable ( BuildServerProvider . PidFileDirectoryVariableName , pidDirectory )
. ExecuteWithCapturedOutput ( "shutdown --razor" )
. Should ( )
. Pass ( )
. And
. HaveStdOutContaining (
string . Format (
LocalizableStrings . ShutDownSucceededWithPid ,
CommandLocalizableStrings . RazorServer ,
pidFile . ProcessId ) ) ;
}
2018-04-15 00:50:32 -07:00
private BuildServerShutdownCommand CreateCommand (
string options = "" ,
IBuildServerProvider serverProvider = null ,
IEnumerable < IBuildServer > buildServers = null ,
ServerEnumerationFlags expectedFlags = ServerEnumerationFlags . None )
2018-03-27 20:26:55 -07:00
{
2018-04-17 17:04:12 -07:00
ParseResult result = Parser . Instance . Parse ( "dotnet build-server shutdown " + options ) ;
2018-03-27 20:26:55 -07:00
return new BuildServerShutdownCommand (
2018-04-17 17:04:12 -07:00
options : result [ "dotnet" ] [ "build-server" ] [ "shutdown" ] ,
2018-03-27 20:26:55 -07:00
result : result ,
2018-04-15 00:50:32 -07:00
serverProvider : serverProvider ,
2018-03-27 20:26:55 -07:00
useOrderedWait : true ,
reporter : _reporter ) ;
}
2018-04-15 00:50:32 -07:00
private Mock < IBuildServer > CreateServerMock ( string name , int pid = 0 , string exceptionMessage = null )
2018-03-27 20:26:55 -07:00
{
2018-04-15 00:50:32 -07:00
var mock = new Mock < IBuildServer > ( MockBehavior . Strict ) ;
2018-03-27 20:26:55 -07:00
2018-04-15 00:50:32 -07:00
mock . SetupGet ( s = > s . ProcessId ) . Returns ( pid ) ;
mock . SetupGet ( s = > s . Name ) . Returns ( name ) ;
if ( exceptionMessage = = null )
{
mock . Setup ( s = > s . Shutdown ( ) ) ;
}
else
{
mock . Setup ( s = > s . Shutdown ( ) ) . Throws ( new Exception ( exceptionMessage ) ) ;
}
2018-03-27 20:26:55 -07:00
return mock ;
}
2018-04-15 00:50:32 -07:00
private void VerifyShutdownCalls ( IEnumerable < Mock < IBuildServer > > mocks )
2018-03-27 20:26:55 -07:00
{
foreach ( var mock in mocks )
{
2018-04-15 00:50:32 -07:00
mock . Verify ( s = > s . Shutdown ( ) , Times . Once ) ;
2018-03-27 20:26:55 -07:00
}
}
2018-04-15 00:50:32 -07:00
private static string FormatShuttingDownMessage ( IBuildServer server )
2018-03-27 20:26:55 -07:00
{
2018-04-15 00:50:32 -07:00
if ( server . ProcessId ! = 0 )
{
return string . Format ( LocalizableStrings . ShuttingDownServerWithPid , server . Name , server . ProcessId ) ;
}
return string . Format ( LocalizableStrings . ShuttingDownServer , server . Name ) ;
2018-03-27 20:26:55 -07:00
}
2018-04-15 00:50:32 -07:00
private static string FormatSuccessMessage ( IBuildServer server )
2018-03-27 20:26:55 -07:00
{
2018-04-15 00:50:32 -07:00
if ( server . ProcessId ! = 0 )
{
return string . Format ( LocalizableStrings . ShutDownSucceededWithPid , server . Name , server . ProcessId ) . Green ( ) ;
}
return string . Format ( LocalizableStrings . ShutDownSucceeded , server . Name ) . Green ( ) ;
2018-03-27 20:26:55 -07:00
}
2018-04-15 00:50:32 -07:00
private static string FormatFailureMessage ( IBuildServer server , string message )
2018-03-27 20:26:55 -07:00
{
2018-04-15 00:50:32 -07:00
if ( server . ProcessId ! = 0 )
{
return string . Format ( LocalizableStrings . ShutDownFailedWithPid , server . Name , server . ProcessId , message ) . Red ( ) ;
}
return string . Format ( LocalizableStrings . ShutDownFailed , server . Name , message ) . Red ( ) ;
2018-03-27 20:26:55 -07:00
}
}
}