Fixed SmokeTestsOnNanoServer to provide dotent runtime to enable testing portable scenario
This commit is contained in:
parent
c14f37ac6a
commit
22175e03a7
|
|
@ -2,14 +2,42 @@
|
||||||
{
|
{
|
||||||
public class RemoteDeploymentConfig
|
public class RemoteDeploymentConfig
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Name or IP address of the server to deploy to
|
||||||
|
/// </summary>
|
||||||
public string ServerName { get; set; }
|
public string ServerName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Account name for the credentials required to setup a powershell session to the target server
|
||||||
|
/// </summary>
|
||||||
public string AccountName { get; set; }
|
public string AccountName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Account password for the credentials required to setup a powershell session to the target server
|
||||||
|
/// </summary>
|
||||||
public string AccountPassword { get; set; }
|
public string AccountPassword { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The file share on the target server to copy the files to
|
||||||
|
/// </summary>
|
||||||
public string FileSharePath { get; set; }
|
public string FileSharePath { get; set; }
|
||||||
|
|
||||||
public string ExecutableRelativePath { get; set; }
|
/// <summary>
|
||||||
|
/// Location of the dotnet runtime zip file which is required for testing portable apps.
|
||||||
|
/// When both <see cref="DotnetRuntimeZipFilePath"/> and <see cref="DotnetRuntimeFolderPath"/> properties
|
||||||
|
/// are provided, the <see cref="DotnetRuntimeZipFilePath"/> property is preferred.
|
||||||
|
/// </summary>
|
||||||
|
public string DotnetRuntimeZipFilePath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Location of the dotnet runtime folder which is required for testing portable apps.
|
||||||
|
/// This property is probably more useful for users as they can point their local 'dotnet' runtime folder.
|
||||||
|
/// </summary>
|
||||||
|
public string DotnetRuntimeFolderPath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Path to the parent folder containing 'dotnet.exe' on remote server's file share
|
||||||
|
/// </summary>
|
||||||
|
public string DotnetRuntimePathOnShare { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using E2ETests.Common;
|
using E2ETests.Common;
|
||||||
using Microsoft.AspNetCore.Server.Testing;
|
using Microsoft.AspNetCore.Server.Testing;
|
||||||
|
|
@ -12,24 +13,55 @@ using Xunit.Abstractions;
|
||||||
|
|
||||||
namespace E2ETests
|
namespace E2ETests
|
||||||
{
|
{
|
||||||
public class SmokeTestsOnNanoServer : IDisposable
|
public class SmokeTestsOnNanoServerUsingStandaloneRuntime : IDisposable
|
||||||
{
|
{
|
||||||
|
private readonly SmokeTestsOnNanoServer _smokeTestsOnNanoServer;
|
||||||
private readonly XunitLogger _logger;
|
private readonly XunitLogger _logger;
|
||||||
private readonly RemoteDeploymentConfig _remoteDeploymentConfig;
|
private readonly RemoteDeploymentConfig _remoteDeploymentConfig;
|
||||||
|
|
||||||
public SmokeTestsOnNanoServer(ITestOutputHelper output)
|
public SmokeTestsOnNanoServerUsingStandaloneRuntime(ITestOutputHelper output)
|
||||||
{
|
{
|
||||||
_logger = new XunitLogger(output, LogLevel.Information);
|
_logger = new XunitLogger(output, LogLevel.Information);
|
||||||
|
_remoteDeploymentConfig = RemoteDeploymentConfigHelper.GetConfiguration();
|
||||||
|
_smokeTestsOnNanoServer = new SmokeTestsOnNanoServer(output, _remoteDeploymentConfig, _logger);
|
||||||
|
}
|
||||||
|
|
||||||
var configuration = new ConfigurationBuilder()
|
[ConditionalTheory, Trait("E2Etests", "NanoServer")]
|
||||||
.SetBasePath(Directory.GetCurrentDirectory())
|
[OSSkipCondition(OperatingSystems.Linux)]
|
||||||
.AddJsonFile("remoteDeploymentConfig.json")
|
[OSSkipCondition(OperatingSystems.MacOSX)]
|
||||||
.AddUserSecrets()
|
[SkipIfEnvironmentVariableNotEnabled("RUN_TESTS_ON_NANO")]
|
||||||
.AddEnvironmentVariables()
|
[InlineData(ServerType.Kestrel, 5000, ApplicationType.Standalone)]
|
||||||
.Build();
|
[InlineData(ServerType.WebListener, 5000, ApplicationType.Standalone)]
|
||||||
|
public async Task Test(ServerType serverType, int portToListen, ApplicationType applicationType)
|
||||||
|
{
|
||||||
|
var applicationBaseUrl = $"http://{_remoteDeploymentConfig.ServerName}:{portToListen}/";
|
||||||
|
await _smokeTestsOnNanoServer.RunTestsAsync(serverType, applicationBaseUrl, applicationType);
|
||||||
|
}
|
||||||
|
|
||||||
_remoteDeploymentConfig = new RemoteDeploymentConfig();
|
public void Dispose()
|
||||||
configuration.GetSection("NanoServer").Bind(_remoteDeploymentConfig);
|
{
|
||||||
|
_logger.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests here test portable app scenario, so we copy the dotnet runtime onto the
|
||||||
|
// target server's file share and after setting up a remote session to the server, we update the PATH environment
|
||||||
|
// to have the path to this copied dotnet runtime folder in the share.
|
||||||
|
// The dotnet runtime is copied only once for all the tests in this class.
|
||||||
|
public class SmokeTestsOnNanoServerUsingSharedRuntime
|
||||||
|
: IClassFixture<SmokeTestsOnNanoServerUsingSharedRuntime.DotnetRuntimeSetupTestFixture>, IDisposable
|
||||||
|
{
|
||||||
|
private readonly SmokeTestsOnNanoServer _smokeTestsOnNanoServer;
|
||||||
|
private readonly RemoteDeploymentConfig _remoteDeploymentConfig;
|
||||||
|
private readonly XunitLogger _logger;
|
||||||
|
|
||||||
|
public SmokeTestsOnNanoServerUsingSharedRuntime(
|
||||||
|
DotnetRuntimeSetupTestFixture dotnetRuntimeSetupTestFixture, ITestOutputHelper output)
|
||||||
|
{
|
||||||
|
_logger = new XunitLogger(output, LogLevel.Information);
|
||||||
|
_remoteDeploymentConfig = RemoteDeploymentConfigHelper.GetConfiguration();
|
||||||
|
_remoteDeploymentConfig.DotnetRuntimePathOnShare = dotnetRuntimeSetupTestFixture.DotnetRuntimePathOnShare;
|
||||||
|
_smokeTestsOnNanoServer = new SmokeTestsOnNanoServer(output, _remoteDeploymentConfig, _logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
[ConditionalTheory, Trait("E2Etests", "NanoServer")]
|
[ConditionalTheory, Trait("E2Etests", "NanoServer")]
|
||||||
|
|
@ -37,21 +69,169 @@ namespace E2ETests
|
||||||
[OSSkipCondition(OperatingSystems.MacOSX)]
|
[OSSkipCondition(OperatingSystems.MacOSX)]
|
||||||
[SkipIfEnvironmentVariableNotEnabled("RUN_TESTS_ON_NANO")]
|
[SkipIfEnvironmentVariableNotEnabled("RUN_TESTS_ON_NANO")]
|
||||||
[InlineData(ServerType.Kestrel, 5000, ApplicationType.Portable)]
|
[InlineData(ServerType.Kestrel, 5000, ApplicationType.Portable)]
|
||||||
[InlineData(ServerType.Kestrel, 5000, ApplicationType.Standalone)]
|
|
||||||
[InlineData(ServerType.WebListener, 5000, ApplicationType.Portable)]
|
[InlineData(ServerType.WebListener, 5000, ApplicationType.Portable)]
|
||||||
[InlineData(ServerType.WebListener, 5000, ApplicationType.Standalone)]
|
|
||||||
public async Task Test(ServerType serverType, int portToListen, ApplicationType applicationType)
|
public async Task Test(ServerType serverType, int portToListen, ApplicationType applicationType)
|
||||||
{
|
{
|
||||||
var applicationBaseUrl = $"http://{_remoteDeploymentConfig.ServerName}:{portToListen}/";
|
var applicationBaseUrl = $"http://{_remoteDeploymentConfig.ServerName}:{portToListen}/";
|
||||||
await RunTestsAsync(serverType, applicationBaseUrl, applicationType);
|
await _smokeTestsOnNanoServer.RunTestsAsync(serverType, applicationBaseUrl, applicationType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RunTestsAsync(ServerType serverType, string applicationBaseUrl, ApplicationType applicationType)
|
public void Dispose()
|
||||||
{
|
{
|
||||||
using (_logger.BeginScope("SmokeTestSuite"))
|
_logger.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copies dotnet runtime to the target server's file share.
|
||||||
|
public class DotnetRuntimeSetupTestFixture : IDisposable
|
||||||
|
{
|
||||||
|
public DotnetRuntimeSetupTestFixture()
|
||||||
|
{
|
||||||
|
RemoteDeploymentConfig = RemoteDeploymentConfigHelper.GetConfiguration();
|
||||||
|
|
||||||
|
DotnetRuntimePathOnShare = Path.Combine(RemoteDeploymentConfig.FileSharePath, "dotnet");
|
||||||
|
|
||||||
|
// Prefer copying the zip file to fileshare and extracting on file share over copying the extracted
|
||||||
|
// dotnet runtime folder from source to file share as the size could be significantly huge.
|
||||||
|
if (!string.IsNullOrEmpty(RemoteDeploymentConfig.DotnetRuntimeZipFilePath))
|
||||||
|
{
|
||||||
|
if (!File.Exists(RemoteDeploymentConfig.DotnetRuntimeZipFilePath))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"Expected dotnet runtime zip file at '{RemoteDeploymentConfig.DotnetRuntimeFolderPath}', but didn't find one.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZippedDotnetRuntimePathOnShare = Path.Combine(
|
||||||
|
RemoteDeploymentConfig.FileSharePath,
|
||||||
|
Path.GetFileName(RemoteDeploymentConfig.DotnetRuntimeZipFilePath));
|
||||||
|
|
||||||
|
if (!File.Exists(ZippedDotnetRuntimePathOnShare))
|
||||||
|
{
|
||||||
|
File.Copy(RemoteDeploymentConfig.DotnetRuntimeZipFilePath, ZippedDotnetRuntimePathOnShare, overwrite: true);
|
||||||
|
Console.WriteLine($"Copied the local dotnet zip folder '{RemoteDeploymentConfig.DotnetRuntimeZipFilePath}' " +
|
||||||
|
$"to the file share path '{RemoteDeploymentConfig.FileSharePath}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Directory.Exists(DotnetRuntimePathOnShare))
|
||||||
|
{
|
||||||
|
Directory.Delete(DotnetRuntimePathOnShare, recursive: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZipFile.ExtractToDirectory(ZippedDotnetRuntimePathOnShare, DotnetRuntimePathOnShare);
|
||||||
|
Console.WriteLine($"Extracted dotnet runtime to folder '{DotnetRuntimePathOnShare}'");
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrEmpty(RemoteDeploymentConfig.DotnetRuntimeFolderPath))
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(RemoteDeploymentConfig.DotnetRuntimeFolderPath))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"Expected dotnet runtime folder at '{RemoteDeploymentConfig.DotnetRuntimeFolderPath}', but didn't find one.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"Copying dotnet runtime folder from '{RemoteDeploymentConfig.DotnetRuntimeFolderPath}' to '{DotnetRuntimePathOnShare}'.");
|
||||||
|
Console.WriteLine("This could take some time.");
|
||||||
|
|
||||||
|
DirectoryCopy(RemoteDeploymentConfig.DotnetRuntimeFolderPath, DotnetRuntimePathOnShare, copySubDirs: true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Dotnet runtime is required to be copied for testing portable apps scenario. " +
|
||||||
|
$"Either supply '{nameof(RemoteDeploymentConfig.DotnetRuntimeFolderPath)}' containing the unzipped dotnet runtime content or " +
|
||||||
|
$"supply the dotnet runtime zip file path via '{nameof(RemoteDeploymentConfig.DotnetRuntimeZipFilePath)}'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public RemoteDeploymentConfig RemoteDeploymentConfig { get; }
|
||||||
|
|
||||||
|
public string ZippedDotnetRuntimePathOnShare { get; }
|
||||||
|
|
||||||
|
public string DotnetRuntimePathOnShare { get; }
|
||||||
|
|
||||||
|
private static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
|
||||||
|
{
|
||||||
|
var dir = new DirectoryInfo(sourceDirName);
|
||||||
|
|
||||||
|
if (!dir.Exists)
|
||||||
|
{
|
||||||
|
throw new DirectoryNotFoundException(
|
||||||
|
"Source directory does not exist or could not be found: "
|
||||||
|
+ sourceDirName);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dirs = dir.GetDirectories();
|
||||||
|
if (!Directory.Exists(destDirName))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(destDirName);
|
||||||
|
}
|
||||||
|
|
||||||
|
var files = dir.GetFiles();
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
var temppath = Path.Combine(destDirName, file.Name);
|
||||||
|
file.CopyTo(temppath, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copySubDirs)
|
||||||
|
{
|
||||||
|
foreach (var subdir in dirs)
|
||||||
|
{
|
||||||
|
var temppath = Path.Combine(destDirName, subdir.Name);
|
||||||
|
DirectoryCopy(subdir.FullName, temppath, copySubDirs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
// In case the source is provided as a folder itself, then we wouldn't have the zip file to begin with.
|
||||||
|
if (!string.IsNullOrEmpty(ZippedDotnetRuntimePathOnShare))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Deleting the dotnet runtime zip file '{ZippedDotnetRuntimePathOnShare}'");
|
||||||
|
File.Delete(ZippedDotnetRuntimePathOnShare);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Failed to delete the dotnet runtime zip file '{ZippedDotnetRuntimePathOnShare}'. Exception: "
|
||||||
|
+ ex.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Deleting the dotnet runtime folder '{DotnetRuntimePathOnShare}'");
|
||||||
|
Directory.Delete(DotnetRuntimePathOnShare, recursive: true);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Failed to delete the dotnet runtime folder '{DotnetRuntimePathOnShare}'. Exception: "
|
||||||
|
+ ex.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SmokeTestsOnNanoServer
|
||||||
|
{
|
||||||
|
private readonly XunitLogger _logger;
|
||||||
|
private readonly RemoteDeploymentConfig _remoteDeploymentConfig;
|
||||||
|
|
||||||
|
public SmokeTestsOnNanoServer(ITestOutputHelper output, RemoteDeploymentConfig config, XunitLogger logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_remoteDeploymentConfig = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RunTestsAsync(
|
||||||
|
ServerType serverType,
|
||||||
|
string applicationBaseUrl,
|
||||||
|
ApplicationType applicationType)
|
||||||
|
{
|
||||||
|
using (_logger.BeginScope(nameof(SmokeTestsOnNanoServerUsingStandaloneRuntime)))
|
||||||
{
|
{
|
||||||
var deploymentParameters = new RemoteWindowsDeploymentParameters(
|
var deploymentParameters = new RemoteWindowsDeploymentParameters(
|
||||||
Helpers.GetApplicationPath(applicationType),
|
Helpers.GetApplicationPath(applicationType),
|
||||||
|
_remoteDeploymentConfig.DotnetRuntimePathOnShare,
|
||||||
serverType,
|
serverType,
|
||||||
RuntimeFlavor.CoreClr,
|
RuntimeFlavor.CoreClr,
|
||||||
RuntimeArchitecture.x64,
|
RuntimeArchitecture.x64,
|
||||||
|
|
@ -75,10 +255,28 @@ namespace E2ETests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
static class RemoteDeploymentConfigHelper
|
||||||
|
{
|
||||||
|
private static RemoteDeploymentConfig _remoteDeploymentConfig;
|
||||||
|
|
||||||
|
public static RemoteDeploymentConfig GetConfiguration()
|
||||||
{
|
{
|
||||||
_logger.Dispose();
|
if (_remoteDeploymentConfig == null)
|
||||||
|
{
|
||||||
|
var configuration = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(Directory.GetCurrentDirectory())
|
||||||
|
.AddJsonFile("remoteDeploymentConfig.json")
|
||||||
|
.AddUserSecrets()
|
||||||
|
.AddEnvironmentVariables()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
_remoteDeploymentConfig = new RemoteDeploymentConfig();
|
||||||
|
configuration.GetSection("NanoServer").Bind(_remoteDeploymentConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _remoteDeploymentConfig;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
"AccountName": "",
|
"AccountName": "",
|
||||||
"AccountPassword": "",
|
"AccountPassword": "",
|
||||||
"FileSharePath": "",
|
"FileSharePath": "",
|
||||||
"ExecutableRelativePath": ""
|
"DotnetRuntimeFolderPath": "",
|
||||||
|
"DotnetRuntimeZipFilePath": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue