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

#441 - Fix exit code 1 if Harmony patching failled #455

Merged
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
157 changes: 79 additions & 78 deletions Allure.XUnit/AllureXunitPatcher.cs
Original file line number Diff line number Diff line change
@@ -1,106 +1,107 @@
using System;

using HarmonyLib;
using System;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;

namespace Allure.XUnit
namespace Allure.XUnit;

internal static class AllureXunitPatcher
{
static class AllureXunitPatcher
{
const string ALLURE_ID = "io.qameta.allure.xunit";
static bool isPatched = false;
static IRunnerLogger logger;
private const string ALLURE_ID = "io.qameta.allure.xunit";
private static bool _isPatched;
private static IRunnerLogger _logger;

static AllureMessageSink CurrentSink
private static AllureMessageSink CurrentSink
{
get
{
get
var sink = AllureMessageSink.CurrentSink;

if (sink is null)
{
var sink = AllureMessageSink.CurrentSink;
if (sink is null)
{
logger.LogWarning("Unable to get current message sink.");
}
return sink;
_logger.LogWarning("Unable to get current message sink.");
}

return sink;
}
}

public static void PatchXunit(IRunnerLogger runnerLogger)
public static void PatchXunit(IRunnerLogger runnerLogger)
{
if (_isPatched)
{
if (isPatched)
{
logger.LogMessage(
"Patching is skipped: Xunit is already patched"
);
return;
}

logger = runnerLogger;
var patcher = new Harmony(ALLURE_ID);
PatchXunitTestRunnerCtors(patcher);
isPatched = true;
_logger.LogMessage(
"Patching is skipped: Xunit is already patched"
);
return;
}

static void PatchXunitTestRunnerCtors(Harmony patcher)
_logger = runnerLogger;

var patcher = new Harmony(ALLURE_ID);
PatchXunitTestRunnerCtors(patcher);
_isPatched = true;
}

private static void PatchXunitTestRunnerCtors(Harmony patcher)
{
var testRunnerType = typeof(XunitTestRunner);
var wasPatched = false;

foreach (var ctor in testRunnerType.GetConstructors())
{
var testRunnerType = typeof(XunitTestRunner);
var wasPatched = false;
foreach (var ctor in testRunnerType.GetConstructors())
try
{
try
{
patcher.Patch(
ctor,
prefix: new HarmonyMethod(
typeof(AllureXunitPatcher),
nameof(OnTestRunnerCreating)
),
postfix: new HarmonyMethod(
typeof(AllureXunitPatcher),
nameof(OnTestRunnerCreated)
)
);
wasPatched = true;
logger.LogImportantMessage(
"{0}'s {1} has been patched",
testRunnerType.Name,
ctor.ToString()
);
}
catch (Exception e)
{
logger.LogError(
"Unable to patch {0}'s {1}: {2}",
testRunnerType.Name,
ctor.ToString(),
e.ToString()
);
}
}
patcher.Patch(
ctor,
prefix: new HarmonyMethod(
typeof(AllureXunitPatcher),
nameof(OnTestRunnerCreating)
),
postfix: new HarmonyMethod(
typeof(AllureXunitPatcher),
nameof(OnTestRunnerCreated)
)
);

wasPatched = true;

if (!wasPatched)
_logger.LogImportantMessage(
"{0}'s {1} has been patched",
testRunnerType.Name,
ctor.ToString()
);
}
catch (Exception e)
{
logger.LogWarning(
"No constructors of {0} were pathched. Some theories may " +
"miss their parameters in the report",
testRunnerType.Name
_logger.LogWarning(
"Unable to patch {0}'s {1}: {2}",
testRunnerType.Name,
ctor.ToString(),
e.ToString()
);
}
}

static void OnTestRunnerCreating(ITest test, ref string skipReason)
if (!wasPatched)
{
if (!CurrentSink.SelectByTestPlan(test))
{
skipReason = "Deselected by the testplan.";
}
_logger.LogWarning(
"No constructors of {0} were patched. Some theories may " +
"miss their parameters in the report",
testRunnerType.Name
);
}
}

static void OnTestRunnerCreated(
ITest test,
object[] testMethodArguments
) =>
CurrentSink.OnTestArgumentsCreated(test, testMethodArguments);
private static void OnTestRunnerCreating(ITest test, ref string skipReason)
{
if (!CurrentSink.SelectByTestPlan(test))
{
skipReason = "Deselected by the test plan.";
}
}

private static void OnTestRunnerCreated(ITest test, object[] testMethodArguments) =>
CurrentSink.OnTestArgumentsCreated(test, testMethodArguments);
}
Loading