/*******************************************************************************
 * Copyright (c) 2000, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.core.tests.performance;

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;

import junit.framework.Test;

import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
import org.eclipse.jdt.internal.compiler.SourceElementParser;
import org.eclipse.jdt.internal.compiler.SourceElementRequestorAdapter;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.batch.CompilationUnit;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.parser.Scanner;
import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.util.Util;
import org.eclipse.test.performance.Performance;

/**
 * Class to test compiler performance.
 * This includes tests on build, batch compiler, Scanner and Parser.
 */
public class FullSourceWorkspaceBuildTests extends FullSourceWorkspaceTests {
	
	// Tests counters
	private static int TESTS_COUNT = 0;
	private final static int ITERATIONS_COUNT = 10;
	private final static int SCAN_REPEAT = 800; // 800 is default

	// Tests thresholds
	private final static int TIME_THRESHOLD = 150;
	
	// Log files
	private static PrintStream[] LOG_STREAMS = new PrintStream[LOG_TYPES.length];

	
	/**
	 * @param name
	 */
	public FullSourceWorkspaceBuildTests(String name) {
		super(name);
	}

	static {
//		TESTS_PREFIX = "testPerfBatch";
//		TESTS_NAMES = new String[] { "testBatchCompilerAllWarnings" };
	}

	public static Test suite() {
		Test suite = buildSuite(testClass());
		TESTS_COUNT = suite.countTestCases();
		createPrintStream(testClass(), LOG_STREAMS, TESTS_COUNT, null);
		return suite;
	}

	private static Class testClass() {
		return FullSourceWorkspaceBuildTests.class;
	}

	/*
	 * Parse several times a file giving its name.
	 */
	private long[] parseFile(String fileName, int kind, int iterations) throws InvalidInputException, IOException {

		// Test for parser
		File file = new File(fileName);
		char[] content = Util.getFileCharContent(file, null);
		CompilerOptions options = new CompilerOptions();
		options.sourceLevel = ClassFileConstants.JDK1_4;
		options.targetJDK = ClassFileConstants.JDK1_4;
		ProblemReporter problemReporter = 
				new ProblemReporter(
					DefaultErrorHandlingPolicies.exitAfterAllProblems(), 
					options, 
					new DefaultProblemFactory());
		
		// Create parser
        Parser parser = null;
		switch (kind) {
		case 1: // SourceElementParser
				parser = new SourceElementParser(new SourceElementRequestorAdapter(), problemReporter.problemFactory, options, true, true);
				break;
			default:
				parser = new Parser(problemReporter, true);
				break;
		}

		// Warm up
		for (int i = 0; i < 2; i++) {
			ICompilationUnit unit = new CompilationUnit(content, file.getName(), null);
			CompilationResult unitResult = new CompilationResult(unit, 0, 1, options.maxProblemsPerUnit);				
			CompilationUnitDeclaration unitDeclaration = parser.dietParse(unit, unitResult);
			parser.getMethodBodies(unitDeclaration);
		}

		// Clean memory
		runGc();

		// Measures
		long parsedLines = 0;
		long parsedCharacters = 0;
		long start = 0;
		if (DEBUG) {
			start = System.currentTimeMillis();
		}
		startMeasuring();
		for (int i = 0; i < iterations; i++) {
			ICompilationUnit unit = new CompilationUnit(content, file.getName(), null);
			CompilationResult unitResult = new CompilationResult(unit, 0, 1, options.maxProblemsPerUnit);				
			CompilationUnitDeclaration unitDeclaration = parser.dietParse(unit, unitResult);
			parser.getMethodBodies(unitDeclaration);
			parsedCharacters += content.length;
			parsedLines += unitResult.getLineSeparatorPositions().length;
		}
		stopMeasuring();

		// Warn if measure time is not enough while debugging
		if (DEBUG) {
			long time = System.currentTimeMillis() - start;
			if (time < TIME_THRESHOLD) {
	            System.err.println(parsedLines + " lines/"+ parsedCharacters + " characters parsed");
			} else {
	            System.out.println(parsedLines + " lines/"+ parsedCharacters + " characters parsed");
			}
		}

		// Return stats
		return new long[] { parsedCharacters, parsedLines };
	}

