package org.apache.lucene.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.
 */

import org.apache.lucene.util.junitcompat.WithNestedTests;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;

import com.carrotsearch.randomizedtesting.SysGlobals;
import com.carrotsearch.randomizedtesting.annotations.Repeat;
import com.carrotsearch.randomizedtesting.rules.SystemPropertiesInvariantRule;
import com.carrotsearch.randomizedtesting.rules.SystemPropertiesRestoreRule;

/**
 * @see TestRuleIgnoreAfterMaxFailures
 * @see SystemPropertiesInvariantRule
 */
public class TestMaxFailuresRule extends WithNestedTests {
  @Rule
  public SystemPropertiesRestoreRule restoreSysProps = new SystemPropertiesRestoreRule();

  public TestMaxFailuresRule() {
    super(true);
  }

  public static class Nested extends WithNestedTests.AbstractNestedTest {
    @Repeat(iterations = 500)
    public void testFailSometimes() {
      assertFalse(random().nextInt(5) == 0);
    }
  }

  @Test
  public void testMaxFailures() {
    int maxFailures = LuceneTestCase.ignoreAfterMaxFailures.maxFailures;
    int failuresSoFar = LuceneTestCase.ignoreAfterMaxFailures.failuresSoFar;
    System.clearProperty(SysGlobals.SYSPROP_ITERATIONS());
    try {
      LuceneTestCase.ignoreAfterMaxFailures.maxFailures = 2;
      LuceneTestCase.ignoreAfterMaxFailures.failuresSoFar = 0;

      JUnitCore core = new JUnitCore();
      final StringBuilder results = new StringBuilder();
      core.addListener(new RunListener() {
        char lastTest;

        @Override
        public void testStarted(Description description) throws Exception {
          lastTest = 'S'; // success.
        }

        @Override
        public void testAssumptionFailure(Failure failure) {
          lastTest = 'A'; // assumption failure.
        }

        @Override
        public void testFailure(Failure failure) throws Exception {
          lastTest = 'F'; // failure
        }

        @Override
        public void testFinished(Description description) throws Exception {
          results.append(lastTest);
        }
      });

      Result result = core.run(Nested.class);
      Assert.assertEquals(500, result.getRunCount());
      Assert.assertEquals(0, result.getIgnoreCount());
      Assert.assertEquals(2, result.getFailureCount());

      // Make sure we had exactly two failures followed by assumption-failures
      // resulting from ignored tests.
      Assert.assertTrue(results.toString(), 
          results.toString().matches("(S*F){2}A+"));
    } finally {
      LuceneTestCase.ignoreAfterMaxFailures.maxFailures = maxFailures;
      LuceneTestCase.ignoreAfterMaxFailures.failuresSoFar = failuresSoFar;
    }
  }
}

@@ -1805,16 +1805,189 @@
 dTest %7B%0A
+    public static final int TOTAL_ITERS = 500;%0A    public static final int DESIRED_FAILURES = TOTAL_ITERS / 10;%0A    private int numFails = 0;%0A    private int numIters = 0;%0A%0A
     @Rep
@@ -2003,19 +2003,27 @@
 tions = 
-500
+TOTAL_ITERS
 )%0A    pu
@@ -2064,44 +2064,295 @@
     
-assertFalse(random().nextInt(5) == 0
+numIters++;%0A      boolean fail = random().nextInt(5) == 0;%0A      if (fail) numFails++;%0A      // some seeds are really lucky ... so cheat.%0A      if (numFails %3C DESIRED_FAILURES && %0A          DESIRED_FAILURES %3C= TOTAL_ITERS - numIters) %7B%0A        fail = true;%0A      %7D%0A      assertFalse(fail
 );%0A 
@@ -3903,24 +3903,25 @@
 F)%7B2%7DA+%22));%0A
+%0A
     %7D finall

fix test to not be so lucky about avoiding failures when we actually want them (merge r1420941)