diff --git a/src/Lucene.Net.Benchmark/ByTask/Benchmark.cs b/src/Lucene.Net.Benchmark/ByTask/Benchmark.cs index 46223a2ade..dae4477cf4 100644 --- a/src/Lucene.Net.Benchmark/ByTask/Benchmark.cs +++ b/src/Lucene.Net.Benchmark/ByTask/Benchmark.cs @@ -58,8 +58,7 @@ public Benchmark(TextReader algReader) } catch (Exception e) when (e.IsException()) { - //e.printStackTrace(); - Console.Error.WriteLine(e.ToString()); + e.PrintStackTrace(); throw new Exception("Error: cannot init PerfRunData!", e); } @@ -145,7 +144,7 @@ public static void Exec(string[] args) } catch (Exception e) when (e.IsException()) { - Console.Error.WriteLine(e.ToString()); + e.PrintStackTrace(); Environment.Exit(1); } @@ -160,7 +159,7 @@ public static void Exec(string[] args) catch (Exception e) when (e.IsException()) { Console.Error.WriteLine("Error: cannot execute the algorithm! " + e.Message); - Console.Error.WriteLine(e.ToString()); + e.PrintStackTrace(); } Console.WriteLine("####################"); diff --git a/src/Lucene.Net.Benchmark/ByTask/Feeds/EnwikiQueryMaker.cs b/src/Lucene.Net.Benchmark/ByTask/Feeds/EnwikiQueryMaker.cs index 08df36a10e..fa709819b9 100644 --- a/src/Lucene.Net.Benchmark/ByTask/Feeds/EnwikiQueryMaker.cs +++ b/src/Lucene.Net.Benchmark/ByTask/Feeds/EnwikiQueryMaker.cs @@ -123,7 +123,7 @@ private static Query[] CreateQueries(IList qs, Analyzer a) } catch (Exception e) when (e.IsException()) { - Console.Error.WriteLine(e.ToString()); + e.PrintStackTrace(); } } diff --git a/src/Lucene.Net.Benchmark/ByTask/Feeds/ReutersQueryMaker.cs b/src/Lucene.Net.Benchmark/ByTask/Feeds/ReutersQueryMaker.cs index 12b80cde78..e6c7df4605 100644 --- a/src/Lucene.Net.Benchmark/ByTask/Feeds/ReutersQueryMaker.cs +++ b/src/Lucene.Net.Benchmark/ByTask/Feeds/ReutersQueryMaker.cs @@ -103,7 +103,7 @@ private static Query[] CreateQueries(IList qs, Analyzer a) } catch (Exception e) when (e.IsException()) { - Console.Error.WriteLine(e.ToString()); + e.PrintStackTrace(); } } diff --git a/src/Lucene.Net.Benchmark/ByTask/Feeds/TrecContentSource.cs b/src/Lucene.Net.Benchmark/ByTask/Feeds/TrecContentSource.cs index 6cb69b5130..4db0cd4fce 100644 --- a/src/Lucene.Net.Benchmark/ByTask/Feeds/TrecContentSource.cs +++ b/src/Lucene.Net.Benchmark/ByTask/Feeds/TrecContentSource.cs @@ -38,7 +38,7 @@ namespace Lucene.Net.Benchmarks.ByTask.Feeds /// /// work.dirspecifies the working directory. Required if "docs.dir" /// denotes a relative path (default=work). - /// docs.dirspecifies the directory where the TREC files reside. + /// docs.dirspecifies the directory where the TREC files reside. /// Can be set to a relative path if "work.dir" is also specified /// (default=trec). /// @@ -161,7 +161,7 @@ private void Read(StringBuilder buf, string lineStart, internal virtual void OpenNextFile() { DoClose(); - //currPathType = null; + //currPathType = null; while (true) { if (nextFile >= inputFiles.Count) @@ -181,7 +181,7 @@ internal virtual void OpenNextFile() } try { - Stream inputStream = StreamUtils.GetInputStream(f); // support either gzip, bzip2, or regular text file, by extension + Stream inputStream = StreamUtils.GetInputStream(f); // support either gzip, bzip2, or regular text file, by extension reader = new StreamReader(inputStream, m_encoding); currPathType = TrecDocParser.PathType(f); return; @@ -234,7 +234,7 @@ private void DoClose() // LUCENENET specific - separate disposing from closing s if (m_verbose) { Console.WriteLine("failed to dispose reader !"); - Console.WriteLine(e.ToString()); + e.PrintStackTrace(Console.Out); } } reader = null; @@ -275,7 +275,7 @@ public override DocData GetNextDocData(DocData docData) docBuf.Length = 0; Read(docBuf, DOC, false, false); - // save parsedFile for passing trecDataParser after the sync block, in + // save parsedFile for passing trecDataParser after the sync block, in // case another thread will open another file in between. parsedPathType = currPathType; @@ -302,7 +302,7 @@ public override DocData GetNextDocData(DocData docData) // count char length of text to be parsed (may be larger than the resulted plain doc body text). AddBytes(docBuf.Length); - // This code segment relies on HtmlParser being thread safe. When we get + // This code segment relies on HtmlParser being thread safe. When we get // here, everything else is already private to that thread, so we're safe. docData = trecDocParser.Parse(docData, name, this, docBuf, parsedPathType); AddItem(); @@ -367,7 +367,7 @@ public override void SetConfig(Config config) { m_encoding = Encoding.GetEncoding("iso-8859-1"); //StandardCharsets.ISO_8859_1.name(); } - // iteration exclusion in doc name + // iteration exclusion in doc name excludeDocnameIteration = config.Get("content.source.excludeIteration", false); } } diff --git a/src/Lucene.Net.Misc/Index/CompoundFileExtractor.cs b/src/Lucene.Net.Misc/Index/CompoundFileExtractor.cs index 514bfdcf59..bfd6dc7343 100644 --- a/src/Lucene.Net.Misc/Index/CompoundFileExtractor.cs +++ b/src/Lucene.Net.Misc/Index/CompoundFileExtractor.cs @@ -144,8 +144,7 @@ public static void Main(string[] args) } catch (Exception ioe) when (ioe.IsIOException()) { - Console.Error.WriteLine(ioe.ToString()); - //Console.Write(ioe.StackTrace); + ioe.PrintStackTrace(); } finally { @@ -162,8 +161,7 @@ public static void Main(string[] args) } catch (Exception ioe) when (ioe.IsIOException()) { - Console.Error.WriteLine(ioe.ToString()); - //Console.Write(ioe.StackTrace); + ioe.PrintStackTrace(); } } } diff --git a/src/Lucene.Net.Replicator/ReplicationClient.cs b/src/Lucene.Net.Replicator/ReplicationClient.cs index ae735c576a..ad8fe91ef6 100644 --- a/src/Lucene.Net.Replicator/ReplicationClient.cs +++ b/src/Lucene.Net.Replicator/ReplicationClient.cs @@ -291,7 +291,8 @@ private void WriteToInfoStream(string message) /// protected virtual void HandleUpdateException(Exception exception) { - WriteToInfoStream(string.Format("an error occurred during revision update: {0}", exception)); + // LUCENENET specific - use utility method, and print full exception to be equivalent to printStackTrace in Java + WriteToInfoStream($"an error occurred during revision update: {exception}"); } /// diff --git a/src/Lucene.Net.TestFramework/Analysis/BaseTokenStreamTestCase.cs b/src/Lucene.Net.TestFramework/Analysis/BaseTokenStreamTestCase.cs index 6ea882ec7a..67a4c892eb 100644 --- a/src/Lucene.Net.TestFramework/Analysis/BaseTokenStreamTestCase.cs +++ b/src/Lucene.Net.TestFramework/Analysis/BaseTokenStreamTestCase.cs @@ -5,7 +5,6 @@ using Lucene.Net.Documents; using Lucene.Net.Index; using Lucene.Net.Support; -using Lucene.Net.Support.Threading; using Lucene.Net.Util; using RandomizedTesting.Generators; using System; @@ -545,7 +544,7 @@ internal static void CheckResetException(Analyzer a, string input) } catch (Exception unexpected) when (unexpected.IsException()) { - unexpected.printStackTrace(Console.Error); + unexpected.PrintStackTrace(Console.Error); Assert.Fail("Got wrong exception when Reset() not called: " + unexpected); } finally diff --git a/src/Lucene.Net.TestFramework/Codecs/Lucene3x/PreFlexRWPostingsFormat.cs b/src/Lucene.Net.TestFramework/Codecs/Lucene3x/PreFlexRWPostingsFormat.cs index c64495ab78..c76ab663bd 100644 --- a/src/Lucene.Net.TestFramework/Codecs/Lucene3x/PreFlexRWPostingsFormat.cs +++ b/src/Lucene.Net.TestFramework/Codecs/Lucene3x/PreFlexRWPostingsFormat.cs @@ -1,4 +1,5 @@ using Lucene.Net.Index; +using Lucene.Net.Support; using Lucene.Net.Util; using Console = Lucene.Net.Util.SystemConsole; @@ -81,4 +82,4 @@ protected override bool SortTermsByUnicode } } #pragma warning restore 612, 618 -} \ No newline at end of file +} diff --git a/src/Lucene.Net.TestFramework/Codecs/Lucene3x/PreFlexRWTermVectorsFormat.cs b/src/Lucene.Net.TestFramework/Codecs/Lucene3x/PreFlexRWTermVectorsFormat.cs index 920907988a..a7b726a4fc 100644 --- a/src/Lucene.Net.TestFramework/Codecs/Lucene3x/PreFlexRWTermVectorsFormat.cs +++ b/src/Lucene.Net.TestFramework/Codecs/Lucene3x/PreFlexRWTermVectorsFormat.cs @@ -1,5 +1,6 @@ using Lucene.Net.Index; using Lucene.Net.Store; +using Lucene.Net.Support; using Lucene.Net.Util; using System; @@ -65,4 +66,4 @@ protected internal override bool SortTermsByUnicode() } } #pragma warning restore 612, 618 -} \ No newline at end of file +} diff --git a/src/Lucene.Net.TestFramework/Index/ThreadedIndexingAndSearchingTestCase.cs b/src/Lucene.Net.TestFramework/Index/ThreadedIndexingAndSearchingTestCase.cs index 29744b0706..8ada053450 100644 --- a/src/Lucene.Net.TestFramework/Index/ThreadedIndexingAndSearchingTestCase.cs +++ b/src/Lucene.Net.TestFramework/Index/ThreadedIndexingAndSearchingTestCase.cs @@ -121,10 +121,10 @@ protected virtual void DoAfterIndexingThreadDone() { } - private ThreadJob[] LaunchIndexingThreads(LineFileDocs docs, - int numThreads, - long stopTime, - ISet delIDs, + private ThreadJob[] LaunchIndexingThreads(LineFileDocs docs, + int numThreads, + long stopTime, + ISet delIDs, ISet delPackIDs, ConcurrentQueue allSubDocs) { @@ -264,7 +264,7 @@ public override void Run() outerInstance.m_delCount.AddAndGet(delSubDocs.SubIDs.Count); if (Verbose) { - Console.WriteLine(Thread.CurrentThread.Name + ": update pack packID=" + delSubDocs.PackID + + Console.WriteLine(Thread.CurrentThread.Name + ": update pack packID=" + delSubDocs.PackID + " count=" + docsList.Count + " docs=" + string.Format(J2N.Text.StringFormatter.InvariantCulture, "{0}", docIDs)); } outerInstance.UpdateDocuments(packIDTerm, docsList); @@ -273,7 +273,7 @@ public override void Run() { if (Verbose) { - Console.WriteLine(Thread.CurrentThread.Name + ": add pack packID=" + packID + + Console.WriteLine(Thread.CurrentThread.Name + ": add pack packID=" + packID + " count=" + docsList.Count + " docs=" + string.Format(J2N.Text.StringFormatter.InvariantCulture, "{0}", docIDs)); } outerInstance.AddDocuments(packIDTerm, docsList); @@ -378,9 +378,8 @@ public override void Run() catch (Exception t) when (t.IsThrowable()) { Console.WriteLine(Thread.CurrentThread.Name + ": hit exc"); - Console.WriteLine(t.ToString()); - Console.Write(t.StackTrace); - outerInstance.m_failed.Value = (true); + outerInstance.m_failed.Value = true; + t.PrintStackTrace(); throw RuntimeException.Create(t); } } @@ -536,8 +535,8 @@ public override void Run() catch (Exception t) when (t.IsThrowable()) { Console.WriteLine(Thread.CurrentThread.Name + ": hit exc"); - outerInstance.m_failed.Value = (true); - Console.WriteLine(t.ToString()); + outerInstance.m_failed.Value = true; + t.PrintStackTrace(Console.Out); throw RuntimeException.Create(t); } } @@ -929,4 +928,4 @@ protected virtual void SmokeTestSearcher(IndexSearcher s) RunQuery(s, pq); } } -} \ No newline at end of file +} diff --git a/src/Lucene.Net.TestFramework/Search/ShardSearchingTestBase.cs b/src/Lucene.Net.TestFramework/Search/ShardSearchingTestBase.cs index a549dda5a5..48057d5085 100644 --- a/src/Lucene.Net.TestFramework/Search/ShardSearchingTestBase.cs +++ b/src/Lucene.Net.TestFramework/Search/ShardSearchingTestBase.cs @@ -736,7 +736,7 @@ public override void Run() catch (Exception t) when (t.IsThrowable()) { Console.WriteLine("FAILED:"); - Console.Out.WriteLine(t.StackTrace); + t.PrintStackTrace(Console.Out); throw RuntimeException.Create(t); } } diff --git a/src/Lucene.Net.TestFramework/Store/MockDirectoryWrapper.cs b/src/Lucene.Net.TestFramework/Store/MockDirectoryWrapper.cs index 46841b47ee..5986ea40e4 100644 --- a/src/Lucene.Net.TestFramework/Store/MockDirectoryWrapper.cs +++ b/src/Lucene.Net.TestFramework/Store/MockDirectoryWrapper.cs @@ -494,6 +494,7 @@ internal virtual void MaybeThrowIOException(string message) if (LuceneTestCase.Verbose) { Console.WriteLine(Thread.CurrentThread.Name + ": MockDirectoryWrapper: now throw random exception" + (message is null ? "" : " (" + message + ")")); + StackTraceHelper.PrintCurrentStackTrace(Console.Out); } throw new IOException("a random IOException" + (message is null ? "" : " (" + message + ")")); } @@ -505,7 +506,8 @@ internal virtual void MaybeThrowIOExceptionOnOpen(string name) { if (LuceneTestCase.Verbose) { - Console.WriteLine(Thread.CurrentThread.Name + ": MockDirectoryWrapper: now throw random exception during open file=" + name); + Console.WriteLine(Thread.CurrentThread.Name + ": MockDirectoryWrapper: now throw random exception during open file=" + name); + StackTraceHelper.PrintCurrentStackTrace(Console.Out); } if (allowRandomFileNotFoundException == false || randomState.NextBoolean()) { @@ -513,7 +515,7 @@ internal virtual void MaybeThrowIOExceptionOnOpen(string name) } else { - throw randomState.NextBoolean() ? (IOException)new FileNotFoundException("a random IOException (" + name + ")") : new DirectoryNotFoundException("a random IOException (" + name + ")"); + throw randomState.NextBoolean() ? new FileNotFoundException("a random IOException (" + name + ")") : new DirectoryNotFoundException("a random IOException (" + name + ")"); } } } @@ -1038,7 +1040,7 @@ protected override void Dispose(bool disposing) catch (Exception t) when (t.IsThrowable()) { Console.Error.WriteLine("ERROR processing leftover segments file " + file + ":"); - Console.WriteLine(t.ToString()); + t.PrintStackTrace(); } } } diff --git a/src/Lucene.Net.TestFramework/Store/MockIndexOutputWrapper.cs b/src/Lucene.Net.TestFramework/Store/MockIndexOutputWrapper.cs index db72c1da0d..e55765efc1 100644 --- a/src/Lucene.Net.TestFramework/Store/MockIndexOutputWrapper.cs +++ b/src/Lucene.Net.TestFramework/Store/MockIndexOutputWrapper.cs @@ -1,4 +1,5 @@ -using Lucene.Net.Util; +using Lucene.Net.Support; +using Lucene.Net.Util; using System; using System.IO; using System.Threading; @@ -97,7 +98,7 @@ private void CheckDiskFull(byte[] b, int offset, DataInput @in, long len) if (LuceneTestCase.Verbose) { Console.WriteLine(Thread.CurrentThread.Name + ": MDW: now throw fake disk full"); - Console.WriteLine(Environment.StackTrace); + StackTraceHelper.PrintCurrentStackTrace(Console.Out); } throw new IOException(message); } @@ -199,4 +200,4 @@ public override string ToString() return "MockIndexOutputWrapper(" + @delegate + ")"; } } -} \ No newline at end of file +} diff --git a/src/Lucene.Net.TestFramework/Support/JavaCompatibility/SystemTypesHelpers.cs b/src/Lucene.Net.TestFramework/Support/JavaCompatibility/SystemTypesHelpers.cs index 68733500de..6f149416d5 100644 --- a/src/Lucene.Net.TestFramework/Support/JavaCompatibility/SystemTypesHelpers.cs +++ b/src/Lucene.Net.TestFramework/Support/JavaCompatibility/SystemTypesHelpers.cs @@ -8,7 +8,6 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; -using Console = Lucene.Net.Util.SystemConsole; using JCG = J2N.Collections.Generic; namespace Lucene.Net @@ -290,16 +289,6 @@ public static void retainAll(this ISet s, ISet other) } } - public static void printStackTrace(this Exception e) - { - Console.Error.WriteLine(e.StackTrace); - } - - public static void printStackTrace(this Exception e, TextWriter destination) - { - destination.WriteLine(e.StackTrace); - } - /// /// Locates resources in the same directory as this type /// diff --git a/src/Lucene.Net.TestFramework/Support/StackTraceHelper.cs b/src/Lucene.Net.TestFramework/Support/StackTraceHelper.cs deleted file mode 100644 index 773f26e299..0000000000 --- a/src/Lucene.Net.TestFramework/Support/StackTraceHelper.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Diagnostics; - -namespace Lucene.Net.Util -{ - /* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - /// - /// LUCENENET specific class to normalize stack trace behavior between different .NET Framework and .NET Standard 1.x, - /// which did not support the StackTrace class. - /// - public static class StackTraceHelper - { - /// - /// Matches the StackTrace for a method name. - /// - /// IMPORTANT: To make the tests pass in release mode, the method(s) named here - /// must be decorated with [MethodImpl(MethodImplOptions.NoInlining)]. - /// - public static bool DoesStackTraceContainMethod(string methodName) - { - StackTrace trace = new StackTrace(); - foreach (var frame in trace.GetFrames()) - { - if (frame.GetMethod().Name.Equals(methodName, StringComparison.Ordinal)) - { - return true; - } - } - return false; - } - - /// - /// Matches the StackTrace for a particular class (not fully-qualified) and method name. - /// - /// IMPORTANT: To make the tests pass in release mode, the method(s) named here - /// must be decorated with [MethodImpl(MethodImplOptions.NoInlining)]. - /// - public static bool DoesStackTraceContainMethod(string className, string methodName) - { - StackTrace trace = new StackTrace(); - foreach (var frame in trace.GetFrames()) - { - var method = frame.GetMethod(); - if (method.DeclaringType.Name.Equals(className, StringComparison.Ordinal) && method.Name.Equals(methodName, StringComparison.Ordinal)) - { - return true; - } - } - return false; - } - } -} diff --git a/src/Lucene.Net.Tests.AllProjects/Support/ExceptionHandling/TestExceptionExtensions.cs b/src/Lucene.Net.Tests.AllProjects/Support/ExceptionHandling/TestExceptionExtensions.cs index 9efc1c5b2f..776f6ac06a 100644 --- a/src/Lucene.Net.Tests.AllProjects/Support/ExceptionHandling/TestExceptionExtensions.cs +++ b/src/Lucene.Net.Tests.AllProjects/Support/ExceptionHandling/TestExceptionExtensions.cs @@ -1,7 +1,9 @@ using Lucene.Net.Attributes; +using Lucene.Net.Util; using NUnit.Framework; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using Assert = Lucene.Net.TestFramework.Assert; @@ -375,6 +377,73 @@ public void TestIsIllegalArgumentException_TestEnvironment(Type exceptionType, b } } + private class MyException : Exception + { + public MyException(string message) : base(message) + { + } + } + + private class MyException2 : Exception + { + public MyException2(string message) : base(message) + { + } + } + + [Test] + public void TestPrintStackTrace() + { + using var sw = new StringWriter(); + + try + { + throw new MyException("Test exception"); + } + catch (Exception e) + { + e.PrintStackTrace(sw); + } + + var str = sw.ToString(); + + Assert.IsTrue(str.Contains(typeof(MyException).FullName!, StringComparison.Ordinal)); + Assert.IsTrue(str.Contains("Test exception", StringComparison.Ordinal)); + Assert.IsTrue(str.Contains(nameof(TestPrintStackTrace), StringComparison.Ordinal)); + } + + [Test] + public void TestPrintStackTrace_WithSuppressed() + { + using var sw = new StringWriter(); + + try + { + throw new MyException("Test exception"); + } + catch (Exception e) + { + try + { + throw new MyException2("Suppressed exception"); + } + catch (Exception suppressed) + { + e.AddSuppressed(suppressed); + } + + e.PrintStackTrace(sw); + } + + var str = sw.ToString(); + + Assert.IsTrue(str.Contains(typeof(MyException).FullName!, StringComparison.Ordinal)); + Assert.IsTrue(str.Contains("Test exception", StringComparison.Ordinal)); + Assert.IsTrue(str.Contains(nameof(TestPrintStackTrace), StringComparison.Ordinal)); + Assert.IsTrue(str.Contains(typeof(MyException2).FullName!, StringComparison.Ordinal)); + Assert.IsTrue(str.Contains("Suppressed exception", StringComparison.Ordinal)); + } + private static void AssertCatches(Action action, Func extensionMethodExpression) { try diff --git a/src/Lucene.Net.Tests.AllProjects/Support/ExceptionHandling/TestStackTraceHelper.cs b/src/Lucene.Net.Tests.AllProjects/Support/ExceptionHandling/TestStackTraceHelper.cs new file mode 100644 index 0000000000..13085e68dc --- /dev/null +++ b/src/Lucene.Net.Tests.AllProjects/Support/ExceptionHandling/TestStackTraceHelper.cs @@ -0,0 +1,59 @@ +using Lucene.Net.Attributes; +using Lucene.Net.Util; +using NUnit.Framework; +using System.IO; + +namespace Lucene.Net.Support.ExceptionHandling +{ + /* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + [TestFixture, LuceneNetSpecific] + public class TestStackTraceHelper : LuceneTestCase + { + [Test] + [TestCase(true, nameof(TestDoesStackTraceContainMethod))] + [TestCase(false, nameof(GetHashCode))] + public void TestDoesStackTraceContainMethod(bool expected, string methodName) + { + Assert.AreEqual(expected, StackTraceHelper.DoesStackTraceContainMethod(methodName)); + } + + [Test] + [TestCase(true, nameof(TestStackTraceHelper), nameof(TestDoesStackTraceContainMethodWithClassName))] + [TestCase(false, nameof(TestStackTraceHelper), nameof(GetHashCode))] + [TestCase(false, nameof(LuceneTestCase), nameof(TestDoesStackTraceContainMethodWithClassName))] + public void TestDoesStackTraceContainMethodWithClassName(bool expected, string className, string methodName) + { + Assert.AreEqual(expected, StackTraceHelper.DoesStackTraceContainMethod(className, methodName)); + } + + [Test] + public void TestPrintCurrentStackTrace() + { + using var sw = new StringWriter(); + StackTraceHelper.PrintCurrentStackTrace(sw); + + string str = sw.ToString(); + + using var sr = new StringReader(str); + string topLine = sr.ReadLine(); + Assert.NotNull(topLine); + Assert.IsTrue(topLine.Contains(nameof(TestPrintCurrentStackTrace))); + } + } +} diff --git a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Core/TestRandomChains.cs b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Core/TestRandomChains.cs index 60c2866988..41720d2065 100644 --- a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Core/TestRandomChains.cs +++ b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Core/TestRandomChains.cs @@ -933,7 +933,7 @@ private T CreateComponent(ConstructorInfo ctor, object[] args, StringBuilder if (Verbose) { Console.WriteLine("Ignoring IAE/UOE from ctor:"); - //cause.printStackTrace(System.err); + ite.InnerException.PrintStackTrace(Console.Error); } } else diff --git a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Util/TestBufferedCharFilter.cs b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Util/TestBufferedCharFilter.cs index ce6e3941e2..739781047e 100644 --- a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Util/TestBufferedCharFilter.cs +++ b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Util/TestBufferedCharFilter.cs @@ -429,7 +429,7 @@ public void Test_ReadCII() //char[] contents = new char[size]; - //public int read() + //public int read() //{ // if (pos >= size) // throw new IOException("Read past end of data"); @@ -453,7 +453,7 @@ public void Test_ReadCII() // return size - pos > 0; //} - //public void close() + //public void close() //{ //} // }); @@ -713,6 +713,8 @@ public void Test_ReadLine() /** * @tests java.io.BufferedReader#ready() */ + [Test, LuceneNetSpecific] + [AwaitsFix(BugUrl = "https://github.com/apache/lucenenet/issues/1102")] // LUCENENET TODO: fix test public void Test_Ready() { // Test for method boolean java.io.BufferedReader.ready() @@ -730,6 +732,7 @@ public void Test_Ready() /** * @tests java.io.BufferedReader#reset() */ + [Test, LuceneNetSpecific] public void Test_Reset() { // Test for method void java.io.BufferedReader.reset() @@ -850,4 +853,4 @@ public override void TearDown() } } } -} \ No newline at end of file +} diff --git a/src/Lucene.Net.Tests.Expressions/JS/TestCustomFunctions.cs b/src/Lucene.Net.Tests.Expressions/JS/TestCustomFunctions.cs index 00b84947ab..3ab9e7e751 100644 --- a/src/Lucene.Net.Tests.Expressions/JS/TestCustomFunctions.cs +++ b/src/Lucene.Net.Tests.Expressions/JS/TestCustomFunctions.cs @@ -63,19 +63,19 @@ public virtual void TestDefaultList() public virtual void TestNoArgMethod() { IDictionary functions = new Dictionary(); - functions["foo"] = GetType().GetMethod("ZeroArgMethod"); + functions["foo"] = GetType().GetMethod(nameof(ZeroArgMethod)); var expr = JavascriptCompiler.Compile("foo()", functions); Assert.AreEqual(5, expr.Evaluate(0, null), DELTA); } - public static double OneArgMethod(double arg1) => 3 + arg1; + public static double OneArgMethod(double arg1) => 3 + arg1; /// tests a method with one arguments [Test] public virtual void TestOneArgMethod() { IDictionary functions = new Dictionary(); - functions["foo"] = GetType().GetMethod("OneArgMethod", new []{ typeof(double)}); + functions["foo"] = GetType().GetMethod(nameof(OneArgMethod), new []{ typeof(double)}); var expr = JavascriptCompiler.Compile("foo(3)", functions); Assert.AreEqual(6, expr.Evaluate(0, null), DELTA); } @@ -87,7 +87,7 @@ public virtual void TestOneArgMethod() public virtual void TestThreeArgMethod() { IDictionary functions = new Dictionary(); - functions["foo"] = GetType().GetMethod("ThreeArgMethod", new []{ typeof(double), typeof(double), typeof(double)}); + functions["foo"] = GetType().GetMethod(nameof(ThreeArgMethod), new []{ typeof(double), typeof(double), typeof(double)}); var expr = JavascriptCompiler.Compile("foo(3, 4, 5)", functions); Assert.AreEqual(12, expr.Evaluate(0, null), DELTA); } @@ -97,20 +97,20 @@ public virtual void TestThreeArgMethod() public virtual void TestTwoMethods() { IDictionary functions = new Dictionary(); - functions["foo"] = GetType().GetMethod("ZeroArgMethod"); - functions["bar"] = GetType().GetMethod("OneArgMethod", new []{typeof(double)}); + functions["foo"] = GetType().GetMethod(nameof(ZeroArgMethod)); + functions["bar"] = GetType().GetMethod(nameof(OneArgMethod), new[] { typeof(double) }); var expr = JavascriptCompiler.Compile("foo() + bar(3)", functions); Assert.AreEqual(11, expr.Evaluate(0, null), DELTA); } - public static string BogusReturnType() => "bogus!"; + public static string BogusReturnType() => "bogus!"; /// wrong return type: must be double [Test] public virtual void TestWrongReturnType() { IDictionary functions = new Dictionary(); - functions["foo"] = GetType().GetMethod("BogusReturnType"); + functions["foo"] = GetType().GetMethod(nameof(BogusReturnType)); try { JavascriptCompiler.Compile("foo()", functions); @@ -122,14 +122,14 @@ public virtual void TestWrongReturnType() } } - public static double BogusParameterType(string s) => 0; + public static double BogusParameterType(string s) => 0; /// wrong param type: must be doubles [Test] public virtual void TestWrongParameterType() { IDictionary functions = new Dictionary(); - functions["foo"] = GetType().GetMethod("BogusParameterType", new []{ typeof(string)}); + functions["foo"] = GetType().GetMethod(nameof(BogusParameterType), new[] { typeof(string) }); try { JavascriptCompiler.Compile("foo(2)", functions); @@ -141,14 +141,14 @@ public virtual void TestWrongParameterType() } } - public virtual double NonStaticMethod() => 0; + public virtual double NonStaticMethod() => 0; /// wrong modifiers: must be static [Test] public virtual void TestWrongNotStatic() { IDictionary functions = new Dictionary(); - functions["foo"] = GetType().GetMethod("NonStaticMethod"); + functions["foo"] = GetType().GetMethod(nameof(NonStaticMethod)); try { JavascriptCompiler.Compile("foo()", functions); @@ -167,8 +167,8 @@ public virtual void TestWrongNotStatic() public virtual void TestWrongNotPublic() { IDictionary functions = new Dictionary(); - functions["foo"] = GetType().GetMethod("NonPublicMethod",BindingFlags.NonPublic|BindingFlags.Static); - + functions["foo"] = GetType().GetMethod(nameof(NonPublicMethod), BindingFlags.NonPublic | BindingFlags.Static); + try { JavascriptCompiler.Compile("foo()", functions); @@ -190,7 +190,7 @@ internal class NestedNotPublic public virtual void TestWrongNestedNotPublic() { IDictionary functions = new Dictionary(); - functions["foo"] = typeof(NestedNotPublic).GetMethod("Method"); + functions["foo"] = typeof(NestedNotPublic).GetMethod(nameof(NestedNotPublic.Method)); try { JavascriptCompiler.Compile("foo()", functions); @@ -204,8 +204,8 @@ public virtual void TestWrongNestedNotPublic() //LUCENENET: testClassLoader() was not ported. (May not apply to Lucene.Net) - - + + internal static string MESSAGE = "This should not happen but it happens"; public static class StaticThrowingException // LUCENENET specific: CA1052 Static holder types should be Static or NotInheritable @@ -223,8 +223,8 @@ public static double Method() public virtual void TestThrowingException() { IDictionary functions = new Dictionary(); - functions["foo"] = typeof(StaticThrowingException).GetMethod("Method"); - string source = "3 * foo() / 5"; + functions["foo"] = typeof(StaticThrowingException).GetMethod(nameof(StaticThrowingException.Method)); + const string source = "3 * foo() / 5"; var expr = JavascriptCompiler.Compile(source, functions); try { @@ -234,14 +234,16 @@ public virtual void TestThrowingException() catch (Exception e) when (e.IsArithmeticException()) { Assert.AreEqual(MESSAGE, e.Message); - StringWriter sw = new StringWriter(); - e.printStackTrace(); + using StringWriter sw = new StringWriter(); + e.PrintStackTrace(sw); + sw.Flush(); //.NET Port + var swString = sw.ToString(); Assert.IsTrue( // LUCENENET: Apparently in .NET 7, they finally fixed this weird display issue with spaces before the comma // and closing parenthesis. It is a pass. - e.StackTrace.Contains("Lucene.Net.Expressions.CompiledExpression.Evaluate(Int32, FunctionValues[])") || - e.StackTrace.Contains("Lucene.Net.Expressions.CompiledExpression.Evaluate(Int32 , FunctionValues[] )") + swString.Contains("Lucene.Net.Expressions.CompiledExpression.Evaluate(Int32, FunctionValues[])") || + swString.Contains("Lucene.Net.Expressions.CompiledExpression.Evaluate(Int32 , FunctionValues[] )") ); } } @@ -252,7 +254,7 @@ public virtual void TestNamespaces() { IDictionary functions = new Dictionary(); functions["foo.bar"] = GetType().GetMethod("ZeroArgMethod"); - string source = "foo.bar()"; + const string source = "foo.bar()"; var expr = JavascriptCompiler.Compile(source, functions); Assert.AreEqual(5, expr.Evaluate(0, null), DELTA); } diff --git a/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyCombined.cs b/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyCombined.cs index 2d1ac3580e..9de607eb1b 100644 --- a/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyCombined.cs +++ b/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyCombined.cs @@ -5,6 +5,7 @@ using NUnit.Framework; using System; using System.Globalization; +using System.IO; using System.Text; using System.Threading; using Assert = Lucene.Net.TestFramework.Assert; @@ -860,7 +861,7 @@ private void AssertConsistentYoungestChild(FacetLabel abPath, int abOrd, int abY stop.Value = true; thread.Join(); - Assert.IsNull(error[0], "Unexpcted exception at retry " + retry + " retrieval " + retrieval[0] + ": \n" + stackTraceStr(error[0])); + Assert.IsNull(error[0], "Unexpcted exception at retry " + retry + " retrieval " + retrieval[0] + ": \n" + StackTraceStr(error[0])); tr.Dispose(); } @@ -926,15 +927,20 @@ private void AssertChildrenArrays(ParallelTaxonomyArrays ca, int retry, int retr /// Grab the stack trace into a string since the exception was thrown in a thread and we want the assert /// outside the thread to show the stack trace in case of failure. /// - private string stackTraceStr(Exception error) + // LUCENENET specific - made static + private static string StackTraceStr(Exception error) { if (error is null) { return ""; } - error.printStackTrace(); - return error.StackTrace; + // LUCENENET specific - we can just return e.ToString() here to get the Java equivalent with less allocations. would otherwise be: + // using var sw = new StringWriter(); + // error.PrintStackTrace(sw); + // sw.Flush(); + // return sw.ToString(); + return error.ToString(); } /// diff --git a/src/Lucene.Net.Tests.Replicator/IndexAndTaxonomyReplicationClientTest.cs b/src/Lucene.Net.Tests.Replicator/IndexAndTaxonomyReplicationClientTest.cs index bfc219bea0..a57115f84c 100644 --- a/src/Lucene.Net.Tests.Replicator/IndexAndTaxonomyReplicationClientTest.cs +++ b/src/Lucene.Net.Tests.Replicator/IndexAndTaxonomyReplicationClientTest.cs @@ -445,7 +445,8 @@ protected override void HandleUpdateException(Exception exception) { if (Verbose) { - Console.WriteLine("hit exception during update: " + exception); + Console.WriteLine("hit exception during update: " + exception.ToTypeMessageString()); // LUCENENET specific - use ToTypeMessageString to mimic Java behavior + exception.PrintStackTrace(Console.Out); } // test that the index can be read and also some basic statistics diff --git a/src/Lucene.Net.Tests.Replicator/IndexReplicationClientTest.cs b/src/Lucene.Net.Tests.Replicator/IndexReplicationClientTest.cs index 01085c8636..8ff27fb5b3 100644 --- a/src/Lucene.Net.Tests.Replicator/IndexReplicationClientTest.cs +++ b/src/Lucene.Net.Tests.Replicator/IndexReplicationClientTest.cs @@ -273,7 +273,7 @@ public void TestConsistencyOnExceptions() } // disable errors -- maybe randomness didn't exhaust all allowed failures, - // and we don't want e.g. CheckIndex to hit false errors. + // and we don't want e.g. CheckIndex to hit false errors. handlerDir.MaxSizeInBytes = 0; handlerDir.RandomIOExceptionRate = 0.0; handlerDir.RandomIOExceptionRateOnOpen = 0.0; @@ -352,7 +352,8 @@ protected override void HandleUpdateException(Exception exception) { if (Verbose) { - Console.WriteLine("hit exception during update: " + exception); + Console.WriteLine("hit exception during update: " + exception.ToTypeMessageString()); // LUCENENET specific - use ToTypeMessageString to mimic Java behavior + exception.PrintStackTrace(Console.Out); } try @@ -406,4 +407,4 @@ protected override void HandleUpdateException(Exception exception) } } -} \ No newline at end of file +} diff --git a/src/Lucene.Net.Tests.Suggest/Spell/TestSpellChecker.cs b/src/Lucene.Net.Tests.Suggest/Spell/TestSpellChecker.cs index b26d87f03d..f1ca96460e 100644 --- a/src/Lucene.Net.Tests.Suggest/Spell/TestSpellChecker.cs +++ b/src/Lucene.Net.Tests.Suggest/Spell/TestSpellChecker.cs @@ -448,7 +448,7 @@ public void TestClose() } /* - * tests if the internally shared indexsearcher is correctly closed + * tests if the internally shared indexsearcher is correctly closed * when the spellchecker is concurrently accessed and closed. */ [Test] @@ -490,7 +490,7 @@ public async Task TestConcurrentAccess() Thread.Sleep(100); // concurrently reset the spell index spellChecker.SetSpellIndex(this.spellindex); - // for debug - prints the internal open searchers + // for debug - prints the internal open searchers // showSearchersOpen(); } @@ -559,7 +559,7 @@ private void AssertSearchersClosed() // for (IndexSearcher searcher : searchers) { // if(searcher.getIndexReader().getRefCount() > 0) // ++count; - // } + // } // System.out.println(count); // } @@ -578,7 +578,7 @@ public SpellCheckWorker(TestSpellChecker outerInstance, IndexReader reader, Atom { this.outerInstance = outerInstance; this.reader = reader; - + this.stop = stop; this.cancellationToken = cancellationToken; this.taskNum = taskNum; @@ -611,7 +611,7 @@ public void Run() } catch (Exception e) when (e.IsThrowable()) { - e.printStackTrace(); + e.PrintStackTrace(); error = e; return; } @@ -630,21 +630,6 @@ public void Run() } } - /// - /// Grab the stack trace into a string since the exception was thrown in a thread and we want the assert - /// outside the thread to show the stack trace in case of failure. - /// - private string stackTraceStr(Exception error) - { - if (error is null) - { - return ""; - } - - error.printStackTrace(); - return error.StackTrace; - } - internal class SpellCheckerMock : SpellChecker { public SpellCheckerMock(Directory spellIndex) diff --git a/src/Lucene.Net.Tests.Suggest/Suggest/LookupBenchmarkTest.cs b/src/Lucene.Net.Tests.Suggest/Suggest/LookupBenchmarkTest.cs index e4669f5e7e..07eba88c7d 100644 --- a/src/Lucene.Net.Tests.Suggest/Suggest/LookupBenchmarkTest.cs +++ b/src/Lucene.Net.Tests.Suggest/Suggest/LookupBenchmarkTest.cs @@ -165,7 +165,7 @@ public void TestStorageNeeds() } /** - * Create instance and populate it. + * Create instance and populate it. */ internal Lookup BuildLookup(Type cls, Input[] input) { @@ -227,7 +227,7 @@ public void TestPerformanceOnPrefixes2_4() } /** - * Run the actual benchmark. + * Run the actual benchmark. */ public void RunPerformanceTest(int minPrefixLen, int maxPrefixLen, int num, bool onlyMorePopular) @@ -290,7 +290,7 @@ public int Call() */ private BenchmarkResult Measure(Func callable) { - double NANOS_PER_MS = 1000000; + const double NANOS_PER_MS = 1000000; try { @@ -305,9 +305,8 @@ private BenchmarkResult Measure(Func callable) } catch (Exception e) when (e.IsException()) { - e.printStackTrace(); + e.PrintStackTrace(); throw RuntimeException.Create(e); - } } diff --git a/src/Lucene.Net.Tests/Index/TestAddIndexes.cs b/src/Lucene.Net.Tests/Index/TestAddIndexes.cs index fe49a296de..b07ceeb147 100644 --- a/src/Lucene.Net.Tests/Index/TestAddIndexes.cs +++ b/src/Lucene.Net.Tests/Index/TestAddIndexes.cs @@ -831,7 +831,7 @@ public CommitAndAddIndexes(int numCopy) internal override void Handle(Exception t) { - t.printStackTrace(Console.Out); + t.PrintStackTrace(Console.Out); UninterruptableMonitor.Enter(failures); try { @@ -936,7 +936,7 @@ internal override void Handle(Exception t) { if (!t.IsAlreadyClosedException() && !t.IsNullPointerException()) { - t.printStackTrace(Console.Out); + t.PrintStackTrace(Console.Out); UninterruptableMonitor.Enter(failures); try { @@ -1046,7 +1046,7 @@ internal override void Handle(Exception t) } if (report) { - t.printStackTrace(Console.Out); + t.PrintStackTrace(Console.Out); UninterruptableMonitor.Enter(failures); try { diff --git a/src/Lucene.Net.Tests/Index/TestAtomicUpdate.cs b/src/Lucene.Net.Tests/Index/TestAtomicUpdate.cs index 48410fe188..bdd356a02e 100644 --- a/src/Lucene.Net.Tests/Index/TestAtomicUpdate.cs +++ b/src/Lucene.Net.Tests/Index/TestAtomicUpdate.cs @@ -68,7 +68,7 @@ public override void Run() catch (Exception e) when (e.IsThrowable()) { Console.WriteLine(Thread.CurrentThread.Name + ": exc"); - Console.WriteLine(e.StackTrace); + e.PrintStackTrace(Console.Out); failed = true; } } diff --git a/src/Lucene.Net.Tests/Index/TestBackwardsCompatibility.cs b/src/Lucene.Net.Tests/Index/TestBackwardsCompatibility.cs index 4989ce80ea..91bf151c48 100644 --- a/src/Lucene.Net.Tests/Index/TestBackwardsCompatibility.cs +++ b/src/Lucene.Net.Tests/Index/TestBackwardsCompatibility.cs @@ -300,7 +300,7 @@ public virtual void TestUnsupportedOldIndexes() if (Verbose) { Console.WriteLine("TEST: got expected exc:"); - Console.WriteLine(e.StackTrace); + e.PrintStackTrace(Console.Out); } // Make sure exc message includes a path= Assert.IsTrue(e.Message.IndexOf("path=\"", StringComparison.Ordinal) != -1, "got exc message: " + e.Message); diff --git a/src/Lucene.Net.Tests/Index/TestBackwardsCompatibility3x.cs b/src/Lucene.Net.Tests/Index/TestBackwardsCompatibility3x.cs index 336580ff9e..77239b5546 100644 --- a/src/Lucene.Net.Tests/Index/TestBackwardsCompatibility3x.cs +++ b/src/Lucene.Net.Tests/Index/TestBackwardsCompatibility3x.cs @@ -231,7 +231,7 @@ public virtual void TestUnsupportedOldIndexes() if (Verbose) { Console.WriteLine("TEST: got expected exc:"); - Console.WriteLine(e.StackTrace); + e.PrintStackTrace(Console.Out); } // Make sure exc message includes a path= Assert.IsTrue(e.Message.IndexOf("path=\"", StringComparison.Ordinal) != -1, "got exc message: " + e.Message); diff --git a/src/Lucene.Net.Tests/Index/TestConcurrentMergeScheduler.cs b/src/Lucene.Net.Tests/Index/TestConcurrentMergeScheduler.cs index 9d3ded4b86..b74750cc00 100644 --- a/src/Lucene.Net.Tests/Index/TestConcurrentMergeScheduler.cs +++ b/src/Lucene.Net.Tests/Index/TestConcurrentMergeScheduler.cs @@ -3,7 +3,6 @@ using Lucene.Net.Documents; using Lucene.Net.Index.Extensions; using Lucene.Net.Store; -using Lucene.Net.Support.Threading; using Lucene.Net.Util; using NUnit.Framework; using RandomizedTesting.Generators; @@ -129,7 +128,7 @@ public virtual void TestFlushExceptions() { if (Verbose) { - Console.WriteLine(ioe.StackTrace); + ioe.PrintStackTrace(Console.Out); } failure.ClearDoFail(); break; diff --git a/src/Lucene.Net.Tests/Index/TestCrashCausesCorruptIndex.cs b/src/Lucene.Net.Tests/Index/TestCrashCausesCorruptIndex.cs index dbd97f2a9d..15ad99a3f6 100644 --- a/src/Lucene.Net.Tests/Index/TestCrashCausesCorruptIndex.cs +++ b/src/Lucene.Net.Tests/Index/TestCrashCausesCorruptIndex.cs @@ -1,4 +1,5 @@ using Lucene.Net.Documents; +using Lucene.Net.Util; using NUnit.Framework; using System; using System.IO; @@ -190,7 +191,7 @@ public override IndexOutput CreateOutput(string name, IOContext cxt) if (Verbose) { Console.WriteLine("TEST: now crash"); - Console.WriteLine(new Exception().StackTrace); + StackTraceHelper.PrintCurrentStackTrace(Console.Out); } throw new CrashingException("crashAfterCreateOutput " + crashAfterCreateOutput); } diff --git a/src/Lucene.Net.Tests/Index/TestDirectoryReaderReopen.cs b/src/Lucene.Net.Tests/Index/TestDirectoryReaderReopen.cs index fbc97cfde9..daeb3926c0 100644 --- a/src/Lucene.Net.Tests/Index/TestDirectoryReaderReopen.cs +++ b/src/Lucene.Net.Tests/Index/TestDirectoryReaderReopen.cs @@ -506,7 +506,7 @@ public override void Run() } catch (Exception r) when (r.IsThrowable()) { - Console.WriteLine(r.StackTrace); + r.PrintStackTrace(Console.Out); this.error = r; } } diff --git a/src/Lucene.Net.Tests/Index/TestDocumentsWriterStallControl.cs b/src/Lucene.Net.Tests/Index/TestDocumentsWriterStallControl.cs index e59ac79119..f059dff520 100644 --- a/src/Lucene.Net.Tests/Index/TestDocumentsWriterStallControl.cs +++ b/src/Lucene.Net.Tests/Index/TestDocumentsWriterStallControl.cs @@ -1,6 +1,5 @@ using J2N.Threading; using J2N.Threading.Atomic; -using Lucene.Net.Support.Threading; using NUnit.Framework; using RandomizedTesting.Generators; using System; @@ -160,8 +159,7 @@ public virtual void TestAccquireReleaseRace() { foreach (Exception throwable in exceptions) { - Console.WriteLine(throwable.ToString()); - Console.Write(throwable.StackTrace); + throwable.PrintStackTrace(); } Assert.Fail("got exceptions in threads"); } @@ -283,8 +281,7 @@ public override void Run() } catch (Exception e) when (e.IsThrowable()) { - Console.WriteLine(e.ToString()); - Console.Write(e.StackTrace); + e.PrintStackTrace(); exceptions.Add(e); } } @@ -351,8 +348,7 @@ public override void Run() } catch (Exception e) when (e.IsThrowable()) { - Console.WriteLine(e.ToString()); - Console.Write(e.StackTrace); + e.PrintStackTrace(); exceptions.Add(e); } diff --git a/src/Lucene.Net.Tests/Index/TestFlushByRamOrCountsPolicy.cs b/src/Lucene.Net.Tests/Index/TestFlushByRamOrCountsPolicy.cs index ae61c4a7ec..731486f464 100644 --- a/src/Lucene.Net.Tests/Index/TestFlushByRamOrCountsPolicy.cs +++ b/src/Lucene.Net.Tests/Index/TestFlushByRamOrCountsPolicy.cs @@ -379,7 +379,7 @@ public override void Run() catch (Exception ex) when (ex.IsThrowable()) { Console.WriteLine("FAILED exc:"); - ex.printStackTrace(Console.Out); + ex.PrintStackTrace(Console.Out); throw RuntimeException.Create(ex); } } diff --git a/src/Lucene.Net.Tests/Index/TestIndexWriter.cs b/src/Lucene.Net.Tests/Index/TestIndexWriter.cs index bda15ce0fe..e48c12ae2e 100644 --- a/src/Lucene.Net.Tests/Index/TestIndexWriter.cs +++ b/src/Lucene.Net.Tests/Index/TestIndexWriter.cs @@ -1329,7 +1329,7 @@ public override void Run() // Jenkins hits a fail we need to study where the // interrupts struck! Console.WriteLine("TEST: got interrupt"); - Console.WriteLine(GetToStringFrom(re)); + Console.WriteLine(LockSafeGetToStringFrom(re)); Exception e = re.InnerException; Assert.IsTrue(e is System.Threading.ThreadInterruptedException); @@ -1356,7 +1356,7 @@ public override void Run() catch (Exception t) when (t.IsThrowable()) { Console.WriteLine("FAILED; unexpected exception"); - Console.WriteLine(GetToStringFrom(t)); + Console.WriteLine(LockSafeGetToStringFrom(t)); failed = true; break; } @@ -1406,7 +1406,7 @@ public override void Run() { failed = true; Console.WriteLine("CheckIndex FAILED: unexpected exception"); - Console.WriteLine(e.ToString()); + e.PrintStackTrace(Console.Out); } try { @@ -1417,7 +1417,7 @@ public override void Run() { failed = true; Console.WriteLine("DirectoryReader.open FAILED: unexpected exception"); - Console.WriteLine(e.ToString()); + e.PrintStackTrace(Console.Out); } } try @@ -1438,12 +1438,14 @@ public override void Run() } } - // LUCENENET specific - since the lock statement can potentially throw System.Threading.ThreadInterruptedException in .NET, - // we need to be vigilant about getting stack trace info from the errors during tests and retry if we get an interrupt exception. /// /// Safely gets the ToString() of an exception while ignoring any System.Threading.ThreadInterruptedException and retrying. /// - private static string GetToStringFrom(Exception exception) + /// + /// LUCENENET specific - since the lock statement can potentially throw System.Threading.ThreadInterruptedException in .NET, + /// we need to be vigilant about getting stack trace info from the errors during tests and retry if we get an interrupt exception. + /// + private static string LockSafeGetToStringFrom(Exception exception) { // Clear interrupt state: try @@ -1460,7 +1462,7 @@ private static string GetToStringFrom(Exception exception) } catch (Exception ie) when (ie.IsInterruptedException()) { - return GetToStringFrom(exception); + return LockSafeGetToStringFrom(exception); } } } diff --git a/src/Lucene.Net.Tests/Index/TestIndexWriterDelete.cs b/src/Lucene.Net.Tests/Index/TestIndexWriterDelete.cs index 525750e988..6ef9c61802 100644 --- a/src/Lucene.Net.Tests/Index/TestIndexWriterDelete.cs +++ b/src/Lucene.Net.Tests/Index/TestIndexWriterDelete.cs @@ -5,6 +5,7 @@ using Lucene.Net.Documents; using Lucene.Net.Index.Extensions; using Lucene.Net.Store; +using Lucene.Net.Support; using Lucene.Net.Support.IO; using Lucene.Net.Util; using NUnit.Framework; @@ -722,14 +723,13 @@ private void DoTestOperationsOnDiskFull(bool updates) { if (Verbose) { - Console.WriteLine(" hit IOException: " + e); - Console.WriteLine(e.StackTrace); + Console.WriteLine(" hit IOException: " + e.ToTypeMessageString()); // LUCENENET specific: ToTypeMessageString() mimics Java behavior + e.PrintStackTrace(Console.Out); } err = e; if (1 == x) { - Console.WriteLine(e.ToString()); - Console.Write(e.StackTrace); + e.PrintStackTrace(); Assert.Fail(testName + " hit IOException after disk space was freed up"); } } @@ -771,8 +771,7 @@ private void DoTestOperationsOnDiskFull(bool updates) } catch (Exception e) when (e.IsIOException()) { - Console.WriteLine(e.ToString()); - Console.Write(e.StackTrace); + e.PrintStackTrace(); Assert.Fail(testName + ":exception when creating IndexReader after disk full during close: " + e); } @@ -784,8 +783,7 @@ private void DoTestOperationsOnDiskFull(bool updates) } catch (Exception e) when (e.IsIOException()) { - Console.WriteLine(e.ToString()); - Console.Write(e.StackTrace); + e.PrintStackTrace(); Assert.Fail(testName + ": exception when searching: " + e); } int result2 = hits.Length; @@ -812,8 +810,7 @@ private void DoTestOperationsOnDiskFull(bool updates) // all docs: if (result2 != START_COUNT && result2 != END_COUNT) { - Console.WriteLine(err.ToString()); - Console.Write(err.StackTrace); + err.PrintStackTrace(); Assert.Fail(testName + ": method did throw exception but hits.Length for search on term 'aaa' is " + result2 + " instead of expected " + START_COUNT + " or " + END_COUNT); } } @@ -989,7 +986,7 @@ public override void Eval(MockDirectoryWrapper dir) if (Verbose) { Console.WriteLine("TEST: mock failure: now fail"); - Console.WriteLine(Environment.StackTrace); + StackTraceHelper.PrintCurrentStackTrace(Console.Out); } throw new IOException("fail after applyDeletes"); } @@ -1003,7 +1000,7 @@ public override void Eval(MockDirectoryWrapper dir) if (Verbose) { Console.WriteLine("TEST: mock failure: saw applyDeletes"); - Console.WriteLine(Environment.StackTrace); + StackTraceHelper.PrintCurrentStackTrace(Console.Out); } sawMaybe = true; } @@ -1048,7 +1045,7 @@ public virtual void TestErrorInDocsWriterAdd() if (Verbose) { Console.WriteLine("TEST: got expected exc:"); - Console.WriteLine(io.StackTrace); + io.PrintStackTrace(Console.Out); } break; } diff --git a/src/Lucene.Net.Tests/Index/TestIndexWriterExceptions.cs b/src/Lucene.Net.Tests/Index/TestIndexWriterExceptions.cs index 93d7da5d89..c62cee0e23 100644 --- a/src/Lucene.Net.Tests/Index/TestIndexWriterExceptions.cs +++ b/src/Lucene.Net.Tests/Index/TestIndexWriterExceptions.cs @@ -235,7 +235,7 @@ public override void Run() if (Verbose) { Console.WriteLine(Thread.CurrentThread.Name + ": EXC: "); - Console.WriteLine(re.StackTrace); + re.PrintStackTrace(Console.Out); } try { @@ -244,7 +244,7 @@ public override void Run() catch (Exception ioe) when (ioe.IsIOException()) { Console.WriteLine(Thread.CurrentThread.Name + ": unexpected exception1"); - Console.WriteLine(ioe.StackTrace); + ioe.PrintStackTrace(Console.Out); failure = ioe; break; } @@ -252,7 +252,7 @@ public override void Run() catch (Exception t) when (t.IsThrowable()) { Console.WriteLine(Thread.CurrentThread.Name + ": unexpected exception2"); - Console.WriteLine(t.StackTrace); + t.PrintStackTrace(Console.Out); failure = t; break; } @@ -269,7 +269,7 @@ public override void Run() catch (Exception t) when (t.IsThrowable()) { Console.WriteLine(Thread.CurrentThread.Name + ": unexpected exception3"); - Console.WriteLine(t.StackTrace); + t.PrintStackTrace(Console.Out); failure = t; break; } @@ -304,7 +304,7 @@ public void Apply(string name) if (Verbose) { Console.WriteLine(Thread.CurrentThread.Name + ": NOW FAIL: " + name); - Console.WriteLine(new Exception().StackTrace); + StackTraceHelper.PrintCurrentStackTrace(Console.Out); } throw new TestPoint1Exception(Thread.CurrentThread.Name + ": intentionally failing at " + name); // LUCENENET TODO: Need to change this to RuntimeException once we add a custom (or flagged) exception that is created by RuntimeException.Create } @@ -345,7 +345,7 @@ public virtual void TestRandomExceptions() thread.Run(); if (thread.failure != null) { - Console.WriteLine(thread.failure.StackTrace); + thread.failure.PrintStackTrace(Console.Out); Assert.Fail("thread " + thread.Name + ": hit unexpected failure"); } @@ -362,7 +362,7 @@ public virtual void TestRandomExceptions() catch (Exception t) when (t.IsThrowable()) { Console.WriteLine("exception during close:"); - Console.WriteLine(t.StackTrace); + t.PrintStackTrace(Console.Out); writer.Rollback(); } @@ -421,7 +421,7 @@ public virtual void TestRandomExceptionsThreads() catch (Exception t) when (t.IsThrowable()) { Console.WriteLine("exception during close:"); - Console.WriteLine(t.StackTrace); + t.PrintStackTrace(Console.Out); writer.Rollback(); } @@ -789,7 +789,7 @@ public virtual void TestDocumentsWriterExceptions() if (Verbose) { Console.WriteLine("TEST: hit expected exception"); - Console.WriteLine(ioe.StackTrace); + ioe.PrintStackTrace(Console.Out); } } @@ -998,7 +998,7 @@ public override void Run() try { Console.WriteLine(Thread.CurrentThread.Name + ": ERROR: hit unexpected exception"); - Console.WriteLine(t.StackTrace); + t.PrintStackTrace(Console.Out); } finally { @@ -1028,7 +1028,7 @@ public override void Eval(MockDirectoryWrapper dir) if (Verbose) { Console.WriteLine("TEST: now throw exc:"); - Console.WriteLine(Environment.StackTrace); + StackTraceHelper.PrintCurrentStackTrace(Console.Out); } throw new IOException("now failing on purpose during sync"); } @@ -1341,7 +1341,7 @@ public virtual void TestSegmentsChecksumError() } catch (Exception e) when (e.IsIOException()) { - Console.WriteLine(e.StackTrace); + e.PrintStackTrace(Console.Out); Assert.Fail("segmentInfos failed to retry fallback to correct segments_N file"); } reader!.Dispose(); // LUCENENET [!]: using null suppression to match Java behavior @@ -1525,7 +1525,7 @@ public virtual void TestSimulatedCrashedWriter() } catch (Exception e) when (e.IsException()) { - Console.WriteLine(e.StackTrace); + e.PrintStackTrace(Console.Out); Assert.Fail("writer failed to open on a crashed index"); } @@ -2364,7 +2364,7 @@ public override void Eval(MockDirectoryWrapper dir) if (Verbose) { Console.WriteLine("TEST: now fail; thread=" + Thread.CurrentThread.Name + " exc:"); - Console.WriteLine(new Exception().StackTrace); + StackTraceHelper.PrintCurrentStackTrace(Console.Out); } shouldFail.Value = false; throw new FakeIOException(); @@ -2535,7 +2535,7 @@ public override void Eval(MockDirectoryWrapper dir) if (Verbose) { Console.WriteLine("TEST: now fail; thread=" + Thread.CurrentThread.Name + " exc:"); - Console.WriteLine(new Exception().StackTrace); + StackTraceHelper.PrintCurrentStackTrace(Console.Out); } throw new FakeIOException(); } diff --git a/src/Lucene.Net.Tests/Index/TestIndexWriterMerging.cs b/src/Lucene.Net.Tests/Index/TestIndexWriterMerging.cs index bddcb786ea..5068f7c9fe 100644 --- a/src/Lucene.Net.Tests/Index/TestIndexWriterMerging.cs +++ b/src/Lucene.Net.Tests/Index/TestIndexWriterMerging.cs @@ -488,7 +488,7 @@ public override void Run() } catch (Exception e) when (e.IsThrowable()) { - Console.WriteLine(e.StackTrace); + e.PrintStackTrace(Console.Out); failure.Add(e); done = true; break; diff --git a/src/Lucene.Net.Tests/Index/TestIndexWriterNRTIsCurrent.cs b/src/Lucene.Net.Tests/Index/TestIndexWriterNRTIsCurrent.cs index cf3269d1a7..a59c724e19 100644 --- a/src/Lucene.Net.Tests/Index/TestIndexWriterNRTIsCurrent.cs +++ b/src/Lucene.Net.Tests/Index/TestIndexWriterNRTIsCurrent.cs @@ -66,16 +66,14 @@ public virtual void TestIsCurrentWithThreads() bool failed = writerThread.failed != null; if (failed) { - Console.WriteLine(writerThread.failed.ToString()); - Console.Write(writerThread.failed.StackTrace); + writerThread.failed.PrintStackTrace(); } for (int i = 0; i < threads.Length; i++) { threads[i].Join(); if (threads[i].failed != null) { - Console.WriteLine(threads[i].failed.ToString()); - Console.Write(threads[i].failed.StackTrace); + threads[i].failed.PrintStackTrace(); failed = true; } } @@ -253,4 +251,4 @@ public override void Run() } } } -} \ No newline at end of file +} diff --git a/src/Lucene.Net.Tests/Index/TestIndexWriterOnDiskFull.cs b/src/Lucene.Net.Tests/Index/TestIndexWriterOnDiskFull.cs index b96cb71ca3..72b48b2afa 100644 --- a/src/Lucene.Net.Tests/Index/TestIndexWriterOnDiskFull.cs +++ b/src/Lucene.Net.Tests/Index/TestIndexWriterOnDiskFull.cs @@ -103,7 +103,7 @@ public virtual void TestAddDocumentOnDiskFull() if (Verbose) { Console.WriteLine("TEST: exception on addDoc"); - Console.WriteLine(e.StackTrace); + e.PrintStackTrace(Console.Out); } hitError = true; } @@ -133,7 +133,7 @@ public virtual void TestAddDocumentOnDiskFull() if (Verbose) { Console.WriteLine("TEST: exception on close; retry w/ no disk space limit"); - Console.WriteLine(e.StackTrace); + e.PrintStackTrace(Console.Out); } dir.MaxSizeInBytes = 0; writer.Dispose(); @@ -427,12 +427,12 @@ public virtual void TestAddIndexOnDiskFull() if (Verbose) { Console.WriteLine(" hit IOException: " + e); - Console.WriteLine(e.StackTrace); + e.PrintStackTrace(Console.Out); } if (1 == x) { - Console.WriteLine(e.StackTrace); + e.PrintStackTrace(Console.Out); Assert.Fail(methodName + " hit IOException after disk space was freed up"); } } @@ -457,7 +457,7 @@ public virtual void TestAddIndexOnDiskFull() } catch (Exception e) when (e.IsIOException()) { - Console.WriteLine(e.StackTrace); + e.PrintStackTrace(Console.Out); Assert.Fail(testName + ": exception when creating IndexReader: " + e); } int result = reader.DocFreq(searchTerm); @@ -474,7 +474,7 @@ public virtual void TestAddIndexOnDiskFull() // all docs: if (result != START_COUNT && result != END_COUNT) { - Console.WriteLine(err.StackTrace); + err.PrintStackTrace(Console.Out); Assert.Fail(testName + ": method did throw exception but docFreq('aaa') is " + result + " instead of expected " + START_COUNT + " or " + END_COUNT); } } @@ -486,7 +486,7 @@ public virtual void TestAddIndexOnDiskFull() } catch (Exception e) when (e.IsIOException()) { - Console.WriteLine(e.StackTrace); + e.PrintStackTrace(Console.Out); Assert.Fail(testName + ": exception when searching: " + e); } int result2 = hits.Length; @@ -503,7 +503,7 @@ public virtual void TestAddIndexOnDiskFull() // all docs: if (result2 != result) { - Console.WriteLine(err.StackTrace); + err.PrintStackTrace(Console.Out); Assert.Fail(testName + ": method did throw exception but hits.Length for search on term 'aaa' is " + result2 + " instead of expected " + result); } } diff --git a/src/Lucene.Net.Tests/Index/TestIndexWriterOnJRECrash.cs b/src/Lucene.Net.Tests/Index/TestIndexWriterOnJRECrash.cs index b88f6e483e..3cdcd2493a 100644 --- a/src/Lucene.Net.Tests/Index/TestIndexWriterOnJRECrash.cs +++ b/src/Lucene.Net.Tests/Index/TestIndexWriterOnJRECrash.cs @@ -286,7 +286,7 @@ public override void Run() } catch (Exception e) when (e.IsIOException()) { - Console.Error.WriteLine("Couldn't pipe from the forked process: " + e.ToString()); + Console.Error.WriteLine("Couldn't pipe from the forked process: " + e.ToTypeMessageString()); // LUCENENET specific - use ToTypeMessageString to mimic Java behavior } } } diff --git a/src/Lucene.Net.Tests/Index/TestIndexWriterOutOfFileDescriptors.cs b/src/Lucene.Net.Tests/Index/TestIndexWriterOutOfFileDescriptors.cs index 784d5435a3..b586a801fb 100644 --- a/src/Lucene.Net.Tests/Index/TestIndexWriterOutOfFileDescriptors.cs +++ b/src/Lucene.Net.Tests/Index/TestIndexWriterOutOfFileDescriptors.cs @@ -146,8 +146,7 @@ public virtual void Test() if (Verbose) { Console.WriteLine("TEST: iter=" + iter + ": exception"); - Console.WriteLine(ioe.ToString()); - Console.Write(ioe.StackTrace); + ioe.PrintStackTrace(); } if (w != null) { diff --git a/src/Lucene.Net.Tests/Index/TestIndexWriterReader.cs b/src/Lucene.Net.Tests/Index/TestIndexWriterReader.cs index ab7d4d11e0..7c3949dcd0 100644 --- a/src/Lucene.Net.Tests/Index/TestIndexWriterReader.cs +++ b/src/Lucene.Net.Tests/Index/TestIndexWriterReader.cs @@ -1,5 +1,6 @@ using Lucene.Net.Attributes; using Lucene.Net.Search; +using Lucene.Net.Support; using Lucene.Net.Util; #if FEATURE_INDEXWRITER_TESTS using J2N.Threading; @@ -529,7 +530,7 @@ internal virtual void CloseDir() internal virtual void Handle(Exception t) { - Console.WriteLine(t.StackTrace); + t.PrintStackTrace(Console.Out); UninterruptableMonitor.Enter(failures); try { @@ -1384,7 +1385,7 @@ public override void Eval(MockDirectoryWrapper dir) if (Verbose) { Console.WriteLine("TEST: now fail; exc:"); - Console.WriteLine(new Exception().StackTrace); + StackTraceHelper.PrintCurrentStackTrace(Console.Out); } shouldFail.Value = false; throw new FakeIOException(); diff --git a/src/Lucene.Net.Tests/Index/TestIndexWriterWithThreads.cs b/src/Lucene.Net.Tests/Index/TestIndexWriterWithThreads.cs index 3d3b9ef4fa..9f5f49ed83 100644 --- a/src/Lucene.Net.Tests/Index/TestIndexWriterWithThreads.cs +++ b/src/Lucene.Net.Tests/Index/TestIndexWriterWithThreads.cs @@ -102,10 +102,10 @@ public override void Run() if (Verbose) { Console.WriteLine("TEST: expected exc:"); - Console.WriteLine(ioe.StackTrace); + ioe.PrintStackTrace(Console.Out); } - //System.out.println(Thread.currentThread().getName() + ": hit exc"); - //ioConsole.WriteLine(e.StackTrace); + //Console.WriteLine(Thread.CurrentThread.Name + ": hit exc"); + //ioe.PrintStackTrace(Console.Out); if (ioe.Message.StartsWith("fake disk full at", StringComparison.Ordinal) || ioe.Message.Equals("now failing on purpose", StringComparison.Ordinal)) { diskFull = true; @@ -129,7 +129,7 @@ public override void Run() if (noErrors) { Console.WriteLine(Thread.CurrentThread.Name + ": ERROR: unexpected IOException:"); - Console.WriteLine(ioe.StackTrace); + ioe.PrintStackTrace(Console.Out); error = ioe; } break; @@ -137,11 +137,11 @@ public override void Run() } catch (Exception t) when (t.IsThrowable()) { - //Console.WriteLine(t.StackTrace); + //t.PrintStackTrace(Console.Out); if (noErrors) { Console.WriteLine(Thread.CurrentThread.Name + ": ERROR: unexpected Throwable:"); - Console.WriteLine(t.StackTrace); + t.PrintStackTrace(Console.Out); error = t; } break; @@ -626,7 +626,7 @@ public override void Run() { failed = true; failure = e; - Console.WriteLine(e.ToString()); + failure.PrintStackTrace(Console.Out); // return; // LUCENENET: redundant return } } diff --git a/src/Lucene.Net.Tests/Index/TestNRTReaderWithThreads.cs b/src/Lucene.Net.Tests/Index/TestNRTReaderWithThreads.cs index c0d93b747a..baad17d267 100644 --- a/src/Lucene.Net.Tests/Index/TestNRTReaderWithThreads.cs +++ b/src/Lucene.Net.Tests/Index/TestNRTReaderWithThreads.cs @@ -140,7 +140,7 @@ public override void Run() } catch (Exception ex) when (ex.IsThrowable()) { - Console.WriteLine(ex.StackTrace); + ex.PrintStackTrace(Console.Out); this.ex = ex; run = false; } diff --git a/src/Lucene.Net.Tests/Index/TestPayloads.cs b/src/Lucene.Net.Tests/Index/TestPayloads.cs index 1affe6ba57..4733a94bf1 100644 --- a/src/Lucene.Net.Tests/Index/TestPayloads.cs +++ b/src/Lucene.Net.Tests/Index/TestPayloads.cs @@ -557,7 +557,7 @@ public override void Run() } catch (Exception e) when (e.IsException()) { - e.printStackTrace(); + e.PrintStackTrace(); Assert.Fail(e.ToString()); } } diff --git a/src/Lucene.Net.Tests/Index/TestSnapshotDeletionPolicy.cs b/src/Lucene.Net.Tests/Index/TestSnapshotDeletionPolicy.cs index 2f94be2a55..8324102931 100644 --- a/src/Lucene.Net.Tests/Index/TestSnapshotDeletionPolicy.cs +++ b/src/Lucene.Net.Tests/Index/TestSnapshotDeletionPolicy.cs @@ -206,7 +206,7 @@ public override void Run() } catch (Exception t) when (t.IsThrowable()) { - Console.WriteLine(t.StackTrace); + t.PrintStackTrace(Console.Out); Assert.Fail("addDocument failed"); } if (i % 2 == 0) diff --git a/src/Lucene.Net.Tests/Index/TestStressIndexing.cs b/src/Lucene.Net.Tests/Index/TestStressIndexing.cs index 253060403a..dfd8c28c49 100644 --- a/src/Lucene.Net.Tests/Index/TestStressIndexing.cs +++ b/src/Lucene.Net.Tests/Index/TestStressIndexing.cs @@ -69,7 +69,7 @@ public override void Run() catch (Exception e) when (e.IsThrowable()) { Console.WriteLine(Thread.CurrentThread + ": exc"); - Console.WriteLine(e.StackTrace); + e.PrintStackTrace(Console.Out); failed = true; } } diff --git a/src/Lucene.Net.Tests/Index/TestStressIndexing2.cs b/src/Lucene.Net.Tests/Index/TestStressIndexing2.cs index 41e9818ff5..5da67a1de9 100644 --- a/src/Lucene.Net.Tests/Index/TestStressIndexing2.cs +++ b/src/Lucene.Net.Tests/Index/TestStressIndexing2.cs @@ -1042,8 +1042,7 @@ public override void Run() } catch (Exception e) when (e.IsThrowable()) { - Console.WriteLine(e.ToString()); - Console.Write(e.StackTrace); + e.PrintStackTrace(); Assert.Fail(e.ToString()); } diff --git a/src/Lucene.Net.Tests/Index/TestStressNRT.cs b/src/Lucene.Net.Tests/Index/TestStressNRT.cs index 5b46b6fd8f..4780a0d860 100644 --- a/src/Lucene.Net.Tests/Index/TestStressNRT.cs +++ b/src/Lucene.Net.Tests/Index/TestStressNRT.cs @@ -419,7 +419,7 @@ public override void Run() catch (Exception e) when (e.IsThrowable()) { Console.WriteLine(Thread.CurrentThread.Name + ": FAILED: unexpected exception"); - Console.WriteLine(e.StackTrace); + e.PrintStackTrace(Console.Out); throw RuntimeException.Create(e); } } @@ -546,7 +546,7 @@ public override void Run() { operations.Value = (int)-1L; Console.WriteLine(Thread.CurrentThread.Name + ": FAILED: unexpected exception"); - Console.WriteLine(e.StackTrace); + e.PrintStackTrace(Console.Out); throw RuntimeException.Create(e); } } diff --git a/src/Lucene.Net.Tests/Index/TestThreadedForceMerge.cs b/src/Lucene.Net.Tests/Index/TestThreadedForceMerge.cs index 56d4bdd323..0158961553 100644 --- a/src/Lucene.Net.Tests/Index/TestThreadedForceMerge.cs +++ b/src/Lucene.Net.Tests/Index/TestThreadedForceMerge.cs @@ -169,7 +169,7 @@ public override void Run() { outerInstance.SetFailed(); Console.WriteLine(Thread.CurrentThread.Name + ": hit exception"); - Console.WriteLine(t.StackTrace); + t.PrintStackTrace(Console.Out); } } } diff --git a/src/Lucene.Net.Tests/Index/TestTransactions.cs b/src/Lucene.Net.Tests/Index/TestTransactions.cs index 4ff4e42731..0604ecedf9 100644 --- a/src/Lucene.Net.Tests/Index/TestTransactions.cs +++ b/src/Lucene.Net.Tests/Index/TestTransactions.cs @@ -87,7 +87,7 @@ public override void Run() catch (Exception e) when (e.IsThrowable()) { Console.WriteLine(Thread.CurrentThread + ": exc"); - Console.Error.WriteLine(e.StackTrace); + e.PrintStackTrace(Console.Out); failed = true; } } diff --git a/src/Lucene.Net.Tests/Search/TestControlledRealTimeReopenThread.cs b/src/Lucene.Net.Tests/Search/TestControlledRealTimeReopenThread.cs index e94b0da9f2..19d119ba35 100644 --- a/src/Lucene.Net.Tests/Search/TestControlledRealTimeReopenThread.cs +++ b/src/Lucene.Net.Tests/Search/TestControlledRealTimeReopenThread.cs @@ -475,7 +475,7 @@ public override void Run() } catch (Exception e) when (e.IsException()) { - e.printStackTrace(); + e.PrintStackTrace(); } finally { diff --git a/src/Lucene.Net.Tests/Search/TestMultiThreadTermVectors.cs b/src/Lucene.Net.Tests/Search/TestMultiThreadTermVectors.cs index 0d06ec9d6a..75ae3621ca 100644 --- a/src/Lucene.Net.Tests/Search/TestMultiThreadTermVectors.cs +++ b/src/Lucene.Net.Tests/Search/TestMultiThreadTermVectors.cs @@ -101,8 +101,7 @@ public virtual void Test() } catch (Exception ioe) when (ioe.IsIOException()) { - Console.WriteLine(ioe.ToString()); - Console.Write(ioe.StackTrace); + ioe.PrintStackTrace(); } } } @@ -187,7 +186,7 @@ public void Run() } catch (Exception e) when (e.IsException()) { - e.printStackTrace(); + e.PrintStackTrace(); } return; } diff --git a/src/Lucene.Net.Tests/Search/TestSearcherManager.cs b/src/Lucene.Net.Tests/Search/TestSearcherManager.cs index 5e2fe78eb3..932a4e196a 100644 --- a/src/Lucene.Net.Tests/Search/TestSearcherManager.cs +++ b/src/Lucene.Net.Tests/Search/TestSearcherManager.cs @@ -173,9 +173,10 @@ public override void Run() if (Verbose) { Console.WriteLine("TEST: reopen thread hit exc"); - Console.Out.Write(t.StackTrace); + t.PrintStackTrace(Console.Out); } - outerInstance.m_failed.Value = (true); + + outerInstance.m_failed.Value = true; throw RuntimeException.Create(t); } } @@ -400,7 +401,7 @@ public void Run() if (Verbose) { Console.WriteLine("FAIL: unexpected exc"); - Console.Out.Write(e.StackTrace); + e.PrintStackTrace(Console.Out); } exc[0] = e; // use success as the barrier here to make sure we see the write diff --git a/src/Lucene.Net.Tests/Search/TestShardSearching.cs b/src/Lucene.Net.Tests/Search/TestShardSearching.cs index 219aba5efd..da0aa18017 100644 --- a/src/Lucene.Net.Tests/Search/TestShardSearching.cs +++ b/src/Lucene.Net.Tests/Search/TestShardSearching.cs @@ -294,7 +294,7 @@ public virtual void TestSimple() if (Verbose) { Console.WriteLine(" searcher expired during search: " + see); - Console.Out.Write(see.StackTrace); + see.PrintStackTrace(Console.Out); } // We can't do this in general: on a very slow // computer it's possible the local searcher diff --git a/src/Lucene.Net.Tests/Search/TestTimeLimitingCollector.cs b/src/Lucene.Net.Tests/Search/TestTimeLimitingCollector.cs index 20fa9066ac..88fb8dbf52 100644 --- a/src/Lucene.Net.Tests/Search/TestTimeLimitingCollector.cs +++ b/src/Lucene.Net.Tests/Search/TestTimeLimitingCollector.cs @@ -158,7 +158,7 @@ private void DoTestSearch() } catch (Exception e) when (e.IsException()) { - e.printStackTrace(); + e.PrintStackTrace(); assertTrue("Unexpected exception: " + e, false); //==fail } assertEquals("Wrong number of results!", totalResults, totalTLCResults); diff --git a/src/Lucene.Net.Tests/Store/TestLockFactory.cs b/src/Lucene.Net.Tests/Store/TestLockFactory.cs index 70d8c1d554..4a7301220b 100644 --- a/src/Lucene.Net.Tests/Store/TestLockFactory.cs +++ b/src/Lucene.Net.Tests/Store/TestLockFactory.cs @@ -100,7 +100,7 @@ public virtual void TestRAMDirectoryNoLocking() } catch (Exception e) when (e.IsException()) { - e.printStackTrace(); + e.PrintStackTrace(Console.Out); Assert.Fail("Should not have hit an IOException with no locking"); } @@ -316,8 +316,8 @@ public override void Run() if (e.ToString().IndexOf(" timed out:", StringComparison.Ordinal) == -1) { HitException = true; - Console.WriteLine("Stress Test Index Writer: creation hit unexpected IOException: " + e.ToString()); - Console.Out.Write(e.StackTrace); + Console.WriteLine("Stress Test Index Writer: creation hit unexpected IOException: " + e.ToTypeMessageString()); // LUCENENET specific: use ToTypeMessageString to mimic Java behavior + e.PrintStackTrace(Console.Out); } else { @@ -332,8 +332,8 @@ public override void Run() catch (Exception e) when (e.IsException()) { HitException = true; - Console.WriteLine("Stress Test Index Writer: creation hit unexpected exception: " + e.ToString()); - e.printStackTrace(Console.Out); + Console.WriteLine("Stress Test Index Writer: creation hit unexpected exception: " + e.ToTypeMessageString()); // LUCENENET specific: use ToTypeMessageString to mimic Java behavior + e.PrintStackTrace(Console.Out); break; } if (writer != null) @@ -345,8 +345,8 @@ public override void Run() catch (Exception e) when (e.IsIOException()) { HitException = true; - Console.WriteLine("Stress Test Index Writer: addDoc hit unexpected exception: " + e.ToString()); - Console.Out.Write(e.StackTrace); + Console.WriteLine("Stress Test Index Writer: addDoc hit unexpected exception: " + e.ToTypeMessageString()); // LUCENENET specific: use ToTypeMessageString to mimic Java behavior + e.PrintStackTrace(Console.Out); break; } try @@ -356,8 +356,8 @@ public override void Run() catch (Exception e) when (e.IsIOException()) { HitException = true; - Console.WriteLine("Stress Test Index Writer: close hit unexpected exception: " + e.ToString()); - Console.Out.Write(e.StackTrace); + Console.WriteLine("Stress Test Index Writer: close hit unexpected exception: " + e.ToTypeMessageString()); // LUCENENET specific: use ToTypeMessageString to mimic Java behavior + e.PrintStackTrace(Console.Out); break; } writer = null; @@ -393,8 +393,8 @@ public override void Run() catch (Exception e) when (e.IsException()) { HitException = true; - Console.WriteLine("Stress Test Index Searcher: create hit unexpected exception: " + e.ToString()); - e.printStackTrace(Console.Out); + Console.WriteLine("Stress Test Index Searcher: create hit unexpected exception: " + e.ToTypeMessageString()); // LUCENENET specific: use ToTypeMessageString to mimic Java behavior + e.PrintStackTrace(Console.Out); break; } try @@ -404,8 +404,8 @@ public override void Run() catch (Exception e) when (e.IsIOException()) { HitException = true; - Console.WriteLine("Stress Test Index Searcher: search hit unexpected exception: " + e.ToString()); - Console.Out.Write(e.StackTrace); + Console.WriteLine("Stress Test Index Searcher: search hit unexpected exception: " + e.ToTypeMessageString()); // LUCENENET specific: use ToTypeMessageString to mimic Java behavior + e.PrintStackTrace(Console.Out); break; } // System.out.println(hits.Length() + " total results"); @@ -416,8 +416,8 @@ public override void Run() catch (Exception e) when (e.IsIOException()) { HitException = true; - Console.WriteLine("Stress Test Index Searcher: close hit unexpected exception: " + e.ToString()); - Console.Out.Write(e.StackTrace); + Console.WriteLine("Stress Test Index Searcher: close hit unexpected exception: " + e.ToTypeMessageString()); // LUCENENET specific: use ToTypeMessageString to mimic Java behavior + e.PrintStackTrace(Console.Out); break; } } diff --git a/src/Lucene.Net.Tests/Support/Threading/JSR166TestCase.cs b/src/Lucene.Net.Tests/Support/Threading/JSR166TestCase.cs index bdd1362944..990b2cd357 100644 --- a/src/Lucene.Net.Tests/Support/Threading/JSR166TestCase.cs +++ b/src/Lucene.Net.Tests/Support/Threading/JSR166TestCase.cs @@ -322,7 +322,7 @@ public void threadUnexpectedException() public void threadUnexpectedException(Exception ex) { threadFailed = true; - ex.printStackTrace(); + ex.PrintStackTrace(); fail("Unexpected exception: " + ex); } diff --git a/src/Lucene.Net.Tests/Util/Packed/TestPackedInts.cs b/src/Lucene.Net.Tests/Util/Packed/TestPackedInts.cs index 3b2e89ec11..ef01e20214 100644 --- a/src/Lucene.Net.Tests/Util/Packed/TestPackedInts.cs +++ b/src/Lucene.Net.Tests/Util/Packed/TestPackedInts.cs @@ -382,7 +382,7 @@ private static void AssertRandomEquality(int valueCount, int bitsPerValue, long } catch (Exception e) when (e.IsException()) { - e.printStackTrace(Console.Error); + e.PrintStackTrace(Console.Error); Assert.Fail(string.Format(CultureInfo.InvariantCulture, "Exception while filling {0}: valueCount={1}, bitsPerValue={2}", packedInt.GetType().Name, valueCount, bitsPerValue)); } } diff --git a/src/Lucene.Net.Tests/Util/TestArrayUtil.cs b/src/Lucene.Net.Tests/Util/TestArrayUtil.cs index 12945998b8..68dcc7ccd5 100644 --- a/src/Lucene.Net.Tests/Util/TestArrayUtil.cs +++ b/src/Lucene.Net.Tests/Util/TestArrayUtil.cs @@ -130,8 +130,7 @@ public virtual void TestParseInt() } catch (Exception e) when (e.IsNumberFormatException()) { - Console.WriteLine(e.ToString()); - Console.Write(e.StackTrace); + e.PrintStackTrace(); Assert.IsTrue(false); } } diff --git a/src/Lucene.Net/Index/CheckIndex.cs b/src/Lucene.Net/Index/CheckIndex.cs index 6eb9d94c89..f06bd1fe18 100644 --- a/src/Lucene.Net/Index/CheckIndex.cs +++ b/src/Lucene.Net/Index/CheckIndex.cs @@ -520,11 +520,10 @@ public virtual Status DoCheckIndex(IList onlySegments) Msg(infoStream, "ERROR: could not read any segments file in directory"); result.MissingSegments = true; - // LUCENENET NOTE: Some tests rely on the error type being in - // the message. We can't get the error type with StackTrace, we - // need ToString() for that. - infoStream?.WriteLine(t.ToString()); - //infoStream.WriteLine(t.StackTrace); + if (infoStream != null) + { + t.PrintStackTrace(infoStream); + } return result; } @@ -568,11 +567,10 @@ public virtual Status DoCheckIndex(IList onlySegments) { Msg(infoStream, "ERROR: could not open segments file in directory"); - // LUCENENET NOTE: Some tests rely on the error type being in - // the message. We can't get the error type with StackTrace, we - // need ToString() for that. - infoStream?.WriteLine(t.ToString()); - //infoStream.WriteLine(t.StackTrace); + if (infoStream != null) + { + t.PrintStackTrace(infoStream); + } result.CantOpenSegments = true; return result; @@ -586,11 +584,10 @@ public virtual Status DoCheckIndex(IList onlySegments) { Msg(infoStream, "ERROR: could not read segment file version in directory"); - // LUCENENET NOTE: Some tests rely on the error type being in - // the message. We can't get the error type with StackTrace, we - // need ToString() for that. - infoStream?.WriteLine(t.ToString()); - //infoStream.WriteLine(t.StackTrace); + if (infoStream != null) + { + t.PrintStackTrace(infoStream); + } result.MissingSegmentVersion = true; return result; @@ -874,10 +871,10 @@ public virtual Status DoCheckIndex(IList onlySegments) comment = "fixIndex() would remove reference to this segment"; Msg(infoStream, " WARNING: " + comment + "; full exception:"); - // LUCENENET NOTE: Some tests rely on the error type being in - // the message. We can't get the error type with StackTrace, we - // need ToString() for that. - infoStream?.WriteLine(t.ToString()); + if (infoStream != null) + { + t.PrintStackTrace(infoStream); + } Msg(infoStream, ""); result.TotLoseDocCount += toLoseDocCount; @@ -960,11 +957,10 @@ public static Status.FieldNormStatus TestFieldNorms(AtomicReader reader, TextWri Msg(infoStream, "ERROR [" + e.Message + "]"); status.Error = e; - // LUCENENET NOTE: Some tests rely on the error type being in - // the message. We can't get the error type with StackTrace, we - // need ToString() for that. - infoStream?.WriteLine(e.ToString()); - //infoStream.WriteLine(e.StackTrace); + if (infoStream != null) + { + e.PrintStackTrace(infoStream); + } } return status; @@ -1666,11 +1662,10 @@ public static Status.TermIndexStatus TestPostings(AtomicReader reader, TextWrite status = new Status.TermIndexStatus(); status.Error = e; - // LUCENENET NOTE: Some tests rely on the error type being in - // the message. We can't get the error type with StackTrace, we - // need ToString() for that. - infoStream?.WriteLine(e.ToString()); - //infoStream.WriteLine(e.StackTrace); + if (infoStream != null) + { + e.PrintStackTrace(infoStream); + } } return status; @@ -1716,11 +1711,10 @@ public static Status.StoredFieldStatus TestStoredFields(AtomicReader reader, Tex Msg(infoStream, "ERROR [" + e.Message + "]"); status.Error = e; - // LUCENENET NOTE: Some tests rely on the error type being in - // the message. We can't get the error type with StackTrace, we - // need ToString() for that. - infoStream?.WriteLine(e.ToString()); - //infoStream.WriteLine(e.StackTrace); + if (infoStream != null) + { + e.PrintStackTrace(infoStream); + } } return status; @@ -1761,11 +1755,10 @@ public static Status.DocValuesStatus TestDocValues(AtomicReader reader, TextWrit Msg(infoStream, "ERROR [" + e.Message + "]"); status.Error = e; - // LUCENENET NOTE: Some tests rely on the error type being in - // the message. We can't get the error type with StackTrace, we - // need ToString() for that. - infoStream?.WriteLine(e.ToString()); - //infoStream.WriteLine(e.StackTrace); + if (infoStream != null) + { + e.PrintStackTrace(infoStream); + } } return status; } @@ -2284,11 +2277,10 @@ public static Status.TermVectorStatus TestTermVectors(AtomicReader reader, TextW Msg(infoStream, "ERROR [" + e.Message + "]"); status.Error = e; - // LUCENENET NOTE: Some tests rely on the error type being in - // the message. We can't get the error type with StackTrace, we - // need ToString() for that. - infoStream?.WriteLine(e.ToString()); - //infoStream.WriteLine(e.StackTrace); + if (infoStream != null) + { + e.PrintStackTrace(infoStream); + } } return status; diff --git a/src/Lucene.Net/Index/IndexFileDeleter.cs b/src/Lucene.Net/Index/IndexFileDeleter.cs index 85b7a8eeea..4ad0b7c235 100644 --- a/src/Lucene.Net/Index/IndexFileDeleter.cs +++ b/src/Lucene.Net/Index/IndexFileDeleter.cs @@ -249,7 +249,7 @@ public IndexFileDeleter(Directory directory, IndexDeletionPolicy policy, Segment } catch (Exception e) when (e.IsIOException()) { - throw new CorruptIndexException("failed to locate current segments_N file \"" + currentSegmentsFile + "\"" + e.ToString(), e); + throw new CorruptIndexException("failed to locate current segments_N file \"" + currentSegmentsFile + "\"" + e, e); // LUCENENET specific: add exception logging and inner exception } if (infoStream.IsEnabled("IFD")) { @@ -694,7 +694,7 @@ internal void DeleteFile(string fileName) if (infoStream.IsEnabled("IFD")) { infoStream.Message("IFD", - "unable to remove file \"" + fileName + "\": " + e.ToString() + "; Will re-try later."); + "unable to remove file \"" + fileName + "\": " + e.ToTypeMessageString() + "; Will re-try later."); // LUCENENET specific: use ToTypeMessageString to mimic Java behavior } if (deletable is null) { diff --git a/src/Lucene.Net/Search/FieldCacheImpl.cs b/src/Lucene.Net/Search/FieldCacheImpl.cs index 08464b59e5..ef25545cae 100644 --- a/src/Lucene.Net/Search/FieldCacheImpl.cs +++ b/src/Lucene.Net/Search/FieldCacheImpl.cs @@ -427,7 +427,7 @@ private void PrintNewInsanity(TextWriter infoStream, TValue value) // OK this insanity involves our entry infoStream.WriteLine("WARNING: new FieldCache insanity created\nDetails: " + insanity.ToString()); infoStream.WriteLine("\nStack:\n"); - infoStream.WriteLine(new Exception().StackTrace); + StackTraceHelper.PrintCurrentStackTrace(infoStream); break; } } @@ -486,7 +486,7 @@ public override int GetHashCode() // LUCENENET specific - Added generic parameter to eliminate casting/boxing internal class CacheKey : CacheKey { - internal readonly TCustom custom; // which custom comparer or parser + internal readonly TCustom custom; // which custom comparer or parser /// /// Creates one of these objects for a custom comparer/parser. @@ -775,7 +775,7 @@ protected override TermsEnum GetTermsEnum(Terms terms) /// Checks the internal cache for an appropriate entry, and if none is /// found, reads the terms in as s and returns an array /// of size reader.MaxDoc of the value each document - /// has in the given field. + /// has in the given field. /// /// NOTE: this was getShorts() in Lucene /// @@ -795,7 +795,7 @@ public virtual FieldCache.Int16s GetInt16s(AtomicReader reader, string field, bo /// Checks the internal cache for an appropriate entry, and if none is found, /// reads the terms in as shorts and returns an array of /// size reader.MaxDoc of the value each document has in the - /// given field. + /// given field. /// /// NOTE: this was getShorts() in Lucene /// diff --git a/src/Lucene.Net/Support/ExceptionHandling/ExceptionExtensions.cs b/src/Lucene.Net/Support/ExceptionHandling/ExceptionExtensions.cs index 09ba5bdf78..d422c7d646 100644 --- a/src/Lucene.Net/Support/ExceptionHandling/ExceptionExtensions.cs +++ b/src/Lucene.Net/Support/ExceptionHandling/ExceptionExtensions.cs @@ -8,6 +8,7 @@ using System.Security; using System.Text; using System.Threading; +using PublicExceptionExtensions = Lucene.Net.Util.ExceptionExtensions; namespace Lucene { @@ -698,5 +699,68 @@ public static bool IsServiceConfigurationError(this Exception e) // it is not sensible to make a public exception that will be factored out along with it. return e is ServiceConfigurationError; } + + /// + /// Prints the stack trace of the exception to the console's standard error output stream. + /// + /// This method mimics Java's behavior of printing the exception type and message first before the stack trace. + /// In .NET, this is done by calling . + /// Additionally, it will print any suppressed exceptions stored in + /// via . + /// + /// The exception to print. + public static void PrintStackTrace(this Exception e) + { + Console.Error.WriteLine(FormatStackTrace(e)); + } + + /// + /// Prints the stack trace of the exception to the specified . + /// + /// This method mimics Java's behavior of printing the exception type and message first before the stack trace. + /// In .NET, this is done by calling . + /// Additionally, it will print any suppressed exceptions stored in + /// via . + /// + /// The exception to print. + /// The destination to write the stack trace to. + public static void PrintStackTrace(this Exception e, TextWriter destination) + { + destination.WriteLine(FormatStackTrace(e)); + } + + private static string FormatStackTrace(this Exception e) + { + var suppressed = PublicExceptionExtensions.GetSuppressedAsListOrDefault(e); + + if (suppressed == null) + { + return e.ToString(); + } + + StringBuilder sb = new(); + sb.AppendLine(e.ToString()); + + foreach (var suppressedException in suppressed) + { + sb.Append("Suppressed: ").AppendLine(suppressedException.ToString()); + } + + return sb.ToString(); + } + + /// + /// Gets a string representation of the exception, including the exception type and message. + /// + /// In Java, calling toString() on an exception returns the exception type and message, + /// without the stack trace. This method mimics that behavior. + /// + /// The exception to get the string representation of. + /// A string representation of the exception, including the exception type and message. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string ToTypeMessageString(this Exception e) + { + return $"{e.GetType().FullName}: {e.Message}"; + } } } diff --git a/src/Lucene.Net/Support/ExceptionHandling/StackTraceHelper.cs b/src/Lucene.Net/Support/ExceptionHandling/StackTraceHelper.cs new file mode 100644 index 0000000000..63101b6be6 --- /dev/null +++ b/src/Lucene.Net/Support/ExceptionHandling/StackTraceHelper.cs @@ -0,0 +1,111 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.CompilerServices; +#nullable enable + +namespace Lucene.Net.Util +{ + /* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + /// + /// LUCENENET specific class to provide some additional functionality around stack traces. + /// + internal static class StackTraceHelper + { + /// + /// Matches the StackTrace for a method name. + /// + /// IMPORTANT: To make the tests pass in release mode, the method(s) named here + /// must be decorated with [MethodImpl(MethodImplOptions.NoInlining)]. + /// + public static bool DoesStackTraceContainMethod(string methodName) + { + if (methodName == null) + { + throw new ArgumentNullException(nameof(methodName)); + } + + StackTrace trace = new StackTrace(); + // ReSharper disable once NullCoalescingConditionIsAlwaysNotNullAccordingToAPIContract + StackFrame[] frames = trace.GetFrames() ?? Array.Empty(); // NOTE: .NET Framework can return null here + + foreach (var frame in frames) + { + if (frame.GetMethod()?.Name.Equals(methodName, StringComparison.Ordinal) == true) + { + return true; + } + } + + return false; + } + + /// + /// Matches the StackTrace for a particular class (not fully-qualified) and method name. + /// + /// IMPORTANT: To make the tests pass in release mode, the method(s) named here + /// must be decorated with [MethodImpl(MethodImplOptions.NoInlining)]. + /// + public static bool DoesStackTraceContainMethod(string className, string methodName) + { + if (className == null) + { + throw new ArgumentNullException(nameof(className)); + } + if (methodName == null) + { + throw new ArgumentNullException(nameof(methodName)); + } + + StackTrace trace = new StackTrace(); + // ReSharper disable once NullCoalescingConditionIsAlwaysNotNullAccordingToAPIContract + StackFrame[] frames = trace.GetFrames() ?? Array.Empty(); // NOTE: .NET Framework can return null here + + foreach (var frame in frames) + { + var method = frame.GetMethod(); + if (method?.DeclaringType?.Name.Equals(className, StringComparison.Ordinal) == true + && method.Name.Equals(methodName, StringComparison.Ordinal)) + { + return true; + } + } + + return false; + } + + /// + /// Prints the current stack trace to the specified . + /// + /// This is equivalent to Java's new Throwable().printStackTrace(destination) + /// or new Exception().printStackTrace(destination). + /// + /// The destination to write the stack trace to. + [MethodImpl(MethodImplOptions.NoInlining)] // Top frame is skipped, so we don't want to inline + public static void PrintCurrentStackTrace(TextWriter destination) + { + if (destination == null) + { + throw new ArgumentNullException(nameof(destination)); + } + + destination.WriteLine(new StackTrace(skipFrames: 1).ToString()); + } + } +} diff --git a/src/Lucene.Net/Support/Util/ExceptionExtensions.cs b/src/Lucene.Net/Support/Util/ExceptionExtensions.cs index 8528498cad..d62ccedd7a 100644 --- a/src/Lucene.Net/Support/Util/ExceptionExtensions.cs +++ b/src/Lucene.Net/Support/Util/ExceptionExtensions.cs @@ -1,8 +1,8 @@ using J2N.Collections.Generic.Extensions; using System; using System.Collections.Generic; -using System.Linq; using JCG = J2N.Collections.Generic; +#nullable enable namespace Lucene.Net.Util { @@ -46,12 +46,20 @@ public static IList GetSuppressedAsList(this Exception e) } else { - suppressed = e.Data[SUPPRESSED_EXCEPTIONS_KEY] as IList; + suppressed = e.Data[SUPPRESSED_EXCEPTIONS_KEY] as IList + ?? throw new InvalidOperationException($"Unexpected type for suppressed exceptions list: {e.Data[SUPPRESSED_EXCEPTIONS_KEY]?.GetType()}"); } return suppressed; } + public static IList? GetSuppressedAsListOrDefault(this Exception e) + { + return e.Data.Contains(SUPPRESSED_EXCEPTIONS_KEY) + ? e.Data[SUPPRESSED_EXCEPTIONS_KEY] as IList + : null; + } + public static void AddSuppressed(this Exception e, Exception exception) { e.GetSuppressedAsList().Add(exception);