Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid Debug Symbol Search #106

Open
wants to merge 5 commits into
base: dev15
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions BoostTestAdapter/Boost/Runner/BoostTest162Runner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ public BoostTest162Runner(IBoostTestRunner runner)

#region IBoostTestRunner

public bool ListContentSupported => this.Runner.ListContentSupported;

public string Source => this.Runner.Source;

public IBoostTestRunnerCapabilities Capabilities => this.Runner.Capabilities;

public int Execute(BoostTestRunnerCommandLineArgs args, BoostTestRunnerSettings settings, IProcessExecutionContext executionContext)
{
var fixedArgs = args;
Expand Down
133 changes: 99 additions & 34 deletions BoostTestAdapter/Boost/Runner/BoostTestRunnerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Management;
using BoostTestAdapter.Utility;
using System.ComponentModel;
using BoostTestAdapter.Utility.ExecutionContext;

namespace BoostTestAdapter.Boost.Runner
Expand All @@ -34,14 +34,19 @@ protected BoostTestRunnerBase(string testRunnerExecutable)
}

#endregion Constructors

#region Properties

/// <summary>
/// Boost Test runner '.exe' file path.
/// Boost.Test runner '.exe' file path
/// </summary>
protected string TestRunnerExecutable { get; private set; }

/// <summary>
/// Caches Boost.Test runner capabilities
/// </summary>
private BoostTestRunnerCapabilities _capabilities = null;

#endregion Properties

#region IBoostTestRunner
Expand All @@ -61,42 +66,22 @@ public virtual string Source
{
get { return this.TestRunnerExecutable; }
}

public virtual bool ListContentSupported
public virtual IBoostTestRunnerCapabilities Capabilities
{
get
{
bool supported = false;

// Try to locate the list_content function debug symbol. If this is not available, this implies that:
// - Debug symbols are not available for the requested source
// - Debug symbols are available but the source is not a Boost Unit Test version >= 3 module
try
{
// Search symbols on the TestRunner not on the source. Source could be .dll which may not contain list_content functionality.
using (DebugHelper dbgHelp = new DebugHelper(this.TestRunnerExecutable))
{

supported =
DebugHelper.FindImport(this.TestRunnerExecutable, "boost_unit_test_framework", StringComparison.OrdinalIgnoreCase) // Boost linked dynamically
|| dbgHelp.ContainsSymbol("boost::unit_test::runtime_config::LIST_CONTENT") // Boost 1.60/1.61
|| dbgHelp.ContainsSymbol("boost::unit_test::runtime_config::btrt_list_content"); // Boost 1.64
}
}
catch (Win32Exception ex)
if (_capabilities == null)
{
Logger.Exception(ex, Resources.CouldNotCreateDbgHelp, this.Source);
}

if (!supported)
{
Logger.Warn(Resources.CouldNotLocateDebugSymbols, this.TestRunnerExecutable);
_capabilities = GetCapabilities();
}

return supported;
return _capabilities;
}
}


#endregion IBoostTestRunner

/// <summary>
/// Provides a ProcessExecutionContextArgs structure containing the necessary information to launch the test process.
/// Aggregates the BoostTestRunnerCommandLineArgs structure with the command-line arguments specified at configuration stage.
Expand All @@ -117,8 +102,6 @@ protected virtual ProcessExecutionContextArgs GetExecutionContextArgs(BoostTestR
};
}

#endregion IBoostTestRunner

/// <summary>
/// Monitors the provided process for the specified timeout.
/// </summary>
Expand Down Expand Up @@ -257,5 +240,87 @@ private static bool KillProcess(Process process, int killTimeout)

return false;
}

/// <summary>
/// Boost.Test 'strings' for '--list_content' which are encoded in a Boost.Test runner/executable
/// </summary>
private static readonly ByteUtilities.BoyerMooreBytePattern[] list_content_markers = new []
{
// Help text
new ByteUtilities.BoyerMooreBytePattern("Lists the content of test tree - names of all test suites and test cases.", System.Text.Encoding.ASCII),
// Environment Variable
new ByteUtilities.BoyerMooreBytePattern("BOOST_TEST_LIST_CONTENT", System.Text.Encoding.ASCII),
// Command-line argument
new ByteUtilities.BoyerMooreBytePattern("list_content", System.Text.Encoding.ASCII)
};

