This commit is contained in:
jhkimnew 2018-03-06 17:21:56 -08:00 коммит произвёл GitHub
Родитель fd2f5524e9
Коммит 191b5128ba
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
13 изменённых файлов: 872 добавлений и 80 удалений

Просмотреть файл

@ -460,6 +460,85 @@ namespace AspNetCoreModule.Test.Framework
}
}
public void SetSiteRooAppConfig(string siteName, string attributeName, object attributeValue)
{
try
{
using (ServerManager serverManager = GetServerManager())
{
Configuration config = serverManager.GetApplicationHostConfiguration();
ConfigurationSection sitesSection = config.GetSection("system.applicationHost/sites");
ConfigurationElementCollection sitesCollection = sitesSection.GetCollection();
ConfigurationElement siteElement = FindElement(sitesCollection, "site", "name", siteName);
if (siteElement == null)
{
throw new Exception("SetSiteConfig::Site Not Found");
}
ConfigurationElementCollection applicationCollection = siteElement.GetCollection();
ConfigurationElement applicationElement = FindElement(applicationCollection, "application", "path", @"/");
applicationElement[attributeName] = attributeValue;
serverManager.CommitChanges();
}
}
catch (Exception ex)
{
throw ex;
}
}
public void SetWarmUpConfig(string siteName, string appName, string attributeName, object attributeValue, bool removeExisting = false)
{
try
{
using (ServerManager serverManager = GetServerManager())
{
Configuration config = serverManager.GetWebConfiguration(siteName, appName);
ConfigurationSection appInitializationSection = config.GetSection("system.webServer/applicationInitialization");
if (attributeName == "initializationPage" || attributeName == "hostName")
{
string initializationPage = (string) attributeValue;
string hostName = null;
if (attributeName == "hostName")
{
initializationPage = ((string[])attributeValue)[0];
hostName = ((string[])attributeValue)[1];
}
ConfigurationElementCollection intializationPagesCollection = appInitializationSection.GetCollection();
ConfigurationElement environmentVariableElement = intializationPagesCollection.CreateElement();
environmentVariableElement["initializationPage"] = initializationPage;
if (hostName != null)
{
environmentVariableElement["hostName"] = hostName;
}
var element = FindElement(intializationPagesCollection, "add", "initializationPage", initializationPage);
if (element != null)
{
if (removeExisting)
{
intializationPagesCollection.Remove(element);
}
else
{
throw new ApplicationException("duplicated collection item");
}
}
intializationPagesCollection.Add(environmentVariableElement);
}
else
{
appInitializationSection[attributeName] = attributeValue;
}
serverManager.CommitChanges();
}
}
catch (Exception ex)
{
throw ex;
}
}
public void SetANCMConfig(string siteName, string appName, string attributeName, object attributeValue, bool removeExisting = false)
{
try
@ -494,7 +573,7 @@ namespace AspNetCoreModule.Test.Framework
{
if (attributeName == "hostingModel")
{
if (attributeValue.ToString().ToLower().Trim() == "inprocess")
if (attributeValue.ToString().ToLower().Trim() == TestWebApplication.HostingModelValue.Inprocess)
{
ANCMInprocessMode = true;
}
@ -1271,11 +1350,13 @@ namespace AspNetCoreModule.Test.Framework
}
}
public void AddBindingToSite(string siteName, string ipAddress, int port, string host, string protocol = "http")
public void AddBindingToSite(string siteName, string ipAddress, int port, string host, string protocol = "http")
{
string bindingInfo = "";
if (ipAddress == null)
{
ipAddress = "*";
}
bindingInfo += ipAddress;
bindingInfo += ":";
bindingInfo += port;

Просмотреть файл

@ -305,7 +305,11 @@ namespace AspNetCoreModule.Test.Framework
{
InitializeIISServer();
}
else
{
TestUtility.ResetHelper(ResetHelperMode.KillIISExpress);
}
string siteRootPath = TestRootDirectory;
if (!Directory.Exists(siteRootPath))
{
@ -381,7 +385,14 @@ namespace AspNetCoreModule.Test.Framework
if (_referenceCount == 0)
{
TestUtility.LogInformation("InitializeTestMachine::Dispose() Start");
TestUtility.ResetHelper(ResetHelperMode.KillIISExpress);
try
{
TestUtility.ResetHelper(ResetHelperMode.KillIISExpress);
}
catch
{
// ignore
}
RollbackIISApplicationhostConfigFile();
TestUtility.LogInformation("InitializeTestMachine::Dispose() End");
}

Просмотреть файл

@ -642,6 +642,22 @@ namespace AspNetCoreModule.Test.Framework
result = true;
}
}
query = "Select * from Win32_Process Where Name = \"iisexpresstray.exe\"";
searcher = new ManagementObjectSearcher(query);
processList = searcher.Get();
foreach (ManagementObject obj in processList)
{
string[] argList = new string[] { string.Empty, string.Empty };
bool foundProcess = true;
if (foundProcess)
{
obj.InvokeMethod("Terminate", null);
result = true;
}
}
return result;
}

Просмотреть файл

