blob: 30ca4190960ff7bac6159a3908d3f312e497bed6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2012 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.core.tests.runtime.perf;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.internal.content.*;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.*;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.core.tests.harness.*;
import org.eclipse.core.tests.runtime.RuntimeTest;
import org.eclipse.core.tests.runtime.RuntimeTestsPlugin;
import org.eclipse.core.tests.session.PerformanceSessionTestSuite;
import org.eclipse.core.tests.session.SessionTestSuite;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
public class ContentTypePerformanceTest extends RuntimeTest {
private final static String CONTENT_TYPE_PREF_NODE = Platform.PI_RUNTIME + IPath.SEPARATOR + "content-types"; //$NON-NLS-1$
private static final String DEFAULT_NAME = "file_" + ContentTypePerformanceTest.class.getName();
private static final int ELEMENTS_PER_LEVEL = 4;
private static final int NUMBER_OF_LEVELS = 4;
private static final String TEST_DATA_ID = "org.eclipse.core.tests.runtime.contenttype.perf.testdata";
private static final int TOTAL_NUMBER_OF_ELEMENTS = computeTotalTypes(NUMBER_OF_LEVELS, ELEMENTS_PER_LEVEL);
private static int computeTotalTypes(int levels, int elementsPerLevel) {
double sum = 0;
for (int i = 0; i <= levels; i++)
sum += Math.pow(elementsPerLevel, i);
return (int) sum;
}
private static String createContentType(Writer writer, int number, String baseTypeId) throws IOException {
String id = "performance" + number;
String definition = generateContentType(number, id, baseTypeId, new String[] {DEFAULT_NAME}, null);
writer.write(definition);
writer.write(System.getProperty("line.separator"));
return id;
}
public static int createContentTypes(Writer writer, String baseTypeId, int created, int numberOfLevels, int nodesPerLevel) throws IOException {
if (numberOfLevels == 0)
return 0;
int local = nodesPerLevel;
for (int i = 0; i < nodesPerLevel; i++) {
String id = createContentType(writer, created + i, baseTypeId);
local += createContentTypes(writer, id, created + local, numberOfLevels - 1, nodesPerLevel);
}
return local;
}
private static String generateContentType(int number, String id, String baseTypeId, String[] fileNames, String[] fileExtensions) {
StringBuffer result = new StringBuffer();
result.append("<content-type id=\"");
result.append(id);
result.append("\" name=\"");
result.append(id);
result.append("\" ");
if (baseTypeId != null) {
result.append("base-type=\"");
result.append(baseTypeId);
result.append("\" ");
}
String fileNameList = Util.toListString(fileNames);
if (fileNameList != null) {
result.append("file-names=\"");
result.append(fileNameList);
result.append("\" ");
}
String fileExtensionsList = Util.toListString(fileExtensions);
if (fileExtensions != null && fileExtensions.length > 0) {
result.append("file-extensions=\"");
result.append(fileExtensionsList);
result.append("\" ");
}
result.append("describer=\"");
result.append(BinarySignatureDescriber.class.getName());
result.append(":");
result.append(getSignatureString(number));
result.append("\"/>");
return result.toString();
}
private static String getContentTypeId(int i) {
return TEST_DATA_ID + ".performance" + i;
}
private static byte[] getSignature(int number) {
byte[] result = new byte[4];
for (int i = 0; i < result.length; i++)
result[i] = (byte) ((number >> (i * 8)) & 0xFFL);
return result;
}
private static String getSignatureString(int number) {
byte[] signature = getSignature(number);
StringBuffer result = new StringBuffer(signature.length * 3 - 1);
for (int i = 0; i < signature.length; i++) {
result.append(Integer.toHexString(0xFF & signature[i]));
result.append(' ');
}
result.deleteCharAt(result.length() - 1);
return result.toString();
}
public static Test suite() {
TestSuite suite = new TestSuite(ContentTypePerformanceTest.class.getName());
// suite.addTest(new ContentTypePerformanceTest("testDoSetUp"));
// suite.addTest(new ContentTypePerformanceTest("testContentMatching"));
// suite.addTest(new ContentTypePerformanceTest("testContentTXTMatching"));
// suite.addTest(new ContentTypePerformanceTest("testContentXMLMatching"));
// suite.addTest(new ContentTypePerformanceTest("testDoTearDown"));
SessionTestSuite setUp = new SessionTestSuite(PI_RUNTIME_TESTS, "testDoSetUp");
setUp.addTest(new ContentTypePerformanceTest("testDoSetUp"));
suite.addTest(setUp);
TestSuite singleRun = new PerformanceSessionTestSuite(PI_RUNTIME_TESTS, 1, "singleSessionTests");
singleRun.addTest(new ContentTypePerformanceTest("testContentMatching"));
singleRun.addTest(new ContentTypePerformanceTest("testNameMatching"));
singleRun.addTest(new ContentTypePerformanceTest("testIsKindOf"));
suite.addTest(singleRun);
TestSuite loadCatalog = new PerformanceSessionTestSuite(PI_RUNTIME_TESTS, 10, "multipleSessionTests");
loadCatalog.addTest(new ContentTypePerformanceTest("testLoadCatalog"));
suite.addTest(loadCatalog);
TestSuite tearDown = new SessionTestSuite(PI_RUNTIME_TESTS, "testDoTearDown");
tearDown.addTest(new ContentTypePerformanceTest("testDoTearDown"));
suite.addTest(tearDown);
return suite;
}
public ContentTypePerformanceTest(String name) {
super(name);
}
private int countTestContentTypes(IContentType[] all) {
String namespace = TEST_DATA_ID + '.';
int count = 0;
for (int i = 0; i < all.length; i++)
if (all[i].getId().startsWith(namespace))
count++;
return count;
}
public IPath getExtraPluginLocation() {
return getTempDir().append(TEST_DATA_ID);
}
private Bundle installContentTypes(String tag, int numberOfLevels, int nodesPerLevel) {
TestRegistryChangeListener listener = new TestRegistryChangeListener(Platform.PI_RUNTIME, ContentTypeBuilder.PT_CONTENTTYPES, null, null);
Bundle installed = null;
listener.register();
try {
IPath pluginLocation = getExtraPluginLocation();
pluginLocation.toFile().mkdirs();
URL installURL = null;
try {
installURL = pluginLocation.toFile().toURL();
} catch (MalformedURLException e) {
fail(tag + ".0.5", e);
}
Writer writer = null;
try {
writer = new BufferedWriter(new FileWriter(pluginLocation.append("plugin.xml").toFile()), 0x10000);
writer.write("<plugin id=\"" + TEST_DATA_ID + "\" name=\"Content Type Performance Test Data\" version=\"1\">");
writer.write(System.getProperty("line.separator"));
writer.write("<requires><import plugin=\"" + PI_RUNTIME_TESTS + "\"/></requires>");
writer.write(System.getProperty("line.separator"));
writer.write("<extension point=\"org.eclipse.core.runtime.contentTypes\">");
writer.write(System.getProperty("line.separator"));
String root = createContentType(writer, 0, null);
createContentTypes(writer, root, 1, numberOfLevels, nodesPerLevel);
writer.write("</extension></plugin>");
} catch (IOException e) {
fail(tag + ".1.0", e);
} finally {
if (writer != null)
try {
writer.close();
} catch (IOException e) {
fail("1.1", e);
}
}
try {
installed = RuntimeTestsPlugin.getContext().installBundle(installURL.toExternalForm());
} catch (BundleException e) {
fail(tag + ".3.0", e);
}
BundleTestingHelper.refreshPackages(RuntimeTestsPlugin.getContext(), new Bundle[] {installed});
assertTrue(tag + ".4.0", listener.eventReceived(10000));
} finally {
listener.unregister();
}
return installed;
}
/**
* Warms up the content type registry.
*/
private void loadChildren() {
final IContentTypeManager manager = Platform.getContentTypeManager();
IContentType[] allTypes = manager.getAllContentTypes();
for (int i = 0; i < allTypes.length; i++) {
String[] fileNames = allTypes[i].getFileSpecs(IContentType.IGNORE_USER_DEFINED | IContentType.FILE_NAME_SPEC);
for (int j = 0; j < fileNames.length; j++)
manager.findContentTypeFor(fileNames[j]);
String[] fileExtensions = allTypes[i].getFileSpecs(IContentType.IGNORE_USER_DEFINED | IContentType.FILE_EXTENSION_SPEC);
for (int j = 0; j < fileExtensions.length; j++)
manager.findContentTypeFor("anyname." + fileExtensions[j]);
}
}
/**
* Returns a loaded content type manager. Except for load time tests, this method should
* be called outside the scope of performance monitoring.
*/
private IContentTypeManager loadContentTypeManager() {
// any cheap interaction that causes the catalog to be built
Platform.getContentTypeManager().getContentType(IContentTypeManager.CT_TEXT);
return Platform.getContentTypeManager();
}
/** Forces all describers to be loaded.*/
private void loadDescribers() {
final IContentTypeManager manager = Platform.getContentTypeManager();
IContentType[] allTypes = manager.getAllContentTypes();
for (int i = 0; i < allTypes.length; i++)
((ContentTypeHandler) allTypes[i]).getTarget().getDescriber();
}
private void loadPreferences() {
new InstanceScope().getNode(CONTENT_TYPE_PREF_NODE);
}
/** Tests how much the size of the catalog affects the performance of content type matching by content analysis */
public void testContentMatching() {
loadPreferences();
// warm up content type registry
final IContentTypeManager manager = loadContentTypeManager();
loadDescribers();
loadChildren();
new PerformanceTestRunner() {
protected void test() {
try {
for (int i = 0; i < TOTAL_NUMBER_OF_ELEMENTS; i++) {
String id = getContentTypeId(i);
IContentType[] result = manager.findContentTypesFor(new ByteArrayInputStream(getSignature(i)), DEFAULT_NAME);
assertEquals("1.0." + i, 1, result.length);
assertEquals("1.1." + i, id, result[0].getId());
}
} catch (IOException e) {
fail("2.0", e);
}
}
}.run(this, 10, 2);
}
/* (non-Javadoc)
* @see junit.framework.TestCase#setUp()
*/
protected void setUp() throws Exception {
super.setUp();
if (getName().equals("testDoSetUp") || getName().equals("testDoTearDown"))
return;
Bundle installed = null;
try {
installed = RuntimeTestsPlugin.getContext().installBundle(getExtraPluginLocation().toFile().toURL().toExternalForm());
} catch (BundleException e) {
fail("1.0", e);
} catch (MalformedURLException e) {
fail("2.0", e);
}
BundleTestingHelper.refreshPackages(RuntimeTestsPlugin.getContext(), new Bundle[] {installed});
}
public void testDoSetUp() {
installContentTypes("1.0", NUMBER_OF_LEVELS, ELEMENTS_PER_LEVEL);
}
public void testDoTearDown() {
ensureDoesNotExistInFileSystem(getExtraPluginLocation().toFile());
}
public void testIsKindOf() {
// warm up preference service
loadPreferences();
// warm up content type registry
final IContentTypeManager manager = loadContentTypeManager();
loadChildren();
final IContentType root = manager.getContentType(getContentTypeId(0));
assertNotNull("2.0", root);
new PerformanceTestRunner() {
protected void test() {
for (int i = 0; i < TOTAL_NUMBER_OF_ELEMENTS; i++) {
IContentType type = manager.getContentType(getContentTypeId(i));
assertNotNull("3.0." + i, type);
assertTrue("3.1." + i, type.isKindOf(root));
}
}
}.run(this, 10, 500);
}
/**
* This test is intended for running as a session test.
*/
public void testLoadCatalog() {
// warm up preference service
loadPreferences();
PerformanceTestRunner runner = new PerformanceTestRunner() {
protected void test() {
// any interation that will cause the registry to be loaded
Platform.getContentTypeManager().getContentType(IContentTypeManager.CT_TEXT);
}
};
runner.run(this, 1, /* must run only once - the suite controls how many sessions are run */1);
// sanity check to make sure we are running with good data
assertEquals("missing content types", TOTAL_NUMBER_OF_ELEMENTS, countTestContentTypes(Platform.getContentTypeManager().getAllContentTypes()));
}
/** Tests how much the size of the catalog affects the performance of content type matching by name */
public void testNameMatching() {
// warm up preference service
loadPreferences();
// warm up content type registry
final IContentTypeManager manager = loadContentTypeManager();
loadDescribers();
loadChildren();
new PerformanceTestRunner() {
protected void test() {
IContentType[] associated = manager.findContentTypesFor("foo.txt");
// we know at least the etxt content type should be here
assertTrue("2.0", associated.length >= 1);
// and it is supposed to be the first one (since it is at the root)
assertEquals("2.1", IContentTypeManager.CT_TEXT, associated[0].getId());
}
}.run(this, 10, 200000);
}
}