/*
 * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
 * (the "License"). You may not use this work except in compliance with the License, which is
 * available at www.apache.org/licenses/LICENSE-2.0
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied, as more fully set forth in the License.
 *
 * See the NOTICE file distributed with this work for information regarding copyright ownership.
 */

package alluxio.testutils;

import alluxio.Constants;

import org.junit.Rule;
import org.junit.rules.RuleChain;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.rules.Timeout;
import org.junit.runner.Description;

import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Collections;
import java.util.List;

/**
 * Base class used for specifying the maximum time a test should run for.
 */
public abstract class BaseIntegrationTest {
  @Rule
  public RuleChain mRules = createRuleChain();

  private RuleChain createRuleChain() {
    RuleChain chain = RuleChain.emptyRuleChain();
    chain = chain.around(logHandler());
    for (TestRule rule : rules()) {
      chain = chain.around(rule);
    }
    // Make Timeout the innermost rule so that other rules run in the main thread. Everything inside
    // Timeout is executed in a new thread.
    chain = chain.around(Timeout.millis(Constants.MAX_TEST_DURATION_MS));
    return chain;
  }

  private TestWatcher logHandler() {
    return new TestWatcher() {
      // When tests fail, save the logs.
      protected void failed(Throwable t, Description description) {
        try {
          Files.copy(Paths.get(Constants.TESTS_LOG),
              Paths.get(Constants.TEST_LOG_DIR, String.format("%s-%s.log",
                  description.getClassName(), description.getMethodName())),
              StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
          if (t != null) {
            t.addSuppressed(e);
          } else {
            throw new RuntimeException(e);
          }
        }
        return;
      }

      // Before each test starts, truncate the log file.
      protected void starting(Description description) {
        try {
          new FileWriter(Constants.TESTS_LOG).close();
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
      }
    };
  }

  /**
   * Subclasses should define their rules in this method so that they can be deterministically
   * ordered and properly nested relative to the global logging and timeout rules.
   *
   * @return the list of rules used by the subclass
   */
  protected List<TestRule> rules() {
    return Collections.EMPTY_LIST;
  }
}

@@ -558,24 +558,83 @@
 Constants;%0A%0A
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;%0A
 import org.j
@@ -640,24 +640,24 @@
 junit.Rule;%0A
-
 import org.j
@@ -815,16 +815,73 @@
 ription;
+%0Aimport org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;
 %0A%0Aimport
@@ -1162,16 +1162,16 @@
 or.%0A */%0A
-
 public a
@@ -1206,16 +1206,236 @@
 nTest %7B%0A
+  /** Logger is required so the log file is initialized, otherwise truncate can fail. */%0A  @SuppressFBWarnings(%22UUF_UNUSED_FIELD%22)%0A  private static final Logger LOG = LoggerFactory.getLogger(BaseIntegrationTest.class);%0A%0A
   @Rule%0A

Add logger to base integration test to avoid edge case. (#7202)