<commit_before>﻿/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the Apache License, Version 2.0, please send an email to 
 * <EMAIL>. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Apache License, Version 2.0.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * ***************************************************************************/

extern alias analysis;
extern alias util;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Threading;
using Microsoft.PythonTools;
using Microsoft.PythonTools.Interpreter;
using Microsoft.PythonTools.Project;
using Microsoft.PythonTools.Project.Web;
using Microsoft.TC.TestHostAdapters;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.VisualStudioTools;
using Microsoft.VisualStudioTools.Project;
using TestUtilities;
using TestUtilities.Python;
using TestUtilities.UI;
using TestUtilities.UI.Python;
using InterpreterExt = analysis::Microsoft.PythonTools.Interpreter.PythonInterpreterFactoryExtensions;
using UIThread = util::Microsoft.VisualStudioTools.UIThread;

namespace PythonToolsUITests {
    [TestClass]
    public class WebProjectTests {
        [ClassInitialize]
        public static void DoDeployment(TestContext context) {
            AssertListener.Initialize();
            PythonTestData.Deploy();
        }

        public TestContext TestContext { get; set; }

        [TestMethod, Priority(0), TestCategory("Core")]
        [HostType("TC Dynamic"), DynamicHostType(typeof(VsIdeHostAdapter))]
        public void LoadWebFlavoredProject() {
            using (var app = new VisualStudioApp(VsIdeTestHostContext.Dte)) {
                var project = app.OpenProject(@"TestData\EmptyWebProject.sln");
                Assert.AreEqual("EmptyWebProject.pyproj", Path.GetFileName(project.FileName), "Wrong project file name");

                var catids = VsIdeTestHostContext.Dte.ObjectExtenders.GetContextualExtenderCATIDs();
                dynamic extender = project.Extender["WebApplication"];
                Assert.IsNotNull(extender, "No WebApplication extender");
                extender.StartWebServerOnDebug = true;
                extender.StartWebServerOnDebug = false;

                var proj = project.GetCommonProject();
                var ccp = proj as IPythonProject2;
                Assert.IsNotNull(ccp);
                Assert.IsNotNull(ccp.FindCommand("PythonRunWebServerCommand"), "No PythonRunWebServerCommand");
                Assert.IsNotNull(ccp.FindCommand("PythonDebugWebServerCommand"), "No PythonDebugWebServerCommand");
                Assert.IsNull(ccp.FindCommand("PythonUpgradeWebFrameworkCommand"), "Unexpected PythonUpgradeWebFrameworkCommand");
            }
        }

        private static void CheckCommandLineArgs(string setValue, string expectedValue = null) {
            using (var app = new VisualStudioApp(VsIdeTestHostContext.Dte)) {
                var project = app.OpenProject(@"TestData\CheckCommandLineArgs.sln");

                var proj = project.GetCommonProject() as IPythonProject2;
                Assert.IsNotNull(proj);

                var outFile = Path.Combine(Path.GetDirectoryName(project.FullName), "output.txt");

                foreach (var cmdName in new[] { "PythonRunWebServerCommand", "PythonDebugWebServerCommand" }) {
                    Console.WriteLine("Testing {0}, writing to {1}", cmdName, outFile);

                    if (File.Exists(outFile)) {
                        File.Delete(outFile);
                    }

                    UIThread.Invoke(() => {
                        proj.SetProperty("CommandLineArguments", string.Format("\"{0}\" \"{1}\"", setValue, outFile));
                        proj.FindCommand(cmdName).Execute(proj);
                    });

                    for (int retries = 10; retries > 0 && !File.Exists(outFile); --retries) {
                        Thread.Sleep(100);
                    }

                    Assert.AreEqual(expectedValue ?? setValue, File.ReadAllText(outFile).Trim());
                }
            }
        }

        [TestMethod, Priority(0), TestCategory("Core")]
        [HostType("TC Dynamic"), DynamicHostType(typeof(VsIdeHostAdapter))]
        public void WebProjectCommandLineArgs() {
            CheckCommandLineArgs(Guid.NewGuid().ToString("N"));
        }

        [TestMethod, Priority(0), TestCategory("Core")]
        [HostType("TC Dynamic"), DynamicHostType(typeof(VsIdeHostAdapter))]
        public void WebProjectStartupModuleArgs() {
            CheckCommandLineArgs("{StartupModule}", "CheckCommandLineArgs");
        }

