/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.core.tests.formatter;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.URL;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import junit.framework.AssertionFailedError;
import junit.framework.ComparisonFailure;
import junit.framework.Test;
import junit.framework.TestSuite;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.formatter.CodeFormatter;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.core.tests.model.ModelTestsUtil;
import org.eclipse.jdt.core.tests.util.Util;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
import org.eclipse.jdt.internal.core.util.CodeSnippetParsingUtil;
import org.eclipse.jdt.internal.formatter.DefaultCodeFormatter;
import org.eclipse.jdt.internal.formatter.DefaultCodeFormatterOptions;
import org.eclipse.text.edits.TextEdit;

/**
 * Comment formatter test suite for massive tests at a given location.
 * <p>
 * This test suite has only one generic test. When running this test suite, one test
 * is created per compilation unit found while traversing the directory specified
 * using the <code>inputDir</code> system property<br>(e.g.
 * <code>-DinputDir=D:\eclipse\workspaces\formatter\inputs\full-src-30</code>).
 * </p><p>
 * Each test formats twice the compilation unit and compare the result to a
 * previous formatting already stored at the same location from a root directory
 * specified using the <code>outputDir</code> system property.
 * </p><p>
 * For example, if <code>outputDir</code> is set to the following value:<br>
 * <code>-DoutputDir=D:\eclipse\workspaces\formatter\outputs</code><br>
 * then a compilation unit found in <code>...\inputs\full-src-30\test\A.java</code>
 * will be compared with the previously stored output in:
 * <code>...\outputs\full-src-30\test\A.java</code>
 * </p><p>
 * To store the outputs on a specific input directory using a specific version,
 * then load a JDT/Core version in the workspace and run this test suite using
 * the following VM arguments:
 * <pre>
 * -DinputDir=D:\eclipse\workspaces\formatter\inputs\full-src-30
 * -DoutputDir=D:\eclipse\workspaces\formatter\outputs,clean
 * </pre>
 * Note the <code>clean</code> arguments added at the end of the outputDir
 * system property to signify that the formatter outputs must be cleaned and
 * stored.
 * </p><p>
 * The <code>logDir</code> system property can be set to tell the suite to
 * write the console output in a file located in the specified directory. That makes
 * the comparison between version and patches easier to do using the eclipse
 * file comparison...
 * </p><p><br>
 * <b>***************************************<br>
 * * Process to run massive tests against a patch *<br>
 * ***************************************</b>
 * <p>
 * Here is the full description of the process to run massive tests against a patch
 * using this test suite and all the compilation units of the JDT/Core performance
 * <b>full-source-R3_0.zip</b> file...
 * </p>
 * <h3>Set-up input directory</h3>
 * <p>
 * The test suite needs to know where are the sources which will be used
 * to massively test the formatter. To make it easy to set-up, only a root directory
 * is necessary. From there, all compilation units found while traversing the tree of
 * this directory will be used for the massive tests.
 * </p><p>
 * In our example, we will extract the content of the <b>full-source-R3_0.zip</b>
 * file located in the <b>org.eclipse.jdt.core.tests.performance</b> plugin
 * somewhere on our local disk... let's say in the
 * <b>D:\tmp\formatter\inputs\full-src-30</b> directory.
 * </p>
 * <h3>Create the output reference</h3>
 * <p>
 * The reference from which the patch output will be compared to while running
 * the massive test needs also to be created. To do this, a launch config
 * for the <code>FormatterMassiveRegressionTests</code> test suite is necessary.
 * </p><p>
 *  For example, create a launch config named
 * <b>FormatterMassiveRegressionTests (Eclipse 3.0 - clean)</b> with the
 * following VM arguments:
 * <pre>
 * -Xmx256M
 * -DinputDir=D:\tmp\formatter\inputs\full-src-30
 * -DoutputDir=D:\tmp\formatter\outputs,clean
 * -DlogDir=D:\tmp\formatter\log
 * </pre>
 * </p><p>
 * Load the last version of JDT/Core plugins (e.g. <code>v_B11</code>) and
 * launch this config...
 * </p><p>
 * When done, the console should have the following content:
 * <pre>
 * Get all files from D:\tmp\formatter\inputs\full-src-30...done
 * Deleting all files from D:\tmp\formatter\outputs\v37\full-src-30...done
 * Version   : v_B11
 * Profiles  : none!
 * Test date : 9/12/10 1:47 PM
 * Input dir : D:\tmp\formatter\inputs\full-src-30
 *             9950 java files to format...
 * Output dir: D:\tmp\formatter\outputs\v37\full-src-30
 *             CLEANED
 * </pre>
 * Looking at the output directory, it should contain the same folders tree than
 * the input one...
 * </p>
 * <h3>Create the log reference</h3>
 * <p>
 * The test suite log several problems which may occur while formatting a unit:
 * 	<ul>
 * 	<li>the file may have compilation errors preventing the formatter to proceed</li>
 * 	<li>there's no output while formatting</li>
 * 	<li>the output may be different while formatting twice</li>
 * 	<li>the output may be different while formatting twice but only by leading whitespaces</li>
 * 	<li>the output may be different while formatting twice but only by whitespaces</li>
 *	</ul>
 * </p><p>
 * Even with last version of the formatter, such problems may happen on one or
 * several tested compilation unit. So, it's important to know which are the existing
 * issues of the used formatter version (e.g. <code>v_B11</code> in our example...).
 * </p><p>
 * To do this, another launch config is necessary to run the massive tests of the
 * loaded JDT/Core version.
 * </p><p>
 *  For example, copy the previous launch config and rename it
 * <b>FormatterMassiveRegressionTests (Eclipse 3.0)</b>. Change the VM 
 * arguments as follows (<i>note that the <code>clean</code> has been removed
 * from the <code>outputDir</code> system property</i>):
 * <pre>
 * -Xmx256M
 * -DinputDir=D:\tmp\formatter\inputs\full-src-30
 * -DoutputDir=D:\tmp\formatter\outputs
 * -DlogDir=D:\tmp\formatter\log
 * </pre>
 * </p><p>
 * Launch the config...
 * </p><p>
 * The log file contains the console output but also the complete list of the units
 * on which problems were observed. As this run was done with the JDT/Core
 * version it can be considered as the reference for this version...
 * </p><p>
 * Note that for our example, the observed problems for <code>v_B11</code>
 * version while running massive tests on a Eclipse 3.0 performance workspace
 * (9951 units) are:
 * 	<ul>
 * 	<li>1 file has compilation errors which prevent the formatter to proceed!</li>
 * 	<li>4 files have different output while reformatting twice!</li>
 * 	<li>10 files have different output while reformatting twice but only by leading whitespaces!</li>
 * 	<li>4 files have different output while reformatting twice but only by whitespaces!</li>
 *	</ul>
 * </p>
 * <h3>Run the massive tests on the patch</h3>
 * <p>
 * As the setup has been done for the massive tests, it's now possible to test a
 * patch applied on the reference version (<code>v_B11</code>). For this, the
 * patch needs of course to be applied first and also the <b>buildnotes_jdt-core.html</b>
 * modified.
 * </p><p>
 * If the patch vXX of bug XXXXXX is about to be tested, then the line
 * <code>Patch vXX for bug XXXXXX</code> needs to be added at the
 * beginning of the first <b>What's new in this drop</b> section of the
 * <b>buildnotes_jdt-core.html</b> file, e.g.:
 * <pre>
 * &lt;h2&gt;What's new in this drop&lt;/h2&gt;
 * Patch v05 for bug 303519
 * &lt;ul&gt;
 * ...
 * </pre>
 * </p><p>
 * Launch the <b>FormatterMassiveRegressionTests (Eclipse 3.0)</b> config...
 * </p><p>
 * Like the previous run, the written log file contains the complete list of the units
 * on which problems were observed. Comparing this log file with the reference one
 * will show whether the patch implies behavior changes for the formatter or not.
 * </p>
 */
@SuppressWarnings({"rawtypes", "unchecked"})
public class FormatterMassiveRegressionTests extends FormatterRegressionTests {

	final File file;
	final IPath path;
	private DefaultCodeFormatterOptions preferences;

	// Directories
//	private final static File INPUT_DIR = new File(System.getProperty("inputDir"));
	private final File inputDir;
	private static File OUTPUT_DIR; // use static to minimize data consumption
	private static File WRITE_DIR;

