merge release/2.2 into master

This commit is contained in:
Justin Kotalik 2018-07-30 14:04:01 -07:00
commit d4d6db80eb
22 changed files with 207 additions and 161 deletions

View File

@ -3,6 +3,8 @@ phases:
parameters:
agentOs: Windows
beforeBuild:
- powershell: "git submodule update --init"
displayName: Update submodules
- powershell: "& ./tools/update_schema.ps1"
displayName: Update ANCM schema
- powershell: Restart-Service w3svc

View File

@ -237,6 +237,13 @@ Language=English
%1
.
Messageid=1035
SymbolicName=ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT
Language=English
%1
.
;
;#endif // _ASPNETCORE_MODULE_MSG_H_
;

View File

@ -7,10 +7,10 @@
#include "requesthandler_config.h"
#include "environmentvariablehelpers.h"
#include "utility.h"
#include "EventLog.h"
#include "SRWExclusiveLock.h"
#include "exceptions.h"
#include "LoggingHelpers.h"
#include "resources.h"
const LPCSTR IN_PROCESS_APPLICATION::s_exeLocationParameterName = "InProcessExeLocation";
@ -220,7 +220,6 @@ IN_PROCESS_APPLICATION::SetCallbackHandles(
m_ShutdownHandlerContext = pvShutdownHandlerContext;
m_AsyncCompletionHandler = async_completion_handler;
m_pLoggerProvider->NotifyStartupComplete();
// Can't check the std err handle as it isn't a critical error
// Initialization complete
UTILITY::LogEventF(g_hEventLog,
@ -498,11 +497,10 @@ Finished:
m_status = APPLICATION_STATUS::SHUTDOWN;
m_fShutdownCalledFromManaged = TRUE;
FreeLibrary(hModule);
m_pLoggerProvider->Stop();
if (!m_fShutdownCalledFromNative)
{
m_pLoggerProvider->NotifyStartupComplete();
LogErrorsOnMainExit(hr);
if (m_fInitialized)
{
@ -533,7 +531,7 @@ IN_PROCESS_APPLICATION::LogErrorsOnMainExit(
if (SUCCEEDED(struStdMsg.CopyA(straStdErrOutput.QueryStr()))) {
UTILITY::LogEventF(g_hEventLog,
EVENTLOG_ERROR_TYPE,
ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT,
ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT,
ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT_MSG,
m_pConfig->QueryApplicationPath()->QueryStr(),
m_pConfig->QueryApplicationPhysicalPath()->QueryStr(),

View File

@ -18,8 +18,7 @@ register_callbacks(
_In_ PFN_SHUTDOWN_HANDLER shutdown_handler,
_In_ PFN_ASYNC_COMPLETION_HANDLER async_completion_handler,
_In_ VOID* pvRequstHandlerContext,
_In_ VOID* pvShutdownHandlerContext,
_Out_ BOOL* pfResetStandardStreams
_In_ VOID* pvShutdownHandlerContext
)
{
if (pInProcessApplication == NULL)
@ -34,7 +33,6 @@ register_callbacks(
pvRequstHandlerContext,
pvShutdownHandlerContext
);
*pfResetStandardStreams = !pInProcessApplication->QueryConfig()->QueryStdoutLogEnabled();
return S_OK;
}

View File

@ -7,48 +7,20 @@
#include "utility.h"
#include "exceptions.h"
#include "debugutil.h"
#include "SRWExclusiveLock.h"
FileOutputManager::FileOutputManager() :
m_hLogFileHandle(INVALID_HANDLE_VALUE),
m_fdPreviousStdOut(-1),
m_fdPreviousStdErr(-1)
m_fdPreviousStdErr(-1),
m_disposed(false)
{
InitializeSRWLock(&m_srwLock);
}
FileOutputManager::~FileOutputManager()
{
HANDLE handle = NULL;
WIN32_FIND_DATA fileData;
if (m_hLogFileHandle != INVALID_HANDLE_VALUE)
{
m_Timer.CancelTimer();
}
// delete empty log file
handle = FindFirstFile(m_struLogFilePath.QueryStr(), &fileData);
if (handle != INVALID_HANDLE_VALUE &&
handle != NULL &&
fileData.nFileSizeHigh == 0 &&
fileData.nFileSizeLow == 0) // skip check of nFileSizeHigh
{
FindClose(handle);
// no need to check whether the deletion succeeds
// as nothing can be done
DeleteFile(m_struLogFilePath.QueryStr());
}
if (m_fdPreviousStdOut >= 0)
{
LOG_LAST_ERROR_IF(SetStdHandle(STD_OUTPUT_HANDLE, (HANDLE)_get_osfhandle(m_fdPreviousStdOut)));
LOG_INFOF("Restoring original stdout: %d", m_fdPreviousStdOut);
}
if (m_fdPreviousStdErr >= 0)
{
LOG_LAST_ERROR_IF(SetStdHandle(STD_ERROR_HANDLE, (HANDLE)_get_osfhandle(m_fdPreviousStdErr)));
LOG_INFOF("Restoring original stderr: %d", m_fdPreviousStdOut);
}
Stop();
}
HRESULT
@ -100,8 +72,6 @@ bool FileOutputManager::GetStdOutContent(STRA* struStdOutput)
}
}
LOG_INFOF("First 4KB captured by stdout: %s", pzFileContents);
return fLogged;
}
@ -174,3 +144,52 @@ FileOutputManager::Start()
return S_OK;
}
HRESULT
FileOutputManager::Stop()
{
if (m_disposed)
{
return S_OK;
}
SRWExclusiveLock lock(m_srwLock);
if (m_disposed)
{
return S_OK;
}
m_disposed = true;
HANDLE handle = NULL;
WIN32_FIND_DATA fileData;
if (m_hLogFileHandle != INVALID_HANDLE_VALUE)
{
m_Timer.CancelTimer();
}
// delete empty log file
handle = FindFirstFile(m_struLogFilePath.QueryStr(), &fileData);
if (handle != INVALID_HANDLE_VALUE &&
handle != NULL &&
fileData.nFileSizeHigh == 0 &&
fileData.nFileSizeLow == 0) // skip check of nFileSizeHigh
{
FindClose(handle);
LOG_LAST_ERROR_IF(!DeleteFile(m_struLogFilePath.QueryStr()));
}
if (m_fdPreviousStdOut >= 0)
{
LOG_LAST_ERROR_IF(!SetStdHandle(STD_OUTPUT_HANDLE, (HANDLE)_get_osfhandle(m_fdPreviousStdOut)));
LOG_INFOF("Restoring original stdout: %d", m_fdPreviousStdOut);
}
if (m_fdPreviousStdErr >= 0)
{
LOG_LAST_ERROR_IF(!SetStdHandle(STD_ERROR_HANDLE, (HANDLE)_get_osfhandle(m_fdPreviousStdErr)));
LOG_INFOF("Restoring original stderr: %d", m_fdPreviousStdOut);
}
return S_OK;
}

View File

@ -19,7 +19,7 @@ public:
virtual bool GetStdOutContent(STRA* struStdOutput) override;
virtual HRESULT Start() override;
virtual void NotifyStartupComplete() override {};
virtual HRESULT Stop() override;
private:
HandleWrapper<InvalidHandleTraits> m_hLogFileHandle;
@ -29,5 +29,7 @@ private:
STRU m_struLogFilePath;
int m_fdPreviousStdOut;
int m_fdPreviousStdErr;
BOOL m_disposed;
SRWLOCK m_srwLock;
};

View File

@ -14,12 +14,12 @@ public:
virtual
~IOutputManager() {};
virtual
void
NotifyStartupComplete() = 0;
virtual
bool
GetStdOutContent(STRA* struStdOutput) = 0;
virtual
HRESULT
Stop() = 0;
};

View File

@ -15,12 +15,12 @@ public:
HRESULT Start()
{
// The process has console, e.g., IIS Express scenario
return S_OK;
}
void NotifyStartupComplete()
HRESULT Stop()
{
return S_OK;
}
bool GetStdOutContent(STRA*)

View File

@ -14,7 +14,7 @@ PipeOutputManager::PipeOutputManager() :
m_hErrReadPipe(INVALID_HANDLE_VALUE),
m_hErrWritePipe(INVALID_HANDLE_VALUE),
m_hErrThread(NULL),
m_fDisposed(FALSE),
m_disposed(FALSE),
m_fdPreviousStdOut(-1),
m_fdPreviousStdErr(-1)
{
@ -23,26 +23,61 @@ PipeOutputManager::PipeOutputManager() :
PipeOutputManager::~PipeOutputManager()
{
StopOutputRedirection();
Stop();
}
VOID
PipeOutputManager::StopOutputRedirection()
HRESULT PipeOutputManager::Start()
{
SECURITY_ATTRIBUTES saAttr = { 0 };
HANDLE hStdErrReadPipe;
HANDLE hStdErrWritePipe;
m_fdPreviousStdOut = _dup(_fileno(stdout));
LOG_IF_DUPFAIL(m_fdPreviousStdOut);
m_fdPreviousStdErr = _dup(_fileno(stderr));
LOG_IF_DUPFAIL(m_fdPreviousStdErr);
RETURN_LAST_ERROR_IF(!CreatePipe(&hStdErrReadPipe, &hStdErrWritePipe, &saAttr, 0 /*nSize*/));
// TODO this still doesn't redirect calls in native, like wprintf
RETURN_LAST_ERROR_IF(!SetStdHandle(STD_ERROR_HANDLE, hStdErrWritePipe));
RETURN_LAST_ERROR_IF(!SetStdHandle(STD_OUTPUT_HANDLE, hStdErrWritePipe));
m_hErrReadPipe = hStdErrReadPipe;
m_hErrWritePipe = hStdErrWritePipe;
// Read the stderr handle on a separate thread until we get 4096 bytes.
m_hErrThread = CreateThread(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE)ReadStdErrHandle,
this, // thread function arguments
0, // default creation flags
NULL); // receive thread identifier
RETURN_LAST_ERROR_IF_NULL(m_hErrThread);
return S_OK;
}
HRESULT PipeOutputManager::Stop()
{
DWORD dwThreadStatus = 0;
STRA straStdOutput;
if (m_fDisposed)
if (m_disposed)
{
return;
return S_OK;
}
SRWExclusiveLock lock(m_srwLock);
if (m_fDisposed)
if (m_disposed)
{
return;
return S_OK;
}
m_fDisposed = true;
m_disposed = true;
fflush(stdout);
fflush(stderr);
@ -115,40 +150,6 @@ PipeOutputManager::StopOutputRedirection()
// Need to flush contents for the new stdout and stderr
_flushall();
}
}
HRESULT PipeOutputManager::Start()
{
SECURITY_ATTRIBUTES saAttr = { 0 };
HANDLE hStdErrReadPipe;
HANDLE hStdErrWritePipe;
m_fdPreviousStdOut = _dup(_fileno(stdout));
LOG_IF_DUPFAIL(m_fdPreviousStdOut);
m_fdPreviousStdErr = _dup(_fileno(stderr));
LOG_IF_DUPFAIL(m_fdPreviousStdErr);
RETURN_LAST_ERROR_IF(!CreatePipe(&hStdErrReadPipe, &hStdErrWritePipe, &saAttr, 0 /*nSize*/));
// TODO this still doesn't redirect calls in native, like wprintf
RETURN_LAST_ERROR_IF(!SetStdHandle(STD_ERROR_HANDLE, hStdErrWritePipe));
RETURN_LAST_ERROR_IF(!SetStdHandle(STD_OUTPUT_HANDLE, hStdErrWritePipe));
m_hErrReadPipe = hStdErrReadPipe;
m_hErrWritePipe = hStdErrWritePipe;
// Read the stderr handle on a separate thread until we get 4096 bytes.
m_hErrThread = CreateThread(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE)ReadStdErrHandle,
this, // thread function arguments
0, // default creation flags
NULL); // receive thread identifier
RETURN_LAST_ERROR_IF_NULL(m_hErrThread);
return S_OK;
}
@ -163,16 +164,17 @@ PipeOutputManager::ReadStdErrHandle(
pLoggingProvider->ReadStdErrHandleInternal();
}
bool PipeOutputManager::GetStdOutContent(STRA* struStdOutput)
bool PipeOutputManager::GetStdOutContent(STRA* straStdOutput)
{
bool fLogged = false;
if (m_dwStdErrReadTotal > 0)
{
if (SUCCEEDED(struStdOutput->Copy(m_pzFileContents, m_dwStdErrReadTotal)))
if (SUCCEEDED(straStdOutput->Copy(m_pzFileContents, m_dwStdErrReadTotal)))
{
fLogged = TRUE;
}
}
return fLogged;
}
@ -194,13 +196,19 @@ PipeOutputManager::ReadStdErrHandleInternal(
}
else if (GetLastError() == ERROR_BROKEN_PIPE)
{
break;
return;
}
}
char tempBuffer[MAX_PIPE_READ_SIZE];
while (true)
{
if (ReadFile(m_hErrReadPipe, tempBuffer, MAX_PIPE_READ_SIZE, &dwNumBytesRead, NULL))
{
}
else if (GetLastError() == ERROR_BROKEN_PIPE)
{
return;
}
}
}
VOID
PipeOutputManager::NotifyStartupComplete()
{
StopOutputRedirection();
}

