<commit_before>﻿// 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 System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.AspNetCore.Server.IntegrationTesting.Common;
using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.Logging;

namespace Microsoft.AspNetCore.Server.IntegrationTesting
{
    /// <summary>
    /// Deployment helper for IISExpress.
    /// </summary>
    public class IISExpressDeployer : ApplicationDeployer
    {
        private const string IISExpressRunningMessage = "IIS Express is running.";
        private const string FailedToInitializeBindingsMessage = "Failed to initialize site bindings";
        private const string UnableToStartIISExpressMessage = "Unable to start iisexpress.";
        private const int MaximumAttempts = 5;

        private static readonly Regex UrlDetectorRegex = new Regex(@"^\s*Successfully registered URL ""(?<url>[^""]+)"" for site.*$");

        private Process _hostProcess;

        public IISExpressDeployer(DeploymentParameters deploymentParameters, ILoggerFactory loggerFactory)
            : base(deploymentParameters, loggerFactory)
        {
        }

        public bool IsWin8OrLater
        {
            get
            {
                var win8Version = new Version(6, 2);

                return (Environment.OSVersion.Version >= win8Version);
            }
        }

        public bool Is64BitHost
        {
            get
            {
                return Environment.Is64BitOperatingSystem;
            }
        }

        public override async Task<DeploymentResult> DeployAsync()
        {
            using (Logger.BeginScope("Deployment"))
            {
                // Start timer
                StartTimer();

                // For now we always auto-publish. Otherwise we'll have to write our own local web.config for the HttpPlatformHandler
                DeploymentParameters.PublishApplicationBeforeDeployment = true;
                if (DeploymentParameters.PublishApplicationBeforeDeployment)
                {
                    DotnetPublish();
                }

                var contentRoot = DeploymentParameters.PublishApplicationBeforeDeployment ? DeploymentParameters.PublishedApplicationRootPath : DeploymentParameters.ApplicationPath;

                var testUri = TestUriHelper.BuildTestUri(ServerType.IISExpress, DeploymentParameters.ApplicationBaseUriHint);

                // Launch the host process.
                var (actualUri, hostExitToken) = await StartIISExpressAsync(testUri, contentRoot);

                Logger.LogInformation("Application ready at URL: {appUrl}", actualUri);

                // Right now this works only for urls like http://localhost:5001/. Does not work for http://localhost:5001/subpath.
                return new DeploymentResult(
                    LoggerFactory,
                    DeploymentParameters,
                    applicationBaseUri: actualUri.ToString(),
                    contentRoot: contentRoot,
                    hostShutdownToken: hostExitToken);
            }
        }