	/*
	 * Test performance for a parser on one file.
	 * Parse is executed many times ({@link #ITERATIONS_COUNT}) to have significant time for execution.
	 * This test is repeated several times ({@link #MEASURES_COUNT}) to average time measuring.
	 *  
	 * @throws InvalidInputException
	 * @throws IOException
	 */
	void parseParserFile(int kind) throws InvalidInputException, IOException {

		// Get workspace path
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		final IWorkspaceRoot workspaceRoot = workspace.getRoot();
		final String targetWorkspacePath = workspaceRoot.getProject(JavaCore.PLUGIN_ID)
			.getLocation()
			.toFile()
			.getCanonicalPath();
		
		// Run test
		for (int i=0; i<MEASURES_COUNT; i++) {
			parseFile(targetWorkspacePath+"/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java", kind, ITERATIONS_COUNT*6);
		}

		// dump measure
		commitMeasurements();
		assertPerformance();
	}

	/*
	 * Scan a file giving its name.
	 * Two kind of scan is currently possible:
	 * 	- 0: only scan all tokens
	 * 	- 1: scan all tokens and get each identifier
	 */
	private void scanFile(String fileName, int kind) throws InvalidInputException, IOException {

		// Test for scanner
		long tokenCount = 0;
		char[] content = Util.getFileCharContent(new File(fileName),
			null);
		Scanner scanner = new Scanner();
		scanner.setSource(content);

		// Warm up
		for (int i = 0; i < 2; i++) {
			scanner.resetTo(0, content.length);
			tokenize: while (true) {
				int token = scanner.getNextToken();
				switch (kind) {
					case 0: // first case: only read tokens
						switch (token) {
							case TerminalTokens.TokenNameEOF:
								break tokenize;
						}
						break;
					case 1: // second case: read tokens + get ids
						switch (token) {
							case TerminalTokens.TokenNameEOF:
								break tokenize;
							case TerminalTokens.TokenNameIdentifier:
								scanner.getCurrentIdentifierSource();
								break;
						}
						break;
				}
			}
		}

		// Clean memory
		runGc();

		// Measures
		long size = 0;
		for (int i = 0; i < MEASURES_COUNT; i++) {
			startMeasuring();
			for (int j = 0; j < SCAN_REPEAT; j++) {
				scanner.resetTo(0, content.length);
				tokenize: while (true) {
					int token = scanner.getNextToken();
					switch (kind) {
						case 0: // first case: only read tokens
							switch (token) {
								case TerminalTokens.TokenNameEOF:
									break tokenize;
							}
							break;
						case 1: // second case: read tokens + get ids
							switch (token) {
								case TerminalTokens.TokenNameEOF:
									break tokenize;
								case TerminalTokens.TokenNameIdentifier:
									char[] c = scanner.getCurrentIdentifierSource();
									size += c.length;
									break;
							}
							break;
					}
					tokenCount++;
				}
			}
			stopMeasuring();
		}

		// Commit
		commitMeasurements();
		assertPerformance();

		// Debug
		if (DEBUG) {
			switch (kind) {
				case 0:
					System.out.println(tokenCount + " tokens read.");
					break;
				case 1:
					System.out.print(tokenCount + " tokens were read ("+size+" characters)");
					break;
			}
		}
	}

	/* (non-Javadoc)
	 * @see junit.framework.TestCase#tearDown()
	 */
	protected void tearDown() throws Exception {

		// End of execution => one test less
		TESTS_COUNT--;

		// Log perf result
		if (LOG_DIR != null) {
			logPerfResult(LOG_STREAMS, TESTS_COUNT);
		}
		
		// Call super at the end as it close print streams
		super.tearDown();
	}