@ -114,6 +114,12 @@ namespace AspNetCoreModule.Test.Framework
}
}
public static class HostingModelValue
{
public static string Inprocess = "inprocess";
public static string Outofprocess = "outofprocess";
}
private string _hostingModel = null;
public string HostingModel
{
@ -171,7 +177,7 @@ namespace AspNetCoreModule.Test.Framework
public string GetProcessFileName()
{
string result = null;
if (this.HostingModel == "inprocess")
if (this.HostingModel == TestWebApplication.HostingModelValue.Inprocess)
{
if (this.IisServerType == ServerType.IIS)
{

Просмотреть файл

@ -37,7 +37,7 @@ namespace AspNetCoreModule.Test.Framework
}
catch
{
if (this.AspNetCoreApp.HostingModel == "inprocess")
if (this.AspNetCoreApp.HostingModel == TestWebApplication.HostingModelValue.Inprocess)
{
// IISExpress seems to be already recycled under Inprocess mode.
}
@ -67,6 +67,8 @@ namespace AspNetCoreModule.Test.Framework
}
}
public string ThumbPrint { get; set; }
public string _siteName = null;
public string SiteName
{
@ -156,8 +158,8 @@ namespace AspNetCoreModule.Test.Framework
public string IisExpressConfigPath { get; set; }
private int _siteId { get; set; }
private IISConfigUtility.AppPoolBitness _appPoolBitness { get; set; }
public TestWebSite(IISConfigUtility.AppPoolBitness appPoolBitness, string loggerPrefix = "ANCMTest", bool startIISExpress = true, bool copyAllPublishedFiles = false, bool attachAppVerifier = false)
public TestWebSite(IISConfigUtility.AppPoolBitness appPoolBitness, string loggerPrefix = "ANCMTest", bool startIISExpress = true, bool copyAllPublishedFiles = false, bool attachAppVerifier = false, bool publishing = true, int tcpPort = -1)
{
_appPoolBitness = appPoolBitness;
@ -253,10 +255,18 @@ namespace AspNetCoreModule.Test.Framework
//
if (_publishedAspnetCoreApp != true)
{
string argumentForDotNet = "publish " + srcPath + " --framework " + SDKVersion;
TestUtility.LogInformation("TestWebSite::TestWebSite() StandardTestApp is not published, trying to publish on the fly: dotnet.exe " + argumentForDotNet);
TestUtility.DeleteDirectory(publishPath);
TestUtility.RunCommand("dotnet", argumentForDotNet);
if (publishing == false && File.Exists(Path.Combine(publishPath, "AspNetCoreModule.TestSites.Standard.dll")))
{
// skip publishing
}
else
{
string argumentForDotNet = "publish " + srcPath + " --framework " + SDKVersion;
TestUtility.LogInformation("TestWebSite::TestWebSite() StandardTestApp is not published, trying to publish on the fly: dotnet.exe " + argumentForDotNet);
TestUtility.DeleteDirectory(publishPath);
TestUtility.RunCommand("dotnet", argumentForDotNet);
}
if (!File.Exists(Path.Combine(publishPath, "AspNetCoreModule.TestSites.Standard.dll")))
{
throw new Exception("Failed to publish");
@ -294,9 +304,6 @@ namespace AspNetCoreModule.Test.Framework
TestUtility.FileCopy(Path.Combine(publishPathOutput, "web.config"), Path.Combine(aspnetCoreAppRootPath, "web.config"));
}
int tcpPort = InitializeTestMachine.SiteId++;
_siteId = tcpPort;
//
// initialize class member variables
//
@ -314,7 +321,16 @@ namespace AspNetCoreModule.Test.Framework
_hostName = "localhost";
_siteName = siteName;
_postFix = postfix;
_tcpPort = tcpPort;
if (tcpPort != -1)
{
_tcpPort = tcpPort;
}
else
{
_tcpPort = InitializeTestMachine.SiteId++;
InitializeTestMachine.SiteId++;
}
_siteId = _tcpPort;
RootAppContext = new TestWebApplication("/", Path.Combine(siteRootPath, "WebSite1"), this);
RootAppContext.RestoreFile("web.config");
@ -385,8 +401,8 @@ namespace AspNetCoreModule.Test.Framework
// Configure hostingModel for aspnetcore app
if (TestFlags.Enabled(TestFlags.InprocessMode))
{
AspNetCoreApp.HostingModel = "inprocess";
iisConfig.SetANCMConfig(siteName, AspNetCoreApp.Name, "hostingModel", "inprocess");
AspNetCoreApp.HostingModel = TestWebApplication.HostingModelValue.Inprocess;
iisConfig.SetANCMConfig(siteName, AspNetCoreApp.Name, "hostingModel", TestWebApplication.HostingModelValue.Inprocess);
}
}
@ -405,30 +421,58 @@ namespace AspNetCoreModule.Test.Framework
public void VerifyWorkerProcessRecycledUnderInprocessMode(string backendProcessId, int timeout = 5000)
{
if (AspNetCoreApp.HostingModel == "inprocess")
if (AspNetCoreApp.HostingModel != TestWebApplication.HostingModelValue.Inprocess)
{
if (backendProcessId == null)
{
System.Threading.Thread.Sleep(3000);
return; // do nothing for outofprocess
}
bool succeeded = false;
for (int i = 0; i < (timeout / 1000); i++)
{
Process backendProcess = null;
try
{
backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
}
else
catch
{
try
{
var backendProcess = Process.GetProcessById(Convert.ToInt32(backendProcessId));
backendProcess.WaitForExit(timeout);
}
catch
{
// IISExpress process is already recycled.
}
succeeded = true;
TestUtility.LogInformation("Process not found.");
break;
}
if (IisServerType == ServerType.IISExpress)
if (backendProcess == null)
{
// restart IISExpress
StartIISExpress();
succeeded = true;
break;
}
backendProcess.WaitForExit(1000);
if (this.IisServerType == ServerType.IISExpress && i == 3)
{
// exit after 3 seconds for IISExpress case
break;
}
}
if (succeeded == false)
{
if (this.IisServerType == ServerType.IIS)
{
throw new Exception("Failed to recycle IIS worker process");
}
else
{
// IISExpress should be killed if it can't be recycled
TestUtility.LogInformation("BugBug: Restart IISExpress...");
TestUtility.ResetHelper(ResetHelperMode.KillIISExpress);
}
}
if (IisServerType == ServerType.IISExpress)
{
// restart IISExpress
StartIISExpress();
}
}
@ -457,15 +501,9 @@ namespace AspNetCoreModule.Test.Framework
_iisExpressPidBackup = TestUtility.RunCommand(cmdline, argument, false, false);
}
public void AttachAppverifier()
public string GetAppVerifierPath()
{
string cmdline;
string processName = "iisexpress.exe";
if (IisServerType == ServerType.IIS)
{
processName = "w3wp.exe";
}
string argument = "-enable Heaps COM RPC Handles Locks Memory TLS Exceptions Threadpool Leak SRWLock -for " + processName;
string cmdline = null;
if (Directory.Exists(Environment.ExpandEnvironmentVariables("%ProgramFiles(x86)%")) && _appPoolBitness == IISConfigUtility.AppPoolBitness.enable32Bit)
{
cmdline = Path.Combine(Environment.ExpandEnvironmentVariables("%windir%"), "syswow64", "appverif.exe");
@ -482,6 +520,18 @@ namespace AspNetCoreModule.Test.Framework
throw new ApplicationException("Not found :" + cmdline + "; this test requires appverif.exe.");
}
}
return cmdline;
}
public void AttachAppverifier()
{
string cmdline = GetAppVerifierPath();
string processName = "iisexpress.exe";
if (IisServerType == ServerType.IIS)
{
processName = "w3wp.exe";
}
string argument = "-enable Heaps COM RPC Handles Locks Memory TLS Exceptions Threadpool Leak SRWLock -for " + processName;
try
{

Просмотреть файл

@ -368,6 +368,16 @@ namespace AspNetCoreModule.Test
return DoAppVerifierTest(appPoolBitness, shutdownTimeout, startUpMode, shutDownMode, repeatCount);
}
[ConditionalTheory]
[ANCMTestFlags(ANCMTestCondition)]
[OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)]
[InlineData(false)]
public Task V21_StressTest(bool enableAppVerifier)
{
return DoStressTest(enableAppVerifier);
}
//////////////////////////////////////////////////////////
// NOTE: below test scenarios are not valid for Win7 OS
//////////////////////////////////////////////////////////

Просмотреть файл

@ -89,7 +89,7 @@ namespace AspNetCoreModule.Test
Thread.Sleep(3000);
string backendProcessId = (await SendReceive(testSite.AspNetCoreApp.GetUri("GetProcessId"))).ResponseBody;
if (testSite.AspNetCoreApp.HostingModel == "inprocess" && backendProcessId_old != null)
if (testSite.AspNetCoreApp.HostingModel == TestWebApplication.HostingModelValue.Inprocess && backendProcessId_old != null)
{
Assert.Equal(backendProcessId_old, backendProcessId);
}
@ -370,6 +370,8 @@ namespace AspNetCoreModule.Test
bool setEnvironmentVariableConfiguration = true;
// Set authentication for ASPNETCORE_IIS_HTTPAUTH test scenarios
recycledProcessId = (await SendReceive(testSite.AspNetCoreApp.GetUri("GetProcessId"))).ResponseBody;
if (environmentVariableName == "ASPNETCORE_IIS_HTTPAUTH" && environmentVariableValue != "ignoredValue")
{
setEnvironmentVariableConfiguration = false;
@ -408,9 +410,9 @@ namespace AspNetCoreModule.Test
expectedValue++;
}
}
Thread.Sleep(500);
testSite.VerifyWorkerProcessRecycledUnderInprocessMode(recycledProcessId);
testSite.VerifyWorkerProcessRecycledUnderInprocessMode(null);
Thread.Sleep(500);
// check JitDebugger before continuing
CleanupVSJitDebuggerWindow();
@ -420,7 +422,7 @@ namespace AspNetCoreModule.Test
Assert.True(expectedEnvironmentVariableValue == (await SendReceive(testSite.AspNetCoreApp.GetUri("ExpandEnvironmentVariables" + environmentVariableName))).ResponseBody);
// verify environment variables passed to backend process
if (testSite.AspNetCoreApp.HostingModel != "inprocess")
if (testSite.AspNetCoreApp.HostingModel != TestWebApplication.HostingModelValue.Inprocess)
{
// Verify other common environment variables
string temp = (await SendReceive(testSite.AspNetCoreApp.GetUri("DumpEnvironmentVariables"))).ResponseBody;
@ -453,7 +455,7 @@ namespace AspNetCoreModule.Test
string appDllFileName = testSite.AspNetCoreApp.GetArgumentFileName();
testSite.AspNetCoreApp.CreateFile(new string[] { fileContent }, "App_Offline.Htm");
for (int i = 0; i < _repeatCount; i++)
{
// check JitDebugger before continuing
@ -601,7 +603,7 @@ namespace AspNetCoreModule.Test
{
using (var testSite = new TestWebSite(appPoolBitness, "DoRapidFailsPerMinuteTest"))
{
if (testSite.AspNetCoreApp.HostingModel == "inprocess")
if (testSite.AspNetCoreApp.HostingModel == TestWebApplication.HostingModelValue.Inprocess)
{
TestUtility.LogInformation("This test is not valid for Inprocess mode");
return;
@ -665,7 +667,7 @@ namespace AspNetCoreModule.Test
{
using (var testSite = new TestWebSite(appPoolBitness, "DoProcessesPerApplicationTest"))
{
if (testSite.AspNetCoreApp.HostingModel == "inprocess")
if (testSite.AspNetCoreApp.HostingModel == TestWebApplication.HostingModelValue.Inprocess)
{
TestUtility.LogInformation("This test is not valid for Inprocess mode");
return;
@ -870,7 +872,7 @@ namespace AspNetCoreModule.Test
public static async Task DoShutdownTimeLimitAndAppOfflineTest(IISConfigUtility.AppPoolBitness appPoolBitness, int valueOfshutdownTimeLimit, int expectedClosingTime, bool isGraceFullShutdownEnabled)
{
using (var testSite = new TestWebSite(appPoolBitness, "DoShutdownTimeLimitTest", startIISExpress: false))
using (var testSite = new TestWebSite(appPoolBitness, "DoShutdownTimeLimitAndAppOfflineTest", startIISExpress: false))
{
using (var iisConfig = new IISConfigUtility(testSite.IisServerType, testSite.IisExpressConfigPath))
{
@ -1000,6 +1002,13 @@ namespace AspNetCoreModule.Test
testSite.VerifyWorkerProcessRecycledUnderInprocessMode(backendProcessId);
//if (testSite.IisServerType == ServerType.IISExpress && testSite.AspNetCoreApp.HostingModel == TestWebApplication.HostingModelValue.Inprocess)
//{
// // for IISExpress/Inprocess mode, we need to put app_offline to close logfile handle
// testSite.AspNetCoreApp.CreateFile(new string[] { "test" }, "App_Offline.Htm");
// Thread.Sleep(1000)
//}
Thread.Sleep(2000);
startTime = DateTime.Now;
Thread.Sleep(1000);
@ -1037,16 +1046,17 @@ namespace AspNetCoreModule.Test
SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
TestUtility.GiveWritePermissionTo(logPath, sid);
backendProcessId = (await SendReceive(testSite.AspNetCoreApp.GetUri("GetProcessId"))).ResponseBody;
startTime = DateTime.Now;
Thread.Sleep(500);
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "stdoutLogEnabled", false);
// check JitDebugger before continuing
CleanupVSJitDebuggerWindow();
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "stdoutLogEnabled", true);
testSite.VerifyWorkerProcessRecycledUnderInprocessMode(null);
testSite.VerifyWorkerProcessRecycledUnderInprocessMode(backendProcessId);
Assert.True(backendProcessId != (await SendReceive(testSite.AspNetCoreApp.GetUri("GetProcessId"))).ResponseBody);
@ -1106,7 +1116,7 @@ namespace AspNetCoreModule.Test
{
using (var testSite = new TestWebSite(appPoolBitness, "DoForwardWindowsAuthTokenTest", startIISExpress: false))
{
if (testSite.AspNetCoreApp.HostingModel == "inprocess")
if (testSite.AspNetCoreApp.HostingModel == TestWebApplication.HostingModelValue.Inprocess)
{
TestUtility.LogInformation("This test is not valid for Inprocess mode");
return;
@ -1281,8 +1291,6 @@ namespace AspNetCoreModule.Test
{
using (var testSite = new TestWebSite(appPoolBitness, "DoCompressionTest", startIISExpress: false))
{
string recycledProcessId = (await SendReceive(testSite.AspNetCoreApp.GetUri("GetProcessId"))).ResponseBody;
using (var iisConfig = new IISConfigUtility(testSite.IisServerType, testSite.IisExpressConfigPath))
{
string startupClass = "StartupCompressionCaching";
@ -1312,6 +1320,7 @@ namespace AspNetCoreModule.Test
testSite.AspNetCoreApp.CreateFile(new string[] { "defaulthtm" }, @"wwwroot\default.htm");
testSite.StartIISExpress();
Thread.Sleep(1000);
SendReceiveContext result = null;
if (!useCompressionMiddleWare && !enableIISCompression)
@ -1351,8 +1360,6 @@ namespace AspNetCoreModule.Test
{
using (var testSite = new TestWebSite(appPoolBitness, "DoCachingTest", startIISExpress: false))
{
string recycledProcessId = (await SendReceive(testSite.AspNetCoreApp.GetUri("GetProcessId"))).ResponseBody;
using (var iisConfig = new IISConfigUtility(testSite.IisServerType, testSite.IisExpressConfigPath))
{
string startupClass = "StartupCompressionCaching";
@ -1650,19 +1657,18 @@ namespace AspNetCoreModule.Test
public static async Task DoWebSocketTest(IISConfigUtility.AppPoolBitness appPoolBitness, string testData)
{
using (var testSite = new TestWebSite(appPoolBitness, "DoWebSocketTest"))
using (var testSite = new TestWebSite(appPoolBitness, "DoWebSocketTest", startIISExpress: false))
{
string recycledProcessId = (await SendReceive(testSite.AspNetCoreApp.GetUri("GetProcessId"))).ResponseBody;
string appDllFileName = testSite.AspNetCoreApp.GetArgumentFileName();
using (var iisConfig = new IISConfigUtility(testSite.IisServerType, testSite.IisExpressConfigPath))
{
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "shutdownTimeLimit", 10);
testSite.VerifyWorkerProcessRecycledUnderInprocessMode(recycledProcessId);
}
testSite.StartIISExpress();
DateTime startTime = DateTime.Now;
await SendReceive(testSite.AspNetCoreApp.GetUri(), expectedResponseBody: "Running");
@ -1744,19 +1750,17 @@ namespace AspNetCoreModule.Test
public static async Task DoWebSocketAppOfflineTest(IISConfigUtility.AppPoolBitness appPoolBitness, string testData)
{
using (var testSite = new TestWebSite(appPoolBitness, "DoWebSocketTest"))
using (var testSite = new TestWebSite(appPoolBitness, "DoWebSocketAppOfflineTest", startIISExpress: false))
{
string recycledProcessId = (await SendReceive(testSite.AspNetCoreApp.GetUri("GetProcessId"))).ResponseBody;
string appDllFileName = testSite.AspNetCoreApp.GetArgumentFileName();
using (var iisConfig = new IISConfigUtility(testSite.IisServerType, testSite.IisExpressConfigPath))
{
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "shutdownTimeLimit", 10);
testSite.VerifyWorkerProcessRecycledUnderInprocessMode(recycledProcessId);
}
testSite.StartIISExpress();
DateTime startTime = DateTime.Now;
// Get Process ID
@ -1787,6 +1791,8 @@ namespace AspNetCoreModule.Test
// put app_offline
testSite.AspNetCoreApp.CreateFile(new string[] { fileContent }, "App_Offline.Htm");
//websocketClient.ExpectedDisposedConnection = true;
bool connectionClosedFromServer = websocketClient.WaitForWebSocketState(WebSocketState.ConnectionClosed);
//if (connectionClosedFromServer)
@ -1830,7 +1836,7 @@ namespace AspNetCoreModule.Test
public static async Task DoWebSocketRecycledWithConfigChangeTest(IISConfigUtility.AppPoolBitness appPoolBitness, string testData)
{
using (var testSite = new TestWebSite(appPoolBitness, "DoWebSocketTest"))
using (var testSite = new TestWebSite(appPoolBitness, "DoWebSocketRecycledWithConfigChangeTest"))
{
string recycledProcessId = (await SendReceive(testSite.AspNetCoreApp.GetUri("GetProcessId"))).ResponseBody;
@ -2115,7 +2121,7 @@ namespace AspNetCoreModule.Test
// Set Shutdown delay time to give more time for the backend program to do the gracefulshutdown
int shutdownDelayTime = 5000;
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "environmentVariable", new string[] { "ANCMTestShutdownDelay", shutdownDelayTime.ToString() });
if (startUpMode != DoAppVerifierTest_StartUpMode.DontUseGracefulShutdown)
{
// Verify websocket with app_offline.htm
@ -2143,12 +2149,12 @@ namespace AspNetCoreModule.Test
// put app_offline
testSite.AspNetCoreApp.CreateFile(new string[] { "test" }, "App_Offline.Htm");
Thread.Sleep(1000);
// wait for the gracefulshutdown finished
Thread.Sleep(shutdownDelayTime);
bool connectionClosedFromServer = websocketClient.WaitForWebSocketState(WebSocketState.ConnectionClosed);
// Verify server side connection closing is done successfully
Assert.True(connectionClosedFromServer, "Closing Handshake initiated from Server");
@ -2164,10 +2170,10 @@ namespace AspNetCoreModule.Test
// reset shutdownDelayTime
shutdownDelayTime = 0;
iisConfig.SetANCMConfig(
testSite.SiteName,
testSite.AspNetCoreApp.Name,
"environmentVariable",
new string[] { "ANCMTestShutdownDelay", shutdownDelayTime.ToString() },
testSite.SiteName,
testSite.AspNetCoreApp.Name,
"environmentVariable",
new string[] { "ANCMTestShutdownDelay", shutdownDelayTime.ToString() },
removeExisting: true); // reset existing correction item
// Verify websocket again
@ -2272,6 +2278,245 @@ namespace AspNetCoreModule.Test
}
}
public static async Task DoStressTest(bool enableAppVerifier)
{
if (!File.Exists(Environment.ExpandEnvironmentVariables("%systemdrive%\\ANCMStressTest.TXT")))
{
TestUtility.LogInformation("Skipping stress test");
return;
}
//
// While running this test, start stressing with running below command in a seperate powershell window
//
// (1..1000) | foreach { (Invoke-WebRequest http://localhost:1234/aspnetcoreapp/getprocessid).StatusCode; }
//
int timeoutValue = 5;
int numberOfSite = 0;
int tcpPort = 1234 + numberOfSite;
TestWebSite testSite = new TestWebSite(IISConfigUtility.AppPoolBitness.noChange, "DoStressTest", startIISExpress: false, publishing: false, tcpPort: tcpPort);
InitializeSite(testSite, timeoutValue : timeoutValue);
numberOfSite++;
tcpPort = 1234 + numberOfSite;
TestWebSite testSite2 = new TestWebSite(IISConfigUtility.AppPoolBitness.noChange, "DoStressTest2", startIISExpress: false, publishing: false, tcpPort: 1234 + numberOfSite);
InitializeSite(testSite2, timeoutValue: timeoutValue, disableGracefulShutdown: true);
numberOfSite++;
tcpPort = 1234 + numberOfSite;
TestWebSite testSite3 = new TestWebSite(IISConfigUtility.AppPoolBitness.enable32Bit, "DoStressTest3", startIISExpress: false, publishing: false, tcpPort: 1234 + numberOfSite);
InitializeSite(testSite3, timeoutValue: timeoutValue, disableGracefulShutdown: true);
numberOfSite++;
if (enableAppVerifier)
{
// enable AppVerifier
testSite.AttachAppverifier();
}
// reset existing worker process process
TestUtility.ResetHelper(ResetHelperMode.KillWorkerProcess);
Thread.Sleep(1000);
try
{
///////////////////////////////////
// Start test sceanrio
///////////////////////////////////
using (var iisConfig = new IISConfigUtility(testSite.IisServerType, testSite.IisExpressConfigPath))
{
bool attachDebugger = true;
for (int i=0; i<10; i++)
{
if (enableAppVerifier)
{
if (attachDebugger)
{
// send a startup request to start a new worker process
TestUtility.RunPowershellScript("( invoke-webrequest http://localhost:" + testSite.TcpPort + " ).StatusCode", "200", retryCount: 5);
Thread.Sleep(1000);
// attach debugger to the worker process
testSite.WorkerProcessID = 0;
// attach debugger
testSite.AttachWinDbg(testSite.WorkerProcessID, "sxi 80000003;g");
// verify windbg process is started
await SendReceive(testSite.AspNetCoreApp.GetUri(), expectedResponseBody: "Running", timeout: 10);
TestUtility.RunPowershellScript("(get-process -name windbg 2> $null).count", "1", retryCount: 5);
attachDebugger = false;
}
// verify debugger is running
TestUtility.RunPowershellScript("(get-process -name windbg 2> $null).count", "1", retryCount: 1);
}
// put delay time for each iteration
Thread.Sleep(3000);
// reset worker process id to refresh
testSite.WorkerProcessID = 0;
switch (i % 7)
{
case 0:
// StopAndStartAppPool:
iisConfig.StopAppPool(testSite.AspNetCoreApp.AppPoolName);
Thread.Sleep((timeoutValue + 1) * 1000);
iisConfig.StartAppPool(testSite.AspNetCoreApp.AppPoolName);
Thread.Sleep((timeoutValue + 1) * 1000);
attachDebugger = true;
break;
case 1:
// CreateAppOfflineHtm
testSite.AspNetCoreApp.DeleteFile("App_Offline.Htm");
testSite.AspNetCoreApp.CreateFile(new string[] { "test" }, "App_Offline.Htm");
break;
case 2:
// Re-create AppOfflineHtm
testSite.AspNetCoreApp.DeleteFile("App_Offline.Htm");
testSite.AspNetCoreApp.CreateFile(new string[] { "test" }, "App_Offline.Htm");
break;
case 3:
// Rename appOfflineHtm
testSite.AspNetCoreApp.MoveFile("App_Offline.Htm", "_App_Offline.Htm");
break;
case 4:
// ConfigurationChangeNotification
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "shutdownTimeLimit", timeoutValue + 1);
Thread.Sleep(1000);
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "shutdownTimeLimit", timeoutValue - 1);
Thread.Sleep(1000);
if (testSite.AspNetCoreApp.HostingModel == TestWebApplication.HostingModelValue.Inprocess)
{
attachDebugger = true;
}
break;
case 5:
iisConfig.SetAppPoolSetting(testSite.AspNetCoreApp.AppPoolName, "enable32BitAppOnWin64", true);
break;
case 6:
iisConfig.SetAppPoolSetting(testSite.AspNetCoreApp.AppPoolName, "enable32BitAppOnWin64", false);
break;
default:
throw new Exception("Not supported value");
}
}
InitializeSite(testSite, cleanup: true);
InitializeSite(testSite2, cleanup: true);
InitializeSite(testSite3, cleanup: true);
}
}
finally
{
if (enableAppVerifier)
{
// cleanup Appverifier
if (testSite != null)
{
testSite.DetachAppverifier();
}
}
}
TestUtility.ResetHelper(ResetHelperMode.KillWorkerProcess);
if (enableAppVerifier)
{
// cleanup windbg process incase it is still running
TestUtility.RunPowershellScript("stop-process -Name windbg -Force -Confirm:$false 2> $null");
}
}
private static void InitializeSite(TestWebSite testSite, int timeoutValue = 0, bool disableGracefulShutdown = false, bool cleanup = false)
{
using (var iisConfig = new IISConfigUtility(testSite.IisServerType, testSite.IisExpressConfigPath))
{
string hexIPAddress = "0x00";
int sslPort = testSite.TcpPort + 6300;
if (cleanup)
{
// Remove the SSL Certificate mapping
iisConfig.RemoveSSLCertificate(sslPort, hexIPAddress);
// Remove the newly created self signed certificate
iisConfig.DeleteCertificate(testSite.ThumbPrint);
// Remove the exported self signed certificate on rootCA
iisConfig.DeleteCertificate(testSite.ThumbPrint, @"Cert:\LocalMachine\Root");
return;
}
string hostName = "";
string subjectName = "localhost";
string ipAddress = "*";
string thumbPrint = null;
if (disableGracefulShutdown)
{
// disable graceful shutdown for the second site
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "environmentVariable", new string[] { "GracefulShutdown", "disabled" });
}
// Add https binding and get https uri information
iisConfig.AddBindingToSite(testSite.SiteName, ipAddress, sslPort, hostName, "https");
// Create a self signed certificate
thumbPrint = iisConfig.CreateSelfSignedCertificate(subjectName);
// Export the self signed certificate to rootCA
iisConfig.ExportCertificateTo(thumbPrint, sslStoreTo: @"Cert:\LocalMachine\Root");
// Configure http.sys ssl certificate mapping to IP:Port endpoint with the newly created self signed certificage
iisConfig.SetSSLCertificate(sslPort, hexIPAddress, thumbPrint);
testSite.ThumbPrint = thumbPrint;
// enable preloadEnabled for the site
iisConfig.SetSiteRooAppConfig(testSite.SiteName, "preloadEnabled", true);
iisConfig.SetWarmUpConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "skipManagedModules", true);
iisConfig.SetWarmUpConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "doAppInitAfterRestart", true);
iisConfig.SetWarmUpConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "initializationPage", "DoSleep1000");
// Set shutdownTimeLimit with 3 seconds and use 5 seconds for delay time to make the shutdownTimeout happen
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "shutdownTimeLimit", timeoutValue);
// set requestTimeout
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "requestTimeout", TimeSpan.Parse("00:00:5")); // 5 seconds
// set startupTimeout
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "startupTimeLimit", timeoutValue);
// Set shutdownTimeLimit
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "shutdownTimeLimit", timeoutValue);
// Set starupTimeLimit and shutdownTimeLimit for test app
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "environmentVariable", new string[] { "ANCMTestShutdownDelay", "1000" });
iisConfig.SetANCMConfig(testSite.SiteName, testSite.AspNetCoreApp.Name, "environmentVariable", new string[] { "ANCMTestStartupDelay", "1000" });
// starting IISExpress was deffered after creating test applications and now it is ready to start.
testSite.StartIISExpress();
}
}
private static bool CleanupVSJitDebuggerWindow()
{
bool result = TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);

Просмотреть файл

@ -16,5 +16,8 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.1.0-preview1-28291" />
</ItemGroup>
<ItemGroup>
<Folder Include="wwwroot\" />
</ItemGroup>
</Project>

Просмотреть файл

@ -88,7 +88,8 @@ namespace AspnetCoreModule.TestSites.Standard
}
host = WebHost.CreateDefaultBuilder(args)
.UseConfiguration(config)
.UseContentRoot(Directory.GetCurrentDirectory())
// BUGBUG below line is commented out because it causes 404 error with inprocess mode
//.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<StartupCompressionCaching>()
.Build();
}

Просмотреть файл

@ -390,10 +390,11 @@ namespace AspnetCoreModule.TestSites.Standard
// Sleep before starting
if (Startup.SleeptimeWhileStarting > 0)
{
Console.WriteLine("Begin: SleeptimeWhileStarting " + Startup.SleeptimeWhileStarting);
Thread.Sleep(Startup.SleeptimeWhileStarting);
Console.WriteLine("End: SleeptimeWhileStarting");
int temp = Startup.SleeptimeWhileStarting;
Startup.SleeptimeWhileStarting = 0;
Console.WriteLine("Begin: SleeptimeWhileStarting " + temp);
Thread.Sleep(temp);
Console.WriteLine("End: SleeptimeWhileStarting");
}
return context.Response.WriteAsync(response);

Просмотреть файл

@ -55,7 +55,8 @@ namespace AspnetCoreModule.TestSites.Standard
context.Context.Response.ContentType = "text/plain";
}
}
);
);
app.UseStaticFiles();
}
}
}

Просмотреть файл

@ -0,0 +1,366 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style>
table {
border: 0
}
.commslog-data {
font-family: Consolas, Courier New, Courier, monospace;
}
.commslog-server {
background-color: red;
color: white
}
.commslog-client {
background-color: green;
color: white
}
</style>
<style type="text/css">
body {
background-repeat: no-repeat;
padding-top: 85px;
font-family: Trebuchet MS, Lucida Sans Unicode, Arial, sans-serif;
font-size: 0.9em;
line-height: 130%;
}
.selectBoxArrow {
margin-top: 1px;
float: left;
position: absolute;
right: 1px;
}
.selectBoxInput {
border: 0px;
padding-left: 1px;
height: 16px;
position: absolute;
top: 0px;
left: 0px;
width: 600px;
}
.selectBox {
border: 1px solid #7f9db9;
height: 20px;
}
.selectBoxOptionContainer {
position: absolute;
border: 1px solid #7f9db9;
height: 100px;
background-color: #FFF;
left: -1px;
top: 20px;
visibility: hidden;
overflow: auto;
}
.selectBoxAnOption {
font-family: arial;
font-size: 12px;
cursor: default;
margin: 1px;
overflow: hidden;
white-space: nowrap;
}
.selectBoxIframe {
position: absolute;
background-color: #FFF;
border: 0px;
z-index: 999;
}
</style>
<script type="text/javascript">
// Path to arrow images
var arrowImage = './images/select_arrow.gif'; // Regular arrow
var arrowImageOver = './images/select_arrow_over.gif'; // Mouse over
var arrowImageDown = './images/select_arrow_down.gif'; // Mouse down
var selectBoxIds = 0;
var currentlyOpenedOptionBox = false;
var editableSelect_activeArrow = false;
function selectBox_switchImageUrl() {
if (this.src.indexOf(arrowImage) >= 0) {
this.src = this.src.replace(arrowImage, arrowImageOver);
} else {
this.src = this.src.replace(arrowImageOver, arrowImage);
}
}
function selectBox_showOptions() {
if (editableSelect_activeArrow && editableSelect_activeArrow != this) {
editableSelect_activeArrow.src = arrowImage;
}
editableSelect_activeArrow = this;
var numId = this.id.replace(/[^\d]/g, '');
var optionDiv = document.getElementById('selectBoxOptions' + numId);
if (optionDiv.style.display == 'block') {
optionDiv.style.display = 'none';
if (navigator.userAgent.indexOf('MSIE') >= 0) document.getElementById('selectBoxIframe' + numId).style.display = 'none';
this.src = arrowImageOver;
} else {
optionDiv.style.display = 'block';
if (navigator.userAgent.indexOf('MSIE') >= 0) document.getElementById('selectBoxIframe' + numId).style.display = 'block';
this.src = arrowImageDown;
if (currentlyOpenedOptionBox && currentlyOpenedOptionBox != optionDiv) currentlyOpenedOptionBox.style.display = 'none';
currentlyOpenedOptionBox = optionDiv;
}
}
function selectOptionValue() {
var parentNode = this.parentNode.parentNode;
var textInput = parentNode.getElementsByTagName('INPUT')[0];
textInput.value = this.innerHTML;
this.parentNode.style.display = 'none';
document.getElementById('arrowSelectBox' + parentNode.id.replace(/[^\d]/g, '')).src = arrowImageOver;
if (navigator.userAgent.indexOf('MSIE') >= 0) document.getElementById('selectBoxIframe' + parentNode.id.replace(/[^\d]/g, '')).style.display = 'none';
}
var activeOption;
function highlightSelectBoxOption() {
if (this.style.backgroundColor == '#316AC5') {
this.style.backgroundColor = '';
this.style.color = '';
} else {
this.style.backgroundColor = '#316AC5';
this.style.color = '#FFF';
}
if (activeOption) {
activeOption.style.backgroundColor = '';
activeOption.style.color = '';
}
activeOption = this;
}
function createEditableSelect(dest) {
dest.className = 'selectBoxInput';
var div = document.createElement('DIV');
div.style.styleFloat = 'left';
div.style.width = dest.offsetWidth + 16 + 'px';
div.style.position = 'relative';
div.id = 'selectBox' + selectBoxIds;
var parent = dest.parentNode;
parent.insertBefore(div, dest);
div.appendChild(dest);
div.className = 'selectBox';
div.style.zIndex = 10000 - selectBoxIds;
var img = document.createElement('IMG');
img.src = arrowImage;
img.className = 'selectBoxArrow';
img.onmouseover = selectBox_switchImageUrl;
img.onmouseout = selectBox_switchImageUrl;
img.onclick = selectBox_showOptions;
img.id = 'arrowSelectBox' + selectBoxIds;
div.appendChild(img);
var optionDiv = document.createElement('DIV');
optionDiv.id = 'selectBoxOptions' + selectBoxIds;
optionDiv.className = 'selectBoxOptionContainer';
optionDiv.style.width = div.offsetWidth - 2 + 'px';
div.appendChild(optionDiv);
if (navigator.userAgent.indexOf('MSIE') >= 0) {
var iframe = document.createElement('<IFRAME src="about:blank" frameborder=0>');
iframe.style.width = optionDiv.style.width;
iframe.style.height = optionDiv.offsetHeight + 'px';
iframe.style.display = 'none';
iframe.id = 'selectBoxIframe' + selectBoxIds;
div.appendChild(iframe);
}
if (dest.getAttribute('selectBoxOptions')) {
var options = dest.getAttribute('selectBoxOptions').split(';');
var optionsTotalHeight = 0;
var optionArray = new Array();
for (var no = 0; no < options.length; no++) {
var anOption = document.createElement('DIV');
anOption.innerHTML = options[no];
anOption.className = 'selectBoxAnOption';
anOption.onclick = selectOptionValue;
anOption.style.width = optionDiv.style.width.replace('px', '') - 2 + 'px';
anOption.onmouseover = highlightSelectBoxOption;
optionDiv.appendChild(anOption);
optionsTotalHeight = optionsTotalHeight + anOption.offsetHeight;
optionArray.push(anOption);
}
if (optionsTotalHeight > optionDiv.offsetHeight) {
for (var no = 0; no < optionArray.length; no++) {
optionArray[no].style.width = optionDiv.style.width.replace('px', '') - 22 + 'px';
}
}
optionDiv.style.display = 'none';
optionDiv.style.visibility = 'visible';
}
selectBoxIds = selectBoxIds + 1;
}
</script>
</head>
<body>
<h1>WebSocket Sample Application</h1>
<p id="stateLabel">Ready to connect...</p>
<div>
<label for="connectionUrl">WebSocket Server URL:</label>
<input id="connectionUrl" />
<button id="connectButton" type="submit">Connect</button>
</div>
<p></p>
<div>
<label for="sendMessage">Message to send:</label>
<input id="sendMessage" disabled selectBoxOptions="CloseFromServerBugRepro;CloseFromServerWithIgnoringExceptionError" />
<button id="sendButton" type="submit" disabled>Send</button>
<button id="closeButton" disabled>Close Socket</button>
<button id="clearButton">Clear Log</button>
</div>
<h2>Communication Log</h2>
<table style="width: 800px">
<thead>
<tr>
<td style="width: 100px">From</td>
<td style="width: 100px">To</td>
<td>Data</td>
</tr>
</thead>
<tbody id="commsLog"></tbody>
</table>
<script type="text/javascript">
createEditableSelect(document.getElementById("sendMessage"));
</script>
<script>
var connectionForm = document.getElementById("connectionForm");
var connectionUrl = document.getElementById("connectionUrl");
var connectButton = document.getElementById("connectButton");
var stateLabel = document.getElementById("stateLabel");
var sendMessage = document.getElementById("sendMessage");
var sendButton = document.getElementById("sendButton");
var sendForm = document.getElementById("sendForm");
var commsLog = document.getElementById("commsLog");
var socket;
var scheme = document.location.protocol == "https:" ? "wss" : "ws";
var port = document.location.port ? (":" + document.location.port) : "";
connectionUrl.value = scheme + "://" + document.location.hostname + port + "/ws";
function updateState() {
function disable() {
sendMessage.disabled = true;
sendButton.disabled = true;
closeButton.disabled = true;
}
function enable() {
sendMessage.disabled = false;
sendButton.disabled = false;
closeButton.disabled = false;
}
connectionUrl.disabled = true;
connectButton.disabled = true;
if (!socket) {
disable();
} else {
switch (socket.readyState) {
case WebSocket.CLOSED:
stateLabel.innerHTML = "Closed";
disable();
connectionUrl.disabled = false;
connectButton.disabled = false;
break;
case WebSocket.CLOSING:
stateLabel.innerHTML = "Closing...";
disable();
break;
case WebSocket.CONNECTING:
stateLabel.innerHTML = "Connecting...";
disable();
break;
case WebSocket.OPEN:
stateLabel.innerHTML = "Open";
enable();
break;
default:
stateLabel.innerHTML = "Unknown WebSocket State: " + socket.readyState;
disable();
break;
}
}
}
closeButton.onclick = function () {
if (!socket || socket.readyState != WebSocket.OPEN) {
alert("socket not connected");
}
socket.close(1000, "Closing from client");
}
clearButton.onclick = function () {
var table = document.getElementById("commsLog");
table.innerHTML = "";
}
sendButton.onclick = function () {
if (!socket || socket.readyState != WebSocket.OPEN) {
alert("socket not connected");
}
var data = sendMessage.value;
socket.send(data);
//document.getElementById("sendMessage").value = "";
commsLog.innerHTML += '<tr>' +
'<td class="commslog-client">Client</td>' +
'<td class="commslog-server">Server</td>' +
'<td class="commslog-data">' + data + '</td>'
'</tr>';
}
connectButton.onclick = function () {
stateLabel.innerHTML = "Connecting";
socket = new WebSocket(connectionUrl.value);
socket.onopen = function (event) {
updateState();
commsLog.innerHTML += '<tr>' +
'<td colspan="3" class="commslog-data">Connection opened</td>' +
'</tr>';
};
socket.onclose = function (event) {
updateState();
commsLog.innerHTML += '<tr>' +
'<td colspan="3" class="commslog-data">Connection closed. Code: ' + event.code + '. Reason: ' + event.reason + '</td>' +
'</tr>';
};
socket.onerror = updateState;
socket.onmessage = function (event) {
commsLog.innerHTML += '<tr>' +
'<td class="commslog-server">Server</td>' +
'<td class="commslog-client">Client</td>' +
'<td class="commslog-data">' + event.data + '</td>'
'</tr>';
};
};
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1 @@
test.htm