mirror of
https://github.com/apache/lucene.git
synced 2025-02-22 18:27:21 +00:00
Soft limit on the sysout bytes instead of a yes/no switch.
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/branches/LUCENE-5622@1591214 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
943f0cab26
commit
48d08fea07
@ -72,7 +72,6 @@ import java.util.StringTokenizer;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.lucene.util.LuceneTestCase.SuppressSysoutChecks;
|
||||
|
||||
@SuppressSysoutChecks(bugUrl = "External tool.")
|
||||
public class TestCompile extends LuceneTestCase {
|
||||
|
||||
public void testCompile() throws Exception {
|
||||
|
@ -42,7 +42,6 @@ import java.util.Map;
|
||||
/**
|
||||
* Testcase for {@link UIMABaseAnalyzer}
|
||||
*/
|
||||
@SuppressSysoutChecks(bugUrl = "UIMA logs via ju.logging")
|
||||
public class UIMABaseAnalyzerTest extends BaseTokenStreamTestCase {
|
||||
|
||||
private UIMABaseAnalyzer analyzer;
|
||||
|
@ -27,7 +27,6 @@ import org.junit.Test;
|
||||
/**
|
||||
* Testcase for {@link UIMATypeAwareAnalyzer}
|
||||
*/
|
||||
@SuppressSysoutChecks(bugUrl = "UIMA logs via ju.logging")
|
||||
public class UIMATypeAwareAnalyzerTest extends BaseTokenStreamTestCase {
|
||||
|
||||
private UIMATypeAwareAnalyzer analyzer;
|
||||
|
@ -31,7 +31,6 @@ import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
/** Base class for all Benchmark unit tests. */
|
||||
@SuppressSysoutChecks(bugUrl = "Output expected.")
|
||||
public abstract class BenchmarkTestCase extends LuceneTestCase {
|
||||
private static File WORKDIR;
|
||||
|
||||
|
@ -67,7 +67,6 @@ import org.apache.lucene.util.LuceneTestCase.SuppressSysoutChecks;
|
||||
/**
|
||||
* Test very simply that perf tasks - simple algorithms - are doing what they should.
|
||||
*/
|
||||
@SuppressSysoutChecks(bugUrl = "Output expected.")
|
||||
public class TestPerfTasksLogic extends BenchmarkTestCase {
|
||||
|
||||
@Override
|
||||
|
@ -42,7 +42,6 @@ import org.apache.lucene.util.LuceneTestCase.SuppressSysoutChecks;
|
||||
import conf.ConfLoader;
|
||||
|
||||
/** Test very simply that perf tasks are parses as expected. */
|
||||
@SuppressSysoutChecks(bugUrl = "Output expected.")
|
||||
public class TestPerfTasksParse extends LuceneTestCase {
|
||||
|
||||
static final String NEW_LINE = System.getProperty("line.separator");
|
||||
|
@ -44,7 +44,6 @@ import java.nio.charset.StandardCharsets;
|
||||
* this test will not work correctly, as it does not dynamically
|
||||
* generate its test trec topics/qrels!
|
||||
*/
|
||||
@SuppressSysoutChecks(bugUrl = "Output expected.")
|
||||
public class TestQualityRun extends BenchmarkTestCase {
|
||||
|
||||
@Override
|
||||
|
@ -1008,7 +1008,6 @@
|
||||
<propertyref prefix="tests.leavetmpdir" />
|
||||
<propertyref prefix="tests.leaveTemporary" />
|
||||
<propertyref prefix="tests.leavetemporary" />
|
||||
<propertyref prefix="tests.sysouts" />
|
||||
<propertyref prefix="solr.test.leavetmpdir" />
|
||||
</syspropertyset>
|
||||
|
||||
|
@ -24,5 +24,4 @@ public class TestFastCompressionMode extends AbstractTestLZ4CompressionMode {
|
||||
super.setUp();
|
||||
mode = CompressionMode.FAST;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ package org.apache.lucene.util.junitcompat;
|
||||
*/
|
||||
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.util.LuceneTestCase.SuppressSysoutChecks;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.JUnitCore;
|
||||
@ -30,8 +29,7 @@ public class TestFailIfDirectoryNotClosed extends WithNestedTests {
|
||||
public TestFailIfDirectoryNotClosed() {
|
||||
super(true);
|
||||
}
|
||||
|
||||
@SuppressSysoutChecks(bugUrl = "Expected.")
|
||||
|
||||
public static class Nested1 extends WithNestedTests.AbstractNestedTest {
|
||||
public void testDummy() throws Exception {
|
||||
Directory dir = newDirectory();
|
||||
|
@ -43,7 +43,6 @@ public class TestSameRandomnessLocalePassedOrNot extends WithNestedTests {
|
||||
super(true);
|
||||
}
|
||||
|
||||
@SuppressSysoutChecks(bugUrl = "Expected.")
|
||||
public static class Nested extends WithNestedTests.AbstractNestedTest {
|
||||
public static String pickString;
|
||||
public static Locale defaultLocale;
|
||||
|
@ -30,7 +30,6 @@ import org.junit.runner.notification.Failure;
|
||||
* console.
|
||||
*/
|
||||
public class TestSeedFromUncaught extends WithNestedTests {
|
||||
@SuppressSysoutChecks(bugUrl = "Expected.")
|
||||
public static class ThrowInUncaught extends AbstractNestedTest {
|
||||
@Test
|
||||
public void testFoo() throws Exception {
|
||||
|
@ -25,7 +25,6 @@ import java.nio.charset.Charset;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.lucene.util.LuceneTestCase.SuppressSysoutChecks;
|
||||
|
||||
@SuppressSysoutChecks(bugUrl = "Output expected.")
|
||||
public class TestDemo extends LuceneTestCase {
|
||||
|
||||
private void testOneSearch(File indexPath, String query, int expectedHitCount) throws Exception {
|
||||
|
@ -24,7 +24,6 @@ import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.lucene.util.LuceneTestCase.SuppressSysoutChecks;
|
||||
|
||||
@SuppressSysoutChecks(bugUrl = "Output expected (external tool).")
|
||||
public class TestMultiPassIndexSplitter extends LuceneTestCase {
|
||||
IndexReader input;
|
||||
int NUM_DOCS = 11;
|
||||
|
@ -230,6 +230,7 @@ import static com.carrotsearch.randomizedtesting.RandomizedTest.systemPropertyAs
|
||||
@ThreadLeakFilters(defaultFilters = true, filters = {
|
||||
QuickPatchThreadsFilter.class
|
||||
})
|
||||
@TestRuleLimitSysouts.Limit(bytes = TestRuleLimitSysouts.DEFAULT_SYSOUT_BYTES_THRESHOLD)
|
||||
public abstract class LuceneTestCase extends Assert {
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@ -248,13 +249,6 @@ public abstract class LuceneTestCase extends Assert {
|
||||
|
||||
/** @see #ignoreAfterMaxFailures*/
|
||||
public static final String SYSPROP_FAILFAST = "tests.failfast";
|
||||
|
||||
/**
|
||||
* If true, enables assertions on writing to system streams.
|
||||
*
|
||||
* @see TestRuleLimitSysouts
|
||||
*/
|
||||
public static final String SYSPROP_SYSOUTS = "tests.sysouts";
|
||||
|
||||
/**
|
||||
* Annotation for tests that should only be run during nightly builds.
|
||||
@ -356,8 +350,8 @@ public abstract class LuceneTestCase extends Assert {
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks any suite which is known to print to {@link System#out} or {@link System#err},
|
||||
* even when {@link #VERBOSE} is disabled.
|
||||
* Ignore {@link TestRuleLimitSysouts} for any suite which is known to print
|
||||
* over the default limit of bytes to {@link System#out} or {@link System#err}.
|
||||
*
|
||||
* @see TestRuleLimitSysouts
|
||||
*/
|
||||
@ -369,7 +363,7 @@ public abstract class LuceneTestCase extends Assert {
|
||||
/** Point to JIRA entry. */
|
||||
public String bugUrl();
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Truly immutable fields and constants, initialized once and valid
|
||||
// for all suites ever since.
|
||||
|
@ -154,9 +154,6 @@ public final class RunListenerPrintReproduceInfo extends RunListener {
|
||||
addVmOpt(b, "testcase", RandomizedContext.current().getTargetClass().getSimpleName());
|
||||
addVmOpt(b, "tests.method", testName);
|
||||
addVmOpt(b, "tests.seed", RandomizedContext.current().getRunnerSeedAsString());
|
||||
|
||||
// Misc switches.
|
||||
addVmOpt(b, SYSPROP_SYSOUTS, System.getProperty(SYSPROP_SYSOUTS));
|
||||
|
||||
// Test groups and multipliers.
|
||||
if (RANDOM_MULTIPLIER > 1) addVmOpt(b, "tests.multiplier", RANDOM_MULTIPLIER);
|
||||
|
@ -5,9 +5,16 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.apache.lucene.util.LuceneTestCase.SuppressSysoutChecks;
|
||||
|
||||
@ -33,25 +40,48 @@ import com.carrotsearch.randomizedtesting.rules.TestRuleAdapter;
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fails the suite if it prints anything to {@link System#out} or {@link System#err},
|
||||
* Fails the suite if it prints over the given limit of bytes to either
|
||||
* {@link System#out} or {@link System#err},
|
||||
* unless the condition is not enforced (see {@link #isEnforced()}).
|
||||
*/
|
||||
public class TestRuleDisallowSysouts extends TestRuleAdapter {
|
||||
/**
|
||||
* Stack trace of any thread that wrote something to sysout or syserr.
|
||||
public class TestRuleLimitSysouts extends TestRuleAdapter {
|
||||
/**
|
||||
* Max limit of bytes printed to either {@link System#out} or {@link System#err}.
|
||||
* This limit is enforced per-class (suite).
|
||||
*/
|
||||
private final static AtomicReference<StackTraceElement[]> firstWriteStack = new AtomicReference<StackTraceElement[]>();
|
||||
public final static int DEFAULT_SYSOUT_BYTES_THRESHOLD = 8 * 1024;
|
||||
|
||||
/**
|
||||
* An annotation specifying the limit of bytes per class.
|
||||
*/
|
||||
@Documented
|
||||
@Inherited
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public static @interface Limit {
|
||||
public int bytes();
|
||||
}
|
||||
|
||||
private final static AtomicInteger bytesWritten = new AtomicInteger();
|
||||
|
||||
private final static DelegateStream capturedSystemOut;
|
||||
private final static DelegateStream capturedSystemErr;
|
||||
|
||||
/**
|
||||
* We capture system output and error streams as early as possible because
|
||||
* certain components (like the Java logging system) steal these references and
|
||||
* never refresh them.
|
||||
*
|
||||
* Also, for this exact reason, we cannot change delegate streams for every suite.
|
||||
* This isn't as elegant as it should be, but there's no workaround for this.
|
||||
*/
|
||||
static {
|
||||
System.out.flush();
|
||||
System.err.flush();
|
||||
|
||||
final String csn = Charset.defaultCharset().name();
|
||||
capturedSystemOut = new DelegateStream(System.out, csn, firstWriteStack);
|
||||
capturedSystemErr = new DelegateStream(System.err, csn, firstWriteStack);
|
||||
capturedSystemOut = new DelegateStream(System.out, csn, bytesWritten);
|
||||
capturedSystemErr = new DelegateStream(System.err, csn, bytesWritten);
|
||||
|
||||
System.setOut(capturedSystemOut.printStream);
|
||||
System.setErr(capturedSystemErr.printStream);
|
||||
@ -63,18 +93,18 @@ public class TestRuleDisallowSysouts extends TestRuleAdapter {
|
||||
private final TestRuleMarkFailure failureMarker;
|
||||
|
||||
/**
|
||||
* Sets {@link #firstWriteStack} to the current stack trace upon the first actual write
|
||||
* to an underlying stream.
|
||||
* Tracks the number of bytes written to an underlying stream by
|
||||
* incrementing an {@link AtomicInteger}.
|
||||
*/
|
||||
static class DelegateStream extends FilterOutputStream {
|
||||
private final AtomicReference<StackTraceElement[]> firstWriteStack;
|
||||
final PrintStream printStream;
|
||||
final AtomicInteger bytesCounter;
|
||||
|
||||
public DelegateStream(OutputStream delegate, String charset, AtomicReference<StackTraceElement[]> firstWriteStack) {
|
||||
public DelegateStream(OutputStream delegate, String charset, AtomicInteger bytesCounter) {
|
||||
super(delegate);
|
||||
try {
|
||||
this.firstWriteStack = firstWriteStack;
|
||||
this.printStream = new PrintStream(this, true, charset);
|
||||
this.bytesCounter = bytesCounter;
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@ -85,7 +115,7 @@ public class TestRuleDisallowSysouts extends TestRuleAdapter {
|
||||
@Override
|
||||
public void write(byte[] b) throws IOException {
|
||||
if (b.length > 0) {
|
||||
bytesWritten();
|
||||
bytesCounter.addAndGet(b.length);
|
||||
}
|
||||
super.write(b);
|
||||
}
|
||||
@ -93,27 +123,19 @@ public class TestRuleDisallowSysouts extends TestRuleAdapter {
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
if (len > 0) {
|
||||
bytesWritten();
|
||||
bytesCounter.addAndGet(len);
|
||||
}
|
||||
super.write(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
bytesWritten();
|
||||
bytesCounter.incrementAndGet();
|
||||
super.write(b);
|
||||
}
|
||||
|
||||
private void bytesWritten() {
|
||||
// This check isn't really needed, but getting the stack is expensive and may involve
|
||||
// jit deopts, so we'll do it anyway.
|
||||
if (firstWriteStack.get() == null) {
|
||||
firstWriteStack.compareAndSet(null, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TestRuleDisallowSysouts(TestRuleMarkFailure failureMarker) {
|
||||
|
||||
public TestRuleLimitSysouts(TestRuleMarkFailure failureMarker) {
|
||||
this.failureMarker = failureMarker;
|
||||
}
|
||||
|
||||
@ -125,6 +147,19 @@ public class TestRuleDisallowSysouts extends TestRuleAdapter {
|
||||
checkCaptureStreams();
|
||||
}
|
||||
resetCaptureState();
|
||||
validateClassAnnotations();
|
||||
}
|
||||
|
||||
private void validateClassAnnotations() {
|
||||
Class<?> target = RandomizedTest.getContext().getTargetClass();
|
||||
if (target.isAnnotationPresent(Limit.class)) {
|
||||
int bytes = target.getAnnotation(Limit.class).bytes();
|
||||
if (bytes < 0 || bytes > 1 * 1024 * 1024) {
|
||||
throw new AssertionError("The sysout limit is insane. Did you want to use "
|
||||
+ "@" + LuceneTestCase.SuppressSysoutChecks.class.getName() + " annotation to "
|
||||
+ "avoid sysout checks entirely?");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -141,13 +176,19 @@ public class TestRuleDisallowSysouts extends TestRuleAdapter {
|
||||
}
|
||||
|
||||
protected boolean isEnforced() {
|
||||
Class<?> target = RandomizedTest.getContext().getTargetClass();
|
||||
|
||||
if (LuceneTestCase.VERBOSE ||
|
||||
LuceneTestCase.INFOSTREAM ||
|
||||
RandomizedTest.getContext().getTargetClass().isAnnotationPresent(SuppressSysoutChecks.class)) {
|
||||
target.isAnnotationPresent(SuppressSysoutChecks.class)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !RandomizedTest.systemPropertyAsBoolean(LuceneTestCase.SYSPROP_SYSOUTS, true);
|
||||
if (!target.isAnnotationPresent(Limit.class)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -163,15 +204,17 @@ public class TestRuleDisallowSysouts extends TestRuleAdapter {
|
||||
capturedSystemOut.printStream.flush();
|
||||
capturedSystemErr.printStream.flush();
|
||||
|
||||
// And check for offenders, but only if everything was successful so far.
|
||||
StackTraceElement[] offenderStack = firstWriteStack.get();
|
||||
if (offenderStack != null && failureMarker.wasSuccessful()) {
|
||||
AssertionError e = new AssertionError("The test or suite printed information to stdout or stderr," +
|
||||
" even though verbose mode is turned off and it's not annotated with @" +
|
||||
SuppressSysoutChecks.class.getSimpleName() + ". This exception contains the stack" +
|
||||
" trace of the first offending call.");
|
||||
e.setStackTrace(offenderStack);
|
||||
throw e;
|
||||
// Check for offenders, but only if everything was successful so far.
|
||||
int limit = RandomizedTest.getContext().getTargetClass().getAnnotation(Limit.class).bytes();
|
||||
if (bytesWritten.get() >= limit && failureMarker.wasSuccessful()) {
|
||||
throw new AssertionError(String.format(Locale.ENGLISH,
|
||||
"The test or suite printed %d bytes to stdout and stderr," +
|
||||
" even though the limit was set to %d bytes. Increase the limit with @%s, ignore it completely" +
|
||||
" with @%s or run with -Dtests.verbose=true",
|
||||
bytesWritten.get(),
|
||||
limit,
|
||||
Limit.class.getSimpleName(),
|
||||
SuppressSysoutChecks.class.getSimpleName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -187,7 +230,7 @@ public class TestRuleDisallowSysouts extends TestRuleAdapter {
|
||||
private void resetCaptureState() {
|
||||
capturedSystemOut.printStream.flush();
|
||||
capturedSystemErr.printStream.flush();
|
||||
firstWriteStack.set(null);
|
||||
}
|
||||
bytesWritten.set(0);
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ import com.carrotsearch.randomizedtesting.rules.SystemPropertiesRestoreRule;
|
||||
SolrIgnoredThreadsFilter.class,
|
||||
QuickPatchThreadsFilter.class
|
||||
})
|
||||
@SuppressSysoutChecks(bugUrl = "Solr dumps logs to console.")
|
||||
@SuppressSysoutChecks(bugUrl = "Solr dumps tons of logs to console.")
|
||||
public abstract class SolrTestCaseJ4 extends LuceneTestCase {
|
||||
private static String coreName = ConfigSolrXmlOld.DEFAULT_DEFAULT_CORE_NAME;
|
||||
public static int DEFAULT_CONNECTION_TIMEOUT = 60000; // default socket connection timeout in ms
|
||||
|
Loading…
x
Reference in New Issue
Block a user