	// Files
	final static String FILES_FILTER = System.getProperty("filesFilter");
	final static int FILES_FILTER_KIND;
	static {
		int kind = 0; // No filter
		if (FILES_FILTER != null) {
			int length = FILES_FILTER.length();
			int idxQM = FILES_FILTER.indexOf('?');
			int idxS = FILES_FILTER.indexOf('*');
			if (idxQM >= 0 && idxS >= 0) {
				kind = 4; // Pure pattern match
			} else if (idxQM >= 0) {
				while (idxQM < length && FILES_FILTER.charAt(idxQM) == '?') {
					idxQM++;
				}
				if (idxQM == length) {
					kind = 3; // Starts with + same length
				} else {
					kind = 4; // Pure pattern match
				}
			} else if (idxS >= 0) {
				while (idxS < length && FILES_FILTER.charAt(idxQM) == '*') {
					idxS++;
				}
				if (idxS == length) {
					kind = 2; // Starts with
				} else {
					kind = 4; // Pure pattern match
				}
			} else {
				kind = 1; // Equals
			}
		}
		FILES_FILTER_KIND = kind;
	}

	// Log
	private static File LOG_FILE;
	private static PrintStream LOG_STREAM;

	// Maintenance
	private static boolean MAINTENANCE = false;

	// Comparison
	private static boolean CLEAN = false;
	private static boolean CAN_COMPARE = true;
	private final boolean canCompare;
	private final int testIndex;

	// Cleaning
	private static boolean LIST = false;
	private final static Map MAX_FILES = new HashMap();

	// Formatting behavior
	final static int FORMAT_REPEAT  = Integer.parseInt(System.getProperty("repeat", "2"));
	private final static boolean NO_COMMENTS = System.getProperty("no_comments", "false").equals("true");
	private final static String JOIN_LINES = System.getProperty("join_lines", null);
	private final static String BRACES = System.getProperty("braces", null);
	private final static int PRESERVED_LINES;
	static {
		String str = System.getProperty("preserved_lines", null);
		int value = -1;
		if (str != null) {
			try {
				value = Integer.parseInt(str);
			}
			catch (NumberFormatException nfe) {
				// skip
			}
		}
		PRESERVED_LINES = value;
	}
	private final int profiles;
	private final static int PROFILE_NEVER_JOIN_LINES = 1;
	private final static int PROFILE_JOIN_LINES_ONLY_COMMENTS = 2;
	private final static int PROFILE_JOIN_LINES_ONLY_CODE = 3;
	private final static int PROFILE_JOIN_LINES_MASK = 0x0003;
	private final static int PROFILE_NO_COMMENTS = 1 << 2;
	private final static int PROFILE_BRACES_NEXT_LINE = 1 << 3;
	private final static int PROFILE_BRACES_NEXT_LINE_ON_WRAP = 2 << 3;
	private final static int PROFILE_BRACES_NEXT_LINE_SHIFTED = 3 << 3;
	private final static int PROFILE_BRACES_MASK = 0x0018;
	private final static int PROFILE_PRESERVED_LINES_MASK = 0x00E0;

	// Time measuring
	static class TimeMeasuring {
		long[] formatting = new long[FORMAT_REPEAT];
		int [] occurences = new int[FORMAT_REPEAT];
		int [] null_output = new int[FORMAT_REPEAT];
	}
	private static TimeMeasuring TIME_MEASURES;
	private static final int ONE_MINUTE = 60000;
	private static final long ONE_HOUR = 3600000L;