View File

@ -13,30 +13,26 @@ public:
PipeOutputManager();
~PipeOutputManager();
// Inherited via ILoggerProvider
virtual HRESULT Start() override;
virtual void NotifyStartupComplete() override;
// Inherited via IOutputManager
virtual HRESULT Stop() override;
virtual bool GetStdOutContent(STRA* struStdOutput) override;
// Thread functions
VOID ReadStdErrHandleInternal(VOID);
static
VOID ReadStdErrHandle(LPVOID pContext);
private:
VOID StopOutputRedirection();
HANDLE m_hErrReadPipe;
HANDLE m_hErrWritePipe;
STRU m_struLogFilePath;
HANDLE m_hErrThread;
CHAR m_pzFileContents[MAX_PIPE_READ_SIZE] = { 0 };
DWORD m_dwStdErrReadTotal;
BOOL m_fDisposed;
SRWLOCK m_srwLock;
int m_fdPreviousStdOut;
int m_fdPreviousStdErr;
BOOL m_disposed;
};

View File

@ -38,33 +38,7 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
shutdownHandler,
onAsyncCompletion,
requestContext,
shutdownContext,
out var resetStandardStreams);
if (resetStandardStreams)
{
ResetStdOutHandles();
}
}
private static void ResetStdOutHandles()
{
// By using the PipeOutputRedirection, after calling RegisterCallbacks,
// stdout and stderr will be redirected to NULL. However, if something wrote
// to stdout before redirecting, (like a Console.WriteLine during startup),
// we need to call Console.Set* to pick up the modified consoles outputs.
Console.SetOut(CreateStreamWriter(Console.OpenStandardOutput()));
Console.SetError(CreateStreamWriter(Console.OpenStandardError()));
}
private static StreamWriter CreateStreamWriter(Stream stdStream)
{
return new StreamWriter(
stdStream,
encoding: Console.OutputEncoding,
bufferSize: 256,
leaveOpen: true)
{ AutoFlush = true };
shutdownContext);
}
public void Dispose()