	/**
	 * Full build with no warning.
	 * 
	 * Not calling tagAsSummary means that this test is currently evaluated
	 * before put it in builds performance results.
	 * 
	 * @throws CoreException
	 * @throws IOException
	 */
	public void testFullBuildNoWarning() throws CoreException, IOException {
		tagAsSummary("Compile>Build>Clean>Full>No warning", false); // do NOT put in fingerprint
		setComment(Performance.EXPLAINS_DEGRADATION_COMMENT, "J2SE 5.0 support");
		startBuild(warningOptions(-1/*no warning*/), false);
	}

	/**
	 * Full build with JavaCore default options.
	 * 
	 * @throws CoreException
	 * @throws IOException
	 */
	public void testFullBuildDefault() throws CoreException, IOException {
		tagAsGlobalSummary("Compile>Build>Clean>Full>Default warnings", true); // put in fingerprint
		setComment(Performance.EXPLAINS_DEGRADATION_COMMENT, "J2SE 5.0 support + additional warnings (e.g. validate unused local and private members)");
		startBuild(warningOptions(0/*default warnings*/), false);
	}

	/**
	 * Full build with all warnings.
	 * 
	 * Not calling tagAsSummary means that this test is currently evaluated
	 * before put it in builds performance results.
	 * 
	 * @throws CoreException
	 * @throws IOException
	 * 
	 */
	public void testFullBuildAllWarnings() throws CoreException, IOException {
		tagAsSummary("Compile>Build>Clean>Full>All warnings", false); // do NOT put in fingerprint
		setComment(Performance.EXPLAINS_DEGRADATION_COMMENT, "J2SE 5.0 support");
		startBuild(warningOptions(1/*all warnings*/), false);
	}

	/**
	 * Batch compiler build with no warning
	 * 
	 * Not calling tagAsSummary means that this test is currently evaluated
	 * before put it in builds performance results.
	 * 
	 * @throws IOException
	 */
	public void testBatchCompilerNoWarning() throws IOException {
		tagAsSummary("Compile>Batch>Compiler>No warning", true); // put in fingerprint
		setComment(Performance.EXPLAINS_DEGRADATION_COMMENT, "J2SE 5.0 support");
		buildUsingBatchCompiler("-nowarn");
	}

	/**
	 * Batch compiler build with default warnings
	 * 
	 * Not calling tagAsSummary means that this test is currently evaluated
	 * before put it in builds performance results.
	 * 
	 * @throws IOException
	 */
	public void testBatchCompilerDefault() throws IOException {
		tagAsSummary("Compile>Batch>Compiler>Default warnings", false); // do NOT put in fingerprint
		setComment(Performance.EXPLAINS_DEGRADATION_COMMENT, "J2SE 5.0 support");
		buildUsingBatchCompiler("");
	}

	/**
	 * Batch compiler build with default javadoc warnings
	 * 
	 * Not calling tagAsSummary means that this test is currently evaluated
	 * before put it in builds performance results.
	 * 
	 * @throws IOException
	 */
	public void testBatchCompilerJavadoc() throws IOException {
		tagAsSummary("Compile>Batch>Compiler>Javadoc warnings", false); // do NOT put in fingerprint
		setComment(Performance.EXPLAINS_DEGRADATION_COMMENT, "J2SE 5.0 support");
		buildUsingBatchCompiler("-warn:javadoc");
	}

	/**
	 * Batch compiler build with invalid javadoc warnings
	 * 
	 * Not calling tagAsSummary means that this test is currently evaluated
	 * before put it in builds performance results.
	 * 
	 * @throws IOException
	 */
	// TODO (frederic) put back after having understood why this test result can have variation over 20%
	public void _testBatchCompilerAllJavadoc() throws IOException {
		tagAsSummary("Compile>Batch>Compiler>All Javadoc warnings", false); // do NOT put in fingerprint
		setComment(Performance.EXPLAINS_DEGRADATION_COMMENT, "J2SE 5.0 support");
		buildUsingBatchCompiler("-warn:allJavadoc");
	}