	// Failures management
	int failureIndex;
	final static int UNEXPECTED_FAILURE = 0;
	final static int NO_OUTPUT_FAILURE = 1;
	final static int COMPILATION_ERRORS_FAILURE = 2;
	final static int FILE_NOT_FOUND_FAILURE = 3;
	final static int COMPARISON_FAILURE = 4;
	final static int REFORMATTING_FAILURE = 5;
	final static int REFORMATTING_EXPECTED_FAILURE = 6;
	final static int REFORMATTING_LEADING_FAILURE = 7;
	final static int REFORMATTING_WHITESPACES_FAILURE = 8;
	static class FormattingFailure {
		String msg;
		int kind;
		List failures = new ArrayList();
		public FormattingFailure(int kind) {
			this.kind = kind;
        }
		public FormattingFailure(int kind, String msg) {
			this(kind);
	        this.msg = msg;
        }
		int size() {
			return this.failures.size();
		}
		public String toString() {
			switch (this.kind) {
				case  UNEXPECTED_FAILURE:
					return "unexpected failure while formatting";
				case  NO_OUTPUT_FAILURE:
					return "no output while formatting";
				case  COMPILATION_ERRORS_FAILURE:
					return "compilation errors which prevent the formatter to proceed";
				case  FILE_NOT_FOUND_FAILURE:
					return "no formatted output to compare with";
				case  COMPARISON_FAILURE:
					return "different output while comparing with previous version";
				default:
			        return "different output while "+this.msg;
			}
        }

	}
	static FormattingFailure[] FAILURES;
	private static final int MAX_FAILURES = Integer.parseInt(System.getProperty("maxFailures", "100")); // Max failures using string comparison
	private static boolean ASSERT_EQUALS_STRINGS = MAX_FAILURES > 0;
	private static String ECLIPSE_VERSION;
	private static String ECLIPSE_MILESTONE;
	private static String JDT_CORE_VERSION;
	private static String PATCH_BUG, PATCH_VERSION;
	private static String TEMP_OUTPUT;
	private static boolean JDT_CORE_HEAD;
	/*
	private final static IPath[] EXPECTED_FAILURES = INPUT_DIR.getPath().indexOf("v34") < 0
		? new IPath[] {
			new Path("org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java"),
			new Path("org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java"),
			new Path("org/eclipse/jdt/internal/core/DeltaProcessor.java"),
			new Path("org/eclipse/jdt/internal/core/JavaProject.java"),
			new Path("org/eclipse/jdt/internal/core/search/indexing/IndexManager.java"),
			new Path("org/eclipse/team/internal/ccvs/ui/AnnotateView.java"),
			new Path("org/eclipse/team/internal/ccvs/ui/HistoryView.java"),
			new Path("org/eclipse/team/internal/ccvs/ui/wizards/UpdateWizard.java"),
		}
		:	new IPath[] {
			// Eclipse
			new Path("org/eclipse/equinox/internal/p2/director/NewDependencyExpander.java"),
			new Path("org/eclipse/jdt/core/JavaCore.java"),
			new Path("org/eclipse/jdt/internal/codeassist/CompletionEngine.java"),
			new Path("org/eclipse/jdt/internal/codeassist/SelectionEngine.java"),
			new Path("org/eclipse/jdt/internal/compiler/ast/Expression.java"),
			new Path("org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java"),
			new Path("org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java"),
			new Path("org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java"),
			new Path("org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java"),
			new Path("org/eclipse/jdt/internal/compiler/batch/Main.java"),
			new Path("org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java"),
			new Path("org/eclipse/jdt/internal/core/CompilationUnit.java"),
			new Path("org/eclipse/jdt/internal/core/ExternalJavaProject.java"),
			new Path("org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java"),
			new Path("org/eclipse/jdt/internal/core/hierarchy/TypeHierarchy.java"),
			new Path("org/eclipse/jdt/internal/core/search/indexing/IndexAllProject.java"),
			new Path("org/eclipse/jdt/internal/core/search/JavaSearchScope.java"),
			new Path("org/eclipse/jdt/internal/eval/EvaluationContext.java"),
			new Path("org/eclipse/jdt/internal/ui/text/javadoc/JavadocContentAccess2.java"),
			new Path("org/eclipse/jdt/internal/apt/pluggable/core/filer/IdeJavaSourceOutputStream.java"),
			new Path("org/eclipse/team/internal/ccvs/ui/mappings/WorkspaceSubscriberContext.java"),
			// Ganymede
			new Path("com/ibm/icu/text/Collator.java"),
			new Path("org/apache/lucene/analysis/ISOLatin1AccentFilter.java"),
	};
	*/

public static Test suite() {
	return suite(new File(System.getProperty("inputDir")), buildProfileString(), new HashMap());
}

protected static Test suite(File inputDir, String profile, Map directories) {

	String name = "FormatterMassiveRegressionTests on "+inputDir.getName();
	if (profile != null && profile.length() > 0) {
		name += " " + profile;
	}
	TestSuite suite = new Suite(name);
	try {
		// Init version
		initVersion();

		// Init profiles
		int profiles = initProfiles(profile);

		// Init directories
		initDirectories(inputDir, profiles, true);

		// Get files from input dir
		FileFilter filter = new FileFilter() {
			public boolean accept(File pathname) {
				String path = pathname.getPath();
				if (pathname.isDirectory()) {
					String dirName = path.substring(path.lastIndexOf(File.separatorChar)+1);
					return !dirName.equals("bin");
				}
				if (path.endsWith(".java")) {
					if (FILES_FILTER_KIND > 0) {
						String fileName = path.substring(path.lastIndexOf(File.separatorChar)+1);
						switch (FILES_FILTER_KIND) {
							case 1: // Equals
								return fileName.equals(FILES_FILTER);
							case 2: // Starts with
								return fileName.startsWith(FILES_FILTER);
							case 3: // Starts with + same length
								return fileName.startsWith(FILES_FILTER) && fileName.length() == FILES_FILTER.length();
							case 4: // Pattern
								return fileName.matches(FILES_FILTER);
						}
					} else {
						return true;
					}
				}
				return false;
            }
		};
		File[] allFiles = (File[]) directories.get(inputDir);
		File listFile = new File(inputDir.getParentFile(), inputDir.getName()+".lst");
		BufferedWriter listFileWriter = null;
		if (allFiles == null) {
			System.out.print("Get all files from ");
			if (LIST || !listFile.exists()) {
				// Get the files list
				System.out.print(inputDir+"...");
				allFiles = ModelTestsUtil.getAllFiles(inputDir, filter);
				// Delete the files list
				if (listFile.exists()) {
					listFile.delete();
				}
				// Initialize the files list writer
				listFileWriter = new BufferedWriter(new FileWriter(listFile));
				listFileWriter.write(Integer.toString(allFiles.length));
				listFileWriter.newLine();
			} else {
				System.out.print("stored list in "+listFile.getPath()+"...");
				BufferedReader listFileReader = new BufferedReader(new InputStreamReader(new FileInputStream(listFile.getAbsolutePath())));
				try {
					// First line is the number of files
					String line = listFileReader.readLine();
					int maxFiles = Integer.parseInt(line);
					// Following lines are the files path
					allFiles = new File[maxFiles];
					for (int i=0; i<maxFiles; i++) {
						allFiles[i] = new File(inputDir, listFileReader.readLine());
						if (!allFiles[i].exists()) {
							throw new IOException("Cannot find file "+allFiles[i]);
						}
					}
				}
				catch (NumberFormatException nfe) {
					nfe.printStackTrace();
					return null;
				}
				catch (IOException ioe) {
					ioe.printStackTrace();
					return null;
				}
				finally {
					listFileReader.close();
				}
			}
			directories.put(inputDir, allFiles);
			System.out.println("done");
		}
		int[] maxFiles = new int[2];
		maxFiles[0] = allFiles.length;
		maxFiles[1] = (int) (Math.log(maxFiles[0])/Math.log(10));
		MAX_FILES.put(inputDir, maxFiles);

		// Add tests to clean the output directory and rebuild the references
//		if (CLEAN) {
//			suite.addTest(new FormatterMassiveRegressionTests(profiles));
//		}

		// Add one test per found file
		try {
			final int inputDirPathLength = inputDir.getPath().length()+1;
			for (int i=0; i<maxFiles[0]; i++) {
				if (CLEAN) {
					suite.addTest(new FormatterMassiveRegressionTests(inputDir, allFiles[i], i, profiles, false/*do not compare while cleaning*/));
				} else {
					suite.addTest(new FormatterMassiveRegressionTests(inputDir, allFiles[i], i, profiles, CAN_COMPARE));
				}
				if (listFileWriter != null) {
					listFileWriter.write(allFiles[i].getPath().substring(inputDirPathLength));
					listFileWriter.newLine();
				}
			}
		}
		finally {
			if (listFileWriter != null) {
				listFileWriter.close();
			}
		}
    } catch (Exception e) {
    	e.printStackTrace();
    }
	return suite;
}

private static String buildProfileString() {
	boolean hasProfile = NO_COMMENTS || PRESERVED_LINES != -1;
	if (JOIN_LINES != null) {
	 	if (JOIN_LINES.equals("never") ||
	 		JOIN_LINES.equals("only_comments") ||
	 		JOIN_LINES.equals("only_code")) {
	 		hasProfile = true;
	 	}
	}
	if (BRACES != null) {
	 	if (BRACES.equals(DefaultCodeFormatterConstants.NEXT_LINE) ||
	 		BRACES.equals(DefaultCodeFormatterConstants.NEXT_LINE_ON_WRAP) ||
	 		BRACES.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
	 		hasProfile = true;
	 	}
	}
	String builtProfile = null;
	if (hasProfile) {
		StringBuffer buffer = new StringBuffer();
		String separator = "";
		if (JOIN_LINES != null) {
			buffer.append("join_lines="+JOIN_LINES);
			separator = ",";
		}
		if (NO_COMMENTS) {
			buffer.append(separator+"no_comments=true");
			separator = ",";
		}
		if (BRACES != null) {
			buffer.append(separator+"braces="+BRACES);
			separator = ",";
		}
		if (PRESERVED_LINES != -1) {
			buffer.append(separator+"preserved_lines="+PRESERVED_LINES);
			separator = ",";
		}
		builtProfile = buffer.toString();
	}

	// Return built profile string
	return builtProfile;
}

private static int initProfiles(String profile) {
	if (profile == null || profile.length() == 0) return 0;
	StringTokenizer tokenizer = new StringTokenizer(profile, ",");
	int profiles = 0;
	while (tokenizer.hasMoreTokens()) {
		String token = tokenizer.nextToken();
		int idx = token.indexOf('=');
		if (idx <= 0) {
			System.err.println("'"+profile+"' is not a valid profile!!!");
			return 0;
		}
		String profileName = token.substring(0, idx);
		if (profileName.equals("join_lines")) {
			String joinLines = token.substring(idx+1);
		 	if (joinLines.equals("never")) {
		 		profiles += PROFILE_NEVER_JOIN_LINES;
		 	} else if (joinLines.equals("only_comments")) {
		 		profiles += PROFILE_JOIN_LINES_ONLY_COMMENTS;
		 	} else if (joinLines.equals("only_code")) {
		 		profiles += PROFILE_JOIN_LINES_ONLY_CODE;
			}
		} else if (profileName.equals("no_comments")) {
			String noComments = token.substring(idx+1);
		 	if (noComments.equals(DefaultCodeFormatterConstants.TRUE)) {
	 			profiles |= PROFILE_NO_COMMENTS;
		 	}
		} else if (profileName.equals("braces")) {
			String braces = token.substring(idx+1);
		 	if (braces.equals(DefaultCodeFormatterConstants.NEXT_LINE)) {
		 		profiles += PROFILE_BRACES_NEXT_LINE;
		 	} else if (braces.equals(DefaultCodeFormatterConstants.NEXT_LINE_ON_WRAP)) {
		 		profiles += PROFILE_BRACES_NEXT_LINE_ON_WRAP;
		 	} else if (braces.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
		 		profiles += PROFILE_BRACES_NEXT_LINE_SHIFTED;
		 	}
		} else if (profileName.equals("preserved_lines")) {
			try {
				String lines = token.substring(idx+1);
	 			int value = Integer.parseInt(lines);
	 			if (value >= 0 && value < 8) {
		 			profiles += value << 5;
	 			}
		 	}
			catch (NumberFormatException nfe) {
				// skip
			}
		}
	}
	return profiles;
}

private static void initDirectories(File inputDir, int profiles, boolean verify) {

	// Verify input directory
	if (!inputDir.exists() && !inputDir.isDirectory()) {
		System.err.println(inputDir+" does not exist or is not a directory!");
		System.exit(1);
	}

	// Get output dir and clean it if specified
	String dir = System.getProperty("outputDir"); //$NON-NLS-1$
	if (dir != null) {
		StringTokenizer tokenizer = new StringTokenizer(dir, ",");
		String outputDir = tokenizer.nextToken();
		while (tokenizer.hasMoreTokens()) {
			String token = tokenizer.nextToken();
			if (token.equals("clean")) {
				CLEAN = true;
			} else if (token.equals("maintenance")) {
				MAINTENANCE = true;
			} else if (token.equals("list")) {
				LIST = true;
			} else {
				TEMP_OUTPUT = token;
			}
		}
		setOutputDir(inputDir, outputDir, profiles);
		if (CLEAN) {
			if ((PATCH_BUG != null || JDT_CORE_HEAD) && TEMP_OUTPUT == null) {
				System.err.println("Reference can only be updated using a version (i.e. with a closed buildnotes_jdt-core.html)!");
				System.exit(1);
			}
			return;
		} else if (!OUTPUT_DIR.exists()) {
			System.err.println("            WARNING: The output directory "+OUTPUT_DIR+" does not exist...");
			System.err.println("            => NO comparison could be done!");
			CAN_COMPARE = false;
		}
		try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // skip
        }
	}

