/*
 * Copyright (C) 2009-2010, Google Inc.
 * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
 * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org>
 * and other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Distribution License v1.0 which
 * accompanies this distribution, is reproduced below, and is
 * available at http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.eclipse.jgit.junit;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.storage.file.WindowCacheConfig;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.SystemReader;
import org.junit.After;
import org.junit.Before;

/**
 * JUnit TestCase with specialized support for temporary local repository.
 * <p>
 * A temporary directory is created for each test, allowing each test to use a
 * fresh environment. The temporary directory is cleaned up after the test ends.
 * <p>
 * Callers should not use {@link org.eclipse.jgit.lib.RepositoryCache} from
 * within these tests as it may wedge file descriptors open past the end of the
 * test.
 * <p>
 * A system property {@code jgit.junit.usemmap} defines whether memory mapping
 * is used. Memory mapping has an effect on the file system, in that memory
 * mapped files in Java cannot be deleted as long as the mapped arrays have not
 * been reclaimed by the garbage collector. The programmer cannot control this
 * with precision, so temporary files may hang around longer than desired during
 * a test, or tests may fail altogether if there is insufficient file
 * descriptors or address space for the test process.
 */
public abstract class LocalDiskRepositoryTestCase {
	private static final boolean useMMAP = "true".equals(System
			.getProperty("jgit.junit.usemmap"));

	/** A fake (but stable) identity for author fields in the test. */
	protected PersonIdent author;

	/** A fake (but stable) identity for committer fields in the test. */
	protected PersonIdent committer;

	/**
	 * A {@link SystemReader} used to coordinate time, envars, etc.
	 * @since 4.2
	 */
	protected MockSystemReader mockSystemReader;

	private final Set<Repository> toClose = new HashSet<>();
	private File tmp;

	/**
	 * Setup test
	 *
	 * @throws Exception
	 */
	@Before
	public void setUp() throws Exception {
		tmp = File.createTempFile("jgit_test_", "_tmp");
		CleanupThread.deleteOnShutdown(tmp);
		if (!tmp.delete() || !tmp.mkdir())
			throw new IOException("Cannot create " + tmp);

		// measure timer resolution before the test to avoid time critical tests
		// are affected by time needed for measurement
		FS.getFileStoreAttributes(tmp.toPath().getParent());

		mockSystemReader = new MockSystemReader();
		mockSystemReader.userGitConfig = new FileBasedConfig(new File(tmp,
				"usergitconfig"), FS.DETECTED);
		// We have to set autoDetach to false for tests, because tests expect to be able
		// to clean up by recursively removing the repository, and background GC might be
		// in the middle of writing or deleting files, which would disrupt this.
		mockSystemReader.userGitConfig.setBoolean(ConfigConstants.CONFIG_GC_SECTION,
				null, ConfigConstants.CONFIG_KEY_AUTODETACH, false);
		mockSystemReader.userGitConfig.save();
		ceilTestDirectories(getCeilings());
		SystemReader.setInstance(mockSystemReader);

		author = new PersonIdent("J. Author", "jauthor@example.com");
		committer = new PersonIdent("J. Committer", "jcommitter@example.com");

		final WindowCacheConfig c = new WindowCacheConfig();
		c.setPackedGitLimit(128 * WindowCacheConfig.KB);
		c.setPackedGitWindowSize(8 * WindowCacheConfig.KB);
		c.setPackedGitMMAP(useMMAP);
		c.setDeltaBaseCacheLimit(8 * WindowCacheConfig.KB);
		c.install();
	}

	/**
	 * Get temporary directory.
	 *
	 * @return the temporary directory
	 */
	protected File getTemporaryDirectory() {
		return tmp.getAbsoluteFile();
	}

	/**
	 * Get list of ceiling directories
	 *
	 * @return list of ceiling directories
	 */
	protected List<File> getCeilings() {
		return Collections.singletonList(getTemporaryDirectory());
	}

	private void ceilTestDirectories(List<File> ceilings) {
		mockSystemReader.setProperty(Constants.GIT_CEILING_DIRECTORIES_KEY, makePath(ceilings));
	}

	private static String makePath(List<?> objects) {
		final StringBuilder stringBuilder = new StringBuilder();
		for (Object object : objects) {
			if (stringBuilder.length() > 0)
				stringBuilder.append(File.pathSeparatorChar);
			stringBuilder.append(object.toString());
		}
		return stringBuilder.toString();
	}

