Skip to content

Commit

Permalink
Merge pull request #802 from icnocop/master
Browse files Browse the repository at this point in the history
Waiting until Internet Explorer process being debugged has exited before continuing when using the web server
  • Loading branch information
mmanela authored Jun 20, 2021
2 parents 20a57e6 + 9016a18 commit f627853
Show file tree
Hide file tree
Showing 21 changed files with 238 additions and 143 deletions.
3 changes: 3 additions & 0 deletions Chutzpah/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ public static class Constants
// from phantom after this amount of time abort
public const int DefaultTestFileTimeout = 10000;

// Default time in seconds to wait for the Internet Explorer tab to open
public const int DefaultIEBrowserTabOpenTimeout = 4;

// Default of how many files to open during test file discovery
public const int DefaultFileSeachLimit = 10000;

Expand Down
4 changes: 2 additions & 2 deletions Chutzpah/FileProbe.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ public FileProbe(IEnvironmentWrapper environment, IFileSystemWrapper fileSystem,
}

/// <summary>
/// Finds a Chutzpah test settings file given a directory. Will recursively scan current direcotry
/// Finds a Chutzpah test settings file given a directory. Will recursively scan current directory
/// and all directories above until it finds the file
/// </summary>
/// <param name="currentDirectory">the directory to start searching from</param>
/// <returns>Eithe the found setting file path or null</returns>
/// <returns>Either the found setting file path or null</returns>
public string FindTestSettingsFile(string currentDirectory)
{
string settingsFilePath = null;
Expand Down
7 changes: 3 additions & 4 deletions Chutzpah/ITestLauncher.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Chutzpah.Models;

namespace Chutzpah
Expand All @@ -11,6 +8,8 @@ namespace Chutzpah
/// </summary>
public interface ITestLauncher
{
Process DebuggingProcess { get; set; }

void LaunchTest(TestContext testContext);
}
}
13 changes: 8 additions & 5 deletions Chutzpah/Models/ChutzpahTestSettingsFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ private ChutzpahTestSettingsFile(bool isDefaultSetings) : this()
public string TestHarnessDirectory { get; set; }

/// <summary>
/// A Regualr Expression which tells Chutpah where to find the names of your tests in the test file.
/// A Regular Expression which tells Chutzpah where to find the names of your tests in the test file.
/// The regex must contain a capture group named TestName like (?<TestName>) that contains the test name (inside of the quotes)
/// </summary>
public string TestPattern { get; set; }
Expand All @@ -213,7 +213,7 @@ private ChutzpahTestSettingsFile(bool isDefaultSetings) : this()
/// <summary>
/// Tells Chutzpah the root path for your AMD paths. This is only needed if your baseUrl is a different location than your source directory.
/// This is common if you are compiling from another language to JavaScript and copying those compiled files to a different folder.
/// For example if you have all your .ts files in /src and you compile them to a /out directry then your AMDBaseUrl is /out and AMDAppDirectory is /src
/// For example if you have all your .ts files in /src and you compile them to a /out directory then your AMDBaseUrl is /out and AMDAppDirectory is /src
///
/// Defaults to the test harness directory if not set
/// </summary>
Expand Down Expand Up @@ -339,7 +339,7 @@ private ChutzpahTestSettingsFile(bool isDefaultSetings) : this()
/// <summary>
/// This is deprecated and only here for back compat for now
/// If True, forces code coverage to run always
/// If Null or not not set, allows code coverage to run if invoked using test adapter, command line or context menu options (default)
/// If Null or not set, allows code coverage to run if invoked using test adapter, command line or context menu options (default)
/// If False, forces code coverage to never run.
/// </summary>
public bool? EnableCodeCoverage
Expand Down Expand Up @@ -368,8 +368,8 @@ public bool? EnableCodeCoverage