	// Get log dir
	try {
		setLogDir(inputDir, profiles, verify);
	} catch (CoreException e) {
		e.printStackTrace();
	}

	// Get write dir
	String wdir = System.getProperty("writeDir"); //$NON-NLS-1$
	if (wdir != null) {
		WRITE_DIR = new File(wdir);
		if (WRITE_DIR.exists()) {
			Util.delete(WRITE_DIR);
		}
		WRITE_DIR.mkdirs();
	}
}

private static void setLogDir(File inputDir, int profiles, boolean verify) throws CoreException {

	// Compute log dir
	File rootLogDir = new File(System.getProperty("logDir"));
	if (!rootLogDir.exists()) {
		if (!rootLogDir.mkdirs()) {
			System.err.println("Cannot create specified log directory: "+rootLogDir+"!!!");
			return;
		}
	}

	// Compute log sub-directories depending on version
	rootLogDir = new File(rootLogDir, ECLIPSE_VERSION);
	String subRootDir;
	if (PATCH_BUG != null) {
		rootLogDir = new File(rootLogDir, "tests");
		rootLogDir = new File(rootLogDir, PATCH_BUG);
		subRootDir = PATCH_VERSION;
	} else if (JDT_CORE_HEAD) {
		subRootDir = "HEAD";
	} else {
		rootLogDir = new File(rootLogDir, ECLIPSE_MILESTONE);
		subRootDir = JDT_CORE_VERSION;
	}

	// Compute log sub-directories depending on profiles
	List subDirs = new ArrayList();
	if (profiles > 0) {
		subDirs.add("profiles");
		setProfilesDir(profiles, subDirs);
	}

	if (FILES_FILTER_KIND > 0) {
		subDirs.add("filter");
		subDirs.add(FILES_FILTER.replace('?', '_').replace('*', '%'));
	}

	// Create log stream
	File logDir = createDir(new File (rootLogDir, subRootDir), subDirs);
	String filePrefix = inputDir.getName().replaceAll("\\.", "");
	String logFileName = filePrefix+".txt";
	LOG_FILE = new File(logDir, logFileName);
	if (verify && LOG_FILE.exists()) {
		File saveDir = new File(new File(rootLogDir, "save"), subRootDir);
		saveDir.mkdirs();
		int i=0;
		while (true) {
			String dirN = Integer.toString(i);
			if (i<10) dirN = "0" + dirN;
			saveDir = new File(saveDir, dirN);
			logDir = createDir(saveDir, subDirs);
			File renamedFile = new File(logDir, logFileName);
			if (LOG_FILE.renameTo(renamedFile)) break;
			i++;
		}
	}
//	LOG_RESOURCE = folder.getFile(logFileName);
	try {
		LOG_STREAM = new PrintStream(new BufferedOutputStream(new FileOutputStream(LOG_FILE)));
		LOG_STREAM.flush();
	}
	catch (FileNotFoundException fnfe) {
		System.err.println("Can't create log file"+LOG_FILE); //$NON-NLS-1$
	}
//	if (LOG_RESOURCE.exists()) {
//		Util.delete(LOG_RESOURCE);
//	}
//	LOG_BUFFER = new StringBuffer();
}

private static File createDir(File rootDir, List subDirs) {
	File dir = rootDir;
	for (int i=0, s=subDirs.size(); i<s; i++) {
		dir = new File (dir, (String) subDirs.get(i));
	}
	dir.mkdirs();
	return dir;
}

private static File setProfilesDir(int profiles, File dir) {
	List subDirs = new ArrayList();
	setProfilesDir(profiles, subDirs);
	return createDir(dir, subDirs);
}

private static void setProfilesDir(int profiles, List subDirs) {
	String joinLines = null;
	switch (profiles & PROFILE_JOIN_LINES_MASK) {
		case PROFILE_NEVER_JOIN_LINES:
			joinLines = "never";
			break;
		case PROFILE_JOIN_LINES_ONLY_COMMENTS:
			joinLines = "only_comments";
			break;
		case PROFILE_JOIN_LINES_ONLY_CODE:
			joinLines = "only_code";
			break;
	}
	if (joinLines != null) {
		subDirs.add("join_lines");
		subDirs.add(joinLines);
	}
	if ((profiles & PROFILE_NO_COMMENTS) != 0) {
		subDirs.add("no_comments");
	}
	String braces = null;
	switch (profiles & PROFILE_BRACES_MASK) {
		case PROFILE_BRACES_NEXT_LINE:
			braces = DefaultCodeFormatterConstants.NEXT_LINE;
			break;
		case PROFILE_BRACES_NEXT_LINE_ON_WRAP:
			braces = DefaultCodeFormatterConstants.NEXT_LINE_ON_WRAP;
			break;
		case PROFILE_BRACES_NEXT_LINE_SHIFTED:
			braces = DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED;
			break;
	}
	if (braces != null) {
		subDirs.add("braces");
		subDirs.add(braces);
	}
	if ((profiles & PROFILE_PRESERVED_LINES_MASK) != 0) {
		int lines = (profiles & PROFILE_PRESERVED_LINES_MASK) >> 5;
		subDirs.add("preserved_lines");
		subDirs.add(Integer.toString(lines));
	}
}

private static void appendProfiles(int profiles, StringBuffer buffer) {
	String joinLines = null;
	boolean first = true;
	switch (profiles & PROFILE_JOIN_LINES_MASK) {
		case PROFILE_NEVER_JOIN_LINES:
			joinLines = "never";
			break;
		case PROFILE_JOIN_LINES_ONLY_COMMENTS:
			joinLines = "only_comments";
			break;
		case PROFILE_JOIN_LINES_ONLY_CODE:
			joinLines = "only_code";
			break;
	}
	if (joinLines != null) {
		buffer.append("join_lines=");
		buffer.append(joinLines);
		first = false;
	}
	if ((profiles & PROFILE_NO_COMMENTS) != 0) {
		if (!first) buffer.append(',');
		buffer.append("no_comments");
		first = false;
	}
	String braces = null;
	switch (profiles & PROFILE_BRACES_MASK) {
		case PROFILE_BRACES_NEXT_LINE:
			braces = DefaultCodeFormatterConstants.NEXT_LINE;
			break;
		case PROFILE_BRACES_NEXT_LINE_ON_WRAP:
			braces = DefaultCodeFormatterConstants.NEXT_LINE_ON_WRAP;
			break;
		case PROFILE_BRACES_NEXT_LINE_SHIFTED:
			braces = DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED;
			break;
	}
	if (braces != null) {
		if (!first) buffer.append(',');
		buffer.append("braces=");
		buffer.append(braces);
		first = false;
	}
	if ((profiles & PROFILE_PRESERVED_LINES_MASK) != 0) {
		int lines = (profiles & PROFILE_PRESERVED_LINES_MASK) >> 5;
		if (!first) buffer.append(',');
		buffer.append("preserved_lines=");
		buffer.append(lines);
		first = false;
	}
	if (first) {
		buffer.append("none!");
	}
}

private static void setOutputDir(File inputDir, String dir, int profiles) {

	// Find the root of the output directory
	OUTPUT_DIR = new File(dir);
	if (OUTPUT_DIR.getName().equals(inputDir.getName())) {
		OUTPUT_DIR = OUTPUT_DIR.getParentFile();
	}
	if (OUTPUT_DIR.getName().equals(ECLIPSE_VERSION)) {
		OUTPUT_DIR = OUTPUT_DIR.getParentFile();
	}

	// Add the temporary output if any
	if (TEMP_OUTPUT != null) {
		StringTokenizer tokenizer = new StringTokenizer(TEMP_OUTPUT, "/");
		while (tokenizer.hasMoreTokens()) {
			OUTPUT_DIR = new File(OUTPUT_DIR, tokenizer.nextToken());
		}
	}

	// Compute output sub-directories depending on profiles
	if (profiles > 0) {
		OUTPUT_DIR = new File(OUTPUT_DIR, "profiles");
		OUTPUT_DIR = setProfilesDir(profiles, OUTPUT_DIR);
	}

	// Compute the final output dir
	File parent = new File(OUTPUT_DIR, ECLIPSE_VERSION);
	if (MAINTENANCE) {
		try {
			int version = Integer.parseInt(ECLIPSE_VERSION.substring(1));
			File maintenance = new File(OUTPUT_DIR, "v"+(version-1));
			if (maintenance.exists()) {
				parent = maintenance;
			}
		}
		catch (NumberFormatException nfe) {
			// skip
		}
	}
	OUTPUT_DIR = new File(parent, inputDir.getName());
}