        [TestMethod, Priority(0), TestCategory("Core")]
        [HostType("TC Dynamic"), DynamicHostType(typeof(VsIdeHostAdapter))]
        public void WebProjectStaticUri() {
            using (var app = new VisualStudioApp(VsIdeTestHostContext.Dte)) {
                var project = app.CreateProject(
                    PythonVisualStudioApp.TemplateLanguageName,
                    PythonVisualStudioApp.EmptyWebProjectTemplate,
                    TestData.GetTempPath(),
                    "WebProjectStaticUri"
                );

                var proj = project.GetCommonProject() ;
                Assert.IsNotNull(proj);

                UIThread.Invoke(() => {
                    proj.SetProjectProperty("PythonWsgiHandler", "NoHandler");

                    proj.SetProjectProperty("StaticUriPattern", "");
                });
                app.ExecuteCommand("Build.RebuildSolution");
                app.WaitForOutputWindowText("Build", "1 succeeded");

                UIThread.Invoke(() => {
                    proj.SetProjectProperty("StaticUriPattern", "^/static/.*$");
                });
                app.ExecuteCommand("Build.RebuildSolution");
                app.WaitForOutputWindowText("Build", "1 succeeded");
                
                var webConfig = File.ReadAllText(Path.Combine(Path.GetDirectoryName(project.FullName), "web.config"));
                if (!webConfig.Contains(@"<add input=""{REQUEST_URI}"" pattern=""^/static/.*$"" ignoreCase=""true"" negate=""true"" />")) {
                    Assert.Fail(string.Format("Did not find rewrite condition in:{0}{0}{1}",
                        Environment.NewLine,
                        webConfig
                    ));
                }

                UIThread.Invoke(() => {
                    proj.SetProjectProperty("StaticUriPattern", "invalid[pattern");
                });
                app.ExecuteCommand("Build.RebuildSolution");
                app.WaitForOutputWindowText("Build", "1 failed");
            }
        }

        #region EndToEndTest

        private static void EndToEndLog(string format, params object[] args) {
            Console.Write("[{0:o}] ", DateTime.Now);
            Console.WriteLine(format, args);
        }

