Skip to content

Commit

Permalink
Handle possible null ref in error handler (microsoft#819)
Browse files Browse the repository at this point in the history
I have a dump that throws access violation exception in native code and the test run fails with: 

`An exception occurred while invoking executor 'executor://mstestadapter/v2': Object reference not set to an instance of an object.`

I looked through the code and the only way I can get this result is when ex would be null in the handler. Otherwise it fails with different error, either from the asserts in the `StackTraceHelper` methods or in upstream error handlers.
  • Loading branch information
nohwnd committed Apr 16, 2021
1 parent e0289e8 commit 179c864
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 7 deletions.
18 changes: 17 additions & 1 deletion src/Adapter/MSTest.CoreAdapter/Execution/TestMethodInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -717,11 +717,27 @@ private object CreateTestClassInstance(TestResult result)
}
catch (Exception ex)
{
if (ex == null)
{
// It seems that ex can be null in some rare cases when initialization fails in native code.
// Get our own exception with a stack trace to satisfy GetStackTraceInformation.
try
{
throw new InvalidOperationException(Resource.UTA_UserCodeThrewNullValueException);
}
catch (Exception exception)
{
ex = exception;
}
}

// In most cases, exception will be TargetInvocationException with real exception wrapped
// in the InnerException; or user code throws an exception
// in the InnerException; or user code throws an exception.
// It also seems that in rare cases the ex can be null.
var actualException = ex.InnerException ?? ex;
var exceptionMessage = StackTraceHelper.GetExceptionMessage(actualException);
var stackTraceInfo = StackTraceHelper.GetStackTraceInformation(actualException);

var errorMessage = string.Format(
CultureInfo.CurrentCulture,
Resource.UTA_InstanceCreationError,
Expand Down
6 changes: 3 additions & 3 deletions src/Adapter/MSTest.CoreAdapter/Execution/TestMethodRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ internal UnitTestResult[] RunTestMethod()
{
testResults = new[]
{
new UTF.TestResult() { TestFailureException = new Exception(string.Format(CultureInfo.CurrentCulture, Resource.UTA_ExecuteThrewException, ex.Message), ex) }
new UTF.TestResult() { TestFailureException = new Exception(string.Format(CultureInfo.CurrentCulture, Resource.UTA_ExecuteThrewException, ex?.Message, ex?.StackTrace), ex) }
};
}

Expand Down Expand Up @@ -324,7 +324,7 @@ internal UnitTestResult[] RunTestMethod()
{
testResults = new[]
{
new UTF.TestResult() { TestFailureException = new Exception(string.Format(CultureInfo.CurrentCulture, Resource.UTA_ExecuteThrewException, ex.Message), ex) }
new UTF.TestResult() { TestFailureException = new Exception(string.Format(CultureInfo.CurrentCulture, Resource.UTA_ExecuteThrewException, ex?.Message, ex?.StackTrace), ex) }
};
}

Expand All @@ -346,7 +346,7 @@ internal UnitTestResult[] RunTestMethod()
}
catch (Exception ex)
{
results.Add(new UTF.TestResult() { TestFailureException = new Exception(string.Format(CultureInfo.CurrentCulture, Resource.UTA_ExecuteThrewException, ex.Message), ex) });
results.Add(new UTF.TestResult() { TestFailureException = new Exception(string.Format(CultureInfo.CurrentCulture, Resource.UTA_ExecuteThrewException, ex?.Message, ex?.StackTrace), ex) });
}
}
}
Expand Down
13 changes: 11 additions & 2 deletions src/Adapter/MSTest.CoreAdapter/Resources/Resource.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion src/Adapter/MSTest.CoreAdapter/Resources/Resource.resx
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ Error: {1}</value>
<value>Class Initialization method {0}.{1} threw exception. {2}: {3}.</value>
</data>
<data name="UTA_ExecuteThrewException" xml:space="preserve">
<value>Exception thrown while executing test. If using extension of TestMethodAttribute then please contact vendor. Error message: {0}</value>
<value>Exception thrown while executing test. If using extension of TestMethodAttribute then please contact vendor. Error message: {0}, Stack trace: {1}</value>
</data>
<data name="UTA_NoTestResult" xml:space="preserve">
<value>Error in executing test. No result returned by extension. If using extension of TestMethodAttribute then please contact vendor.</value>
Expand Down Expand Up @@ -320,4 +320,7 @@ Error: {1}</value>
<data name="Execution_Test_Cancelled" xml:space="preserve">
<value>Test '{0}' execution has been aborted.</value>
</data>
<data name="UTA_UserCodeThrewNullValueException" xml:space="preserve">
<value>The called code threw an exception that was caught, but the exception value was null</value>
</data>
</root>

0 comments on commit 179c864

Please sign in to comment.