private static void initFailures() {
	FAILURES = new FormattingFailure[REFORMATTING_WHITESPACES_FAILURE+1];
	for (int i=UNEXPECTED_FAILURE; i<=COMPARISON_FAILURE; i++) {
		FAILURES[i] = new FormattingFailure(i);
	}
	FAILURES[REFORMATTING_FAILURE] = new FormattingFailure(REFORMATTING_FAILURE, "reformatting twice");
	FAILURES[REFORMATTING_LEADING_FAILURE] = new FormattingFailure(REFORMATTING_LEADING_FAILURE, "reformatting twice but only by leading whitespaces");
	FAILURES[REFORMATTING_WHITESPACES_FAILURE] = new FormattingFailure(REFORMATTING_WHITESPACES_FAILURE, "reformatting twice but only by whitespaces");
	FAILURES[REFORMATTING_EXPECTED_FAILURE] = new FormattingFailure(REFORMATTING_EXPECTED_FAILURE, "reformatting twice but was expected");
}

/*
 * Read JDT/Core build notes file to see what version is currently running.
 */
private static void initVersion() {
	if (JDT_CORE_VERSION == null) {
		BufferedReader buildnotesReader;
	    try {
			URL platformURL = Platform.getBundle("org.eclipse.jdt.core").getEntry("/");
			String path = new File(FileLocator.toFileURL(platformURL).getFile(), "buildnotes_jdt-core.html").getAbsolutePath();
		    buildnotesReader = new BufferedReader(new InputStreamReader(new FileInputStream(path)));
	    } catch (IOException ioe) {
		    ioe.printStackTrace();
		    return;
	    }
		String line;
		JDT_CORE_HEAD = true;
		try {
			while ((line = buildnotesReader.readLine()) != null) {
				if (line.startsWith("<a name=\"")) {
					boolean first = JDT_CORE_VERSION == null;
					JDT_CORE_VERSION = line.substring(line.indexOf('"')+1, line.lastIndexOf('"'));
					if (!first) break;
				} else if (line.startsWith("Eclipse SDK ")) {
					StringTokenizer tokenizer = new StringTokenizer(line);
					tokenizer.nextToken(); // 'Eclipse'
					tokenizer.nextToken(); // 'SDK'
					String milestone = tokenizer.nextToken();
					ECLIPSE_VERSION = "v"+milestone.charAt(0)+milestone.charAt(2);
					ECLIPSE_MILESTONE = milestone.substring(3);
					tokenizer.nextToken(); // '-'
					JDT_CORE_HEAD = tokenizer.nextToken().equals("%date%");
				} else if (line.startsWith("<h2>What's new")) {
					line = buildnotesReader.readLine();
					if (line.startsWith("Patch")) {
						StringTokenizer tokenizer = new StringTokenizer(line);
						tokenizer.nextToken(); // 'Patch'
						PATCH_VERSION = tokenizer.nextToken();
						while (tokenizer.hasMoreTokens()) {
							PATCH_BUG = tokenizer.nextToken();
						}
						try {
							Integer.parseInt(PATCH_BUG);
						}
						catch (NumberFormatException nfe) {
							// try to split
							StringTokenizer bugTokenizer = new StringTokenizer(PATCH_BUG, "+");
							try {
								while (bugTokenizer.hasMoreTokens()) {
									Integer.parseInt(bugTokenizer.nextToken());
								}
							}
							catch (NumberFormatException nfe2) {
								System.err.println("Invalid patch bug number noticed in JDT/Core buildnotes: "+PATCH_BUG);
							}
						}
					}
					if (!JDT_CORE_HEAD) break;
				}
			}
		} catch (Exception e) {
			try {
		        buildnotesReader.close();
	        } catch (IOException ioe) {
		        ioe.printStackTrace();
	        }
		}
	}
}

/*
 * Constructor used to clean the output directory.
 *
public FormatterMassiveRegressionTests(int profiles) {
	super("testDeleteOutputDir");
	this.canCompare = false;
	this.file = null;
	this.inputDir = OUTPUT_DIR;
	this.testIndex = -1;
	this.profiles = profiles;
	this.path = new Path(OUTPUT_DIR.getPath());
}

/*
 * Constructor used to dump references in the output directory.
 *
public FormatterMassiveRegressionTests(File[] files) {
	super("testMakeReferences");
	assertNotNull("This test needs some files to proceed!", files);
	this.canCompare = false;
	this.file = null;
	this.inputFiles = files;
	this.testIndex = -1;
	this.path = new Path(OUTPUT_DIR.getPath());
}

/*
 * Contructor used to compare outputs.
 */
public FormatterMassiveRegressionTests(File inputDir, File file, int index, int profiles, boolean compare) {
	super(CLEAN ? "testReference" : "testCompare");
	this.canCompare = compare;
	this.file = file;
	this.inputDir = inputDir;
	this.testIndex = index;
	this.profiles = profiles;
	this.path = new Path(file.getPath().substring(inputDir.getPath().length()+1));
}

/* (non-Javadoc)
 * @see junit.framework.TestCase#getName()
 */
public String getName() {
	StringBuffer name = new StringBuffer(super.getName());
	if (this.testIndex >= 0) {
		int n = this.testIndex == 0 ? 0 : (int) (Math.log(this.testIndex)/Math.log(10));
		int max = ((int[])MAX_FILES.get(this.inputDir))[1];
		for (int i=n; i<max; i++) {
			name.append('0');
		}
		name.append(this.testIndex);
	}
	if (this.profiles > 0) {
		name.append('_');
		name.append(this.profiles);
	}
	name.append(" - ");
	name.append(this.path);
	return name.toString();
}

/* (non-Javadoc)
 * @see org.eclipse.jdt.core.tests.formatter.FormatterRegressionTests#setUpSuite()
 */
public void setUp() throws Exception {
	super.setUp();

	// Setup preferences
	this.preferences = DefaultCodeFormatterOptions.getEclipseDefaultSettings();

	// Setup no comments profile
	if ((this.profiles & PROFILE_NO_COMMENTS) != 0) {
		this.preferences.comment_format_javadoc_comment = false;
		this.preferences.comment_format_block_comment = false;
		this.preferences.comment_format_line_comment = false;
	}

	// Setup join lines profile
	String joinLines = null;
	switch (this.profiles & PROFILE_JOIN_LINES_MASK) {
		case PROFILE_NEVER_JOIN_LINES:
			joinLines = "never";
			break;
		case PROFILE_JOIN_LINES_ONLY_COMMENTS:
			joinLines = "only_comments";
			break;
		case PROFILE_JOIN_LINES_ONLY_CODE:
			joinLines = "only_code";
			break;
	}
	if (joinLines != null) {
		if (!joinLines.equals("only_comments")) {
			this.preferences.join_lines_in_comments = false;
		}
		if (!joinLines.equals("only_code")) {
			this.preferences.join_wrapped_lines = false;
		}
	}

	// Setup braces profile
	String braces = null;
	switch (this.profiles & PROFILE_BRACES_MASK) {
		case PROFILE_BRACES_NEXT_LINE:
			braces = DefaultCodeFormatterConstants.NEXT_LINE;
			break;
		case PROFILE_BRACES_NEXT_LINE_ON_WRAP:
			braces = DefaultCodeFormatterConstants.NEXT_LINE_ON_WRAP;
			break;
		case PROFILE_BRACES_NEXT_LINE_SHIFTED:
			braces = DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED;
			break;
	}
	if (braces != null) {
		this.preferences.brace_position_for_annotation_type_declaration = braces;
		this.preferences.brace_position_for_anonymous_type_declaration = braces;
		this.preferences.brace_position_for_array_initializer = braces;
		this.preferences.brace_position_for_block = braces;
		this.preferences.brace_position_for_block_in_case = braces;
		this.preferences.brace_position_for_constructor_declaration = braces;
		this.preferences.brace_position_for_enum_constant = braces;
		this.preferences.brace_position_for_enum_declaration = braces;
		this.preferences.brace_position_for_method_declaration = braces;
		this.preferences.brace_position_for_switch = braces;
		this.preferences.brace_position_for_type_declaration = braces;
	}

	// Setup preserved lines profile
	if ((this.profiles & PROFILE_PRESERVED_LINES_MASK) != 0) {
		int lines = (this.profiles & PROFILE_PRESERVED_LINES_MASK) >> 5;
		this.preferences.number_of_empty_lines_to_preserve = lines;
	}
}