        private async Task<(Uri url, CancellationToken hostExitToken)> StartIISExpressAsync(Uri uri, string contentRoot)
        {
            using (Logger.BeginScope("StartIISExpress"))
            {
                var port = uri.Port;
                if (port == 0)
                {
                    port = TestUriHelper.GetNextPort();
                }

                for (var attempt = 0; attempt < MaximumAttempts; attempt++)
                {
                    Logger.LogInformation("Attempting to start IIS Express on port: {port}", port);

                    if (!string.IsNullOrWhiteSpace(DeploymentParameters.ServerConfigTemplateContent))
                    {
                        var serverConfig = DeploymentParameters.ServerConfigTemplateContent;

                        // Pass on the applicationhost.config to iis express. With this don't need to pass in the /path /port switches as they are in the applicationHost.config
                        // We take a copy of the original specified applicationHost.Config to prevent modifying the one in the repo.

                        if (serverConfig.Contains("[ANCMPath]"))
                        {
                            // We need to pick the bitness based the OS / IIS Express, not the application.
                            // We'll eventually add support for choosing which IIS Express bitness to run: https://github.com/aspnet/Hosting/issues/880
                            var ancmFile = Path.Combine(contentRoot, Is64BitHost ? @"x64\aspnetcore.dll" : @"x86\aspnetcore.dll");
                            // Bin deployed by Microsoft.AspNetCore.AspNetCoreModule.nupkg

                            if (!File.Exists(Environment.ExpandEnvironmentVariables(ancmFile)))
                            {
                                throw new FileNotFoundException("AspNetCoreModule could not be found.", ancmFile);
                            }

                            Logger.LogDebug("Writing ANCMPath '{ancmPath}' to config", ancmFile);
                            serverConfig =
                                serverConfig.Replace("[ANCMPath]", ancmFile);
                        }

                        Logger.LogDebug("Writing ApplicationPhysicalPath '{applicationPhysicalPath}' to config", contentRoot);
                        Logger.LogDebug("Writing Port '{port}' to config", port);
                        serverConfig =
                            serverConfig
                                .Replace("[ApplicationPhysicalPath]", contentRoot)
                                .Replace("[PORT]", port.ToString());

                        DeploymentParameters.ServerConfigLocation = Path.GetTempFileName();

                        if (serverConfig.Contains("[HostingModel]"))
                        {
                            var hostingModel = DeploymentParameters.HostingModel.ToString();
                            serverConfig.Replace("[HostingModel]", hostingModel);
                            Logger.LogDebug("Writing HostingModel '{hostingModel}' to config", hostingModel);
                        }

                        Logger.LogDebug("Saving Config to {configPath}", DeploymentParameters.ServerConfigLocation);

                        if (Logger.IsEnabled(LogLevel.Trace))
                        {
                            Logger.LogTrace($"Config File Content:{Environment.NewLine}===START CONFIG==={Environment.NewLine}{{configContent}}{Environment.NewLine}===END CONFIG===", serverConfig);
                        }
<commit_msg>Check existence of ANCMV2 Path (#1397)<commit_after>﻿// 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 System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.AspNetCore.Server.IntegrationTesting.Common;
using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.Logging;

namespace Microsoft.AspNetCore.Server.IntegrationTesting
{
    /// <summary>
    /// Deployment helper for IISExpress.
    /// </summary>
    public class IISExpressDeployer : ApplicationDeployer
    {
        private const string IISExpressRunningMessage = "IIS Express is running.";
        private const string FailedToInitializeBindingsMessage = "Failed to initialize site bindings";
        private const string UnableToStartIISExpressMessage = "Unable to start iisexpress.";
        private const int MaximumAttempts = 5;

        private static readonly Regex UrlDetectorRegex = new Regex(@"^\s*Successfully registered URL ""(?<url>[^""]+)"" for site.*$");

        private Process _hostProcess;

        public IISExpressDeployer(DeploymentParameters deploymentParameters, ILoggerFactory loggerFactory)
            : base(deploymentParameters, loggerFactory)
        {
        }

        public bool IsWin8OrLater
        {
            get
            {
                var win8Version = new Version(6, 2);

                return (Environment.OSVersion.Version >= win8Version);
            }
        }

        public bool Is64BitHost
        {
            get
            {
                return Environment.Is64BitOperatingSystem;
            }
        }

        public override async Task<DeploymentResult> DeployAsync()
        {
            using (Logger.BeginScope("Deployment"))
            {
                // Start timer
                StartTimer();

                // For now we always auto-publish. Otherwise we'll have to write our own local web.config for the HttpPlatformHandler
                DeploymentParameters.PublishApplicationBeforeDeployment = true;
                if (DeploymentParameters.PublishApplicationBeforeDeployment)
                {
                    DotnetPublish();
                }

                var contentRoot = DeploymentParameters.PublishApplicationBeforeDeployment ? DeploymentParameters.PublishedApplicationRootPath : DeploymentParameters.ApplicationPath;

                var testUri = TestUriHelper.BuildTestUri(ServerType.IISExpress, DeploymentParameters.ApplicationBaseUriHint);

                // Launch the host process.
                var (actualUri, hostExitToken) = await StartIISExpressAsync(testUri, contentRoot);

                Logger.LogInformation("Application ready at URL: {appUrl}", actualUri);

                // Right now this works only for urls like http://localhost:5001/. Does not work for http://localhost:5001/subpath.
                return new DeploymentResult(
                    LoggerFactory,
                    DeploymentParameters,
                    applicationBaseUri: actualUri.ToString(),
                    contentRoot: contentRoot,
                    hostShutdownToken: hostExitToken);
            }
        }

        private async Task<(Uri url, CancellationToken hostExitToken)> StartIISExpressAsync(Uri uri, string contentRoot)
        {
            using (Logger.BeginScope("StartIISExpress"))
            {
                var port = uri.Port;
                if (port == 0)
                {
                    port = TestUriHelper.GetNextPort();
                }

                for (var attempt = 0; attempt < MaximumAttempts; attempt++)
                {
                    Logger.LogInformation("Attempting to start IIS Express on port: {port}", port);

                    if (!string.IsNullOrWhiteSpace(DeploymentParameters.ServerConfigTemplateContent))
                    {
                        var serverConfig = DeploymentParameters.ServerConfigTemplateContent;

                        // Pass on the applicationhost.config to iis express. With this don't need to pass in the /path /port switches as they are in the applicationHost.config
                        // We take a copy of the original specified applicationHost.Config to prevent modifying the one in the repo.

                        if (serverConfig.Contains("[ANCMPath]"))
                        {
                            // We need to pick the bitness based the OS / IIS Express, not the application.
                            // We'll eventually add support for choosing which IIS Express bitness to run: https://github.com/aspnet/Hosting/issues/880
                            var ancmFile = Path.Combine(contentRoot, Is64BitHost ? @"x64\aspnetcore.dll" : @"x86\aspnetcore.dll");
                            // Bin deployed by Microsoft.AspNetCore.AspNetCoreModule.nupkg

                            if (!File.Exists(Environment.ExpandEnvironmentVariables(ancmFile)))
                            {
                                throw new FileNotFoundException("AspNetCoreModule could not be found.", ancmFile);
                            }

                            Logger.LogDebug("Writing ANCMPath '{ancmFile}' to config", ancmFile);
                            serverConfig =
                                serverConfig.Replace("[ANCMPath]", ancmFile);
                        }

                        if (serverConfig.Contains("[ANCMV2Path]"))
                        {
                            var ancmFile = Path.Combine(contentRoot, Is64BitHost ? @"x64\aspnetcorev2.dll" : @"x86\aspnetcorev2.dll");

                            if (!File.Exists(Environment.ExpandEnvironmentVariables(ancmFile)))
                            {
                                throw new FileNotFoundException("AspNetCoreModuleV2 could not be found.", ancmFile);
                            }

                            Logger.LogDebug("Writing ANCMV2Path '{ancmFile}' to config", ancmFile);
                            serverConfig =
                                serverConfig.Replace("[ANCMV2Path]", ancmFile);
                        }

                        Logger.LogDebug("Writing ApplicationPhysicalPath '{applicationPhysicalPath}' to config", contentRoot);
                        Logger.LogDebug("Writing Port '{port}' to config", port);
                        serverConfig =
                            serverConfig
                                .Replace("[ApplicationPhysicalPath]", contentRoot)
                                .Replace("[PORT]", port.ToString());

                        DeploymentParameters.ServerConfigLocation = Path.GetTempFileName();

                        if (serverConfig.Contains("[HostingModel]"))
                        {
                            var hostingModel = DeploymentParameters.HostingModel.ToString();
                            serverConfig.Replace("[HostingModel]", hostingModel);
                            Logger.LogDebug("Writing HostingModel '{hostingModel}' to config", hostingModel);
                        }

                        Logger.LogDebug("Saving Config to {configPath}", DeploymentParameters.ServerConfigLocation);

                        if (Logger.IsEnabled(LogLevel.Trace))
                        {
                            Logger.LogTrace($"Config File Content:{Environment.NewLine}===START CONFIG==={Environment.NewLine}{{configContent}}{Environment.NewLine}===END CONFIG===", serverConfig);
                        }

{'fraction_non_alphanumeric': 0.0796913411636165, 'fraction_numerical': 0.005394700901393062, 'mean_word_length': 1.764772512743062, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '986329', 'n_tokens_mistral': 3401, 'n_tokens_neox': 3161, 'n_words': 828}