	/**
	 * Batch compiler build with all warnings
	 * 
	 * Not calling tagAsSummary means that this test is currently evaluated
	 * before put it in builds performance results.
	 * 
	 * @throws IOException
	 */
	public void testBatchCompilerAllWarnings() throws IOException {
		tagAsSummary("Compile>Batch>Compiler>All warnings", false); // do NOT put in fingerprint

		String allOptions = "-warn:" +
			"allDeprecation," +
			"allJavadoc," +
			"assertIdentifier," +
			"charConcat," +
			"conditionAssign," +
			"constructorName," +
			"deprecation," +
			"emptyBlock," +
			"fieldHiding," +
			"finally," +
			"indirectStatic," +
			"intfNonInherited," +
			"localHiding," +
			"maskedCatchBlock," +
			"nls," +
			"noEffectAssign," +
			"pkgDefaultMethod," +
			"semicolon," +
			"unqualifiedField," +
			"unusedArgument," +
			"unusedImport," +
			"unusedLocal," +
			"unusedPrivate," +
			"unusedThrown," +
			"unnecessaryElse," +
			"uselessTypeCheck," +
			"specialParamHiding," +
			"staticReceiver," +
			"syntheticAccess," +
			"tasks(TODO|FIX|XXX)";
		setComment(Performance.EXPLAINS_DEGRADATION_COMMENT, "J2SE 5.0 support");
		buildUsingBatchCompiler(allOptions);
	}

	/**
	 * Test performance for Scanner on one file.
	 * Scan is executed many times ({@link #SCAN_REPEAT}) to have significant time for execution.
	 * This test is repeated several times ({@link #ITERATIONS_COUNT}) to average time measuring.
	 *  
	 * @throws InvalidInputException
	 * @throws IOException
	 */
	public void testScanner() throws InvalidInputException, IOException {
		// Do no longer print result in performance fingerprint
		tagAsSummary("Compile>Scan>Parser>Default", true); // put in fingerprint

		// Get workspace path
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		final IWorkspaceRoot workspaceRoot = workspace.getRoot();
		final String targetWorkspacePath = workspaceRoot.getProject(JavaCore.PLUGIN_ID)
			.getLocation()
			.toFile()
			.getCanonicalPath();
		
		// Run test
//		scanFile(targetWorkspacePath+"/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java", 0/*only scan tokens*/);
		scanFile(targetWorkspacePath+"/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java", 1/*scan tokens+get identifiers*/);
	}

	/**
	 * Test performance for Parser on one file.
	 * Parse is executed many times ({@link #ITERATIONS_COUNT}) to have significant time for execution.
	 * This test is repeated several times ({@link #MEASURES_COUNT}) to average time measuring.
	 *  
	 * @throws InvalidInputException
	 * @throws IOException
	 */
	public void testParser() throws InvalidInputException, IOException {
		tagAsSummary("Compile>Parse>Parser>Default", true); // put in fingerprint
		parseParserFile(0); // Parser kind
	}

	/**
	 * Test performance for SourceElementParser on one file.
	 * Parse is executed many times ({@link #ITERATIONS_COUNT}) to have significant time for execution.
	 * This test is repeated several times ({@link #MEASURES_COUNT}) to average time measuring.
	 * 
	 * Note: This test has been temporarily removed as there's unexplicable difference between
	 * HEAD and 3.0 versions for CPU Time results (10% faster) and Elapsed process (25% slower)...
	 * TODO (frederic) Put back when platform-releng will have stabilized performance results process.
	 *  
	 * @throws InvalidInputException
	 * @throws IOException
	 */
	public void _testSourceParser() throws InvalidInputException, IOException {
		tagAsSummary("Compile>SrcParse>Parser>Default", true); // put in fingerprint
		parseParserFile(1); // SourceElementParser kind
	}
}