/* (non-Javadoc)
 * @see org.eclipse.jdt.core.tests.formatter.FormatterRegressionTests#setUpSuite()
 */
public void setUpSuite() throws Exception {

	// Init directories
	initDirectories(this.inputDir, this.profiles, false);

	// Delete output dir before compute reference
	if (CLEAN) {
		System.out.print("Deleting all files from "+OUTPUT_DIR+"...");
		Util.delete(OUTPUT_DIR);
		System.out.println("done");
	}
	// Init failure
	else if (this.canCompare) {
		initFailures();
	}

	// Dump the version
	if (CLEAN) {
		File versionFile = new Path(OUTPUT_DIR.getPath()).append("version.txt").toFile();
		OUTPUT_DIR.mkdirs();
		String version = JDT_CORE_VERSION;
		if (TEMP_OUTPUT != null) {
				version += " + " + TEMP_OUTPUT;
			if (PATCH_BUG != null) {
				version += " " + PATCH_VERSION + " of " + PATCH_BUG;
			}
		}
		Util.writeToFile(version, versionFile.getAbsolutePath());
	}

	// Init time measuring
	TIME_MEASURES = new TimeMeasuring();

	// Print
	print();
}

private void print() {

	StringBuffer buffer = new StringBuffer();

	// Log version info
	buffer.append("Version   : ");
	if (PATCH_BUG != null) {
		buffer.append("'Patch ");
		buffer.append(PATCH_VERSION);
		buffer.append(" for bug ");
		buffer.append(PATCH_BUG);
		buffer.append("' applied on ");
	}
	if (JDT_CORE_HEAD) {
		buffer.append("HEAD on top of ");
	}
	buffer.append(JDT_CORE_VERSION);
	buffer.append(LINE_SEPARATOR);

	// Profiles
	buffer.append("Profiles  : ");
	appendProfiles(this.profiles, buffer);
	buffer.append(LINE_SEPARATOR);

	// Log date of test
	long start = System.currentTimeMillis();
	SimpleDateFormat format = new SimpleDateFormat();
	Date now = new Date(start);
	buffer.append("Test date : ");
	buffer.append(format.format(now));
	buffer.append(LINE_SEPARATOR);

	// Input dir
	buffer.append("Input dir : ");
	buffer.append(this.inputDir);
	buffer.append(LINE_SEPARATOR);

	// Files
	buffer.append("            ");
	int[] maxFiles = (int[]) MAX_FILES.get(this.inputDir);
	buffer.append(maxFiles[0]);
	buffer.append(" java files to format...");

	// Flush to console to show startup
	String firstBuffer = buffer.toString();
	System.out.println(firstBuffer);

	// Output dir
	buffer.setLength(0);
	buffer.append("Output dir: ");
	buffer.append(OUTPUT_DIR);
	buffer.append(LINE_SEPARATOR);
	if (CLEAN) {
		buffer.append("            CLEANED");
		buffer.append(LINE_SEPARATOR);
	}

	// Log dir
	if (LOG_FILE != null) {
		buffer.append("Log file  : ");
		buffer.append(LOG_FILE);
		buffer.append(LINE_SEPARATOR);
	}

	// Write dir
	if (WRITE_DIR != null) {
		buffer.append("Write dir : ");
		buffer.append(WRITE_DIR);
		buffer.append(LINE_SEPARATOR);
	}

	// Comparison
	if (CAN_COMPARE) {
		if (!CLEAN) {
			buffer.append("Compare vs: ");
			File versionFile = new File(OUTPUT_DIR, "version.txt");
			if (versionFile.exists()) {
				String fileContent = Util.fileContent(versionFile.getAbsolutePath());
				if (TEMP_OUTPUT != null) {
					buffer.append(TEMP_OUTPUT);
					buffer.append(" on top of ");
				}
				buffer.append(fileContent);
			} else {
				buffer.append("???");
			}
		}
	} else {
		buffer.append("Compare vs: none");
	}
	buffer.append(LINE_SEPARATOR);

	// Write logs
	System.out.println(buffer.toString());
	if (LOG_STREAM != null) {
		LOG_STREAM.println(firstBuffer);
		LOG_STREAM.println(buffer.toString());
		LOG_STREAM.flush();
	}
}

/* (non-Javadoc)
 * @see org.eclipse.jdt.core.tests.formatter.FormatterRegressionTests#tearDown()
 */
public void tearDown() throws Exception {
	// verify whether the max failures has been reached or not
	if (ASSERT_EQUALS_STRINGS && FAILURES != null) {
		ASSERT_EQUALS_STRINGS = FAILURES[COMPARISON_FAILURE].size() < MAX_FAILURES;
	}
}

/* (non-Javadoc)
 * @see org.eclipse.jdt.core.tests.formatter.FormatterRegressionTests#tearDownSuite()
 */
public void tearDownSuite() throws Exception {

	// Display time measures
	StringBuffer buffer1 = new StringBuffer();
	if (CLEAN) {
//		buffer1.append(" cannot be done as the directory was cleaned!");
//		buffer1.append(LINE_SEPARATOR);
		return;
	} else {
		buffer1.append("Time measures:");
		buffer1.append(LINE_SEPARATOR);
		for (int i=0; i<FORMAT_REPEAT; i++) {
			buffer1.append("	- "+counterToString(i+1)).append(" format:").append(LINE_SEPARATOR);
			buffer1.append("		+ elapsed = "+timeString(TIME_MEASURES.formatting[i])).append(LINE_SEPARATOR);
			buffer1.append("		+ occurrences = "+TIME_MEASURES.occurences[i]).append(LINE_SEPARATOR);
			buffer1.append("		+ null output = "+TIME_MEASURES.null_output[i]).append(LINE_SEPARATOR);
		}
	}
	buffer1.append(LINE_SEPARATOR);

	// Display stored failures
	int max = FAILURES.length;
	for (int i=0; i<max; i++) {
		List failures = FAILURES[i].failures;
		int size = failures.size();
		if (size > 0) {
			buffer1.append(size);
			buffer1.append(" file");
			if (size == 1) {
				buffer1.append(" has ");
			} else {
				buffer1.append("s have ");
			}
			buffer1.append(FAILURES[i]);
			buffer1.append('!');
			buffer1.append(LINE_SEPARATOR);
		}
	}
	buffer1.append(LINE_SEPARATOR);
	StringBuffer buffer2 = new StringBuffer(LINE_SEPARATOR);
	for (int i=0; i<max; i++) {
		List failures = FAILURES[i].failures;
		int size = failures.size();
		if (size > 0) {
			buffer2.append("List of file(s) with ");
			buffer2.append(FAILURES[i]);
			buffer2.append(':');
			buffer2.append(LINE_SEPARATOR);
			for (int j=0; j<size; j++) {
				buffer2.append("	- ");
				buffer2.append(failures.get(j));
				buffer2.append(LINE_SEPARATOR);
			}
		}
	}

	// Log failures
	System.out.println(buffer1.toString());
	if (LOG_STREAM == null) {
		System.out.println(buffer2.toString());
	} else {
		LOG_STREAM.print(buffer1.toString());
		LOG_STREAM.print(buffer2.toString());
		LOG_STREAM.close();
	}
//	LOG_BUFFER.append(buffer1.toString());
//	LOG_BUFFER.append(buffer2.toString());
//	InputStream stream= new InputStream() {
//		private Reader reader= new StringReader(LOG_BUFFER.toString());
//		public int read() throws IOException {
//			return this.reader.read();
//		}
//	};
//	if (LOG_RESOURCE.exists()) {
//		LOG_RESOURCE.setContents(
//			stream,
//			IResource.FORCE | IResource.KEEP_HISTORY,
//			null);
//	} else {
//		LOG_RESOURCE.create(stream, IResource.FORCE, null);
//	}
}

/*
 * Asserts that the given actual source (usually coming from a file content) is equal to the expected one.
 * Note that 'expected' is assumed to have the '\n' line separator.
 * The line separators in 'actual' are converted to '\n' before the comparison.
 */