	/**
	 * Tear down the test
	 *
	 * @throws Exception
	 */
	@After
	public void tearDown() throws Exception {
		RepositoryCache.clear();
		for (Repository r : toClose)
			r.close();
		toClose.clear();

		// Since memory mapping is controlled by the GC we need to
		// tell it this is a good time to clean up and unlock
		// memory mapped files.
		//
		if (useMMAP)
			System.gc();
		if (tmp != null)
			recursiveDelete(tmp, false, true);
		if (tmp != null && !tmp.exists())
			CleanupThread.removed(tmp);

		SystemReader.setInstance(null);
	}

	/**
	 * Increment the {@link #author} and {@link #committer} times.
	 */
	protected void tick() {
		mockSystemReader.tick(5 * 60);
		final long now = mockSystemReader.getCurrentTime();
		final int tz = mockSystemReader.getTimezone(now);

		author = new PersonIdent(author, now, tz);
		committer = new PersonIdent(committer, now, tz);
	}

	/**
	 * Recursively delete a directory, failing the test if the delete fails.
	 *
	 * @param dir
	 *            the recursively directory to delete, if present.
	 */
	protected void recursiveDelete(File dir) {
		recursiveDelete(dir, false, true);
	}

	private static boolean recursiveDelete(final File dir,
			boolean silent, boolean failOnError) {
		assert !(silent && failOnError);
		int options = FileUtils.RECURSIVE | FileUtils.RETRY
				| FileUtils.SKIP_MISSING;
		if (silent) {
			options |= FileUtils.IGNORE_ERRORS;
		}
		try {
			FileUtils.delete(dir, options);
		} catch (IOException e) {
			reportDeleteFailure(failOnError, dir, e);
			return !failOnError;
		}
		return true;
	}

	private static void reportDeleteFailure(boolean failOnError, File f,
			Exception cause) {
		String severity = failOnError ? "ERROR" : "WARNING";
		String msg = severity + ": Failed to delete " + f;
		if (failOnError) {
			fail(msg);
		} else {
			System.err.println(msg);
		}
		cause.printStackTrace(new PrintStream(System.err));
	}

	/** Constant <code>MOD_TIME=1</code> */
	public static final int MOD_TIME = 1;

	/** Constant <code>SMUDGE=2</code> */
	public static final int SMUDGE = 2;

	/** Constant <code>LENGTH=4</code> */
	public static final int LENGTH = 4;

	/** Constant <code>CONTENT_ID=8</code> */
	public static final int CONTENT_ID = 8;

	/** Constant <code>CONTENT=16</code> */
	public static final int CONTENT = 16;

	/** Constant <code>ASSUME_UNCHANGED=32</code> */
	public static final int ASSUME_UNCHANGED = 32;

	/**
	 * Represent the state of the index in one String. This representation is
	 * useful when writing tests which do assertions on the state of the index.
	 * By default information about path, mode, stage (if different from 0) is
	 * included. A bitmask controls which additional info about
	 * modificationTimes, smudge state and length is included.
	 * <p>
	 * The format of the returned string is described with this BNF:
	 *
	 * <pre>
	 * result = ( "[" path mode stage? time? smudge? length? sha1? content? "]" )* .
	 * mode = ", mode:" number .
	 * stage = ", stage:" number .
	 * time = ", time:t" timestamp-index .
	 * smudge = "" | ", smudged" .
	 * length = ", length:" number .
	 * sha1 = ", sha1:" hex-sha1 .
	 * content = ", content:" blob-data .
	 * </pre>
	 *
	 * 'stage' is only presented when the stage is different from 0. All
	 * reported time stamps are mapped to strings like "t0", "t1", ... "tn". The
	 * smallest reported time-stamp will be called "t0". This allows to write
	 * assertions against the string although the concrete value of the time
	 * stamps is unknown.
	 *
	 * @param repo
	 *            the repository the index state should be determined for
	 * @param includedOptions
	 *            a bitmask constructed out of the constants {@link #MOD_TIME},
	 *            {@link #SMUDGE}, {@link #LENGTH}, {@link #CONTENT_ID} and
	 *            {@link #CONTENT} controlling which info is present in the
	 *            resulting string.
	 * @return a string encoding the index state
	 * @throws IllegalStateException
	 * @throws IOException
	 */
	public static String indexState(Repository repo, int includedOptions)
			throws IllegalStateException, IOException {
		DirCache dc = repo.readDirCache();
		StringBuilder sb = new StringBuilder();
		TreeSet<Instant> timeStamps = new TreeSet<>();

		// iterate once over the dircache just to collect all time stamps
		if (0 != (includedOptions & MOD_TIME)) {
			for (int i = 0; i < dc.getEntryCount(); ++i) {
				timeStamps.add(dc.getEntry(i).getLastModifiedInstant());
			}
		}

		// iterate again, now produce the result string
		for (int i=0; i<dc.getEntryCount(); ++i) {
			DirCacheEntry entry = dc.getEntry(i);
			sb.append("["+entry.getPathString()+", mode:" + entry.getFileMode());
			int stage = entry.getStage();
			if (stage != 0)
				sb.append(", stage:" + stage);
			if (0 != (includedOptions & MOD_TIME)) {
				sb.append(", time:t"+
						timeStamps.headSet(entry.getLastModifiedInstant())
								.size());
			}
			if (0 != (includedOptions & SMUDGE))
				if (entry.isSmudged())
					sb.append(", smudged");
			if (0 != (includedOptions & LENGTH))
				sb.append(", length:"
						+ Integer.toString(entry.getLength()));
			if (0 != (includedOptions & CONTENT_ID))
				sb.append(", sha1:" + ObjectId.toString(entry.getObjectId()));
			if (0 != (includedOptions & CONTENT)) {
				sb.append(", content:"
						+ new String(repo.open(entry.getObjectId(),
								Constants.OBJ_BLOB).getCachedBytes(), UTF_8));
			}
			if (0 != (includedOptions & ASSUME_UNCHANGED))
				sb.append(", assume-unchanged:"
						+ Boolean.toString(entry.isAssumeValid()));
			sb.append("]");
		}
		return sb.toString();
	}


