/*******************************************************************************
 * Copyright (c) 2000, 2015 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;

/**
 */
@SuppressWarnings({"rawtypes", "unchecked"})
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
		
		// 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 occurrences.
	 */
	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();
	}
}