View File

@ -59,8 +59,7 @@ namespace Microsoft.AspNetCore.Server.IIS
PFN_SHUTDOWN_HANDLER shutdownCallback,
PFN_ASYNC_COMPLETION asyncCallback,
IntPtr pvRequestContext,
IntPtr pvShutdownContext,
out bool resetStandardStreams);
IntPtr pvShutdownContext);
[DllImport(AspNetCoreModuleDll)]
private static extern unsafe int http_write_response_bytes(IntPtr pInProcessHandler, HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks, int nChunks, out bool fCompletionExpected);
@ -147,10 +146,9 @@ namespace Microsoft.AspNetCore.Server.IIS
PFN_SHUTDOWN_HANDLER shutdownCallback,
PFN_ASYNC_COMPLETION asyncCallback,
IntPtr pvRequestContext,
IntPtr pvShutdownContext,
out bool resetStandardStreams)
IntPtr pvShutdownContext)
{
Validate(register_callbacks(pInProcessApplication, requestCallback, shutdownCallback, asyncCallback, pvRequestContext, pvShutdownContext, out resetStandardStreams));
Validate(register_callbacks(pInProcessApplication, requestCallback, shutdownCallback, asyncCallback, pvRequestContext, pvShutdownContext));
}
public static unsafe int HttpWriteResponseBytes(IntPtr pInProcessHandler, HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks, int nChunks, out bool fCompletionExpected)

