diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index a9c2648e4fc..8001ad7121c 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -65,6 +65,9 @@ Improvements * LUCENE-9109: Use StackWalker to implement TestSecurityManager's detection of JVM exit (Uwe Schindler) +* LUCENE-9110: Refactor stack analysis in tests to use generalized LuceneTestCase + methods that use StackWalker (Uwe Schindler) + Bug fixes * LUCENE-8663: NRTCachingDirectory.slowFileExists may open a file while @@ -96,6 +99,9 @@ Improvements * LUCENE-9109: Backport some changes from master (except StackWalker) to improve TestSecurityManager (Uwe Schindler) +* LUCENE-9110: Backport refactored stack analysis in tests to use generalized + LuceneTestCase methods (Uwe Schindler) + Optimizations --------------------- (No changes) diff --git a/lucene/core/src/test/org/apache/lucene/TestMergeSchedulerExternal.java b/lucene/core/src/test/org/apache/lucene/TestMergeSchedulerExternal.java index ef82685bece..b6897259a93 100644 --- a/lucene/core/src/test/org/apache/lucene/TestMergeSchedulerExternal.java +++ b/lucene/core/src/test/org/apache/lucene/TestMergeSchedulerExternal.java @@ -89,18 +89,15 @@ public class TestMergeSchedulerExternal extends LuceneTestCase { private static class FailOnlyOnMerge extends MockDirectoryWrapper.Failure { @Override public void eval(MockDirectoryWrapper dir) throws IOException { - StackTraceElement[] trace = new Exception().getStackTrace(); - for (int i = 0; i < trace.length; i++) { - if ("doMerge".equals(trace[i].getMethodName())) { - IOException ioe = new IOException("now failing during merge"); - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - ioe.printStackTrace(pw); - if (infoStream.isEnabled("IW")) { - infoStream.message("IW", "TEST: now throw exc:\n" + sw.toString()); - } - throw ioe; + if (callStackContainsAnyOf("doMerge")) { + IOException ioe = new IOException("now failing during merge"); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + ioe.printStackTrace(pw); + if (infoStream.isEnabled("IW")) { + infoStream.message("IW", "TEST: now throw exc:\n" + sw.toString()); } + throw ioe; } } } diff --git a/lucene/core/src/test/org/apache/lucene/index/TestConcurrentMergeScheduler.java b/lucene/core/src/test/org/apache/lucene/index/TestConcurrentMergeScheduler.java index fad831fb74b..4683a512be8 100644 --- a/lucene/core/src/test/org/apache/lucene/index/TestConcurrentMergeScheduler.java +++ b/lucene/core/src/test/org/apache/lucene/index/TestConcurrentMergeScheduler.java @@ -54,21 +54,7 @@ public class TestConcurrentMergeScheduler extends LuceneTestCase { @Override public void eval(MockDirectoryWrapper dir) throws IOException { if (doFail && isTestThread()) { - boolean isDoFlush = false; - boolean isClose = false; - StackTraceElement[] trace = new Exception().getStackTrace(); - for (int i = 0; i < trace.length; i++) { - if (isDoFlush && isClose) { - break; - } - if ("flush".equals(trace[i].getMethodName())) { - isDoFlush = true; - } - if ("close".equals(trace[i].getMethodName())) { - isClose = true; - } - } - if (isDoFlush && !isClose && random().nextBoolean()) { + if (callStackContainsAnyOf("flush") && false == callStackContainsAnyOf("close") && random().nextBoolean()) { hitExc = true; throw new IOException(Thread.currentThread().getName() + ": now failing during flush"); } diff --git a/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReaderReopen.java b/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReaderReopen.java index 7a7a160d453..2723f7ff6fa 100644 --- a/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReaderReopen.java +++ b/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReaderReopen.java @@ -659,16 +659,13 @@ public class TestDirectoryReaderReopen extends LuceneTestCase { } //System.out.println("failOn: "); //new Throwable().printStackTrace(System.out); - StackTraceElement[] trace = new Exception().getStackTrace(); - for (int i = 0; i < trace.length; i++) { - if ("readLiveDocs".equals(trace[i].getMethodName())) { - if (VERBOSE) { - System.out.println("TEST: now fail; exc:"); - new Throwable().printStackTrace(System.out); - } - failed = true; - throw new FakeIOException(); + if (callStackContainsAnyOf("readLiveDocs")) { + if (VERBOSE) { + System.out.println("TEST: now fail; exc:"); + new Throwable().printStackTrace(System.out); } + failed = true; + throw new FakeIOException(); } } }); diff --git a/lucene/core/src/test/org/apache/lucene/index/TestIndexFileDeleter.java b/lucene/core/src/test/org/apache/lucene/index/TestIndexFileDeleter.java index eedcfdb8344..d560298ec10 100644 --- a/lucene/core/src/test/org/apache/lucene/index/TestIndexFileDeleter.java +++ b/lucene/core/src/test/org/apache/lucene/index/TestIndexFileDeleter.java @@ -414,12 +414,8 @@ public class TestIndexFileDeleter extends LuceneTestCase { @Override public void eval(MockDirectoryWrapper dir) throws IOException { if (doFailExc.get() && random().nextInt(4) == 1) { - Exception e = new Exception(); - StackTraceElement stack[] = e.getStackTrace(); - for (int i = 0; i < stack.length; i++) { - if (stack[i].getClassName().equals(IndexFileDeleter.class.getName()) && stack[i].getMethodName().equals("decRef")) { - throw new RuntimeException("fake fail"); - } + if (callStackContains(IndexFileDeleter.class, "decRef")) { + throw new RuntimeException("fake fail"); } } } @@ -497,12 +493,8 @@ public class TestIndexFileDeleter extends LuceneTestCase { @Override public void eval(MockDirectoryWrapper dir) throws IOException { if (doFailExc.get() && random().nextInt(4) == 1) { - Exception e = new Exception(); - StackTraceElement stack[] = e.getStackTrace(); - for (int i = 0; i < stack.length; i++) { - if (stack[i].getClassName().equals(MockDirectoryWrapper.class.getName()) && stack[i].getMethodName().equals("deleteFile")) { - throw new MockDirectoryWrapper.FakeIOException(); - } + if (callStackContains(MockDirectoryWrapper.class, "deleteFile")) { + throw new MockDirectoryWrapper.FakeIOException(); } } } diff --git a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java index 027ef696cf1..dc70a63c497 100644 --- a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java +++ b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java @@ -3048,13 +3048,8 @@ public class TestIndexWriter extends LuceneTestCase { dir.failOn(new MockDirectoryWrapper.Failure() { @Override public void eval(MockDirectoryWrapper dir) throws IOException { - StackTraceElement[] trace = new Exception().getStackTrace(); - for (int i = 0; i < trace.length; i++) { - if ("flush".equals(trace[i].getMethodName()) - && "org.apache.lucene.index.DocumentsWriterPerThread".equals(trace[i].getClassName())) { - flushingThreads.add(Thread.currentThread().getName()); - break; - } + if (callStackContains(DocumentsWriterPerThread.class, "flush")) { + flushingThreads.add(Thread.currentThread().getName()); } } }); @@ -3384,15 +3379,12 @@ public class TestIndexWriter extends LuceneTestCase { try (Directory dir = new FilterDirectory(newDirectory()) { @Override public IndexOutput createOutput(String name, IOContext context) throws IOException { - StackTraceElement[] trace = new Exception().getStackTrace(); - for (int i = 0; i < trace.length; i++) { - if ("flush".equals(trace[i].getMethodName()) && DefaultIndexingChain.class.getName().equals(trace[i].getClassName())) { - try { - inFlush.countDown(); - latch.await(); - } catch (InterruptedException e) { - throw new AssertionError(e); - } + if (callStackContains(DefaultIndexingChain.class, "flush")) { + try { + inFlush.countDown(); + latch.await(); + } catch (InterruptedException e) { + throw new AssertionError(e); } } return super.createOutput(name, context); diff --git a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterDelete.java b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterDelete.java index 4c9a4e01a22..80be5b2014e 100644 --- a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterDelete.java +++ b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterDelete.java @@ -731,15 +731,7 @@ public class TestIndexWriterDelete extends LuceneTestCase { } new Throwable().printStackTrace(System.out); if (sawMaybe && !failed) { - boolean seen = false; - StackTraceElement[] trace = new Exception().getStackTrace(); - for (int i = 0; i < trace.length; i++) { - if ("applyDeletesAndUpdates".equals(trace[i].getMethodName()) || - "slowFileExists".equals(trace[i].getMethodName())) { - seen = true; - break; - } - } + boolean seen = callStackContainsAnyOf("applyDeletesAndUpdates", "slowFileExists"); if (!seen) { // Only fail once we are no longer in applyDeletes failed = true; @@ -751,16 +743,12 @@ public class TestIndexWriterDelete extends LuceneTestCase { } } if (!failed) { - StackTraceElement[] trace = new Exception().getStackTrace(); - for (int i = 0; i < trace.length; i++) { - if ("applyDeletesAndUpdates".equals(trace[i].getMethodName())) { - if (VERBOSE) { - System.out.println("TEST: mock failure: saw applyDeletes"); - new Throwable().printStackTrace(System.out); - } - sawMaybe = true; - break; + if (callStackContainsAnyOf("applyDeletesAndUpdates")) { + if (VERBOSE) { + System.out.println("TEST: mock failure: saw applyDeletes"); + new Throwable().printStackTrace(System.out); } + sawMaybe = true; } } } diff --git a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java index 0bfa1e1e202..b44976482cc 100644 --- a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java +++ b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java @@ -567,19 +567,7 @@ public class TestIndexWriterExceptions extends LuceneTestCase { @Override public void eval(MockDirectoryWrapper dir) throws IOException { if (doFail) { - StackTraceElement[] trace = new Exception().getStackTrace(); - boolean sawFlush = false; - boolean sawFinishDocument = false; - for (int i = 0; i < trace.length; i++) { - if ("flush".equals(trace[i].getMethodName())) { - sawFlush = true; - } - if ("finishDocument".equals(trace[i].getMethodName())) { - sawFinishDocument = true; - } - } - - if (sawFlush && sawFinishDocument == false && count++ >= 30) { + if (callStackContainsAnyOf("flush") && false == callStackContainsAnyOf("finishDocument") && count++ >= 30) { doFail = false; throw new IOException("now failing during flush"); } @@ -872,16 +860,14 @@ public class TestIndexWriterExceptions extends LuceneTestCase { @Override public void eval(MockDirectoryWrapper dir) throws IOException { if (doFail) { - StackTraceElement[] trace = new Exception().getStackTrace(); - for (int i = 0; i < trace.length; i++) { - if (doFail && MockDirectoryWrapper.class.getName().equals(trace[i].getClassName()) && "sync".equals(trace[i].getMethodName())) { - didFail = true; - if (VERBOSE) { - System.out.println("TEST: now throw exc:"); - new Throwable().printStackTrace(System.out); - } - throw new IOException("now failing on purpose during sync"); + if (callStackContains(MockDirectoryWrapper.class, "sync")) { + didFail = true; + if (VERBOSE) { + System.out.println("TEST: now throw exc:"); + new Throwable().printStackTrace(System.out); } + throw new IOException("now failing on purpose during sync"); + } } } @@ -949,28 +935,10 @@ public class TestIndexWriterExceptions extends LuceneTestCase { @Override public void eval(MockDirectoryWrapper dir) throws IOException { - StackTraceElement[] trace = new Exception().getStackTrace(); - boolean isCommit = false; - boolean isDelete = false; - boolean isSyncMetadata = false; - boolean isInGlobalFieldMap = false; - for (int i = 0; i < trace.length; i++) { - if (isCommit && isDelete && isInGlobalFieldMap && isSyncMetadata) { - break; - } - if (SegmentInfos.class.getName().equals(trace[i].getClassName()) && stage.equals(trace[i].getMethodName())) { - isCommit = true; - } - if (MockDirectoryWrapper.class.getName().equals(trace[i].getClassName()) && "deleteFile".equals(trace[i].getMethodName())) { - isDelete = true; - } - if (SegmentInfos.class.getName().equals(trace[i].getClassName()) && "writeGlobalFieldMap".equals(trace[i].getMethodName())) { - isInGlobalFieldMap = true; - } - if (MockDirectoryWrapper.class.getName().equals(trace[i].getClassName()) && "syncMetaData".equals(trace[i].getMethodName())) { - isSyncMetadata = true; - } - } + boolean isCommit = callStackContains(SegmentInfos.class, stage); + boolean isDelete = callStackContains(MockDirectoryWrapper.class, "deleteFile"); + boolean isSyncMetadata = callStackContains(MockDirectoryWrapper.class, "syncMetaData"); + boolean isInGlobalFieldMap = callStackContains(SegmentInfos.class, "writeGlobalFieldMap"); if (isInGlobalFieldMap && dontFailDuringGlobalFieldMap) { isCommit = false; } @@ -1384,17 +1352,7 @@ public class TestIndexWriterExceptions extends LuceneTestCase { @Override public void eval(MockDirectoryWrapper dir) throws IOException { - - StackTraceElement[] trace = new Exception().getStackTrace(); - boolean fail = false; - for (int i = 0; i < trace.length; i++) { - if (TermVectorsConsumer.class.getName().equals(trace[i].getClassName()) && stage.equals(trace[i].getMethodName())) { - fail = true; - break; - } - } - - if (fail) { + if (callStackContains(TermVectorsConsumer.class, stage)) { throw new RuntimeException(EXC_MSG); } } @@ -1726,11 +1684,8 @@ public class TestIndexWriterExceptions extends LuceneTestCase { @Override public IndexInput openInput(String name, IOContext context) throws IOException { if (doFail && name.startsWith("segments_")) { - StackTraceElement[] trace = new Exception().getStackTrace(); - for (int i = 0; i < trace.length; i++) { - if ("readCommit".equals(trace[i].getMethodName()) || "readLatestCommit".equals(trace[i].getMethodName())) { - throw new UnsupportedOperationException("expected UOE"); - } + if (callStackContainsAnyOf("readCommit", "readLatestCommit")) { + throw new UnsupportedOperationException("expected UOE"); } } return super.openInput(name, context); @@ -1946,17 +1901,7 @@ public class TestIndexWriterExceptions extends LuceneTestCase { if (random().nextInt(10) != 0) { return; } - boolean maybeFail = false; - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - - for (int i = 0; i < trace.length; i++) { - if ("rollbackInternal".equals(trace[i].getMethodName())) { - maybeFail = true; - break; - } - } - - if (maybeFail) { + if (callStackContainsAnyOf("rollbackInternal")) { if (VERBOSE) { System.out.println("TEST: now fail; thread=" + Thread.currentThread().getName() + " exc:"); new Throwable().printStackTrace(System.out); @@ -2019,17 +1964,14 @@ public class TestIndexWriterExceptions extends LuceneTestCase { // Already failed return; } - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - - for (int i = 0; i < trace.length; i++) { - if ("merge".equals(trace[i].getMethodName())) { - if (VERBOSE) { - System.out.println("TEST: now fail; thread=" + Thread.currentThread().getName() + " exc:"); - new Throwable().printStackTrace(System.out); - } - didFail.set(true); - throw new FakeIOException(); + + if (callStackContainsAnyOf("merge")) { + if (VERBOSE) { + System.out.println("TEST: now fail; thread=" + Thread.currentThread().getName() + " exc:"); + new Throwable().printStackTrace(System.out); } + didFail.set(true); + throw new FakeIOException(); } } }); diff --git a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterOnDiskFull.java b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterOnDiskFull.java index cd97703ad09..b560e44ff23 100644 --- a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterOnDiskFull.java +++ b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterOnDiskFull.java @@ -18,7 +18,6 @@ package org.apache.lucene.index; import java.io.IOException; - import org.apache.lucene.analysis.MockAnalyzer; import org.apache.lucene.codecs.LiveDocsFormat; import org.apache.lucene.document.Document; @@ -478,16 +477,13 @@ public class TestIndexWriterOnDiskFull extends LuceneTestCase { if (!doFail) { return; } - StackTraceElement[] trace = new Exception().getStackTrace(); - for (int i = 0; i < trace.length; i++) { - if (SegmentMerger.class.getName().equals(trace[i].getClassName()) && "mergeTerms".equals(trace[i].getMethodName()) && !didFail1) { - didFail1 = true; - throw new IOException("fake disk full during mergeTerms"); - } - if (LiveDocsFormat.class.getName().equals(trace[i].getClassName()) && "writeLiveDocs".equals(trace[i].getMethodName()) && !didFail2) { - didFail2 = true; - throw new IOException("fake disk full while writing LiveDocs"); - } + if (callStackContains(SegmentMerger.class, "mergeTerms") && !didFail1) { + didFail1 = true; + throw new IOException("fake disk full during mergeTerms"); + } + if (callStackContains(LiveDocsFormat.class, "writeLiveDocs") && !didFail2) { + didFail2 = true; + throw new IOException("fake disk full while writing LiveDocs"); } } } diff --git a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterOnVMError.java b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterOnVMError.java index 99f7d539bf0..73704dd6a17 100644 --- a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterOnVMError.java +++ b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterOnVMError.java @@ -238,14 +238,7 @@ public class TestIndexWriterOnVMError extends LuceneTestCase { @Override public void eval(MockDirectoryWrapper dir) throws IOException { if (r.nextInt(3000) == 0) { - StackTraceElement stack[] = Thread.currentThread().getStackTrace(); - boolean ok = false; - for (int i = 0; i < stack.length; i++) { - if (stack[i].getClassName().equals(IndexWriter.class.getName())) { - ok = true; - } - } - if (ok) { + if (callStackContains(IndexWriter.class)) { throw new OutOfMemoryError("Fake OutOfMemoryError"); } } @@ -259,14 +252,7 @@ public class TestIndexWriterOnVMError extends LuceneTestCase { @Override public void eval(MockDirectoryWrapper dir) throws IOException { if (r.nextInt(3000) == 0) { - StackTraceElement stack[] = Thread.currentThread().getStackTrace(); - boolean ok = false; - for (int i = 0; i < stack.length; i++) { - if (stack[i].getClassName().equals(IndexWriter.class.getName())) { - ok = true; - } - } - if (ok) { + if (callStackContains(IndexWriter.class)) { throw new UnknownError("Fake UnknownError"); } } @@ -281,16 +267,11 @@ public class TestIndexWriterOnVMError extends LuceneTestCase { doTest(new Failure() { @Override public void eval(MockDirectoryWrapper dir) throws IOException { - StackTraceElement stack[] = Thread.currentThread().getStackTrace(); - boolean ok = false; - for (int i = 0; i < stack.length; i++) { - if (stack[i].getClassName().equals(IndexFileDeleter.class.getName()) && stack[i].getMethodName().equals("checkpoint")) { - ok = true; + if (r.nextInt(4) == 0) { + if (callStackContains(IndexFileDeleter.class, "checkpoint")) { + throw new OutOfMemoryError("Fake OutOfMemoryError"); } } - if (ok && r.nextInt(4) == 0) { - throw new OutOfMemoryError("Fake OutOfMemoryError"); - } } }); } diff --git a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterReader.java b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterReader.java index 5996d7e81ea..6982c8bec2c 100644 --- a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterReader.java +++ b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterReader.java @@ -1067,17 +1067,14 @@ public class TestIndexWriterReader extends LuceneTestCase { dir.failOn(new MockDirectoryWrapper.Failure() { @Override public void eval(MockDirectoryWrapper dir) throws IOException { - StackTraceElement[] trace = new Exception().getStackTrace(); if (shouldFail.get()) { - for (int i = 0; i < trace.length; i++) { - if ("getReadOnlyClone".equals(trace[i].getMethodName())) { - if (VERBOSE) { - System.out.println("TEST: now fail; exc:"); - new Throwable().printStackTrace(System.out); - } - shouldFail.set(false); - throw new FakeIOException(); + if (callStackContainsAnyOf("getReadOnlyClone")) { + if (VERBOSE) { + System.out.println("TEST: now fail; exc:"); + new Throwable().printStackTrace(System.out); } + shouldFail.set(false); + throw new FakeIOException(); } } } diff --git a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterWithThreads.java b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterWithThreads.java index 48e42bd3075..cfbf3f79513 100644 --- a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterWithThreads.java +++ b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterWithThreads.java @@ -407,26 +407,7 @@ public class TestIndexWriterWithThreads extends LuceneTestCase { dir.setAssertNoUnrefencedFilesOnClose(false); if (doFail) { - StackTraceElement[] trace = new Exception().getStackTrace(); - boolean sawAbortOrFlushDoc = false; - boolean sawClose = false; - boolean sawMerge = false; - for (int i = 0; i < trace.length; i++) { - if (sawAbortOrFlushDoc && sawMerge && sawClose) { - break; - } - if ("abort".equals(trace[i].getMethodName()) || - "finishDocument".equals(trace[i].getMethodName())) { - sawAbortOrFlushDoc = true; - } - if ("merge".equals(trace[i].getMethodName())) { - sawMerge = true; - } - if ("close".equals(trace[i].getMethodName())) { - sawClose = true; - } - } - if (sawAbortOrFlushDoc && !sawClose && !sawMerge) { + if (callStackContainsAnyOf("abort", "finishDocument") && false == callStackContainsAnyOf("merge", "close")) { if (onlyOnce) { doFail = false; } @@ -473,15 +454,12 @@ public class TestIndexWriterWithThreads extends LuceneTestCase { @Override public void eval(MockDirectoryWrapper dir) throws IOException { if (doFail) { - StackTraceElement[] trace = new Exception().getStackTrace(); - for (int i = 0; i < trace.length; i++) { - if ("flush".equals(trace[i].getMethodName()) && DefaultIndexingChain.class.getName().equals(trace[i].getClassName())) { - if (onlyOnce) - doFail = false; - //System.out.println(Thread.currentThread().getName() + ": NOW FAIL: onlyOnce=" + onlyOnce); - //new Throwable().printStackTrace(System.out); - throw new IOException("now failing on purpose"); - } + if (callStackContains(DefaultIndexingChain.class, "flush")) { + if (onlyOnce) + doFail = false; + //System.out.println(Thread.currentThread().getName() + ": NOW FAIL: onlyOnce=" + onlyOnce); + //new Throwable().printStackTrace(System.out); + throw new IOException("now failing on purpose"); } } } diff --git a/lucene/core/src/test/org/apache/lucene/index/TestPersistentSnapshotDeletionPolicy.java b/lucene/core/src/test/org/apache/lucene/index/TestPersistentSnapshotDeletionPolicy.java index 21424cc1793..e244cd01c16 100644 --- a/lucene/core/src/test/org/apache/lucene/index/TestPersistentSnapshotDeletionPolicy.java +++ b/lucene/core/src/test/org/apache/lucene/index/TestPersistentSnapshotDeletionPolicy.java @@ -116,11 +116,8 @@ public class TestPersistentSnapshotDeletionPolicy extends TestSnapshotDeletionPo dir.failOn(new MockDirectoryWrapper.Failure() { @Override public void eval(MockDirectoryWrapper dir) throws IOException { - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - for (int i = 0; i < trace.length; i++) { - if (PersistentSnapshotDeletionPolicy.class.getName().equals(trace[i].getClassName()) && "persist".equals(trace[i].getMethodName())) { - throw new IOException("now fail on purpose"); - } + if (callStackContains(PersistentSnapshotDeletionPolicy.class, "persist")) { + throw new IOException("now fail on purpose"); } } }); diff --git a/lucene/highlighter/src/test/org/apache/lucene/search/uhighlight/TestUnifiedHighlighterTermVec.java b/lucene/highlighter/src/test/org/apache/lucene/search/uhighlight/TestUnifiedHighlighterTermVec.java index 6a92546d8f0..b2319d1a1cd 100644 --- a/lucene/highlighter/src/test/org/apache/lucene/search/uhighlight/TestUnifiedHighlighterTermVec.java +++ b/lucene/highlighter/src/test/org/apache/lucene/search/uhighlight/TestUnifiedHighlighterTermVec.java @@ -133,8 +133,8 @@ public class TestUnifiedHighlighterTermVec extends LuceneTestCase { @Override public Fields getTermVectors(int docID) throws IOException { // if we're invoked by ParallelLeafReader then we can't do our assertion. TODO see LUCENE-6868 - if (calledBy(ParallelLeafReader.class) == false - && calledBy(CheckIndex.class) == false) { + if (callStackContains(ParallelLeafReader.class) == false + && callStackContains(CheckIndex.class) == false) { assertFalse("Should not request TVs for doc more than once.", seenDocIDs.get(docID)); seenDocIDs.set(docID); } @@ -170,14 +170,6 @@ public class TestUnifiedHighlighterTermVec extends LuceneTestCase { } } - private static boolean calledBy(Class clazz) { - for (StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) { - if (stackTraceElement.getClassName().equals(clazz.getName())) - return true; - } - return false; - } - @Test(expected = IllegalArgumentException.class) public void testUserFailedToIndexOffsets() throws IOException { FieldType fieldType = new FieldType(UHTestHelper.tvType); // note: it's indexed too diff --git a/lucene/test-framework/src/java/org/apache/lucene/index/BaseFieldInfoFormatTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/index/BaseFieldInfoFormatTestCase.java index 3cd7fcdc3eb..ed211266bbd 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/index/BaseFieldInfoFormatTestCase.java +++ b/lucene/test-framework/src/java/org/apache/lucene/index/BaseFieldInfoFormatTestCase.java @@ -102,10 +102,8 @@ public abstract class BaseFieldInfoFormatTestCase extends BaseIndexFileFormatTes Failure fail = new Failure() { @Override public void eval(MockDirectoryWrapper dir) throws IOException { - for (StackTraceElement e : Thread.currentThread().getStackTrace()) { - if (doFail && "createOutput".equals(e.getMethodName())) { - throw new FakeIOException(); - } + if (doFail && callStackContainsAnyOf("createOutput")) { + throw new FakeIOException(); } } }; @@ -137,10 +135,8 @@ public abstract class BaseFieldInfoFormatTestCase extends BaseIndexFileFormatTes Failure fail = new Failure() { @Override public void eval(MockDirectoryWrapper dir) throws IOException { - for (StackTraceElement e : Thread.currentThread().getStackTrace()) { - if (doFail && "close".equals(e.getMethodName())) { - throw new FakeIOException(); - } + if (doFail && callStackContainsAnyOf("close")) { + throw new FakeIOException(); } } }; @@ -172,10 +168,8 @@ public abstract class BaseFieldInfoFormatTestCase extends BaseIndexFileFormatTes Failure fail = new Failure() { @Override public void eval(MockDirectoryWrapper dir) throws IOException { - for (StackTraceElement e : Thread.currentThread().getStackTrace()) { - if (doFail && "openInput".equals(e.getMethodName())) { - throw new FakeIOException(); - } + if (doFail && callStackContainsAnyOf("openInput")) { + throw new FakeIOException(); } } }; @@ -208,10 +202,8 @@ public abstract class BaseFieldInfoFormatTestCase extends BaseIndexFileFormatTes Failure fail = new Failure() { @Override public void eval(MockDirectoryWrapper dir) throws IOException { - for (StackTraceElement e : Thread.currentThread().getStackTrace()) { - if (doFail && "close".equals(e.getMethodName())) { - throw new FakeIOException(); - } + if (doFail && callStackContainsAnyOf("close")) { + throw new FakeIOException(); } } }; diff --git a/lucene/test-framework/src/java/org/apache/lucene/index/BaseSegmentInfoFormatTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/index/BaseSegmentInfoFormatTestCase.java index 91eb971b0d7..a3a5391055d 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/index/BaseSegmentInfoFormatTestCase.java +++ b/lucene/test-framework/src/java/org/apache/lucene/index/BaseSegmentInfoFormatTestCase.java @@ -292,10 +292,8 @@ public abstract class BaseSegmentInfoFormatTestCase extends BaseIndexFileFormatT Failure fail = new Failure() { @Override public void eval(MockDirectoryWrapper dir) throws IOException { - for (StackTraceElement e : Thread.currentThread().getStackTrace()) { - if (doFail && "createOutput".equals(e.getMethodName())) { - throw new FakeIOException(); - } + if (doFail && callStackContainsAnyOf("createOutput")) { + throw new FakeIOException(); } } }; @@ -325,10 +323,8 @@ public abstract class BaseSegmentInfoFormatTestCase extends BaseIndexFileFormatT Failure fail = new Failure() { @Override public void eval(MockDirectoryWrapper dir) throws IOException { - for (StackTraceElement e : Thread.currentThread().getStackTrace()) { - if (doFail && "close".equals(e.getMethodName())) { - throw new FakeIOException(); - } + if (doFail && callStackContainsAnyOf("close")) { + throw new FakeIOException(); } } }; @@ -358,10 +354,8 @@ public abstract class BaseSegmentInfoFormatTestCase extends BaseIndexFileFormatT Failure fail = new Failure() { @Override public void eval(MockDirectoryWrapper dir) throws IOException { - for (StackTraceElement e : Thread.currentThread().getStackTrace()) { - if (doFail && "openInput".equals(e.getMethodName())) { - throw new FakeIOException(); - } + if (doFail && callStackContainsAnyOf("openInput")) { + throw new FakeIOException(); } } }; @@ -392,10 +386,8 @@ public abstract class BaseSegmentInfoFormatTestCase extends BaseIndexFileFormatT Failure fail = new Failure() { @Override public void eval(MockDirectoryWrapper dir) throws IOException { - for (StackTraceElement e : Thread.currentThread().getStackTrace()) { - if (doFail && "close".equals(e.getMethodName())) { - throw new FakeIOException(); - } + if (doFail && callStackContainsAnyOf("close")) { + throw new FakeIOException(); } } }; diff --git a/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java index 0b999042030..545b57b55fc 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java +++ b/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java @@ -21,6 +21,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; +import java.lang.StackWalker.StackFrame; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; @@ -2707,6 +2708,27 @@ public abstract class LuceneTestCase extends Assert { } } } + + /** Inspects stack trace to figure out if a method of a specific class called us. */ + public static boolean callStackContains(Class clazz, String methodName) { + final String className = clazz.getName(); + return StackWalker.getInstance().walk(s -> s.skip(1) // exclude this utility method + .anyMatch(f -> className.equals(f.getClassName()) && methodName.equals(f.getMethodName()))); + } + + /** Inspects stack trace to figure out if one of the given method names (no class restriction) called us. */ + public static boolean callStackContainsAnyOf(String... methodNames) { + return StackWalker.getInstance().walk(s -> s.skip(1) // exclude this utility method + .map(StackFrame::getMethodName) + .anyMatch(Set.of(methodNames)::contains)); + } + + /** Inspects stack trace if the given class called us. */ + public static boolean callStackContains(Class clazz) { + return StackWalker.getInstance().walk(s -> s.skip(1) // exclude this utility method + .map(StackFrame::getClassName) + .anyMatch(clazz.getName()::equals)); + } /** A runnable that can throw any checked exception. */ @FunctionalInterface