/*******************************************************************************
 * Copyright (c) 2000, 2009 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.PrintStream;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;

import junit.framework.Test;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.search.*;
import org.eclipse.jdt.core.tests.model.AbstractJavaModelTests;
import org.eclipse.jdt.internal.core.search.processing.IJob;
import org.eclipse.test.performance.Performance;

/**
 */
public class FullSourceWorkspaceSearchTests extends FullSourceWorkspaceTests implements IJavaSearchConstants {

	// Tests counters
	private static int TESTS_COUNT = 0;
	private final static int ITERATIONS_COUNT = 10;
	private final static int WARMUP_COUNT = 4;

	// Log file streams
	private static PrintStream[] LOG_STREAMS = new PrintStream[DIM_NAMES.length];

	// Formats
	private final static NumberFormat INT_FORMAT = NumberFormat.getIntegerInstance();

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

	static {
//		org.eclipse.jdt.internal.core.search.processing.JobManager.VERBOSE = true;
//		TESTS_NAMES = new String[] {
//			"testIndexing",
//			"testIndexingOneProject",
//			"testSearchAllTypeNames",
//			"testNewSearchAllTypeNames",
//			"testSearchAllTypeNameMatches",
//		};
	}
	/*
	 * Specific way to build test suite.
	 * We need to know whether test perf indexing is in list to allow
	 * index manager disabling.
	 * CAUTION: If test perf indexing is not included in test suite,
	 * then time for other tests may include time spent to index files!
	 */
	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 FullSourceWorkspaceSearchTests.class;
	}

	protected void setUp() throws Exception {
		super.setUp();
	}
	/* (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);
		}
		super.tearDown();
	}
	/**
	 * Simple search result collector: only count matches.
	 */
	class JavaSearchResultCollector extends SearchRequestor {
		int count = 0;
		public void acceptSearchMatch(SearchMatch match) throws CoreException {
			this.count++;
		}
	}
	static int SEARCH_ALL_TYPE_NAMES_COUNT = -1;
	/**
	 * Simple type name requestor: only count classes and interfaces.
	 * @deprecated
	 */
	class OldSearchTypeNameRequestor implements ITypeNameRequestor {
		int count = 0;
		public void acceptClass(char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path){
			this.count++;
		}
		public void acceptInterface(char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path){
			this.count++;
		}
	}
	/**
	 * Simple type name requestor: only count classes and interfaces.
	 */
	class SearchTypeNameRequestor extends TypeNameRequestor {
		int count = 0;
		public void acceptType(int modifiers, char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path) {
			this.count++;
		}
	}
	/**
	 * Simple type name requestor: only count classes and interfaces.
	 */
	class SearchTypeNameMatchRequestor extends TypeNameMatchRequestor {
		int count = 0;
		public void acceptTypeNameMatch(TypeNameMatch match) {
			this.count++;
		}
	}
	/**
	 * Job to measure times in same thread than index manager.
	 */
	class	 Measuring implements IJob {
		boolean start;
		Measuring(boolean start) {
			this.start = start;
		}
		public boolean belongsTo(String jobFamily) {
			return true;
		}
		public void cancel() {
			// nothing to cancel
		}
		public void ensureReadyToRun() {
		}
		/**
		 * Execute the current job, answer whether it was successful.
		 */
		public boolean execute(IProgressMonitor progress) {
			if (this.start) {
				startMeasuring();
			} else {
				stopMeasuring();
			}
			return true;
		}
		public String getJobFamily() {
			return "FullSourceWorkspaceSearchTests.Measuring";
		}
	}

	protected void search(String patternString, int searchFor, int limitTo, IJavaSearchScope scope, SearchRequestor resultCollector) throws CoreException {
		int matchMode = patternString.indexOf('*') != -1 || patternString.indexOf('?') != -1
			? SearchPattern.R_PATTERN_MATCH
			: SearchPattern.R_EXACT_MATCH;
		SearchPattern pattern = SearchPattern.createPattern(
			patternString,
			searchFor,
			limitTo,
			matchMode | SearchPattern.R_CASE_SENSITIVE);
		new SearchEngine().search(
			pattern,
			new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()},
			scope,
			resultCollector,
			null);
	}

	/**
	 * Clean last category table cache
	 * @param type Tells whether previous search was a type search or not
	 * @param scope TODO
	 */
	protected void cleanCategoryTableCache(boolean type, IJavaSearchScope scope, JavaSearchResultCollector resultCollector) throws CoreException {
		long time = System.currentTimeMillis();
		if (type) {
			search("foo", FIELD, DECLARATIONS, scope, resultCollector);
		} else {
			search("Foo", TYPE, DECLARATIONS, scope, resultCollector);
		}
		if (DEBUG) System.out.println("Time to clean category table cache: "+(System.currentTimeMillis()-time));
	}

	/**
	 * Performance tests for search: Indexing entire workspace
	 *
	 * First wait that already started indexing jobs ends before performing test and measure.
	 * Consider this initial indexing jobs as warm-up for this test.
	 */
	public void testIndexing() throws CoreException {
		tagAsSummary("Indexing all workspace projects", false); // do NOT put in fingerprint

		// Wait for indexing end (we use initial indexing as warm-up)
		AbstractJavaModelTests.waitUntilIndexesReady();

		// Remove project previous indexing
		INDEX_MANAGER.removeIndexFamily(new Path(""));
		INDEX_MANAGER.reset();

		// Clean memory
		runGc();

		// Restart brand new indexing
		INDEX_MANAGER.request(new Measuring(true/*start measuring*/));
		for (int j=0, length=ALL_PROJECTS.length; j<length; j++) {
			INDEX_MANAGER.indexAll(ALL_PROJECTS[j].getProject());
		}
		AbstractJavaModelTests.waitUntilIndexesReady();

		// end measure
		INDEX_MANAGER.request(new Measuring(false /*end measuring*/));
		AbstractJavaModelTests.waitUntilIndexesReady();

		// Commit
		commitMeasurements();
		assertPerformance();
	}

	/**
	 * Performance tests for search: Indexing one project (JDT/Core).
	 */
	public void testIndexingOneProject() throws CoreException {
		tagAsSummary("Indexing JDT/Core project", true); // put in fingerprint

		// Warm-up
		for (int i=0 ; i<WARMUP_COUNT; i++) {
			INDEX_MANAGER.removeIndexFamily(JDT_CORE_PROJECT.getPath());
			INDEX_MANAGER.indexAll(JDT_CORE_PROJECT.getProject());
			AbstractJavaModelTests.waitUntilIndexesReady();
		}

		// Measures
		for (int i=0; i<MEASURES_COUNT; i++) {
			runGc();
			INDEX_MANAGER.removeIndexFamily(JDT_CORE_PROJECT.getPath());
			INDEX_MANAGER.request(new Measuring(true/*start measuring*/));
			INDEX_MANAGER.indexAll(JDT_CORE_PROJECT.getProject());
			AbstractJavaModelTests.waitUntilIndexesReady();
			INDEX_MANAGER.request(new Measuring(false /*end measuring*/));
			AbstractJavaModelTests.waitUntilIndexesReady();
		}

		// Commit
		commitMeasurements();
		assertPerformance();
	}

	/**
	 * Performance tests for search: Search All Types Names using 2.1 API.
	 *
	 * @deprecated As we use deprecated API
	 */
	public void testSearchAllTypeNames() throws CoreException {
		tagAsGlobalSummary("Search all type names", true); // put in global fingerprint
		OldSearchTypeNameRequestor requestor = new OldSearchTypeNameRequestor();

		// Wait for indexing end
		AbstractJavaModelTests.waitUntilIndexesReady();

		// Warm up
		IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
		for (int i=0 ; i<WARMUP_COUNT; i++) {
			new SearchEngine().searchAllTypeNames(
				null,
				null,
				SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE,
				IJavaSearchConstants.TYPE,
				scope,
				requestor,
				WAIT_UNTIL_READY_TO_SEARCH,
				null);
			if (i==0) {
				System.out.println("	All type names = "+INT_FORMAT.format(requestor.count));
				if (SEARCH_ALL_TYPE_NAMES_COUNT == -1) {
					SEARCH_ALL_TYPE_NAMES_COUNT = requestor.count;
				} else {
					assertEquals("We should find same number of types in the workspace whatever the search method is!", SEARCH_ALL_TYPE_NAMES_COUNT, requestor.count);
				}
			}
		}

		// Measures
		JavaSearchResultCollector resultCollector = new JavaSearchResultCollector();
		for (int i=0; i<MEASURES_COUNT; i++) {
			cleanCategoryTableCache(true, scope, resultCollector);
			runGc();
			startMeasuring();
			for (int j=0; j<ITERATIONS_COUNT; j++) {
				new SearchEngine().searchAllTypeNames(
					null,
					null,
					SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE,
					IJavaSearchConstants.TYPE,
					scope,
					requestor,
					WAIT_UNTIL_READY_TO_SEARCH,
					null);
			}
			stopMeasuring();
		}

		// Commit
		commitMeasurements();
		assertPerformance();
	}

	/**
	 * Performance tests for search: Search All Types Names.
	 */
	public void testNewSearchAllTypeNames() throws CoreException {
		tagAsSummary("Cold search all type names", true);	// put in fingerprint
		SearchTypeNameRequestor requestor = new SearchTypeNameRequestor();

		// Wait for indexing end
		AbstractJavaModelTests.waitUntilIndexesReady();

		// Warm up
		IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
		for (int i=0 ; i<WARMUP_COUNT; i++) {
			new SearchEngine().searchAllTypeNames(
				null,
				SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE,
				null,
				SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE,
				IJavaSearchConstants.TYPE,
				scope,
				requestor,
				WAIT_UNTIL_READY_TO_SEARCH,
				null);
			if (i == 0) {
				System.out.println("	All type names = "+INT_FORMAT.format(requestor.count));
				if (SEARCH_ALL_TYPE_NAMES_COUNT == -1) {
					SEARCH_ALL_TYPE_NAMES_COUNT = requestor.count;
				} else {
					assertEquals("We should find same number of types in the workspace whatever the search method is!", SEARCH_ALL_TYPE_NAMES_COUNT, requestor.count);
				}
			}
		}

		// Measures
		JavaSearchResultCollector resultCollector = new JavaSearchResultCollector();
		for (int i=0; i<MEASURES_COUNT; i++) {
			cleanCategoryTableCache(true, scope, resultCollector);
			runGc();
			startMeasuring();
			new SearchEngine().searchAllTypeNames(
				null,
				SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE,
				null,
				SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE,
				IJavaSearchConstants.TYPE,
				scope,
				requestor,
				WAIT_UNTIL_READY_TO_SEARCH,
				null);
			stopMeasuring();
		}

		// Commit
		commitMeasurements();
		assertPerformance();
	}

	/**
	 * Performance tests for search: Search All Types Names Matches.
	 *
	 * This test use a collector which accepts IType.
	 */
	public void testSearchAllTypeNameMatches() throws CoreException {
		tagAsSummary("Search all type name matches", false); // do NOT put in fingerprint
		SearchTypeNameMatchRequestor requestor = new SearchTypeNameMatchRequestor();

		// Wait for indexing end
		AbstractJavaModelTests.waitUntilIndexesReady();

		// Warm up
		IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
		for (int i=0 ; i<WARMUP_COUNT; i++) {
			new SearchEngine().searchAllTypeNames(
				null,
				SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE,
				null,
				SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE,
				IJavaSearchConstants.TYPE,
				scope,
				requestor,
				WAIT_UNTIL_READY_TO_SEARCH,
				null);
			if (i == 0) {
				System.out.println("	All type names = "+INT_FORMAT.format(requestor.count));
				if (SEARCH_ALL_TYPE_NAMES_COUNT == -1) {
					SEARCH_ALL_TYPE_NAMES_COUNT = requestor.count;
				} else {
					assertEquals("We should find same number of types in the workspace whatever the search method is!", SEARCH_ALL_TYPE_NAMES_COUNT, requestor.count);
				}
			}
		}

		// Measures
		JavaSearchResultCollector resultCollector = new JavaSearchResultCollector();
		for (int i=0; i<MEASURES_COUNT; i++) {
			cleanCategoryTableCache(true, scope, resultCollector);
			runGc();
			startMeasuring();
			new SearchEngine().searchAllTypeNames(
				null,
				SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE,
				null,
				SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE,
				IJavaSearchConstants.TYPE,
				scope,
				requestor,
				WAIT_UNTIL_READY_TO_SEARCH,
				null);
			stopMeasuring();
		}

		// Commit
		commitMeasurements();
		assertPerformance();
	}

	/**
	 * Performance tests for search:  Types occurrences.
	 *
	 * Note that following search have been tested:
	 *		- "String":				> 65000 macthes (CAUTION: needs -Xmx512M)
	 *		- "Object":			13497 matches
	 *		- ""IResource":	5886 macthes
	 *		- "JavaCore":		2145 matches
	 */
	public void testSearchType() throws CoreException {
		tagAsSummary("Search type occurences", true); // put in fingerprint

		// Wait for indexing end
		AbstractJavaModelTests.waitUntilIndexesReady();

		// Warm up
		IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] { JDT_CORE_PROJECT }, IJavaSearchScope.SOURCES);
		String name = "JavaCore";
		JavaSearchResultCollector resultCollector = new JavaSearchResultCollector();
		for (int i=0 ; i<WARMUP_COUNT; i++) {
			search(name, TYPE, ALL_OCCURRENCES, scope, resultCollector);
			if (i==0) {
				System.out.println("	- "+INT_FORMAT.format(resultCollector.count)+" occurences for type '"+name+"' in project "+JDT_CORE_PROJECT.getElementName());
			}
		}

		// Measures
		for (int i=0; i<MEASURES_COUNT; i++) {
			cleanCategoryTableCache(true, scope, resultCollector);
			runGc();
			startMeasuring();
			search(name, TYPE, ALL_OCCURRENCES, scope, resultCollector);
			stopMeasuring();
		}

		// Commit
		commitMeasurements();
		assertPerformance();
	}

	/**
	 * Performance tests for search: Fields occurrences.
	 */
	public void testSearchField() throws CoreException {
		tagAsSummary("Search field occurences", true); // put in fingerprint

		// Wait for indexing end
		AbstractJavaModelTests.waitUntilIndexesReady();

		// Warm up
		IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] { JDT_CORE_PROJECT }, IJavaSearchScope.SOURCES);
		String name = "TYPE";
		JavaSearchResultCollector resultCollector = new JavaSearchResultCollector();
		for (int i=0 ; i<WARMUP_COUNT; i++) {
			search(name, FIELD, ALL_OCCURRENCES, scope, resultCollector);
			if (i==0) {
				System.out.println("	- "+INT_FORMAT.format(resultCollector.count)+" occurences for field '"+name+"' in project "+JDT_CORE_PROJECT.getElementName());
			}
		}

		// Measures
		for (int i=0; i<MEASURES_COUNT; i++) {
			cleanCategoryTableCache(false, scope, resultCollector);
			runGc();
			startMeasuring();
			search(name, FIELD, ALL_OCCURRENCES, scope, resultCollector);
			stopMeasuring();
		}

		// Commit
		commitMeasurements();
		assertPerformance();
	}

	/**
	 * Performance tests for search: Methods occurrences.
	 * This search do NOT use binding resolution.
	 */
	public void testSearchMethod() throws CoreException {
		tagAsSummary("Search method occurences (no resolution)", false); // do NOT put in fingerprint
		setComment(Performance.EXPLAINS_DEGRADATION_COMMENT, "Test is not enough stable and will be replaced by another one...");

		// Wait for indexing end
		AbstractJavaModelTests.waitUntilIndexesReady();

		// Warm up
		IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] { JDT_CORE_PROJECT }, IJavaSearchScope.SOURCES);
		String name = "equals";
		JavaSearchResultCollector resultCollector = new JavaSearchResultCollector();
		for (int i=0 ; i<WARMUP_COUNT; i++) {
			search(name, METHOD, ALL_OCCURRENCES, scope, resultCollector);
			if (i==0) {
				System.out.println("	- "+INT_FORMAT.format(resultCollector.count)+" occurences for method '"+name+"' in project "+JDT_CORE_PROJECT.getElementName());
			}
		}

		// Measures
		for (int i=0; i<MEASURES_COUNT; i++) {
			// clean before test
			cleanCategoryTableCache(false, scope, resultCollector);
			runGc();

			// test
			startMeasuring();
			search(name, METHOD, ALL_OCCURRENCES, scope, resultCollector);
			stopMeasuring();
		}

		// Commit
		commitMeasurements();
		assertPerformance();
	}

	/**
	 * Performance tests for search: Methods occurrences.
	 * This search use binding resolution.
	 */
	public void testSearchBinaryMethod() throws CoreException {
		tagAsSummary("Search method occurences", true); // put in fingerprint

		// Wait for indexing end
		AbstractJavaModelTests.waitUntilIndexesReady();

		// Warm up
		IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] { JDT_CORE_PROJECT }, IJavaSearchScope.SOURCES);
		String name = "java.lang.Object.hashCode()";
		JavaSearchResultCollector resultCollector = new JavaSearchResultCollector();
		for (int i=0 ; i<WARMUP_COUNT; i++) {
			search(name, METHOD, ALL_OCCURRENCES, scope, resultCollector);
			if (i==0) {
				System.out.println("	- "+INT_FORMAT.format(resultCollector.count)+" occurences for method '"+name+"' in project "+JDT_CORE_PROJECT.getElementName());
			}
		}

		// Measures
		for (int i=0; i<MEASURES_COUNT; i++) {
			// clean before test
			cleanCategoryTableCache(false, scope, resultCollector);
			runGc();

			// test
			startMeasuring();
			search(name, METHOD, ALL_OCCURRENCES, scope, resultCollector);
			stopMeasuring();
		}

		// Commit
		commitMeasurements();
		assertPerformance();
	}

	/**
	 * Performance tests for search: Constructors occruences.
	 */
	public void testSearchConstructor() throws CoreException {
		tagAsSummary("Search constructor occurences", false); // do NOT put in fingerprint

		// Wait for indexing end
		AbstractJavaModelTests.waitUntilIndexesReady();

		// Warm up
		IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] { JDT_CORE_PROJECT }, IJavaSearchScope.SOURCES);
		String name = "String";
		JavaSearchResultCollector resultCollector = new JavaSearchResultCollector();
		for (int i=0 ; i<WARMUP_COUNT; i++) {
			search(name, CONSTRUCTOR, ALL_OCCURRENCES, scope, resultCollector);
			if (i==0) {
				System.out.println("	- "+INT_FORMAT.format(resultCollector.count)+" occurences for constructor '"+name+"' in project "+JDT_CORE_PROJECT.getElementName());
			}
		}

		// Measures
		for (int i=0; i<MEASURES_COUNT; i++) {
			cleanCategoryTableCache(false, scope, resultCollector);
			runGc();
			startMeasuring();
			search(name, CONSTRUCTOR, ALL_OCCURRENCES, scope, resultCollector);
			stopMeasuring();
		}

		// Commit
		commitMeasurements();
		assertPerformance();
	}

	/**
	 * Performance tests for search: Package Declarations.
	 * @deprecated because this test does not last enough to be pertinent
	 * @see #testSearchPackageDeclarationsWorkspace() This test is the only
	 * 	valid test to ensure that no regression occurs while searching for package
	 * 	declarations
	 */
	public void _testSearchPackageDeclarations() throws CoreException {
		tagAsSummary("Search package declarations", false); // do NOT put in fingerprint

		// Wait for indexing end
		AbstractJavaModelTests.waitUntilIndexesReady();

		// Warm up
		IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] { JDT_CORE_PROJECT }, IJavaSearchScope.SOURCES);
		String name = "*";
		JavaSearchResultCollector resultCollector = new JavaSearchResultCollector();
		for (int i=0 ; i<WARMUP_COUNT; i++) {
			search(name, PACKAGE, DECLARATIONS, scope, resultCollector);
			if (i==0) {
				System.out.println("	- "+INT_FORMAT.format(resultCollector.count)+" package declarations in project "+JDT_CORE_PROJECT.getElementName());
			}
		}

		// Measures
		for (int i=0; i<MEASURES_COUNT; i++) {
			cleanCategoryTableCache(false, scope, resultCollector);
			runGc();
			startMeasuring();
			// TODO (frederic) increase time for this test in next version as bug 183062 fix make its time around 2ms!
//			for (int j=0; j<20; j++)
				search(name, PACKAGE, DECLARATIONS, scope, resultCollector);
			stopMeasuring();
		}

		// Commit
		commitMeasurements();
		assertPerformance();
	}

	/**
	 * Performance tests for search: Package Declarations on workspace scope.
	 */
	public void testSearchPackageDeclarationsWorkspace() throws CoreException {
		tagAsSummary("Search workspace package declarations", false); // do NOT put in fingerprint

		// Wait for indexing end
		AbstractJavaModelTests.waitUntilIndexesReady();

		// Warm up
		IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
		String name = "*";
		JavaSearchResultCollector resultCollector = new JavaSearchResultCollector();
		for (int i=0 ; i<WARMUP_COUNT; i++) {
			search(name, PACKAGE, DECLARATIONS, scope, resultCollector);
			if (i==0) {
				System.out.println("	- "+INT_FORMAT.format(resultCollector.count)+" package declarations in workspace.");
			}
		}

		// Measures
		for (int i=0; i<MEASURES_COUNT; i++) {
			cleanCategoryTableCache(false, scope, resultCollector);
			runGc();
			startMeasuring();
			for (int j=0; j<10; j++)
				search(name, PACKAGE, DECLARATIONS, scope, resultCollector);
			stopMeasuring();
		}

		// Commit
		commitMeasurements();
		assertPerformance();
	}

	/**
	 * Performance tests for search: Simulate a Goto Package action.
	 * This action searches all package declarations on the entire workspace.
	 * Not activated, as this is more a JDT/UI performance tests, but released
	 * to keep a trace in the repository...
	 * @deprecated
	 */
	public void _testGotoPackage() throws CoreException {

		// Wait for indexing end
		AbstractJavaModelTests.waitUntilIndexesReady();

		// Warm up
		IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
		String name = "*";
		final List packageList= new ArrayList();
		SearchRequestor requestor = new SearchRequestor() {
			public void acceptSearchMatch(SearchMatch match) throws CoreException {
				IJavaElement enclosingElement= (IJavaElement) match.getElement();
				enclosingElement.getElementName();
				IPackageFragment pkg= (IPackageFragment) enclosingElement;
				if (pkg.getCompilationUnits().length == 0 && pkg.getClassFiles().length == 0) {
					return;
				}
				packageList.add(enclosingElement);
			}
		};
		for (int i=0 ; i<WARMUP_COUNT; i++) {
			search(name, PACKAGE, DECLARATIONS, scope, requestor);
			if (i==0) {
				System.out.println("	- "+INT_FORMAT.format(packageList.size())+" package declarations in workspace.");
			}
		}

		// Measures
		for (int i=0; i<MEASURES_COUNT; i++) {
			cleanCategoryTableCache(false, scope, new JavaSearchResultCollector());
			runGc();
			startMeasuring();
			search(name, PACKAGE, DECLARATIONS, scope, requestor);
			stopMeasuring();
		}

		// Commit
		commitMeasurements();
		assertPerformance();
	}
}