        private void EndToEndTest(
            string templateName,
            string moduleName,
            string textInResponse,
            string pythonVersion
        ) {
            EndToEndLog("Starting {0} {1}", templateName, pythonVersion);
            using (var app = new VisualStudioApp(VsIdeTestHostContext.Dte)) {
                var pyProj = app.CreateProject(
                    PythonVisualStudioApp.TemplateLanguageName,
                    templateName,
                    TestData.GetTempPath(),
                    TestContext.TestName
                ).GetPythonProject();

                EndToEndLog("Created project {0}", pyProj.ProjectFile);

                Assert.IsInstanceOfType(pyProj.GetLauncher(), typeof(PythonWebLauncher));

                var factory = CreateVirtualEnvironment(pythonVersion, app, pyProj);
<commit_msg>Fix FormatException in end to end logging<commit_after>﻿/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the Apache License, Version 2.0, please send an email to 
 * <EMAIL>. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Apache License, Version 2.0.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * ***************************************************************************/

extern alias analysis;
extern alias util;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Threading;
using Microsoft.PythonTools;
using Microsoft.PythonTools.Interpreter;
using Microsoft.PythonTools.Project;
using Microsoft.PythonTools.Project.Web;
using Microsoft.TC.TestHostAdapters;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.VisualStudioTools;
using Microsoft.VisualStudioTools.Project;
using TestUtilities;
using TestUtilities.Python;
using TestUtilities.UI;
using TestUtilities.UI.Python;
using InterpreterExt = analysis::Microsoft.PythonTools.Interpreter.PythonInterpreterFactoryExtensions;
using UIThread = util::Microsoft.VisualStudioTools.UIThread;

namespace PythonToolsUITests {
    [TestClass]
    public class WebProjectTests {
        [ClassInitialize]
        public static void DoDeployment(TestContext context) {
            AssertListener.Initialize();
            PythonTestData.Deploy();
        }

        public TestContext TestContext { get; set; }

        [TestMethod, Priority(0), TestCategory("Core")]
        [HostType("TC Dynamic"), DynamicHostType(typeof(VsIdeHostAdapter))]
        public void LoadWebFlavoredProject() {
            using (var app = new VisualStudioApp(VsIdeTestHostContext.Dte)) {
                var project = app.OpenProject(@"TestData\EmptyWebProject.sln");
                Assert.AreEqual("EmptyWebProject.pyproj", Path.GetFileName(project.FileName), "Wrong project file name");

                var catids = VsIdeTestHostContext.Dte.ObjectExtenders.GetContextualExtenderCATIDs();
                dynamic extender = project.Extender["WebApplication"];
                Assert.IsNotNull(extender, "No WebApplication extender");
                extender.StartWebServerOnDebug = true;
                extender.StartWebServerOnDebug = false;

                var proj = project.GetCommonProject();
                var ccp = proj as IPythonProject2;
                Assert.IsNotNull(ccp);
                Assert.IsNotNull(ccp.FindCommand("PythonRunWebServerCommand"), "No PythonRunWebServerCommand");
                Assert.IsNotNull(ccp.FindCommand("PythonDebugWebServerCommand"), "No PythonDebugWebServerCommand");
                Assert.IsNull(ccp.FindCommand("PythonUpgradeWebFrameworkCommand"), "Unexpected PythonUpgradeWebFrameworkCommand");
            }
        }

        private static void CheckCommandLineArgs(string setValue, string expectedValue = null) {
            using (var app = new VisualStudioApp(VsIdeTestHostContext.Dte)) {
                var project = app.OpenProject(@"TestData\CheckCommandLineArgs.sln");

                var proj = project.GetCommonProject() as IPythonProject2;
                Assert.IsNotNull(proj);

                var outFile = Path.Combine(Path.GetDirectoryName(project.FullName), "output.txt");

                foreach (var cmdName in new[] { "PythonRunWebServerCommand", "PythonDebugWebServerCommand" }) {
                    Console.WriteLine("Testing {0}, writing to {1}", cmdName, outFile);

                    if (File.Exists(outFile)) {
                        File.Delete(outFile);
                    }

                    UIThread.Invoke(() => {
                        proj.SetProperty("CommandLineArguments", string.Format("\"{0}\" \"{1}\"", setValue, outFile));
                        proj.FindCommand(cmdName).Execute(proj);
                    });

                    for (int retries = 10; retries > 0 && !File.Exists(outFile); --retries) {
                        Thread.Sleep(100);
                    }

                    Assert.AreEqual(expectedValue ?? setValue, File.ReadAllText(outFile).Trim());
                }
            }
        }

        [TestMethod, Priority(0), TestCategory("Core")]
        [HostType("TC Dynamic"), DynamicHostType(typeof(VsIdeHostAdapter))]
        public void WebProjectCommandLineArgs() {
            CheckCommandLineArgs(Guid.NewGuid().ToString("N"));
        }

        [TestMethod, Priority(0), TestCategory("Core")]
        [HostType("TC Dynamic"), DynamicHostType(typeof(VsIdeHostAdapter))]
        public void WebProjectStartupModuleArgs() {
            CheckCommandLineArgs("{StartupModule}", "CheckCommandLineArgs");
        }

        [TestMethod, Priority(0), TestCategory("Core")]
        [HostType("TC Dynamic"), DynamicHostType(typeof(VsIdeHostAdapter))]
        public void WebProjectStaticUri() {
            using (var app = new VisualStudioApp(VsIdeTestHostContext.Dte)) {
                var project = app.CreateProject(
                    PythonVisualStudioApp.TemplateLanguageName,
                    PythonVisualStudioApp.EmptyWebProjectTemplate,
                    TestData.GetTempPath(),
                    "WebProjectStaticUri"
                );

                var proj = project.GetCommonProject() ;
                Assert.IsNotNull(proj);

                UIThread.Invoke(() => {
                    proj.SetProjectProperty("PythonWsgiHandler", "NoHandler");

                    proj.SetProjectProperty("StaticUriPattern", "");
                });
                app.ExecuteCommand("Build.RebuildSolution");
                app.WaitForOutputWindowText("Build", "1 succeeded");

                UIThread.Invoke(() => {
                    proj.SetProjectProperty("StaticUriPattern", "^/static/.*$");
                });
                app.ExecuteCommand("Build.RebuildSolution");
                app.WaitForOutputWindowText("Build", "1 succeeded");
                
                var webConfig = File.ReadAllText(Path.Combine(Path.GetDirectoryName(project.FullName), "web.config"));
                if (!webConfig.Contains(@"<add input=""{REQUEST_URI}"" pattern=""^/static/.*$"" ignoreCase=""true"" negate=""true"" />")) {
                    Assert.Fail(string.Format("Did not find rewrite condition in:{0}{0}{1}",
                        Environment.NewLine,
                        webConfig
                    ));
                }

                UIThread.Invoke(() => {
                    proj.SetProjectProperty("StaticUriPattern", "invalid[pattern");
                });
                app.ExecuteCommand("Build.RebuildSolution");
                app.WaitForOutputWindowText("Build", "1 failed");
            }
        }

        #region EndToEndTest

        private static void EndToEndLog(string format, params object[] args) {
            Console.Write("[{0:o}] ", DateTime.Now);
            if (args != null && args.Length > 0) {
                Console.WriteLine(format, args);
            } else {
                Console.WriteLine(format);
            }
        }

        private void EndToEndTest(
            string templateName,
            string moduleName,
            string textInResponse,
            string pythonVersion
        ) {
            EndToEndLog("Starting {0} {1}", templateName, pythonVersion);
            using (var app = new VisualStudioApp(VsIdeTestHostContext.Dte)) {
                var pyProj = app.CreateProject(
                    PythonVisualStudioApp.TemplateLanguageName,
                    templateName,
                    TestData.GetTempPath(),
                    TestContext.TestName
                ).GetPythonProject();

                EndToEndLog("Created project {0}", pyProj.ProjectFile);

                Assert.IsInstanceOfType(pyProj.GetLauncher(), typeof(PythonWebLauncher));

                var factory = CreateVirtualEnvironment(pythonVersion, app, pyProj);

{'fraction_non_alphanumeric': 0.11971450848677502, 'fraction_numerical': 0.0038985185629460805, 'mean_word_length': 2.355604749446569, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5549419', 'n_tokens_mistral': 4354, 'n_tokens_neox': 3946, 'n_words': 855}