blob: 285195a77922f3a0d63de7a1e4572fd644d14066 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2017 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
* Martin Oberhuber (Wind River) - [306573] Add tests for import from snapshot
*******************************************************************************/
package org.eclipse.core.tests.resources.perf;
import java.io.ByteArrayInputStream;
import java.net.URI;
import java.util.Random;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.tests.harness.PerformanceTestRunner;
import org.eclipse.core.tests.resources.ResourceTest;
/**
* Basic performance calculations for standard workspace operations.
*/
public class WorkspacePerformanceTest extends ResourceTest {
private static final String chars = "abcdefghijklmnopqrstuvwxyz";
static final int REPEATS = 5;
private static final int TREE_WIDTH = 10;
private static final int DEFAULT_TOTAL_RESOURCES = 10000;
private final Random random = new Random();
IFolder testFolder;
IProject testProject;
public static Test suite() {
return new TestSuite(WorkspacePerformanceTest.class);
// TestSuite suite = new TestSuite();
// suite.addTest(new WorkspacePerformanceTest("testRefreshProject"));
// return suite;
}
public WorkspacePerformanceTest() {
super();
}
public WorkspacePerformanceTest(String name) {
super(name);
}
IFolder copyFolder() {
IFolder destination = testProject.getFolder("CopyDestination");
try {
testFolder.copy(destination.getFullPath(), IResource.NONE, getMonitor());
} catch (CoreException e) {
fail("Failed to copy project in performance test", e);
}
return destination;
}
/**
* Creates a project and fills it with contents
*/
void createAndPopulateProject(final int totalResources) {
try {
getWorkspace().run((IWorkspaceRunnable) monitor -> {
testProject.create(getMonitor());
testProject.open(getMonitor());
createFolder(testFolder, totalResources);
}, getMonitor());
} catch (CoreException e) {
fail("Failed to create project in performance test", e);
}
}
private byte[] createBytes(int length) {
byte[] bytes = new byte[length];
random.nextBytes(bytes);
return bytes;
}
/**
* Creates and returns a folder with lots of contents
*/
IFolder createFolder(IFolder topFolder, int totalResources) throws CoreException {
topFolder.create(IResource.NONE, true, getMonitor());
//tree depth is log of total resource count with the width as the log base
int depth = (int) (Math.log(totalResources) / Math.log(TREE_WIDTH));
recursiveCreateChildren(topFolder, depth - 1);
return topFolder;
}
private String createString(int length) {
StringBuffer buf = new StringBuffer(length);
//fill the string with random characters up to the desired length
for (int i = 0; i < length; i++) {
buf.append(chars.charAt(random.nextInt(chars.length())));
}
return buf.toString();
}
/**
* Deletes the test project without deleting content, and then recreates
* the project without discovering content on disk. This sets us up
* for benchmarking performance of refresh local.
*/
void deleteAndRecreateProject() throws CoreException {
//delete without deleting contents
testProject.delete(IResource.NEVER_DELETE_PROJECT_CONTENT, null);
//recreate project but don't discover content
testProject.create(null);
testProject.open(IResource.NONE, null);
}
IFolder moveFolder() {
IFolder destination = testFolder.getProject().getFolder("MoveDestination");
try {
testFolder.move(destination.getFullPath(), IResource.NONE, getMonitor());
} catch (CoreException e) {
fail("Failed to move folder during performance test", e);
}
return destination;
}
/**
* Create children of the given folder, and recurse to the given depth
*/
private void recursiveCreateChildren(IFolder parentFolder, int depth) throws CoreException {
//create TREE_WIDTH files
for (int i = 0; i < TREE_WIDTH; i++) {
IFile file = parentFolder.getFile(createString(10));
file.create(new ByteArrayInputStream(createBytes(5000)), IResource.NONE, getMonitor());
}
if (depth <= 0) {
return;
}
//create TREE_WIDTH folders
for (int i = 0; i < TREE_WIDTH; i++) {
IFolder folder = parentFolder.getFolder(createString(6));
folder.create(IResource.NONE, true, getMonitor());
recursiveCreateChildren(folder, depth - 1);
}
}
@Override
protected void setUp() throws Exception {
testProject = getWorkspace().getRoot().getProject("Project");
testFolder = testProject.getFolder("TopFolder");
}
/**
* Benchmark test of creating a project and populating it with folders and files.
*/
public void testCreateResources() {
PerformanceTestRunner runner = new PerformanceTestRunner() {
@Override
protected void setUp() {
waitForBackgroundActivity();
}
@Override
protected void tearDown() throws CoreException {
testProject.delete(IResource.FORCE, null);
}
@Override
protected void test() {
createAndPopulateProject(DEFAULT_TOTAL_RESOURCES);
}
};
runner.run(this, REPEATS, 1);
}
public void testDeleteProject() {
//create the project contents
PerformanceTestRunner runner = new PerformanceTestRunner() {
@Override
protected void setUp() {
createAndPopulateProject(DEFAULT_TOTAL_RESOURCES);
waitForBackgroundActivity();
}
@Override
protected void test() {
try {
testProject.delete(IResource.NONE, null);
} catch (CoreException e) {
fail("Failed to delete project during performance test", e);
}
}
};
runner.run(this, REPEATS, 1);
}
public void testFolderCopy() {
//create the project contents
new PerformanceTestRunner() {
@Override
protected void setUp() {
createAndPopulateProject(DEFAULT_TOTAL_RESOURCES);
waitForBackgroundActivity();
}
@Override
protected void tearDown() throws CoreException {
testProject.delete(IResource.FORCE, null);
}
@Override
protected void test() {
copyFolder();
}
}.run(this, REPEATS, 1);
}
public void testFolderMove() {
//create the project contents
new PerformanceTestRunner() {
@Override
protected void setUp() {
createAndPopulateProject(DEFAULT_TOTAL_RESOURCES);
waitForBackgroundActivity();
}
@Override
protected void tearDown() throws CoreException {
testProject.delete(IResource.FORCE, null);
}
@Override
protected void test() {
moveFolder();
}
}.run(this, REPEATS, 1);
}
public void testRefreshProject() {
PerformanceTestRunner runner = new PerformanceTestRunner() {
@Override
protected void setUp() throws CoreException {
createAndPopulateProject(50000);
deleteAndRecreateProject();
waitForBackgroundActivity();
}
@Override
protected void tearDown() throws CoreException {
testProject.delete(IResource.FORCE, null);
}
@Override
protected void test() {
try {
testProject.refreshLocal(IResource.DEPTH_INFINITE, null);
} catch (CoreException e) {
fail("Failed to refresh during testRefreshProject", e);
}
}
};
runner.setFingerprintName("Refresh Project");
runner.run(this, REPEATS, 1);
}
public void testCloseOpenProject() {
// 8 minutes total test time, 400 msec test execution time (*3 inner loops)
new PerformanceTestRunner() {
@Override
protected void setUp() {
createAndPopulateProject(50000);
waitForBackgroundActivity();
}
@Override
protected void tearDown() throws CoreException {
testProject.delete(IResource.FORCE, null);
}
@Override
protected void test() {
try {
testProject.close(null);
testProject.open(null);
} catch (CoreException e) {
fail("Failed to close/open during testCloseOpenProject", e);
}
}
}.run(this, REPEATS, 3);
}
public void testLoadSnapshot() {
// 2 minutes total test time, 528 msec test execution time
IProject snapProject = getWorkspace().getRoot().getProject("SnapProject");
ensureExistsInWorkspace(snapProject, true);
final URI snapshotLocation = snapProject.getFile("snapshot.zip").getLocationURI();
createAndPopulateProject(50000);
waitForBackgroundActivity();
try {
testProject.saveSnapshot(IProject.SNAPSHOT_TREE, snapshotLocation, null);
testProject.delete(IResource.FORCE, null);
} catch (CoreException e) {
fail("Failed to create snapshot during testLoadSnapshot");
}
waitForBackgroundActivity();
new PerformanceTestRunner() {
@Override
protected void setUp() {
}
@Override
protected void tearDown() throws CoreException {
testProject.delete(IResource.FORCE, null);
}
@Override
protected void test() {
try {
testProject.create(null);
testProject.loadSnapshot(IProject.SNAPSHOT_TREE, snapshotLocation, null);
testProject.open(null);
} catch (CoreException e) {
fail("Failed to load snapshot during testLoadSnapshot", e);
}
}
}.run(this, REPEATS, 1);
}
/**
* Waits until background activity settles down before running a performance test.
*
*/
public void waitForBackgroundActivity() {
waitForSnapshot();
waitForRefresh();
waitForBuild();
}
/**
* Wait for snapshot to complete by running and joining a workspace modification job.
* This job will get queued to run behind any scheduled snapshot job.
*/
private void waitForSnapshot() {
Job wait = new Job("Wait") {
@Override
protected IStatus run(IProgressMonitor monitor) {
return Status.OK_STATUS;
}
};
wait.setRule(getWorkspace().getRoot());
wait.schedule();
try {
wait.join();
} catch (InterruptedException e) {
//ignore interruption
}
}
}