/// <summary>
/// Tells Chutzpah to create a failed test case when an unhandle exception occurs when
/// running a test that happens ouside of a test itself. This is useful in some build systems
/// Tells Chutzpah to create a failed test case when an unhandled exception occurs when
/// running a test that happens outside of a test itself. This is useful in some build systems
/// to provide better failure reporting
/// </summary>
public bool? CreateFailedTestForFileError { get; set; }
Expand All @@ -396,6 +396,8 @@ public Regex TestPatternRegex
}
}

public int? IEBrowserTabOpenTimeout { get; set; }

public override int GetHashCode()
{
if (SettingsFileDirectory == null)
Expand Down Expand Up @@ -508,6 +510,7 @@ public ChutzpahTestSettingsFile InheritFrom(ChutzpahTestSettingsFile parent)
this.MochaInterface = this.MochaInterface ?? parent.MochaInterface;
this.RootReferencePathMode = this.RootReferencePathMode ?? parent.RootReferencePathMode;
this.TestFileTimeout = this.TestFileTimeout ?? parent.TestFileTimeout;
this.IEBrowserTabOpenTimeout = this.IEBrowserTabOpenTimeout ?? parent.IEBrowserTabOpenTimeout;
this.TestHarnessReferenceMode = this.TestHarnessReferenceMode ?? parent.TestHarnessReferenceMode;
this.TestPattern = this.TestPattern ?? parent.TestPattern;
this.UserAgent = this.UserAgent ?? parent.UserAgent;
Expand Down
9 changes: 9 additions & 0 deletions Chutzpah/TestRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,15 @@ private void ExecuteTestContexts(
}
});

if ((options.TestLaunchMode == TestLaunchMode.Custom)
&& (webServerHost != null))
{
// if is being debugged using the web server, wait until the debugging process has exited before continuing
while (!options.CustomTestLauncher.DebuggingProcess.HasExited)
{
Thread.Sleep(1000);
}
}