protected void assertSourceEquals(String message, String expected, String actual) {
	if (expected == null) {
		assertNull(message, actual);
		return;
	}
	if (actual == null) {
		assertEquals(message, expected, null);
		return;
	}
	expected = Util.convertToIndependantLineDelimiter(expected);
	actual = Util.convertToIndependantLineDelimiter(actual);
	if (ASSERT_EQUALS_STRINGS) {
		assertEquals(message, expected, actual);
	} else {
		assertTrue(message, actual.equals(expected));
	}
}

DefaultCodeFormatter codeFormatter() {
	DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(this.preferences, getDefaultCompilerOptions());
	return codeFormatter;
}

void compareFormattedSource() throws IOException, Exception {
	String source = new String(org.eclipse.jdt.internal.compiler.util.Util.getFileCharContent(this.file, null));
	String actualResult = null;
	try {
		// Format the source
		actualResult = runFormatter(codeFormatter(), source, CodeFormatter.K_COMPILATION_UNIT | CodeFormatter.F_INCLUDE_COMMENTS, 0, 0, source.length(), null, true);

		// Look for output to compare with
		File outputFile = new Path(OUTPUT_DIR.getPath()).append(this.path).toFile();
		if (actualResult != null && FAILURES != null && this.canCompare) {
			try {
				String expectedResult = new String(org.eclipse.jdt.internal.compiler.util.Util.getFileCharContent(outputFile, null));
				assertSourceEquals("Unexpected format output!", expectedResult, actualResult);
			}
			catch (FileNotFoundException fnfe) {
				this.failureIndex = FILE_NOT_FOUND_FAILURE;
				FAILURES[FILE_NOT_FOUND_FAILURE].failures.add(this.path);
				return;
			}
			catch (ComparisonFailure cf) {
				this.failureIndex = COMPARISON_FAILURE;
				throw cf;
			}
			catch (AssertionFailedError afe) {
				this.failureIndex = COMPARISON_FAILURE;
				throw afe;
			}
		}
	}
	catch (Exception e) {
//		System.err.println(e.getMessage()+" occurred in "+getName());
		throw e;
	}
	finally {
		// Write file
		if (actualResult != null) {
			if (WRITE_DIR != null) {
				File writtenFile = new Path(WRITE_DIR.getPath()).append(this.path).toFile();
				writtenFile.getParentFile().mkdirs();
				Util.writeToFile(actualResult, writtenFile.getAbsolutePath());
			}
		}
	}
}

private String counterToString(int count) {
	int reminder = count%10;
	StringBuffer buffer = new StringBuffer();
	buffer.append(count);
	switch (reminder) {
		case 1:
			buffer.append("st");
			break;
		case 2:
			buffer.append("nd");
			break;
		case 3:
			buffer.append("rd");
			break;
		default:
			buffer.append("th");
			break;
	}
	return buffer.toString();
}

private Map getDefaultCompilerOptions() {
	Map optionsMap = new HashMap(30);
	optionsMap.put(CompilerOptions.OPTION_LocalVariableAttribute, CompilerOptions.DO_NOT_GENERATE);
	optionsMap.put(CompilerOptions.OPTION_LineNumberAttribute, CompilerOptions.DO_NOT_GENERATE);
	optionsMap.put(CompilerOptions.OPTION_SourceFileAttribute, CompilerOptions.DO_NOT_GENERATE);
	optionsMap.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.PRESERVE);
	optionsMap.put(CompilerOptions.OPTION_DocCommentSupport, CompilerOptions.DISABLED);
	optionsMap.put(CompilerOptions.OPTION_ReportMethodWithConstructorName, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportOverridingPackageDefaultMethod, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportOverridingMethodWithoutSuperInvocation, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode, CompilerOptions.DISABLED);
	optionsMap.put(CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, CompilerOptions.DISABLED);
	optionsMap.put(CompilerOptions.OPTION_ReportHiddenCatchBlock, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportUnusedParameter, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportUnusedImport, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportSyntheticAccessEmulation, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportNoEffectAssignment, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportNonExternalizedStringLiteral, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportNoImplicitStringConversion, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportIndirectStaticAccess, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportIncompatibleNonInheritedInterfaceMethod, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportLocalVariableHiding, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportFieldHiding, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportPossibleAccidentalBooleanAssignment, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportEmptyStatement, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportAssertIdentifier, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportEnumIdentifier, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportUndocumentedEmptyBlock, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportInvalidJavadoc, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility, CompilerOptions.PUBLIC);
	optionsMap.put(CompilerOptions.OPTION_ReportInvalidJavadocTags, CompilerOptions.DISABLED);
	optionsMap.put(CompilerOptions.OPTION_ReportMissingJavadocTagDescription, CompilerOptions.RETURN_TAG);
	optionsMap.put(CompilerOptions.OPTION_ReportInvalidJavadocTagsDeprecatedRef, CompilerOptions.DISABLED);
	optionsMap.put(CompilerOptions.OPTION_ReportInvalidJavadocTagsNotVisibleRef, CompilerOptions.DISABLED);
	optionsMap.put(CompilerOptions.OPTION_ReportMissingJavadocTags, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility, CompilerOptions.PUBLIC);
	optionsMap.put(CompilerOptions.OPTION_ReportMissingJavadocTagsOverriding, CompilerOptions.DISABLED);
	optionsMap.put(CompilerOptions.OPTION_ReportMissingJavadocComments, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportMissingJavadocCommentsVisibility, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportMissingJavadocCommentsOverriding, CompilerOptions.DISABLED);
	optionsMap.put(CompilerOptions.OPTION_ReportFinallyBlockNotCompletingNormally, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportUnusedDeclaredThrownException, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_ReportUnusedDeclaredThrownExceptionWhenOverriding, CompilerOptions.DISABLED);
	optionsMap.put(CompilerOptions.OPTION_ReportUnqualifiedFieldAccess, CompilerOptions.IGNORE);
	optionsMap.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_6);
	optionsMap.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
	optionsMap.put(CompilerOptions.OPTION_TaskTags, ""); //$NON-NLS-1$
	optionsMap.put(CompilerOptions.OPTION_TaskPriorities, ""); //$NON-NLS-1$
	optionsMap.put(CompilerOptions.OPTION_TaskCaseSensitive, CompilerOptions.DISABLED);
	optionsMap.put(CompilerOptions.OPTION_ReportUnusedParameterWhenImplementingAbstract, CompilerOptions.DISABLED);
	optionsMap.put(CompilerOptions.OPTION_ReportUnusedParameterWhenOverridingConcrete, CompilerOptions.DISABLED);
	optionsMap.put(CompilerOptions.OPTION_ReportSpecialParameterHidingField, CompilerOptions.DISABLED);
	optionsMap.put(CompilerOptions.OPTION_MaxProblemPerUnit, String.valueOf(100));
	optionsMap.put(CompilerOptions.OPTION_InlineJsr, CompilerOptions.DISABLED);
	optionsMap.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_6);
	return optionsMap;
}

/*
private boolean isExpectedFailure() {
	int length = EXPECTED_FAILURES.length;
	for (int i=0; i<length; i++) {
		IPath expectedFailure= EXPECTED_FAILURES[i];
		if (this.path.toString().indexOf(expectedFailure.toString()) >= 0) {
			this.failureIndex = REFORMATTING_EXPECTED_FAILURE;
			FAILURES[REFORMATTING_EXPECTED_FAILURE].failures.add(this.path);
			return true;
		}
	}
	return false;
}
*/

/*
private boolean runFormatterWithoutComments(CodeFormatter codeFormatter, String source, int kind, int indentationLevel, int offset, int length, String lineSeparator) {
	DefaultCodeFormatterOptions preferencesWithoutComment = DefaultCodeFormatterOptions.getEclipseDefaultSettings();
	preferencesWithoutComment.comment_format_line_comment = false;
	preferencesWithoutComment.comment_format_block_comment = false;
	preferencesWithoutComment.comment_format_javadoc_comment = false;
	DefaultCodeFormatter codeFormatterWithoutComment = new DefaultCodeFormatter(preferencesWithoutComment);

	TextEdit edit = codeFormatterWithoutComment.format(kind, source, offset, length, indentationLevel, lineSeparator);//$NON-NLS-1$
	if (edit == null) return false;
	String initialResult = org.eclipse.jdt.internal.core.util.Util.editedString(source, edit);

	int count = 1;
	String result = initialResult;
	String previousResult = result;
	while (count++ < FORMAT_REPEAT) {
		edit = codeFormatterWithoutComment.format(kind, result, 0, result.length(), indentationLevel, lineSeparator);//$NON-NLS-1$
		if (edit == null) return false;
		previousResult = result;
		result = org.eclipse.jdt.internal.core.util.Util.editedString(result, edit);
	}
	return previousResult.equals(result);
}
*/