	/**
	 * Creates a new empty bare repository.
	 *
	 * @return the newly created bare repository, opened for access. The
	 *         repository will not be closed in {@link #tearDown()}; the caller
	 *         is responsible for closing it.
	 * @throws IOException
	 *             the repository could not be created in the temporary area
	 */
	protected FileRepository createBareRepository() throws IOException {
		return createRepository(true /* bare */);
	}

	/**
	 * Creates a new empty repository within a new empty working directory.
	 *
	 * @return the newly created repository, opened for access. The repository
	 *         will not be closed in {@link #tearDown()}; the caller is
	 *         responsible for closing it.
	 * @throws IOException
	 *             the repository could not be created in the temporary area
	 */
	protected FileRepository createWorkRepository() throws IOException {
		return createRepository(false /* not bare */);
	}

	/**
	 * Creates a new empty repository.
	 *
	 * @param bare
	 *            true to create a bare repository; false to make a repository
	 *            within its working directory
	 * @return the newly created repository, opened for access. The repository
	 *         will not be closed in {@link #tearDown()}; the caller is
	 *         responsible for closing it.
	 * @throws IOException
	 *             the repository could not be created in the temporary area
	 * @since 5.3
	 */
	protected FileRepository createRepository(boolean bare)
			throws IOException {
		return createRepository(bare, false /* auto close */);
	}

	/**
	 * Creates a new empty repository.
	 *
	 * @param bare
	 *            true to create a bare repository; false to make a repository
	 *            within its working directory
	 * @param autoClose
	 *            auto close the repository in {@link #tearDown()}
	 * @return the newly created repository, opened for access
	 * @throws IOException
	 *             the repository could not be created in the temporary area
	 * @deprecated use {@link #createRepository(boolean)} instead
	 */
	@Deprecated
	public FileRepository createRepository(boolean bare, boolean autoClose)
			throws IOException {
		File gitdir = createUniqueTestGitDir(bare);
		FileRepository db = new FileRepository(gitdir);
		assertFalse(gitdir.exists());
		db.create(bare);
		if (autoClose) {
			addRepoToClose(db);
		}
		return db;
	}

	/**
	 * Adds a repository to the list of repositories which is closed at the end
	 * of the tests
	 *
	 * @param r
	 *            the repository to be closed
	 */
	public void addRepoToClose(Repository r) {
		toClose.add(r);
	}

	/**
	 * Creates a unique directory for a test
	 *
	 * @param name
	 *            a subdirectory
	 * @return a unique directory for a test
	 * @throws IOException
	 */
	protected File createTempDirectory(String name) throws IOException {
		File directory = new File(createTempFile(), name);
		FileUtils.mkdirs(directory);
		return directory.getCanonicalFile();
	}

	/**
	 * Creates a new unique directory for a test repository
	 *
	 * @param bare
	 *            true for a bare repository; false for a repository with a
	 *            working directory
	 * @return a unique directory for a test repository
	 * @throws IOException
	 */
	protected File createUniqueTestGitDir(boolean bare) throws IOException {
		String gitdirName = createTempFile().getPath();
		if (!bare)
			gitdirName += "/";
		return new File(gitdirName + Constants.DOT_GIT);
	}

