private void PreparePrivateANCMFiles()
        {
            var    solutionRoot = GetSolutionDirectory();
            string outputPath   = string.Empty;

            _setupScriptPath = Path.Combine(solutionRoot, "tools");

            // First try with release build
            outputPath = Path.Combine(solutionRoot, "artifacts", "build", "AspNetCore", "bin", "Release");

            // If release build is not available, try with debug build
            if (!File.Exists(Path.Combine(outputPath, "Win32", "aspnetcore.dll")) ||
                !File.Exists(Path.Combine(outputPath, "x64", "aspnetcore.dll")) ||
                !File.Exists(Path.Combine(outputPath, "x64", "aspnetcore_schema.xml")))
            {
                outputPath = Path.Combine(solutionRoot, "artifacts", "build", "AspNetCore", "bin", "Debug");
            }

            if (!File.Exists(Path.Combine(outputPath, "Win32", "aspnetcore.dll")) ||
                !File.Exists(Path.Combine(outputPath, "x64", "aspnetcore.dll")) ||
                !File.Exists(Path.Combine(outputPath, "x64", "aspnetcore_schema.xml")))
            {
                throw new ApplicationException("aspnetcore.dll is not available; check if there is any build issue!!!");
            }

            //
            // NOTE:
            // ANCM schema file can't be overwritten here
            // If there is any schema change, that should be updated with installing setup or manually copied with the new schema file.
            //

            if (TestFlags.Enabled(TestFlags.UseIISExpress))
            {
                //
                // Initialize 32 bit IisExpressAspnetcore_path
                //
                IisExpressAspnetcore_path     = Path.Combine(outputPath, "x64", "aspnetcore.dll");
                IisExpressAspnetcore_X86_path = Path.Combine(outputPath, "Win32", "aspnetcore.dll");
            }
            else  // if use Full IIS server
            {
                bool updateSuccess = false;
                for (int i = 0; i < 3; i++)
                {
                    updateSuccess = false;
                    try
                    {
                        TestUtility.ResetHelper(ResetHelperMode.KillWorkerProcess);
                        TestUtility.ResetHelper(ResetHelperMode.StopW3svcStartW3svc);
                        Thread.Sleep(1000);

                        // Copy private file on Inetsrv directory
                        TestUtility.FileCopy(Path.Combine(outputPath, "x64", "aspnetcore.dll"), FullIisAspnetcore_path, overWrite: true, ignoreExceptionWhileDeletingExistingFile: false);

                        if (TestUtility.IsOSAmd64)
                        {
                            // Copy 32bit private file on Inetsrv directory
                            TestUtility.FileCopy(Path.Combine(outputPath, "Win32", "aspnetcore.dll"), FullIisAspnetcore_X86_path, overWrite: true, ignoreExceptionWhileDeletingExistingFile: false);
                        }
                        updateSuccess = true;
                    }
                    catch
                    {
                        updateSuccess = false;
                    }
                    if (updateSuccess)
                    {
                        break;
                    }
                }
                if (!updateSuccess)
                {
                    throw new ApplicationException("Failed to update aspnetcore.dll");
                }

                // update applicationhost.config for IIS server with the new private ASPNET Core file name
                if (TestFlags.Enabled(TestFlags.UseFullIIS))
                {
                    using (var iisConfig = new IISConfigUtility(ServerType.IIS, null))
                    {
                        iisConfig.AddModule("AspNetCoreModule", FullIisAspnetcore_path, null);
                    }
                }
            }
        }
        public InitializeTestMachine()
        {
            _referenceCount++;

            // This method should be called only one time
            if (_referenceCount == 1)
            {
                TestUtility.LogInformation("InitializeTestMachine::InitializeTestMachine() Start");

                _InitializeTestMachineCompleted = false;

                TestUtility.LogInformation("InitializeTestMachine::Start");
                if (Environment.ExpandEnvironmentVariables("%ANCMTEST_DEBUG%").ToLower() == "true")
                {
                    System.Diagnostics.Debugger.Launch();
                }

                //
                // Clean up IISExpress processes
                //
                TestUtility.ResetHelper(ResetHelperMode.KillIISExpress);

                //
                // Initalize IIS server
                //

                if (TestFlags.Enabled(TestFlags.UseFullIIS))
                {
                    InitializeIISServer();
                }
                else
                {
                    TestUtility.ResetHelper(ResetHelperMode.KillIISExpress);
                }

                string siteRootPath = TestRootDirectory;
                if (!Directory.Exists(siteRootPath))
                {
                    //
                    // Create a new directory and set the write permission for the SID of AuthenticatedUser
                    //
                    Directory.CreateDirectory(siteRootPath);
                    DirectorySecurity  sec = Directory.GetAccessControl(siteRootPath);
                    SecurityIdentifier authenticatedUser = new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null);
                    sec.AddAccessRule(new FileSystemAccessRule(authenticatedUser, FileSystemRights.Modify | FileSystemRights.Synchronize, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow));
                    Directory.SetAccessControl(siteRootPath, sec);
                }

                foreach (string directory in Directory.GetDirectories(siteRootPath))
                {
                    bool successDeleteChildDirectory = true;
                    try
                    {
                        TestUtility.DeleteDirectory(directory);
                    }
                    catch
                    {
                        successDeleteChildDirectory = false;
                        TestUtility.LogInformation("Failed to delete " + directory);
                    }
                    if (successDeleteChildDirectory)
                    {
                        try
                        {
                            TestUtility.DeleteDirectory(siteRootPath);
                        }
                        catch
                        {
                            TestUtility.LogInformation("Failed to delete " + siteRootPath);
                        }
                    }
                }

                //
                // Intialize Private ANCM files for Full IIS server or IISExpress
                //
                if (TestFlags.Enabled(TestFlags.UsePrivateANCM))
                {
                    PreparePrivateANCMFiles();
                }

                _InitializeTestMachineCompleted = true;
                TestUtility.LogInformation("InitializeTestMachine::InitializeTestMachine() End");
            }

            for (int i = 0; i < 120; i++)
            {
                if (_InitializeTestMachineCompleted)
                {
                    break;
                }
                else
                {
                    TestUtility.LogInformation("InitializeTestMachine::InitializeTestMachine() Waiting...");
                    Thread.Sleep(500);
                }
            }
            if (!_InitializeTestMachineCompleted)
            {
                throw new ApplicationException("InitializeTestMachine failed");
            }
        }
        public TestWebSite(IISConfigUtility.AppPoolBitness appPoolBitness, string loggerPrefix = "ANCMTest", bool copyAllPublishedFiles = false, bool attachAppVerifier = false, bool publishing = true, int tcpPort = -1)
        {
            AppPoolBitness = appPoolBitness;

            //
            // Initialize IisServerType
            //
            if (TestFlags.Enabled(TestFlags.UseFullIIS))
            {
                IisServerType = ServerType.IIS;
            }
            else
            {
                IisServerType = ServerType.IISExpress;
            }

            //
            // Use localhost hostname for IISExpress
            //
            if (IisServerType == ServerType.IISExpress &&
                TestFlags.Enabled(TestFlags.Wow64BitMode))
            {
                //
                // In Wow64/IISExpress test context, always use 32 bit worker process
                //
                if (AppPoolBitness == IISConfigUtility.AppPoolBitness.noChange)
                {
                    TestUtility.LogInformation("Warning!!! In Wow64, _appPoolBitness should be set with enable32bit");
                    AppPoolBitness = IISConfigUtility.AppPoolBitness.enable32Bit;
                }
            }

            TestUtility.LogInformation("TestWebSite::TestWebSite() Start");

            string solutionPath = InitializeTestMachine.GetSolutionDirectory();

            if (IisServerType == ServerType.IIS)
            {
                // check JitDebugger before continuing
                TestUtility.ResetHelper(ResetHelperMode.KillVSJitDebugger);
            }

            // initialize logger for TestUtility
            _logger = new LoggerFactory()
                      .AddConsole()
                      .CreateLogger(string.Format(loggerPrefix));

            testHelper = new TestUtility(_logger);

            //
            // Initialize context variables
            //
            string siteRootPath = string.Empty;
            string siteName     = string.Empty;
            string postfix      = string.Empty;

            // repeat three times until getting the valid temporary directory path
            for (int i = 0; i < 3; i++)
            {
                postfix      = Path.GetRandomFileName();
                siteName     = loggerPrefix.Replace(" ", "") + "_" + postfix;
                siteRootPath = Path.Combine(InitializeTestMachine.TestRootDirectory, siteName);
                if (!Directory.Exists(siteRootPath))
                {
                    break;
                }
            }

            TestUtility.DirectoryCopy(Path.Combine(solutionPath, "test", "WebRoot"), siteRootPath);
            string aspnetCoreAppRootPath = Path.Combine(siteRootPath, "AspNetCoreApp");
            string srcPath = TestUtility.GetApplicationPath();

            // copy http.config to the test site root directory and initialize iisExpressConfigPath with the path
            if (IisServerType == ServerType.IISExpress)
            {
                IisExpressConfigPath = Path.Combine(siteRootPath, "http.config");
                TestUtility.FileCopy(Path.Combine(solutionPath, "test", "AspNetCoreModule.Test", "http.config"), IisExpressConfigPath);
            }

            //
            // By default we use DotnetCore v2.0
            //
            string SDKVersion = "netcoreapp2.0";

            if (TestFlags.Enabled(TestFlags.UseDotNetCore21))
            {
                SDKVersion = "netcoreapp2.1";
            }

            string publishPath       = Path.Combine(srcPath, "bin", "Debug", SDKVersion, "publish");
            string publishPathOutput = Path.Combine(InitializeTestMachine.TestRootDirectory, "publishPathOutput");

            //
            // Publish aspnetcore app
            //
            if (_publishedAspnetCoreApp != true)
            {
                if ((publishing == false && File.Exists(Path.Combine(publishPath, "AspNetCoreModule.TestSites.Standard.dll"))) ||
                    Debugger.IsAttached && 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);

                    try
                    {
                        if (TestFlags.Enabled(TestFlags.UseDotNetCore21))
                        {
                            TestUtility.FileCopy(Path.Combine(srcPath, "AspNetCoreModule.TestSites.Standard.csproj.UseDotNetCore21"), Path.Combine(srcPath, "AspNetCoreModule.TestSites.Standard.csproj"));
                        }
                        else
                        {
                            TestUtility.FileCopy(Path.Combine(srcPath, "AspNetCoreModule.TestSites.Standard.csproj.UseDotNetCore20"), Path.Combine(srcPath, "AspNetCoreModule.TestSites.Standard.csproj"));
                        }
                    }
                    catch
                    {
                        TestUtility.LogInformation("Failed to overwrite project file, update the project file manually");
                    }

                    TestUtility.RunCommand("dotnet", argumentForDotNet);
                }

                if (!File.Exists(Path.Combine(publishPath, "AspNetCoreModule.TestSites.Standard.dll")))
                {
                    throw new Exception("Failed to publish");
                }
                TestUtility.DirectoryCopy(publishPath, publishPathOutput);
                TestUtility.FileCopy(Path.Combine(publishPathOutput, "web.config"), Path.Combine(publishPathOutput, "web.config.bak"));

                // Adjust the arguments attribute value with IISConfigUtility from a temporary site
                using (var iisConfig = new IISConfigUtility(IisServerType, IisExpressConfigPath))
                {
                    string tempSiteName     = "ANCMTest_Temp";
                    int    tempId           = InitializeTestMachine.SiteId - 1;
                    string argumentFileName = (new TestWebApplication("/", publishPathOutput, null)).GetArgumentFileName();
                    if (string.IsNullOrEmpty(argumentFileName))
                    {
                        argumentFileName = "AspNetCoreModule.TestSites.Standard.dll";
                    }
                    iisConfig.CreateSite(tempSiteName, HostNameBinding, publishPathOutput, tempId, tempId);
                    iisConfig.SetANCMConfig(tempSiteName, "/", "arguments", Path.Combine(publishPathOutput, argumentFileName));
                    iisConfig.DeleteSite(tempSiteName);
                }
                _publishedAspnetCoreApp = true;
            }

            if (copyAllPublishedFiles)
            {
                // Copy all the files in the pubishpath to the standardAppRootPath
                TestUtility.DirectoryCopy(publishPath, aspnetCoreAppRootPath);
                TestUtility.FileCopy(Path.Combine(publishPathOutput, "web.config.bak"), Path.Combine(aspnetCoreAppRootPath, "web.config"));
            }
            else
            {
                // Copy only web.config file, which points to the shared publishPathOutput, to the standardAppRootPath
                TestUtility.CreateDirectory(aspnetCoreAppRootPath);
                TestUtility.FileCopy(Path.Combine(publishPathOutput, "web.config"), Path.Combine(aspnetCoreAppRootPath, "web.config"));
            }

            //
            // initialize class member variables
            //
            string appPoolName = null;

            if (IisServerType == ServerType.IIS)
            {
                appPoolName = "AspNetCoreModuleTestAppPool";
            }
            else if (IisServerType == ServerType.IISExpress)
            {
                appPoolName = "Clr4IntegratedAppPool";
            }

            // Initialize member variables
            _hostName = "localhost";
            _siteName = siteName;
            _postFix  = postfix;
            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");
            RootAppContext.DeleteFile("app_offline.htm");
            RootAppContext.AppPoolName   = appPoolName;
            RootAppContext.IisServerType = IisServerType;

            AspNetCoreApp             = new TestWebApplication("/AspNetCoreApp", aspnetCoreAppRootPath, this);
            AspNetCoreApp.AppPoolName = appPoolName;
            AspNetCoreApp.RestoreFile("web.config");
            AspNetCoreApp.DeleteFile("app_offline.htm");
            AspNetCoreApp.IisServerType = IisServerType;

            WebSocketApp             = new TestWebApplication("/WebSocketApp", Path.Combine(siteRootPath, "WebSocket"), this);
            WebSocketApp.AppPoolName = appPoolName;
            WebSocketApp.RestoreFile("web.config");
            WebSocketApp.DeleteFile("app_offline.htm");
            WebSocketApp.IisServerType = IisServerType;

            URLRewriteApp             = new TestWebApplication("/URLRewriteApp", Path.Combine(siteRootPath, "URLRewrite"), this);
            URLRewriteApp.AppPoolName = appPoolName;
            URLRewriteApp.RestoreFile("web.config");
            URLRewriteApp.DeleteFile("app_offline.htm");
            URLRewriteApp.IisServerType = IisServerType;

            //
            // Create site and apps
            //
            using (var iisConfig = new IISConfigUtility(IisServerType, IisExpressConfigPath))
            {
                // Create apppool
                if (IisServerType == ServerType.IIS)
                {
                    iisConfig.DeleteAppPool(appPoolName);
                    iisConfig.CreateAppPool(appPoolName);
                    iisConfig.SetAppPoolSetting(appPoolName, "rapidFailProtectionMaxCrashes", 100);

                    // Switch bitness
                    if (TestUtility.IsOSAmd64 && appPoolBitness == IISConfigUtility.AppPoolBitness.enable32Bit)
                    {
                        iisConfig.SetAppPoolSetting(appPoolName, "enable32BitAppOnWin64", true);
                    }
                }

                if (TestFlags.Enabled(TestFlags.UsePrivateANCM) && IisServerType == ServerType.IISExpress)
                {
                    if (TestUtility.IsOSAmd64)
                    {
                        if (AppPoolBitness == IISConfigUtility.AppPoolBitness.enable32Bit)
                        {
                            iisConfig.AddModule("AspNetCoreModule", (InitializeTestMachine.IisExpressAspnetcore_X86_path), null);
                        }
                        else
                        {
                            iisConfig.AddModule("AspNetCoreModule", (InitializeTestMachine.IisExpressAspnetcore_path), null);
                        }
                    }
                    else
                    {
                        iisConfig.AddModule("AspNetCoreModule", (InitializeTestMachine.IisExpressAspnetcore_path), null);
                    }
                }

                iisConfig.CreateSite(siteName, HostNameBinding, RootAppContext.PhysicalPath, SiteId, TcpPort, appPoolName);
                iisConfig.CreateApp(siteName, AspNetCoreApp.Name, AspNetCoreApp.PhysicalPath, appPoolName);
                iisConfig.CreateApp(siteName, WebSocketApp.Name, WebSocketApp.PhysicalPath, appPoolName);
                iisConfig.CreateApp(siteName, URLRewriteApp.Name, URLRewriteApp.PhysicalPath, appPoolName);


                // Configure hostingModel for aspnetcore app
                if (TestFlags.Enabled(TestFlags.InprocessMode))
                {
                    AspNetCoreApp.HostingModel = TestWebApplication.HostingModelValue.Inprocess;
                    iisConfig.SetHandler(siteName, AspNetCoreApp.Name, "aspNetCore", "modules", "AspNetCoreModuleV2");
                    iisConfig.SetANCMConfig(siteName, AspNetCoreApp.Name, "hostingModel", TestWebApplication.HostingModelValue.Inprocess);
                    AspNetCoreApp.DeleteFile("web.config.bak");
                    AspNetCoreApp.BackupFile("web.config");
                }
            }

            TestUtility.LogInformation("TestWebSite::TestWebSite() End");
        }
        public void CreateDirectory(string directory)
        {
            string directoryPath = Path.Combine(_physicalPath, directory);

            TestUtility.CreateDirectory(directoryPath);
        }
        public void CreateFile(string[] content, string file = "app_offline.htm")
        {
            string filePath = Path.Combine(_physicalPath, file);

            TestUtility.CreateFile(filePath, content);
        }
        public void DeleteFile(string file = "app_offline.htm")
        {
            string filePath = Path.Combine(_physicalPath, file);

            TestUtility.DeleteFile(filePath);
        }