View File

@ -65,7 +65,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
}
AddTemporaryAppHostConfig();
var apppool = ConfigureAppPool(contentRoot);
ConfigureAppPool(contentRoot);
ConfigureSite(contentRoot, port);
@ -73,11 +73,11 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
_serverManager.CommitChanges();
await WaitUntilSiteStarted(apppool);
await WaitUntilSiteStarted();
}
}
private async Task WaitUntilSiteStarted(ApplicationPool appPool)
private async Task WaitUntilSiteStarted()
{
var sw = Stopwatch.StartNew();
@ -85,12 +85,19 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
{
try
{
var site = _serverManager.Sites.FirstOrDefault(s => s.Name.Equals(WebSiteName));
var serverManager = new ServerManager();
var appPool = serverManager.ApplicationPools.FirstOrDefault(s => s.Name.Equals(AppPoolName));
var site = serverManager.Sites.FirstOrDefault(s => s.Name.Equals(WebSiteName));
if (site.State == ObjectState.Started)
{
_logger.LogInformation($"Site {WebSiteName} has started.");
return;
var workerProcess = appPool.WorkerProcesses.SingleOrDefault();
if (workerProcess != null)
{
HostProcess = Process.GetProcessById(workerProcess.ProcessId);
_logger.LogInformation($"Site {WebSiteName} has started.");
return;
}
}
else if (site.State != ObjectState.Starting)
{
@ -99,7 +106,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
_logger.LogInformation($"Tried to start site, state: {state.ToString()}");
}
}
catch (COMException comException)
catch (Exception ex) when (ex is DllNotFoundException || (ex is COMException && (uint)ex.HResult == 0x800710D8) )
{
// Accessing the site.State property while the site
// is starting up returns the COMException
@ -107,7 +114,6 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
// (Exception from HRESULT: 0x800710D8)
// This also means the site is not started yet, so catch and retry
// after waiting.
_logger.LogWarning($"ComException: {comException.Message}");
}
await Task.Delay(_retryDelay);
@ -123,11 +129,15 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
return;
}
RestoreAppHostConfig();
StopSite();
StopAppPool();
_serverManager.CommitChanges();
await WaitUntilSiteStopped();
RestoreAppHostConfig();
}
private async Task WaitUntilSiteStopped()
@ -146,8 +156,11 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
{
if (site.State == ObjectState.Stopped)
{
_logger.LogInformation($"Site {WebSiteName} has stopped successfully.");
return;
if (HostProcess.HasExited)
{
_logger.LogInformation($"Site {WebSiteName} has stopped successfully.");
return;
}
}
}
catch (COMException)
@ -276,6 +289,20 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
return config;
}
private void StopSite()
{
var site = _serverManager.Sites.Where(sites => sites.Name == WebSiteName).SingleOrDefault();
site.Stop();
}
private void StopAppPool()
{
var appPool = _serverManager.ApplicationPools.Where(pool => pool.Name == AppPoolName).SingleOrDefault();
appPool.Stop();
}
private void SetGlobalModuleSection(Configuration config, string dllRoot)
{
var ancmFile = GetAncmLocation(dllRoot);

View File

@ -106,7 +106,11 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
5,
200);
Logger.LogInformation($"Found debug log file: {file}");
if (arr.Length == 0)
{
Logger.LogWarning($"{file} is empty.");
}
foreach (var line in arr)
{
Logger.LogInformation(line);

View File

@ -68,7 +68,6 @@
<section name="httpTracing" overrideModeDefault="Deny" />
<section name="isapiFilters" allowDefinition="MachineToApplication" overrideModeDefault="Deny" />
<section name="modules" allowDefinition="MachineToApplication" overrideModeDefault="Deny" />
<section name="applicationInitialization" allowDefinition="MachineToApplication" overrideModeDefault="Allow" />
<section name="odbcLogging" overrideModeDefault="Deny" />
<sectionGroup name="security">
<section name="access" overrideModeDefault="Deny" />

View File

@ -108,6 +108,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
public async Task CheckStdoutLoggingToPipe_DoesNotCrashProcess(string path)
{
var deploymentParameters = Helpers.GetBaseDeploymentParameters(publish: true);
deploymentParameters.GracefulShutdown = true;
var deploymentResult = await DeployAsync(deploymentParameters);
await Helpers.AssertStarts(deploymentResult, path);
@ -126,6 +127,8 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
public async Task CheckStdoutLoggingToPipeWithFirstWrite(string path)
{
var deploymentParameters = Helpers.GetBaseDeploymentParameters(publish: true);
deploymentParameters.GracefulShutdown = true;
var firstWriteString = path + path;
deploymentParameters.WebConfigBasedEnvironmentVariables["ASPNETCORE_INPROCESS_INITIAL_WRITE"] = firstWriteString;

View File

@ -0,0 +1,17 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit;
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
{
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)]
public sealed class SkipInVSTSAttribute : Attribute, ITestCondition
{
public bool IsMet => string.IsNullOrEmpty(Environment.GetEnvironmentVariable("SYSTEM_TASKDEFINITIONSURI"));
public string SkipReason => "Running in VSTS";
}
}

View File

@ -29,9 +29,6 @@ namespace PipeOutputManagerTests
PipeOutputManager* pManager = new PipeOutputManager();
ASSERT_EQ(S_OK, pManager->Start());
pManager->NotifyStartupComplete();
}
TEST(PipeManagerOutputTest, SetInvalidHandlesForErrAndOut)
@ -47,8 +44,6 @@ namespace PipeOutputManagerTests
PipeOutputManager* pManager = new PipeOutputManager();
ASSERT_EQ(S_OK, pManager->Start());
pManager->NotifyStartupComplete();
_dup2(m_fdPreviousStdOut, _fileno(stdout));
_dup2(m_fdPreviousStdErr, _fileno(stderr));

View File

@ -30,7 +30,6 @@
<None Include="$(MSBuildThisFileDirectory)..\..\src\AspNetCoreModuleV2\AspNetCore\bin\$(Configuration)\x64\aspnetcorev2.pdb" CopyToOutputDirectory="PreserveNewest" Visible="true" Link="%(FileName)%(Extension)" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Server.IntegrationTesting" Version="$(MicrosoftAspNetCoreServerIntegrationTestingPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(MicrosoftAspNetCoreHostingPackageVersion)" />

View File

@ -7,5 +7,4 @@ using Xunit;
[assembly: CollectionBehavior(DisableTestParallelization = true)]
[assembly: RequiresIIS]
[assembly: OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, SkipReason = "https://github.com/aspnet/IISIntegration/issues/1069")]

View File

@ -18,6 +18,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
// So these tests always have to use ports in this range, and we can't rely on OS-allocated ports without a whole lot of ceremony around
// creating self-signed certificates and registering SSL bindings with HTTP.sys
// Test specific to IISExpress
[SkipInVSTS]
public class HttpsTest : IISFunctionalTestBase
{
public HttpsTest(ITestOutputHelper output) : base(output)