	/**
	 * Allocates a new unique file path that does not exist.
	 * <p>
	 * Unlike the standard {@code File.createTempFile} the returned path does
	 * not exist, but may be created by another thread in a race with the
	 * caller. Good luck.
	 * <p>
	 * This method is inherently unsafe due to a race condition between creating
	 * the name and the first use that reserves it.
	 *
	 * @return a unique path that does not exist.
	 * @throws IOException
	 */
	protected File createTempFile() throws IOException {
		File p = File.createTempFile("tmp_", "", tmp);
		if (!p.delete()) {
			throw new IOException("Cannot obtain unique path " + tmp);
		}
		return p;
	}

	/**
	 * Run a hook script in the repository, returning the exit status.
	 *
	 * @param db
	 *            repository the script should see in GIT_DIR environment
	 * @param hook
	 *            path of the hook script to execute, must be executable file
	 *            type on this platform
	 * @param args
	 *            arguments to pass to the hook script
	 * @return exit status code of the invoked hook
	 * @throws IOException
	 *             the hook could not be executed
	 * @throws InterruptedException
	 *             the caller was interrupted before the hook completed
	 */
	protected int runHook(final Repository db, final File hook,
			final String... args) throws IOException, InterruptedException {
		final String[] argv = new String[1 + args.length];
		argv[0] = hook.getAbsolutePath();
		System.arraycopy(args, 0, argv, 1, args.length);

		final Map<String, String> env = cloneEnv();
		env.put("GIT_DIR", db.getDirectory().getAbsolutePath());
		putPersonIdent(env, "AUTHOR", author);
		putPersonIdent(env, "COMMITTER", committer);

		final File cwd = db.getWorkTree();
		final Process p = Runtime.getRuntime().exec(argv, toEnvArray(env), cwd);
		p.getOutputStream().close();
		p.getErrorStream().close();
		p.getInputStream().close();
		return p.waitFor();
	}

	private static void putPersonIdent(final Map<String, String> env,
			final String type, final PersonIdent who) {
		final String ident = who.toExternalString();
		final String date = ident.substring(ident.indexOf("> ") + 2);
		env.put("GIT_" + type + "_NAME", who.getName());
		env.put("GIT_" + type + "_EMAIL", who.getEmailAddress());
		env.put("GIT_" + type + "_DATE", date);
	}

	/**
	 * Create a string to a UTF-8 temporary file and return the path.
	 *
	 * @param body
	 *            complete content to write to the file. If the file should end
	 *            with a trailing LF, the string should end with an LF.
	 * @return path of the temporary file created within the trash area.
	 * @throws IOException
	 *             the file could not be written.
	 */
	protected File write(String body) throws IOException {
		final File f = File.createTempFile("temp", "txt", tmp);
		try {
			write(f, body);
			return f;
		} catch (Error | RuntimeException | IOException e) {
			f.delete();
			throw e;
		}
	}

	/**
	 * Write a string as a UTF-8 file.
	 *
	 * @param f
	 *            file to write the string to. Caller is responsible for making
	 *            sure it is in the trash directory or will otherwise be cleaned
	 *            up at the end of the test. If the parent directory does not
	 *            exist, the missing parent directories are automatically
	 *            created.
	 * @param body
	 *            content to write to the file.
	 * @throws IOException
	 *             the file could not be written.
	 */
	protected void write(File f, String body) throws IOException {
		JGitTestUtil.write(f, body);
	}

	/**
	 * Read a file's content
	 *
	 * @param f
	 *            the file
	 * @return the content of the file
	 * @throws IOException
	 */
	protected String read(File f) throws IOException {
		return JGitTestUtil.read(f);
	}

	private static String[] toEnvArray(Map<String, String> env) {
		final String[] envp = new String[env.size()];
		int i = 0;
		for (Map.Entry<String, String> e : env.entrySet())
			envp[i++] = e.getKey() + "=" + e.getValue();
		return envp;
	}

	private static HashMap<String, String> cloneEnv() {
		return new HashMap<>(System.getenv());
	}

	private static final class CleanupThread extends Thread {
		private static final CleanupThread me;
		static {
			me = new CleanupThread();
			Runtime.getRuntime().addShutdownHook(me);
		}

		static void deleteOnShutdown(File tmp) {
			synchronized (me) {
				me.toDelete.add(tmp);
			}
		}

		static void removed(File tmp) {
			synchronized (me) {
				me.toDelete.remove(tmp);
			}
		}

		private final List<File> toDelete = new ArrayList<>();

		@Override
		public void run() {
			// On windows accidentally open files or memory
			// mapped regions may prevent files from being deleted.
			// Suggesting a GC increases the likelihood that our
			// test repositories actually get removed after the
			// tests, even in the case of failure.
			System.gc();
			synchronized (this) {
				boolean silent = false;
				boolean failOnError = false;
				for (File tmp : toDelete)
					recursiveDelete(tmp, silent, failOnError);
			}
		}
	}
}
