We have unit tests in our project that contain test case data that can extend beyond 4000 characters. When running unit tests in a partition, the following exception is thrown (versions: Nunit 4.3.2 and NUnit3TestAdapter 5.0.0):
Error Message:
NUnit.Engine.NUnitEngineException: An exception occurred in the driver while exploring tests.
---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
---> System.ArgumentException: The output byte buffer is too small to contain the encoded data, encoding codepage '65001' and fallback 'System.Text.EncoderReplacementFallback'. (Parameter 'bytes')
at System.Text.Encoding.ThrowBytesOverflow()
at System.Text.Encoding.ThrowBytesOverflow(EncoderNLS encoder, Boolean nothingEncoded)
at System.Text.Encoding.GetBytesWithFallback(ReadOnlySpan`1 chars, Int32 originalCharsLength, Span`1 bytes, Int32 originalBytesLength, EncoderNLS encoder, Boolean throwForDestinationOverflow)
at System.Text.Encoding.GetBytesWithFallback(Char* pOriginalChars, Int32 originalCharCount, Byte* pOriginalBytes, Int32 originalByteCount, Int32 charsConsumedSoFar, Int32 bytesWrittenSoFar, Boolean throwForDestinationOverflow)
at System.Text.UTF8Encoding.GetBytes(ReadOnlySpan`1 chars, Span`1 bytes)
at NUnit.Framework.Internal.Filters.PartitionFilter.ComputeHashValue(String name)
at NUnit.Framework.Internal.Filters.PartitionFilter.ComputePartitionNumber(ITest value)
at NUnit.Framework.Internal.Filters.PartitionFilter.Match(ITest test)
at NUnit.Framework.Internal.TestFilter.MatchDescendant(ITest test)
at NUnit.Framework.Internal.TestFilter.MatchDescendant(ITest test)
at NUnit.Framework.Internal.TestFilter.MatchDescendant(ITest test)
at NUnit.Framework.Internal.TestFilter.Pass(ITest test, Boolean negated)
at NUnit.Framework.Internal.TestFilter.Pass(ITest test)
at NUnit.Framework.Internal.TestSuite..ctor(TestSuite suite, ITestFilter filter)
at NUnit.Framework.Internal.TestAssembly..ctor(TestAssembly assembly, ITestFilter filter)
at NUnit.Framework.Api.NUnitTestAssemblyRunner.ExploreTests(ITestFilter filter)
at NUnit.Framework.Api.FrameworkController.ExploreTests(String filter)
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
--- End of inner exception stack trace ---
at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at NUnit.Engine.Drivers.NUnitNetStandardDriver.ExecuteMethod(MethodInfo method, Object[] args)
at NUnit.Engine.Drivers.NUnitNetStandardDriver.ExecuteMethod(String methodName, Object[] args)
at NUnit.Engine.Drivers.NUnitNetStandardDriver.Explore(String filter)
at NUnit.Engine.Runners.DirectTestRunner.Explore(TestFilter filter)
--- End of inner exception stack trace ---
at NUnit.Engine.Runners.DirectTestRunner.Explore(TestFilter filter)
at NUnit.Engine.Runners.MasterTestRunner.Explore(TestFilter filter)
at NUnit.VisualStudio.TestAdapter.NUnitEngine.NUnitEngineAdapter.Explore(TestFilter filter) in C:\repos\nunit\nunit3-vs-adapter\src\NUnitTestAdapter\NUnitEngine\NUnitEngineAdapter.cs:line 95
at NUnit.VisualStudio.TestAdapter.NUnit3TestExecutor.RunAssembly(String assemblyPath, IGrouping`2 testCases, TestFilter filter, String assemblyName) in C:\repos\nunit\nunit3-vs-adapter\src\NUnitTestAdapter\NUnit3TestExecutor.cs:line 293
Stack Trace:
at NUnit.Engine.Runners.DirectTestRunner.Explore(TestFilter filter)
at NUnit.Engine.Runners.MasterTestRunner.Explore(TestFilter filter)
at NUnit.VisualStudio.TestAdapter.NUnitEngine.NUnitEngineAdapter.Explore(TestFilter filter) in C:\repos\nunit\nunit3-vs-adapter\src\NUnitTestAdapter\NUnitEngine\NUnitEngineAdapter.cs:line 95
at NUnit.VisualStudio.TestAdapter.NUnit3TestExecutor.RunAssembly(String assemblyPath, IGrouping`2 testCases, TestFilter filter, String assemblyName) in C:\repos\nunit\nunit3-vs-adapter\src\NUnitTestAdapter\NUnit3TestExecutor.cs:line 293
Local reproduction
- Create a new NUnit test project using the test file below.
- Run
dotnet test -- NUnit.Where="partition = 1/1" from the command line.
namespace ExampleTestProject
{
[TestFixture]
public class Tests
{
private const string _myLongString = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras lobortis vehicula risus, in interdum nibh scelerisque mattis. Morbi varius tempus massa nec rutrum. Aliquam ac nisi eget lectus varius consequat ac vitae nisi. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Curabitur dictum massa ut rutrum facilisis. Etiam porttitor tortor a justo finibus laoreet. Sed quis purus vel nibh condimentum tristique. Nullam in dapibus lorem. Nunc viverra fringilla leo molestie tempus. Sed tincidunt urna erat, in ultricies lorem cursus ac. Quisque vehicula lacinia ultricies. Nullam finibus nulla vitae rhoncus euismod. Pellentesque convallis semper metus, sit amet imperdiet nisl euismod quis. Nam ut iaculis leo, nec pharetra dolor.\r\n\r\nMaecenas sit amet lacus ipsum. Phasellus enim neque, fringilla non ex non, commodo mollis orci. Sed malesuada risus orci, auctor tincidunt nisi molestie non. Integer iaculis justo lacinia mi ornare, eget posuere lacus sagittis. Donec ut est tincidunt, convallis augue et, ornare dolor. Pellentesque auctor ut nisi non vulputate. Nullam vitae rutrum quam. Nullam vitae ex pellentesque, luctus urna nec, posuere quam. Vivamus ut lorem quis augue hendrerit ultrices nec sit amet eros.\r\n\r\nInteger non porttitor lacus, nec ornare nisl. Ut dignissim eros et dui egestas aliquam. Nulla cursus velit non luctus bibendum. Sed commodo consectetur nulla ac tempor. Morbi sapien nulla, tristique vel ipsum quis, rhoncus fringilla lacus. Sed urna turpis, aliquet vitae elit ut, gravida imperdiet ex. Suspendisse potenti. Ut tempus, enim non feugiat fringilla, augue metus semper enim, eget faucibus nibh ipsum in risus. Donec lacus sapien, sollicitudin laoreet tempus id, porttitor et magna. Aenean maximus lacus eget nunc egestas, nec sagittis metus gravida. Etiam ac auctor est. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque arcu dolor, consequat in nibh at, lacinia luctus magna. Integer rutrum maximus volutpat. Sed at lorem nec nisl accumsan interdum et vitae leo.\r\n\r\nClass aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Ut id est suscipit, sagittis nisl vitae, mattis mauris. Nulla volutpat est id mauris rutrum efficitur. Vestibulum ultrices nunc nunc, vel blandit diam dignissim in. Vestibulum quis vestibulum magna, in ornare orci. Nunc a libero sit amet velit feugiat dignissim. Vivamus eu enim nec ante pharetra pretium vitae ac leo. Nunc diam ex, iaculis eget erat ac, tempor rutrum leo. Sed gravida sapien fermentum quam blandit pharetra.\r\n\r\nSed porta laoreet nulla, non molestie mauris eleifend vitae. Pellentesque in convallis magna. Pellentesque pharetra eros et erat imperdiet mollis. Integer vitae accumsan ipsum. Praesent suscipit justo ut justo imperdiet, efficitur sollicitudin eros malesuada. Cras libero sapien, iaculis quis venenatis eget, finibus vitae nisi. Mauris diam dolor, dictum eget ligula at, lacinia mattis diam. Phasellus et interdum sapien. Morbi augue ipsum, euismod sit amet imperdiet ac, vulputate ac massa. Donec metus justo, eleifend viverra dui vel, blandit euismod elit. Vivamus a tortor interdum, scelerisque nisl sit amet, convallis mauris. Aliquam mollis maximus suscipit. Praesent sed convallis nunc.\r\n\r\nMorbi cursus ornare condimentum. Donec vel erat sodales, gravida felis nec, vulputate erat. Morbi congue metus diam, at convallis metus efficitur in. Suspendisse iaculis nisi id sem feugiat, sit amet aliquam arcu semper. Donec pharetra posuere tellus, vitae posuere dolor bibendum sit amet. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Maecenas sagittis ut felis a faucibus. In in gravida mi. Sed consectetur diam nec mi consectetur, et elementum orci faucibus. Proin non turpis ac dui vulputate congue. Praesent at tellus vel lorem elementum interdum. Nulla facilisi. Cras at faucibus risus. Nam euismod scelerisque aliquet. Etiam pulvinar at ex non pretium. Maecenas elementum enim at lacus facilisis egestas. Nam viverra, lacus a pretium sodales, turpis sem tempus magna, cursus pulvinar ligula tellus id metus. Donec egestas a nisi in congue. Nam vel ipsum maximus, tristique leo vel, interdum tortor. Proin in eros risus. Duis vel odio nulla. Donec sollicitudin ipsum vitae lectus luctus molestie. Vestibulum interdum, sem vel ornare hendrerit, odio velit laoreet justo, at vulputate dui magna eleifend orci. Etiam vel consectetur nunc. Mauris ac tristique mauris. Etiam id accumsan leo. In hac habitasse platea dictumst. Nunc eu metus urna. Curabitur at facilisis turpis. Nullam sed arcu porttitor urna cursus efficitur. Fusce congue turpis turpis. Quisque dui mi, mattis id sapien at, congue condimentum dui. Pellentesque malesuada feugiat mauris, vel vehicula libero luctus a. Maecenas at bibendum nisl, vel dapibus turpis. In risus ligula, malesuada lacinia iaculis vel, varius dignissim urna. Morbi vestibulum scelerisque libero id tincidunt. In rhoncus mollis semper. Pellentesque diam eros biam.";
[TestCase(_myLongString)]
public void SampleTest(string text)
{
}
}
}
Root cause
It appears that tests names greater than 4096 bytes overflow the buffer in the ParitionFilter.
Solution options
Existing documentation presents a solution by adding a different pattern for the display name, either through the TestName attribute paramter or through a .runsettings file. However, this is generally cautioned against, and the error message isn't instructive on a solution.
Instead, I'd like to suggest that the PartitionFilter class only include the first 4096 bytes of the test name in the hash, trimming the excess. If that seems reasonable, I'd be happy to contribute a PR to that effect.
We have unit tests in our project that contain test case data that can extend beyond 4000 characters. When running unit tests in a partition, the following exception is thrown (versions: Nunit 4.3.2 and NUnit3TestAdapter 5.0.0):
Local reproduction
dotnet test -- NUnit.Where="partition = 1/1"from the command line.Root cause
It appears that tests names greater than 4096 bytes overflow the buffer in the ParitionFilter.
Solution options
Existing documentation presents a solution by adding a different pattern for the display name, either through the
TestNameattribute paramter or through a.runsettingsfile. However, this is generally cautioned against, and the error message isn't instructive on a solution.Instead, I'd like to suggest that the PartitionFilter class only include the first 4096 bytes of the test name in the hash, trimming the excess. If that seems reasonable, I'd be happy to contribute a PR to that effect.