From 0a3ceed5530c7259a5d692f4a52f95f2ea3b4333 Mon Sep 17 00:00:00 2001 From: Shad Storhaug Date: Sun, 25 Apr 2021 20:21:33 +0700 Subject: [PATCH] ExceptionExtensions: Added support and tests for filtering types that correspond to RuntimeException in Java (see #446). --- .../ExceptionHandling/ExceptionExtensions.cs | 2 + .../Util/LuceneTestFrameworkInitializer.cs | 2 + .../Store/TestMockDirectoryWrapper.cs | 2 +- .../Analysis/TestGraphTokenizers.cs | 2 +- .../TestExceptionExtensions.cs | 236 +++++++++++++++++- .../ExceptionHandling/ExceptionExtensions.cs | 111 +++++--- 6 files changed, 307 insertions(+), 48 deletions(-) diff --git a/src/Lucene.Net.TestFramework/Support/ExceptionHandling/ExceptionExtensions.cs b/src/Lucene.Net.TestFramework/Support/ExceptionHandling/ExceptionExtensions.cs index 9583df3f93..f4fdd2c4ad 100644 --- a/src/Lucene.Net.TestFramework/Support/ExceptionHandling/ExceptionExtensions.cs +++ b/src/Lucene.Net.TestFramework/Support/ExceptionHandling/ExceptionExtensions.cs @@ -53,6 +53,8 @@ internal static class ExceptionExtensions [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsIllegalArgumentException(this Exception e) { + if (e is null || e.IsAlwaysIgnored()) return false; + return e is ArgumentException && !(e is ArgumentNullException) && // Corresponds to NullPointerException, so we don't catch it here. !(e is ArgumentOutOfRangeException); // Corresponds to IndexOutOfBoundsException (and subclasses), so we don't catch it here. diff --git a/src/Lucene.Net.TestFramework/Support/Util/LuceneTestFrameworkInitializer.cs b/src/Lucene.Net.TestFramework/Support/Util/LuceneTestFrameworkInitializer.cs index 7d8c489d2a..2ad8ccd1c6 100644 --- a/src/Lucene.Net.TestFramework/Support/Util/LuceneTestFrameworkInitializer.cs +++ b/src/Lucene.Net.TestFramework/Support/Util/LuceneTestFrameworkInitializer.cs @@ -233,6 +233,8 @@ private void Initialize() Lucene.ExceptionExtensions.NUnitAssertionExceptionType = typeof(NUnit.Framework.AssertionException); Lucene.ExceptionExtensions.NUnitMultipleAssertExceptionType = typeof(NUnit.Framework.MultipleAssertException); Lucene.ExceptionExtensions.NUnitInconclusiveExceptionType = typeof(NUnit.Framework.InconclusiveException); + Lucene.ExceptionExtensions.NUnitSuccessExceptionType = typeof(NUnit.Framework.SuccessException); + Lucene.ExceptionExtensions.NUnitInvalidPlatformException = Type.GetType("NUnit.Framework.Internal.InvalidPlatformException, NUnit.Framework"); // Identify the Debug.Assert() exception so it can be excluded from being swallowed by catch blocks. // These types are internal, so we can identify them using Reflection. diff --git a/src/Lucene.Net.Tests.TestFramework/Store/TestMockDirectoryWrapper.cs b/src/Lucene.Net.Tests.TestFramework/Store/TestMockDirectoryWrapper.cs index da42a1450f..ee9e1e2307 100644 --- a/src/Lucene.Net.Tests.TestFramework/Store/TestMockDirectoryWrapper.cs +++ b/src/Lucene.Net.Tests.TestFramework/Store/TestMockDirectoryWrapper.cs @@ -276,7 +276,7 @@ public void TestAbuseClosedIndexInput() } // @out.close(); IndexInput @in = dir.OpenInput("foo", IOContext.DEFAULT); @in.Dispose(); - Assert.Throws(() => @in.ReadByte()); + Assert.Throws(() => @in.ReadByte()); } // LUCENENET: This test compiles, but is not compatible with 4.8.0 (tested in Java Lucene), as it was ported from 8.2.0 diff --git a/src/Lucene.Net.Tests/Analysis/TestGraphTokenizers.cs b/src/Lucene.Net.Tests/Analysis/TestGraphTokenizers.cs index 60ed3d4ec8..2198e9235b 100644 --- a/src/Lucene.Net.Tests/Analysis/TestGraphTokenizers.cs +++ b/src/Lucene.Net.Tests/Analysis/TestGraphTokenizers.cs @@ -1,4 +1,4 @@ -using J2N.Text; +using J2N.Text; using Lucene.Net.Analysis.TokenAttributes; using Lucene.Net.Diagnostics; using NUnit.Framework; diff --git a/src/Lucene.Net.Tests/Support/ExceptionHandling/TestExceptionExtensions.cs b/src/Lucene.Net.Tests/Support/ExceptionHandling/TestExceptionExtensions.cs index 1ec9d9f77a..1d7990fa9d 100644 --- a/src/Lucene.Net.Tests/Support/ExceptionHandling/TestExceptionExtensions.cs +++ b/src/Lucene.Net.Tests/Support/ExceptionHandling/TestExceptionExtensions.cs @@ -1,5 +1,8 @@ using J2N.Text; using Lucene.Net.Attributes; +using Lucene.Net.Index; +using Lucene.Net.Queries.Function.DocValues; +using Lucene.Net.Search; using Lucene.Net.Util; using NUnit.Framework; using NUnit.Framework.Interfaces; @@ -9,6 +12,9 @@ using System.IO; using System.Linq; using System.Reflection; +using System.Resources; +using System.Security; +using System.Threading; using Assert = Lucene.Net.TestFramework.Assert; using JCG = J2N.Collections.Generic; @@ -53,6 +59,9 @@ public class TestExceptionExtensions : LuceneTestCase // .NET Core 2.1 Only Type.GetType("System.CrossAppDomainMarshaledException, System.Private.CoreLib"); + private static readonly Type NUnitFrameworkInternalInvalidPlatformExceptionType = + Type.GetType("NUnit.Framework.Internal.InvalidPlatformException, NUnit.Framework"); + // Load exception types from all assemblies private static readonly Assembly[] LuceneAssemblies = new Assembly[] @@ -158,12 +167,26 @@ private static IEnumerable LoadKnownErrorExceptionTypes() typeof(Lucene.Net.QueryParsers.Flexible.Core.QueryNodeError), typeof(Lucene.Net.QueryParsers.Flexible.Standard.Parser.TokenMgrError), typeof(Lucene.Net.QueryParsers.Surround.Parser.TokenMgrError), + + typeof(NUnit.Framework.SuccessException), // Not sure about this, but it seems reasonable to ignore it in most cases because it is NUnit result state }; } + private static readonly IEnumerable KnownExceptionTypes = AllExceptionTypes + // Exceptions in Java exclude Errors + .Except(KnownErrorExceptionTypes) + // Special Case: We never want to catch this NUnit exception + .Where(t => !Type.Equals(t, NUnitFrameworkInternalInvalidPlatformExceptionType)); + + private static readonly IEnumerable KnownThrowableExceptionTypes = AllExceptionTypes + // Special Case: We never want to catch this NUnit exception + .Where(t => !Type.Equals(t, NUnitFrameworkInternalInvalidPlatformExceptionType)); + + private static readonly IEnumerable KnownIOExceptionTypes = new Type[] { typeof(UnauthorizedAccessException), typeof(ObjectDisposedException), + typeof(Lucene.AlreadyClosedException), }.Union(AllIOExceptionTypes); private static readonly IEnumerable KnownIndexOutOfBoundsExceptionTypes = new Type[] { @@ -190,7 +213,17 @@ private static IEnumerable LoadKnownErrorExceptionTypes() typeof(ArgumentOutOfRangeException), // Types for use as Java Aliases in .NET - typeof(IllegalArgumentException), + typeof(Lucene.IllegalArgumentException), + typeof(Lucene.ArrayIndexOutOfBoundsException), + typeof(Lucene.IndexOutOfBoundsException), + typeof(Lucene.NullPointerException), // ArgumentNullException subclass + typeof(Lucene.StringIndexOutOfBoundsException), + + // Subclasses + typeof(System.DuplicateWaitObjectException), + typeof(System.Globalization.CultureNotFoundException), + typeof(System.Text.DecoderFallbackException), + typeof(System.Text.EncoderFallbackException), }; private static readonly IEnumerable KnownIllegalArgumentExceptionTypes_TestEnvironment = new Type[] { @@ -198,8 +231,159 @@ private static IEnumerable LoadKnownErrorExceptionTypes() // Types for use as Java Aliases in .NET typeof(IllegalArgumentException), + + // Subclasses + typeof(System.DuplicateWaitObjectException), + typeof(System.Globalization.CultureNotFoundException), + typeof(System.Text.DecoderFallbackException), + typeof(System.Text.EncoderFallbackException), }; + private static readonly IEnumerable KnownRuntimeExceptionTypes = LoadKnownRuntimeExceptionTypes(); + + private static IEnumerable LoadKnownRuntimeExceptionTypes() + { + var result = new HashSet + { + + // ****************************************************************************************** + // CONFIRMED TYPES - these are for sure mapping to a type in Java that we want to catch + // ****************************************************************************************** + + typeof(SystemException), // Roughly corresponds to RuntimeException + + // Corresponds to IndexOutOfBoundsException, StringIndexOutOfBoundsException, and ArrayIndexOutOfBoundsException + typeof(IndexOutOfRangeException), + typeof(ArgumentOutOfRangeException), + typeof(Lucene.ArrayIndexOutOfBoundsException), + typeof(Lucene.IndexOutOfBoundsException), + typeof(Lucene.StringIndexOutOfBoundsException), + + // Corresponds to NullPointerException + typeof(NullReferenceException), + typeof(ArgumentNullException), + typeof(Lucene.NullPointerException), + + // Corresponds to IllegalArgumentException + typeof(ArgumentException), + typeof(Lucene.IllegalArgumentException), + + // Corresponds to UnsupportedOperationException + typeof(NotSupportedException), + typeof(Lucene.UnsupportedOperationException), + + // Corresponds to Lucene's ThreadInterruptedException + typeof(ThreadInterruptedException), + + // Corresponds to SecurityException + typeof(SecurityException), + + // Corresponds to ClassCastException + typeof(InvalidCastException), + + // Corresponds to IllegalStateException + typeof(InvalidOperationException), + typeof(Lucene.IllegalStateException), + + // Corresponds to MissingResourceException + typeof(MissingManifestResourceException), + + // Corresponds to NumberFormatException + typeof(FormatException), + typeof(Lucene.NumberFormatException), + + // Corresponds to ArithmeticException + typeof(ArithmeticException), + + // Corresponds to IllformedLocaleException + typeof(CultureNotFoundException), + + // Corresponds to JUnit's AssumptionViolatedException + typeof(NUnit.Framework.InconclusiveException), + + // Known implementations of IRuntimeException + + typeof(RuntimeException), + typeof(LuceneSystemException), + + typeof(BytesRefHash.MaxBytesLengthExceededException), + typeof(CollectionTerminatedException), + typeof(DocTermsIndexDocValues.DocTermsIndexException), + typeof(MergePolicy.MergeException), + typeof(SearcherExpiredException), + typeof(TimeLimitingCollector.TimeExceededException), + typeof(BooleanQuery.TooManyClausesException), + + // Other known runtime exceptions + typeof(AlreadySetException), // Subclasses InvalidOperationException + typeof(J2N.IO.BufferUnderflowException), + typeof(J2N.IO.BufferOverflowException), + typeof(J2N.IO.InvalidMarkException), + typeof(Lucene.Net.Spatial.Queries.UnsupportedSpatialOperation), // Subclasses NotSupportedException + + //typeof(NUnit.Framework.Internal.InvalidPlatformException), + + // ****************************************************************************************** + // UNCONFIRMED TYPES - these are SystemException types that are included, but require more + // research to determine whether they actually are something we don't want to catch as a RuntimeException. + // ****************************************************************************************** + + typeof(AccessViolationException), + typeof(AppDomainUnloadedException), + typeof(ArrayTypeMismatchException), + typeof(BadImageFormatException), + typeof(CannotUnloadAppDomainException), + typeof(KeyNotFoundException), + typeof(ContextMarshalException), + typeof(DataMisalignedException), + typeof(DivideByZeroException), // Subclasses ArithmeticException, so probably okay + typeof(DllNotFoundException), + typeof(DuplicateWaitObjectException), + typeof(EntryPointNotFoundException), + typeof(ExecutionEngineException), + typeof(InsufficientExecutionStackException), + typeof(InvalidProgramException), + typeof(InvalidDataException), + typeof(MulticastNotSupportedException), + typeof(NotFiniteNumberException), // Subclasses ArithmeticException, so probably okay + typeof(NotImplementedException), + typeof(OperationCanceledException), + typeof(OverflowException), // Subclasses ArithmeticException, so probably okay + typeof(PlatformNotSupportedException), + typeof(RankException), + typeof(System.Reflection.CustomAttributeFormatException), // Maybe like AnnotationTypeMismatchException in Java...? + typeof(System.Resources.MissingSatelliteAssemblyException), + typeof(System.Runtime.CompilerServices.SwitchExpressionException), + typeof(System.Runtime.InteropServices.COMException), + typeof(System.Runtime.InteropServices.ExternalException), + typeof(System.Runtime.InteropServices.InvalidComObjectException), + typeof(System.Runtime.InteropServices.InvalidOleVariantTypeException), + typeof(System.Runtime.InteropServices.MarshalDirectiveException), + typeof(System.Runtime.InteropServices.SafeArrayRankMismatchException), + typeof(System.Runtime.InteropServices.SafeArrayTypeMismatchException), + typeof(System.Runtime.InteropServices.SEHException), + typeof(System.Runtime.Serialization.SerializationException), + typeof(System.Security.Cryptography.CryptographicException), + typeof(System.Security.VerificationException), + typeof(System.Text.DecoderFallbackException), // LUCENENET TODO: Need to be sure about this one + typeof(System.Text.EncoderFallbackException), // LUCENENET TODO: Need to be sure about this one + typeof(System.Threading.AbandonedMutexException), + typeof(System.Threading.SemaphoreFullException), + typeof(System.Threading.SynchronizationLockException), + typeof(System.Threading.Tasks.TaskCanceledException), + typeof(System.Threading.ThreadAbortException), + typeof(System.Threading.ThreadStartException), + typeof(System.Threading.ThreadStateException), + typeof(System.TimeoutException), + typeof(System.TypeAccessException), + typeof(System.TypeInitializationException), + typeof(System.TypeLoadException), + typeof(System.TypeUnloadedException), + }; + + return result; + } + #endregion Known types of exception families #region Special case constructors @@ -365,9 +549,9 @@ public static IEnumerable ThrowableTypeExpressions { // expectedToThrow is true when we expect the error to be thrown and false when we expect it to be caught yield return new TestCaseData( - exceptionType, // exception type (to make NUnit display them all) - true, // expectedToThrow - new Action(() => ThrowException(exceptionType))); // throw exception expression + exceptionType, // exception type (to make NUnit display them all) + !KnownThrowableExceptionTypes.Contains(exceptionType), // expectedToThrow + new Action(() => ThrowException(exceptionType))); // throw exception expression } } } @@ -397,12 +581,27 @@ public static IEnumerable ExceptionTypeExpressions // expectedToThrow is true when we expect the error to be thrown and false when we expect it to be caught yield return new TestCaseData( exceptionType, // exception type (to make NUnit display them all) - KnownErrorExceptionTypes.Contains(exceptionType), // expectedToThrow + !KnownExceptionTypes.Contains(exceptionType), // expectedToThrow new Action(() => ThrowException(exceptionType))); // throw exception expression } } } + public static IEnumerable RuntimeExceptionTypeExpressions + { + get + { + foreach (var exceptionType in AllExceptionTypes) + { + // expectedToThrow is true when we expect the error to be thrown and false when we expect it to be caught + yield return new TestCaseData( + exceptionType, // exception type (to make NUnit display them all) + !KnownRuntimeExceptionTypes.Contains(exceptionType),// expectedToThrow + new Action(() => ThrowException(exceptionType))); // throw exception expression + } + } + } + public static IEnumerable IOExceptionTypeExpressions { get @@ -579,6 +778,24 @@ public void TestIsException(Type exceptionType, bool expectedToThrow, Action exp } } + // This test ensures that all known Error types from Java are not caught by + // our IsRuntimeException() handler. + [Test] + [TestCaseSource("RuntimeExceptionTypeExpressions")] + public void TestIsRuntimeException(Type exceptionType, bool expectedToThrow, Action expression) // LUCENENET NOTE: exceptionType is only here to make NUnit display them all + { + static bool extensionMethod(Exception e) => e.IsRuntimeException(); + + if (expectedToThrow) + { + AssertDoesNotCatch(expression, extensionMethod); + } + else + { + AssertCatches(expression, extensionMethod); + } + } + [Test] [TestCaseSource("IOExceptionTypeExpressions")] public void TestIsIOException(Type exceptionType, bool expectedToThrow, Action expression) // LUCENENET NOTE: exceptionType is only here to make NUnit display them all @@ -722,13 +939,20 @@ private void AssertDoesNotCatch(Action action, Func extensionMe { action(); } + catch (NUnit.Framework.AssertionException e) + { + // Special case - need to suppress this from being thrown to the outer catch + // or we will get a false failure + Assert.IsFalse(extensionMethodExpression(e)); + Assert.Pass($"Expected: Did not catch exception {e.GetType().FullName}"); + } catch (Exception e) when (extensionMethodExpression(e)) { // not expected Assert.Fail($"Exception caught when expected to be thrown: {e.GetType().FullName}"); } } - catch (Exception e) + catch (Exception e) when (!(e is NUnit.Framework.AssertionException)) { // expected Assert.Pass($"Expected: Did not catch exception {e.GetType().FullName}"); diff --git a/src/Lucene.Net/Support/ExceptionHandling/ExceptionExtensions.cs b/src/Lucene.Net/Support/ExceptionHandling/ExceptionExtensions.cs index 67c111f4e2..c8cc58ae48 100644 --- a/src/Lucene.Net/Support/ExceptionHandling/ExceptionExtensions.cs +++ b/src/Lucene.Net/Support/ExceptionHandling/ExceptionExtensions.cs @@ -37,12 +37,21 @@ namespace Lucene /// internal static class ExceptionExtensions { - internal static Type NUnitResultStateExceptionType = null; // All NUnit exceptions derive from this base class + internal static Type NUnitResultStateExceptionType = null; // All NUnit public exceptions derive from this base class internal static Type NUnitAssertionExceptionType = null; internal static Type NUnitMultipleAssertExceptionType = null; internal static Type NUnitInconclusiveExceptionType = null; + internal static Type NUnitSuccessExceptionType = null; // Since this doesn't correspond to anything in Java, we should always ignore it + internal static Type NUnitInvalidPlatformException = null; // Internal exception that subclasses ArgumentException that probably isn't thrown outside of NUnit, but if it ever is we should ignore it always internal static Type DebugAssertExceptionType = null; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool IsAlwaysIgnored(this Exception e) + { + return (!(NUnitSuccessExceptionType is null) && NUnitSuccessExceptionType.IsAssignableFrom(e.GetType())) || + (!(NUnitInvalidPlatformException is null) && NUnitInvalidPlatformException.IsAssignableFrom(e.GetType())); + } + /// /// Used to check whether corresponds to a Throwable /// in Java. Throwable is the base class for all errors in Java. @@ -52,7 +61,9 @@ internal static class ExceptionExtensions [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsThrowable(this Exception e) { - return !(e is null); + if (e is null || e.IsAlwaysIgnored()) return false; + + return true; } /// @@ -66,7 +77,7 @@ public static bool IsThrowable(this Exception e) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsAssertionError(this Exception e) { - if (e is null) return false; + if (e is null || e.IsAlwaysIgnored()) return false; return e is AssertionException || (!(DebugAssertExceptionType is null) && DebugAssertExceptionType.IsAssignableFrom(e.GetType())) || @@ -86,7 +97,10 @@ public static bool IsAssertionError(this Exception e) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsError(this Exception e) { - if (e is null) return false; + if (e is null || e.IsAlwaysIgnored() || + // Exclude InconclusiveException - AssumptionViolatedException derives from RuntimeException in Java so it is not an Error type + (!(NUnitInconclusiveExceptionType is null) && NUnitInconclusiveExceptionType.IsAssignableFrom(e.GetType())) + ) return false; return e is IError || @@ -97,9 +111,7 @@ e is AssertionException || // Ignore .NET debug assert statements (only valid when test framework is attached) (!(DebugAssertExceptionType is null) && DebugAssertExceptionType.IsAssignableFrom(e.GetType())) || // Ignore NUnit exceptions (in tests) - (!(NUnitResultStateExceptionType is null) && NUnitResultStateExceptionType.IsAssignableFrom(e.GetType()) && - // Exclude InconclusiveException - AssumptionViolatedException derives from RuntimeException in Java so it is not an Error type - (!(NUnitInconclusiveExceptionType is null) && NUnitInconclusiveExceptionType.IsAssignableFrom(e.GetType())) == false); + (!(NUnitResultStateExceptionType is null) && NUnitResultStateExceptionType.IsAssignableFrom(e.GetType())); } /// @@ -117,6 +129,8 @@ e is AssertionException || [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsException(this Exception e) { + if (e is null || e.IsAlwaysIgnored()) return false; + return e is Exception && !IsError(e); // IMPORTANT: Error types should not be identified here. } @@ -132,52 +146,56 @@ public static bool IsException(this Exception e) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsRuntimeException(this Exception e) { - // LUCENENET TODO: After creating a RuntimeException replacement (that at least implments IRuntimeException, - // we can use the below code instead and do the proper catch in TestIndexWriterExceptions.IndexerThread using IsRuntimeException(). - // For now, this is close enough but we need a separate exception type for our tests to do checks. - return IsException(e); - - //if (e is null) return false; - - //return e is IRuntimeException || + //// LUCENENET TODO: After creating a RuntimeException replacement (that at least implments IRuntimeException, + //// we can use the below code instead and do the proper catch in TestIndexWriterExceptions.IndexerThread using IsRuntimeException(). + //// For now, this is close enough but we need a separate exception type for our tests to do checks. + //return IsException(e); - // e is IndexOutOfRangeException || - // e is ArgumentOutOfRangeException || - // e is ArgumentException || + if (e is null || - // e is NullReferenceException || - // e is ArgumentNullException || + e.IsAlwaysIgnored() || - // e is NotSupportedException || + // Some Java errors derive from SystemException in .NET, but we don't want to include them here + e.IsError() || - // e is ThreadInterruptedException || + // .NET made IOException a SystemExcpetion, but those should not be included here + e.IsIOException() || - // e is SecurityException || + // ObjectDisposedException is a special case because in Lucene the AlreadyClosedException derived + // from IOException and was therefore a checked excpetion type. + e is ObjectDisposedException || - //// e is ObjectDisposedException || // AlreadyClosedException subclasses IOException, so this one doesn't count here + // These seem to correspond closely to java.lang.ReflectiveOperationException, which are not derived from RuntimeException + e is MemberAccessException || + e is ReflectionTypeLoadException || + e is AmbiguousMatchException + ) + { + return false; + } - // // Known implemetnations of IRuntimeException - // //e is BytesRefHash.MaxBytesLengthExceededException || - // //e is CollectionTerminatedException || - // //e is TimeLimitingCollector.TimeExceededException || - // //e is BooleanQuery.TooManyClausesException || + // Known implemetnations of IRuntimeException - // //e is Lucene.Net.Util.AlreadySetException || // Subclasses InvalidOperationException + // LuceneExcpetion + // BytesRefHash.MaxBytesLengthExceededException + // CollectionTerminatedException + // TimeLimitingCollector.TimeExceededException + // BooleanQuery.TooManyClausesException + return e is IRuntimeException || - // e is J2N.IO.BufferUnderflowException || - // e is J2N.IO.BufferOverflowException || - // e is J2N.IO.InvalidMarkException || + // LUCENENET NOTE: There may be some other types to exclude here, but this is pretty similar to what Java is doing + // once you weed out the above exclusions. This handler is only used in a few places (mostly tests to check exception handling) + // so it is not likely it matters beyond this point. - // e is InvalidCastException || + // See the tests to see the list of exception types that are expected to be caught here + e is SystemException || - // (e is InvalidOperationException && !(e is ObjectDisposedException)) || + e is J2N.IO.BufferUnderflowException || + e is J2N.IO.BufferOverflowException || + e is J2N.IO.InvalidMarkException || - // e is MissingManifestResourceException || - - // (e is FormatException && !(e is J2N.ParseException)) || // Thrown only on datetime and number format problems, ignore ParseException - - // NUnitInconclusiveExceptionType is null ? false : NUnitInconclusiveExceptionType.IsAssignableFrom(e.GetType()); + (NUnitInconclusiveExceptionType is null ? false : NUnitInconclusiveExceptionType.IsAssignableFrom(e.GetType())); } /// @@ -195,6 +213,8 @@ public static bool IsRuntimeException(this Exception e) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsIOException(this Exception e) { + if (e is null || e.IsAlwaysIgnored()) return false; + return e is IOException || e.IsAlreadyClosedException() || // In Lucene, AlreadyClosedException subclass IOException instead of InvalidOperationException, so we need a special case here e is UnauthorizedAccessException; // In Java, java.nio.file.AccessDeniedException subclasses IOException @@ -210,6 +230,8 @@ public static bool IsIOException(this Exception e) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsArrayIndexOutOfBoundsException(this Exception e) { + if (e is null || e.IsAlwaysIgnored()) return false; + return e is ArgumentOutOfRangeException || e is IndexOutOfRangeException; // LUCENENET TODO: These could be real problems where excptions can be prevevented that our catch blocks are hiding } @@ -224,6 +246,8 @@ public static bool IsArrayIndexOutOfBoundsException(this Exception e) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsStringIndexOutOfBoundsException(this Exception e) { + if (e is null || e.IsAlwaysIgnored()) return false; + return e is ArgumentOutOfRangeException || e is IndexOutOfRangeException; // LUCENENET TODO: These could be real problems where excptions can be prevevented that our catch blocks are hiding } @@ -238,6 +262,8 @@ public static bool IsStringIndexOutOfBoundsException(this Exception e) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsIndexOutOfBoundsException(this Exception e) { + if (e is null || e.IsAlwaysIgnored()) return false; + return e is ArgumentOutOfRangeException || e is IndexOutOfRangeException; // LUCENENET TODO: These could be real problems where excptions can be prevevented that our catch blocks are hiding } @@ -337,6 +363,8 @@ public static bool IsIllegalAccessException(this Exception e) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsIllegalArgumentException(this Exception e) { + if (e is null || e.IsAlwaysIgnored()) return false; + // LUCENENET: In production, there is a chance that we will upgrade to ArgumentNullExcpetion or ArgumentOutOfRangeException // and it is still important that those are caught. However, we have a copy of this method in the test environment // where this is done more strictly to catch ArgumentException without its known subclasses so we can be more explicit in tests. @@ -355,6 +383,8 @@ public static bool IsIllegalArgumentException(this Exception e) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsNullPointerException(this Exception e) { + if (e is null || e.IsAlwaysIgnored()) return false; + return e is ArgumentNullException || e is NullReferenceException; // LUCENENET TODO: These could be real problems where excptions can be prevevented that our catch blocks are hiding } @@ -379,6 +409,7 @@ public static bool IsInstantiationException(this Exception e) // or security exceptions such as MemberAccessException or TypeAccessException. return e is MissingMethodException || e is TypeLoadException || + e is ReflectionTypeLoadException || e is TypeInitializationException; // May happen due to a class initializer that throws an uncaught exception. }