private boolean sourceHasCompilationErrors(String source) {
	CodeSnippetParsingUtil codeSnippetParsingUtil = new CodeSnippetParsingUtil();
	codeSnippetParsingUtil.parseCompilationUnit(source.toCharArray(), getDefaultCompilerOptions(), true);
	if (codeSnippetParsingUtil.recordedParsingInformation != null) {
		CategorizedProblem[] problems = codeSnippetParsingUtil.recordedParsingInformation.problems;
		int length = problems == null ? 0 : problems.length;
		for (int i=0; i<length; i++) {
			if (((DefaultProblem)problems[i]).isError()) {
				return true;
			}
		}
	}
	return false;
}

String runFormatter(CodeFormatter codeFormatter, String source, int kind, int indentationLevel, int offset, int length, String lineSeparator, boolean repeat) {
	long timeStart = System.currentTimeMillis();
	TextEdit edit = codeFormatter.format(kind, source, offset, length, indentationLevel, lineSeparator);
	if (FAILURES != null) { // Comparison has started
		TIME_MEASURES.formatting[0] += System.currentTimeMillis() - timeStart;
		TIME_MEASURES.occurences[0]++;
		if (edit == null) TIME_MEASURES.null_output[0]++;
	}
	if (edit == null) {
		if (sourceHasCompilationErrors(source)) {
			this.failureIndex = COMPILATION_ERRORS_FAILURE;
			FAILURES[COMPILATION_ERRORS_FAILURE].failures.add(this.path);
			return null;
		}
		this.failureIndex = NO_OUTPUT_FAILURE;
		throw new AssertionFailedError("Formatted source should not be null!");
	}
	String initialResult = org.eclipse.jdt.internal.core.util.Util.editedString(source, edit);

	int count = 0;
	String result = initialResult;
	String previousResult = result;
	while (++count < FORMAT_REPEAT) {
		timeStart = System.currentTimeMillis();
		edit = codeFormatter.format(kind, result, 0, result.length(), indentationLevel, lineSeparator);
		if (FAILURES != null) { // Comparison has started
			TIME_MEASURES.formatting[count] += System.currentTimeMillis() - timeStart;
			TIME_MEASURES.occurences[count]++;
			if (edit == null) TIME_MEASURES.null_output[count]++;
		}
		if (edit == null) return null;
		previousResult = result;
		result = org.eclipse.jdt.internal.core.util.Util.editedString(result, edit);
	}
	if (!previousResult.equals(result)) {

		if (FAILURES != null) {
			// Try to compare without leading spaces
			String trimmedExpected = ModelTestsUtil.trimLinesLeadingWhitespaces(previousResult);
			String trimmedActual= ModelTestsUtil.trimLinesLeadingWhitespaces(result);
			if (trimmedExpected.equals(trimmedActual)) {
				this.failureIndex = REFORMATTING_LEADING_FAILURE;
				FAILURES[REFORMATTING_LEADING_FAILURE].failures.add(this.path);
				return initialResult;
			}

			// Try to compare without spaces at all
			if (ModelTestsUtil.removeWhiteSpace(previousResult).equals(ModelTestsUtil.removeWhiteSpace(result))) {
				this.failureIndex = REFORMATTING_WHITESPACES_FAILURE;
				FAILURES[REFORMATTING_WHITESPACES_FAILURE].failures.add(this.path);
				return initialResult;
			}
		}

		/*
		// Try to see if the formatting also fails without comments
		if (!runFormatterWithoutComments(null, source, kind, indentationLevel, offset, length, lineSeparator)) {
			return initialResult;
		}

		// format without comments is OK => there's a problem with comment formatting
		String counterString = counterToString(count-1);
		assertSourceEquals(counterString+" formatting is different from first one!", previousResult, result);
		*/
//		if (!isExpectedFailure()) {
			String counterString = counterToString(count);
			try {
				assertSourceEquals(counterString+" formatting is different from first one!", previousResult, result);
			}
			catch (ComparisonFailure cf) {
				this.failureIndex = REFORMATTING_FAILURE;
				throw cf;
			}
			catch (AssertionFailedError afe) {
				this.failureIndex = REFORMATTING_FAILURE;
				throw afe;
			}
//		}
	}
	return initialResult;
}

/**
 * Returns a string to display the given time as a duration
 * formatted as:
 *	<ul>
 *	<li>"XXXms" if the duration is less than 0.1s (e.g. "543ms")</li>
 *	<li>"X.YYs" if the duration is less than 1s (e.g. "5.43s")</li>
 *	<li>"XX.Ys" if the duration is less than 1mn (e.g. "54.3s")</li>
 *	<li>"XXmn XXs" if the duration is less than 1h (e.g. "54mn 3s")</li>
 *	<li>"XXh XXmn XXs" if the duration is over than 1h (e.g. "5h 4mn 3s")</li>
 *	</ul>
 *
 * @param time The time to format as a long.
 * @return The formatted string.
 */
public String timeString(long time) {
	NumberFormat format = NumberFormat.getInstance();
	format.setMaximumFractionDigits(3);
	StringBuffer buffer = new StringBuffer();
	if (time == 0) {
		// print nothing
	} else {
		long h = time / ONE_HOUR;
		if (h > 0) buffer.append(h).append("h "); //$NON-NLS-1$
		long remaining = time % ONE_HOUR;
		long m = remaining / ONE_MINUTE;
		if (h > 0 || m > 0) buffer.append(m).append("mn "); //$NON-NLS-1$
		remaining = remaining % ONE_MINUTE;
		if ((remaining % 1000) == 0) {
			buffer.append(remaining/1000);
		} else {
			buffer.append(format.format(remaining/1000.0));
		}
		buffer.append("s"); //$NON-NLS-1$
	}
	return buffer.toString();
}

/*
 * Test to delete the output directory.
 *
public void testDeleteOutputDir() throws IOException, Exception {
	Util.delete(this.inputDir);
}

/*
 * Test to fill the output directory with reference.
 */
public void testReference() throws IOException, Exception {

	// Dump the version
//	if (this.testIndex == 0) {
//		File versionFile = new Path(OUTPUT_DIR.getPath()).append("version.txt").toFile();
//		OUTPUT_DIR.mkdirs();
//		Util.writeToFile(JDT_CORE_VERSION, versionFile.getAbsolutePath());
//	}

	// Get the source from file
	String source = new String(org.eclipse.jdt.internal.compiler.util.Util.getFileCharContent(this.file, null));
	try {
		// Format the source
		TextEdit edit = codeFormatter().format(CodeFormatter.K_COMPILATION_UNIT | CodeFormatter.F_INCLUDE_COMMENTS, source, 0, source.length(), 0, null);

		// Write the result
		if (edit != null) {
			String formatResult = org.eclipse.jdt.internal.core.util.Util.editedString(source, edit);
			String inputPath = this.file.getPath().substring(this.inputDir.getPath().length()+1);
			File writtenFile = new Path(OUTPUT_DIR.getPath()).append(inputPath).toFile();
			writtenFile.getParentFile().mkdirs();
			Util.writeToFile(formatResult, writtenFile.getAbsolutePath());
		}
	}
	catch (Exception ex) {
		// skip silently
	}
}

/*
 * Test to compare the formatter output with an existing file.
 */
public void testCompare() throws IOException, Exception {
	try {
		compareFormattedSource();
	}
	catch (ComparisonFailure cf) {
		if (this.failureIndex == -1) {
			FAILURES[UNEXPECTED_FAILURE].failures.add(this.path);
		} else {
			FAILURES[this.failureIndex].failures.add(this.path);
		}
		throw cf;
	}
	catch (AssertionFailedError afe) {
		if (this.failureIndex == -1) {
			FAILURES[UNEXPECTED_FAILURE].failures.add(this.path);
		} else {
			FAILURES[this.failureIndex].failures.add(this.path);
		}
		throw afe;
	}
	catch (Exception ex) {
		FAILURES[UNEXPECTED_FAILURE].failures.add(this.path);
		throw ex;
	}
}
}