/// <summary>
/// Boost.Test 'strings' for '--version' which are encoded in a Boost.Test runner/executable
/// </summary>
private static readonly ByteUtilities.BoyerMooreBytePattern[] version_markers = new[]
{
// Help text
new ByteUtilities.BoyerMooreBytePattern("Prints Boost.Test version and exits.", System.Text.Encoding.ASCII)
};

/// <summary>
/// Acquires the Boost.Test runner's capabilities by looking up markers from the test module
/// </summary>
/// <returns>The Boost.Test runner's capabilities</returns>
private BoostTestRunnerCapabilities GetCapabilities()
{
using (new Utility.TimedScope("Looking up '--list_content' and '--version' via Boyer-Moore string search"))
{
var listContent = true;

// Search symbols on the TestRunner not on the source. Source could be .dll which may not contain list_content functionality.
using (DebugHelper dbgHelp = CreateDebugHelper(this.TestRunnerExecutable))
{
if (dbgHelp != null)
{
listContent = DebugHelper.FindImport(this.TestRunnerExecutable, "boost_unit_test_framework", StringComparison.OrdinalIgnoreCase);
}
}

var buffer = System.IO.File.ReadAllBytes(this.TestRunnerExecutable);

// At least 3 markers need to be available to ensure that the test module is
// a Boost.Test runner with '--list_content' capabilities
listContent = listContent || list_content_markers.Select(marker => buffer.IndexOf(marker)).All(index => index >= 0);

if (!listContent)
{
Logger.Warn(Resources.CouldNotLocateDebugSymbols, this.TestRunnerExecutable);
}

// Don't bother checking for the '--version' symbol if '--list_content' is not available
var version = listContent && version_markers.Select(marker => buffer.IndexOf(marker)).All(index => index >= 0);

return new BoostTestRunnerCapabilities
{
ListContent = listContent,
Version = version
};
}
}

/// <summary>
/// Creates a DebugHelper instance for the specified source
/// </summary>
/// <param name="source">The module/source for which to inspect debug symbols</param>
/// <returns>A new DebugHelper instance for the specified source or null if one cannot be created</returns>
private static DebugHelper CreateDebugHelper(string source)
{
try
{
return new DebugHelper(source);
}
catch (Win32Exception ex)
{
Logger.Exception(ex, Resources.CouldNotCreateDbgHelp, source);
}

return null;
}
}
}
}
21 changes: 21 additions & 0 deletions BoostTestAdapter/Boost/Runner/BoostTestRunnerCapabilities.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// (C) Copyright 2015 ETAS GmbH (http://www.etas.com/)
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

namespace BoostTestAdapter.Boost.Runner
{
/// <summary>
/// Default implementation of IBoostTestRunnerCapabilities
/// </summary>
public class BoostTestRunnerCapabilities : IBoostTestRunnerCapabilities
{
#region IBoostTestRunnerCapabilities

public bool ListContent { get; set; } = false;

public bool Version { get; set; } = false;

#endregion
}
}
57 changes: 57 additions & 0 deletions BoostTestAdapter/Boost/Runner/BoostTestRunnerCapabilityOverride.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// (C) Copyright 2015 ETAS GmbH (http://www.etas.com/)
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

using BoostTestAdapter.Utility;
using BoostTestAdapter.Utility.ExecutionContext;