// Clean up test context
foreach (var testContext in testContexts)
Expand Down
2 changes: 1 addition & 1 deletion Chutzpah/UrlBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public string GenerateServerFileUrl(TestContext testContext, string absolutePath
string parentPath = null;
if (isBuiltInDependency)
{
// We need a fully qualified url when using vitural server path
// We need a fully qualified url when using virtual server path
fullyQualified = true;

parentPath = fileProbe.BuiltInDependencyDirectory;
Expand Down
2 changes: 1 addition & 1 deletion VS.Common/Settings/ChutzpahUTESettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public ChutzpahUTESettings()
[Browsable(true)]
[Category("UTE")]
[DisplayName("Max degree of Parallelism")]
[Description("The maximum amount of concurreny Chutzpah should use")]
[Description("The maximum amount of concurrency Chutzpah should use")]
public int MaxDegreeOfParallelism
{
get { return maxDegreeOfParallelism; }
Expand Down
44 changes: 25 additions & 19 deletions VS.Common/VS.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -45,28 +45,29 @@
<HintPath>..\packages\VSSDK.GraphModel.11.0.4\lib\net45\Microsoft.VisualStudio.GraphModel.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.Imaging, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.VisualStudio.Imaging.14.3.25407\lib\net45\Microsoft.VisualStudio.Imaging.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.OLE.Interop, Version=7.1.40304.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<HintPath>..\packages\VSSDK.OLE.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.OLE.Interop.dll</HintPath>
<Private>False</Private>
<HintPath>..\packages\Microsoft.VisualStudio.OLE.Interop.7.10.6070\lib\Microsoft.VisualStudio.OLE.Interop.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Shell.14.0, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<EmbedInteropTypes>False</EmbedInteropTypes>
<Private>False</Private>
<HintPath>..\packages\Microsoft.VisualStudio.Shell.14.0.14.3.25407\lib\Microsoft.VisualStudio.Shell.14.0.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Shell.Immutable.10.0, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\VSSDK.Shell.Immutable.10.10.0.4\lib\net40\Microsoft.VisualStudio.Shell.Immutable.10.0.dll</HintPath>
<Private>False</Private>
<HintPath>..\packages\Microsoft.VisualStudio.Shell.Immutable.10.0.10.0.30319\lib\net40\Microsoft.VisualStudio.Shell.Immutable.10.0.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Shell.Immutable.11.0, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\VSSDK.Shell.Immutable.11.11.0.4\lib\net45\Microsoft.VisualStudio.Shell.Immutable.11.0.dll</HintPath>
<Private>False</Private>
<HintPath>..\packages\Microsoft.VisualStudio.Shell.Immutable.11.0.11.0.50727\lib\net45\Microsoft.VisualStudio.Shell.Immutable.11.0.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Shell.Immutable.12.0, Version=12.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.VisualStudio.Shell.Immutable.12.0.12.0.21003\lib\net45\Microsoft.VisualStudio.Shell.Immutable.12.0.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Shell.Immutable.14.0, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
<HintPath>..\packages\Microsoft.VisualStudio.Shell.Immutable.14.0.14.3.25407\lib\net45\Microsoft.VisualStudio.Shell.Immutable.14.0.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Shell.Interop, Version=7.1.40304.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<HintPath>..\packages\VSSDK.Shell.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.dll</HintPath>
<Private>False</Private>
<HintPath>..\packages\Microsoft.VisualStudio.Shell.Interop.7.10.6071\lib\Microsoft.VisualStudio.Shell.Interop.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Shell.Interop.10.0, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<EmbedInteropTypes>False</EmbedInteropTypes>
Expand All @@ -82,20 +83,25 @@
<EmbedInteropTypes>True</EmbedInteropTypes>
</Reference>
<Reference Include="Microsoft.VisualStudio.Shell.Interop.8.0, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<HintPath>..\packages\VSSDK.Shell.Interop.8.8.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.8.0.dll</HintPath>
<Private>False</Private>
<HintPath>..\packages\Microsoft.VisualStudio.Shell.Interop.8.0.8.0.50727\lib\Microsoft.VisualStudio.Shell.Interop.8.0.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Shell.Interop.9.0, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<HintPath>..\packages\VSSDK.Shell.Interop.9.9.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.9.0.dll</HintPath>
<Private>False</Private>
<HintPath>..\packages\Microsoft.VisualStudio.Shell.Interop.9.0.9.0.30729\lib\Microsoft.VisualStudio.Shell.Interop.9.0.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TextManager.Interop, Version=7.1.40304.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<HintPath>..\packages\VSSDK.TextManager.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.dll</HintPath>
<Private>False</Private>
<HintPath>..\packages\Microsoft.VisualStudio.TextManager.Interop.7.10.6070\lib\Microsoft.VisualStudio.TextManager.Interop.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TextManager.Interop.8.0, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<HintPath>..\packages\VSSDK.TextManager.Interop.8.8.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.8.0.dll</HintPath>
<Private>False</Private>
<HintPath>..\packages\Microsoft.VisualStudio.TextManager.Interop.8.0.8.0.50727\lib\Microsoft.VisualStudio.TextManager.Interop.8.0.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Threading, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.VisualStudio.Threading.14.1.111\lib\net45\Microsoft.VisualStudio.Threading.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Utilities, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.VisualStudio.Utilities.14.3.25407\lib\net45\Microsoft.VisualStudio.Utilities.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.Validation, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.VisualStudio.Validation.14.1.111\lib\net45\Microsoft.VisualStudio.Validation.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
Expand Down
106 changes: 58 additions & 48 deletions VS.Common/VsDebuggerTestLauncher.cs
Original file line number Diff line number Diff line change
@@ -1,59 +1,69 @@
using System;
using System.Diagnostics;
using Chutzpah.Models;
using Chutzpah.Utility;

namespace Chutzpah.VS.Common
{
public class VsDebuggerTestLauncher : ITestLauncher
using System;
using System.Diagnostics;
using Chutzpah.Models;
using Chutzpah.Utility;

namespace Chutzpah.VS.Common
{
public class VsDebuggerTestLauncher : ITestLauncher
{
readonly IUrlBuilder urlBuilder;

public Process DebuggingProcess { get; set; }

public VsDebuggerTestLauncher(IUrlBuilder urlBuilder)
{
this.urlBuilder = urlBuilder;
}

public void LaunchTest(TestContext testContext)
}

public void LaunchTest(TestContext testContext)
{
var file = testContext.TestHarnessPath;
file = urlBuilder.GenerateFileUrl(testContext, file, fullyQualified: true);

// Start IE.
ProcessStartInfo startInfo = new ProcessStartInfo()
{
UseShellExecute = true,
FileName = BrowserPathHelper.GetBrowserPath("ie"),
Arguments = string.Format("-noframemerging -suspended -debug {0}", file)
// -noframemerging
// This is what VS does when launching the script debugger.
// Unsure whether strictly necessary.
// -suspended
// This is what VS does when launching the script debugger.
// Seems to cause IE to suspend all threads which is what we want.
// -debug
// This is what VS does when launching the script debugger.
// Not sure exactly what it does.
};
Process ieMainProcess = Process.Start(startInfo);

// Get child 'tab' process spawned by IE.
// We need to wait a few ms for IE to open the process.
Process ieTabProcess = null;
for (int i = 0;; ++i) {
System.Threading.Thread.Sleep(10);
ieTabProcess = ProcessExtensions.FindFirstChildProcessOf(ieMainProcess.Id);
if (ieTabProcess != null) {
break; }
if (i > 400) { // 400 * 10 = 4s timeout
throw new InvalidOperationException("Timeout waiting for Internet Explorer child process to start."); }
}

// Debug the script in that tab process.
DteHelpers.DebugAttachToProcess(ieTabProcess.Id, "script");

// Resume the threads in the IE process which where started off suspended.
ieTabProcess.Resume();
}
}
}
ProcessStartInfo startInfo = new ProcessStartInfo()
{
UseShellExecute = true,
FileName = BrowserPathHelper.GetBrowserPath("ie"),
Arguments = string.Format("-noframemerging -suspended -debug {0}", file)
// -noframemerging
// This is what VS does when launching the script debugger.
// Unsure whether strictly necessary.
// -suspended
// This is what VS does when launching the script debugger.
// Seems to cause IE to suspend all threads which is what we want.
// -debug
// This is what VS does when launching the script debugger.
// Not sure exactly what it does.
};
Process ieMainProcess = Process.Start(startInfo);

int ieBrowserTabOpenTimeout = ((testContext.TestFileSettings.IEBrowserTabOpenTimeout ?? Constants.DefaultIEBrowserTabOpenTimeout) * 100);

// Get child 'tab' process spawned by IE.
for (int i = 0;; ++i)
{
// We need to wait a few ms for IE to open the process.
System.Threading.Thread.Sleep(10);

this.DebuggingProcess = ProcessExtensions.FindFirstChildProcessOf(ieMainProcess.Id);
if (this.DebuggingProcess != null)
{
break;
}

if (i > ieBrowserTabOpenTimeout)
{
throw new InvalidOperationException("Timeout waiting for Internet Explorer child process to start.");
}
}

// Debug the script in that tab process.
DteHelpers.DebugAttachToProcess(this.DebuggingProcess.Id, "script");

// Resume the threads in the IE process which where started off suspended.
this.DebuggingProcess.Resume();
}
}
}
2 changes: 1 addition & 1 deletion VS.Common/app.config
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Encodings.Web" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Net.Http.Headers" publicKeyToken="adb9793829ddae60" culture="neutral" />
Expand Down
Loading

0 comments on commit f627853

Please sign in to comment.