namespace BoostTestAdapter.Boost.Runner
{
/// <summary>
/// An IBoostTestRunner wrapper which overrides the capabilities
/// of the underlying Boost.Test runner
/// </summary>
public class BoostTestRunnerCapabilityOverride : IBoostTestRunner
{
#region Constructors

/// <summary>
/// Constructor
/// </summary>
/// <param name="runner">The underlying Boost.Test runner</param>
/// <param name="capabilities">The overriden capability set of the Boost.Test runner</param>
public BoostTestRunnerCapabilityOverride(IBoostTestRunner runner, IBoostTestRunnerCapabilities capabilities)
{
Code.Require(runner, "runner");
Code.Require(capabilities, "capabilities");

Runner = runner;
Capabilities = capabilities;
}

#endregion

#region Properties

/// <summary>
/// Underlying Boost.Test runner instance
/// </summary>
public IBoostTestRunner Runner { get; private set; }

#endregion

#region IBoostTestRunner

public IBoostTestRunnerCapabilities Capabilities { get; private set; }

public string Source => Runner.Source;

public int Execute(BoostTestRunnerCommandLineArgs args, BoostTestRunnerSettings settings, IProcessExecutionContext executionContext)
{
return Runner.Execute(args, settings, executionContext);
}

#endregion
}
}
31 changes: 25 additions & 6 deletions BoostTestAdapter/Boost/Runner/BoostTestRunnerCommandLineArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ public class BoostTestRunnerCommandLineArgs : ICloneable
internal const string ListContentArg = "--list_content";
internal const string HelpArg = "--help";

internal const string VersionArg = "--version";

private const string TestSeparator = ",";

private const char ArgSeparator = ' ';
Expand Down Expand Up @@ -229,6 +231,7 @@ public BoostTestRunnerCommandLineArgs()
this.SavePattern = false;
this.ListContent = null;
this.Help = false;
this.Version = false;

this.Environment = new Dictionary<string, string>();
}
Expand Down Expand Up @@ -351,7 +354,7 @@ public string ReportFile
public string AutoStartDebug { get; set; }

/// <summary>
/// Flag which displays Boost UTF test information in standard out.
/// Flag which displays Boost.Test test information in standard out.
/// </summary>
public bool BuildInfo { get; set; }

Expand All @@ -367,7 +370,7 @@ public string ReportFile
public bool ColorOutput { get; set; }

/// <summary>
/// Determines the result code the Boost UTF uses on exit.
/// Determines the result code the Boost.Test uses on exit.
/// </summary>
public bool ResultCode { get; set; }

Expand All @@ -382,7 +385,7 @@ public string ReportFile
public bool UseAltStack { get; set; }

/// <summary>
/// Instructs the Boost UTF to break on floating-point exceptions.
/// Instructs the Boost.Test to break on floating-point exceptions.
/// </summary>
public bool DetectFPExceptions { get; set; }

Expand All @@ -393,7 +396,7 @@ public string ReportFile
public bool SavePattern { get; set; }

/// <summary>
/// The Boost UTF lists all tests which are to be executed without actually executing the tests.
/// The Boost.Test lists all tests which are to be executed without actually executing the tests.
/// </summary>
/// <remarks>Introduced in Boost 1.59 / Boost Test 3</remarks>
public ListContentFormat? ListContent { get; set; }
Expand All @@ -403,6 +406,11 @@ public string ReportFile
/// </summary>
public bool Help { get; set; }

/// <summary>
/// Version information output.
/// </summary>
public bool Version { get; set; }

/// <summary>
/// Path (relative to the WorkingDirectory) to the report file which will host the standard output content.
/// </summary>
Expand Down Expand Up @@ -448,7 +456,16 @@ public override string ToString()
{
AddArgument(HelpArg, args);

// return immediately since Boost UTF should ignore the rest of the arguments
// return immediately since Boost.Test should ignore the rest of the arguments
return AppendRedirection(args).ToString().TrimEnd();
}

// --version
if (this.Version)
{
AddArgument(VersionArg, args);

// return immediately since Boost.Test should ignore the rest of the arguments
return AppendRedirection(args).ToString().TrimEnd(null);
}

Expand All @@ -457,7 +474,7 @@ public override string ToString()
{
AddArgument(ListContentArg, ListContentFormatToString(this.ListContent.Value), args);

// return immediately since Boost UTF should ignore the rest of the arguments
// return immediately since Boost.Test should ignore the rest of the arguments
return AppendRedirection(args).ToString().TrimEnd(null);
}

Expand Down Expand Up @@ -809,6 +826,8 @@ public BoostTestRunnerCommandLineArgs Clone()
clone.DetectFPExceptions = this.DetectFPExceptions;
clone.SavePattern = this.SavePattern;
clone.ListContent = this.ListContent;
clone.Help = this.Help;
clone.Version = this.Version;

return clone;
}
Expand Down
Loading