blob: f085f941530e88dc10912bd8e4561c5f1cb6505b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 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
*******************************************************************************/
package org.eclipse.equinox.p2.tests.engine;
import java.io.File;
import java.net.URI;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
import org.eclipse.equinox.internal.p2.engine.*;
import org.eclipse.equinox.internal.p2.repository.DownloadProgressEvent;
import org.eclipse.equinox.internal.p2.touchpoint.natives.Util;
import org.eclipse.equinox.internal.provisional.p2.core.eventbus.ProvisioningListener;
import org.eclipse.equinox.internal.provisional.p2.repository.RepositoryEvent;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.engine.*;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.query.*;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
import org.eclipse.equinox.p2.tests.AbstractProvisioningTest;
import org.eclipse.equinox.p2.tests.TestActivator;
import org.junit.Test;
/**
* Simple test of the engine API.
*/
public class PhaseSetTest extends AbstractProvisioningTest {
PauseJob pause = null;
public PhaseSetTest(String name) {
super(name);
}
public PhaseSetTest() {
super("");
}
public void testNullPhases() {
try {
new PhaseSet(null) {
// empty PhaseSet
};
} catch (IllegalArgumentException exepcted) {
return;
}
fail();
}
public void testNoTrustCheck() {
IPhaseSet set1 = PhaseSetFactory.createDefaultPhaseSet();
IPhaseSet set2 = PhaseSetFactory.createDefaultPhaseSetExcluding(new String[] {PhaseSetFactory.PHASE_CHECK_TRUST});
assertTrue("1.0", !set1.equals(set2));
}
public void testEmptyPhases() {
IProfile profile = createProfile("PhaseSetTest");
PhaseSet phaseSet = new PhaseSet(new Phase[] {}) {
// empty PhaseSet
};
InstallableUnitOperand op = new InstallableUnitOperand(createResolvedIU(createIU("iu")), null);
InstallableUnitOperand[] operands = new InstallableUnitOperand[] {op};
ProvisioningContext context = new ProvisioningContext(getAgent());
IStatus result = phaseSet.perform(new EngineSession(null, profile, context), operands, new NullProgressMonitor());
assertTrue(result.isOK());
}
@Test
public void testPauseNotRunningPhaseSet() {
PhaseSet set = (PhaseSet) PhaseSetFactory.createDefaultPhaseSet();
assertFalse("Can pause not running phaseset.", set.pause());
}
@Test
public void testResumeNotPausedPhaseSet() {
PhaseSet set = (PhaseSet) PhaseSetFactory.createDefaultPhaseSet();
assertFalse("Can resume not phaused phaseset.", set.resume());
}
abstract class PauseJob extends Job {
public PauseJob(String name) {
super(name);
}
private boolean isPaused = false;
Job resume = null;
public boolean isPaused() {
return isPaused;
}
public void setPause(boolean paused) {
isPaused = paused;
}
}
@Test
public void testPauseAndResume() throws ProvisionException, OperationCanceledException, InterruptedException {
URI repoLoc = getTestData("Load test data.", "/testData/pausefeature").toURI();
final PhaseSet phaseSet = (PhaseSet) PhaseSetFactory.createDefaultPhaseSet();
pause = new PauseJob("pause") {
@Override
protected IStatus run(IProgressMonitor monitor) {
if (!phaseSet.pause())
return new Status(IStatus.ERROR, TestActivator.PI_PROV_TESTS, "pause() failed.");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
setPause(true);
resume = new Job("resume") {
@Override
protected IStatus run(IProgressMonitor monitor1) {
pause.setPause(false);
if (!phaseSet.resume())
return new Status(IStatus.ERROR, TestActivator.PI_PROV_TESTS, "resume() failed.");
return Status.OK_STATUS;
}
};
resume.schedule(10000);
return Status.OK_STATUS;
}
};
basicTest(repoLoc, phaseSet, pause, QueryUtil.createIUQuery("org.eclipse.equinox.launcher"), IStatus.OK, null);
assertTrue("Pause job is failed.", pause.getResult().isOK());
pause.resume.join();
assertTrue("Resume job is failed.", pause.resume.getResult().isOK());
}
private void basicTest(URI repoURI, PhaseSet phaseSet, final PauseJob pauseJob, IQuery<IInstallableUnit> query, int expectedCode, IProgressMonitor monitor) throws ProvisionException, InterruptedException {
class ProvTestListener implements ProvisioningListener {
boolean hasProvisioningEventAfterPaused = false;
CountDownLatch latch = new CountDownLatch(1);
boolean canStart = false;
@Override
public void notify(EventObject o) {
if (o instanceof BeginOperationEvent) {
canStart = true;
}
if (o instanceof RepositoryEvent || o instanceof ProfileEvent)
return;
if (canStart && o instanceof DownloadProgressEvent) {
// make sure to pause downloading after it has started
pauseJob.schedule();
canStart = false;
return;
}
if (o instanceof CommitOperationEvent || o instanceof RollbackOperationEvent) {
latch.countDown();
pauseJob.cancel();
return;
}
if (pauseJob.isPaused() && !(o instanceof PhaseEvent)) {
hasProvisioningEventAfterPaused = true;
}
}
}
ProvTestListener listener = new ProvTestListener();
getEventBus().addListener(listener);
try {
getMetadataRepositoryManager().loadRepository(repoURI, null);
getArtifactRepositoryManager().loadRepository(repoURI, null);
doProvisioning(repoURI, phaseSet, query, expectedCode, monitor);
// make sure the listener handles all event already that are dispatched asynchronously
listener.latch.await(10, TimeUnit.SECONDS);
assertFalse("Engine still do provisioning after pausing.", listener.hasProvisioningEventAfterPaused);
pauseJob.join();
} finally {
getEventBus().removeListener(listener);
}
}
private void doProvisioning(URI repoLoc, final PhaseSet phaseSet, IQuery<IInstallableUnit> query, int expectedResult, IProgressMonitor monitor) throws ProvisionException {
File testFolder = new File(System.getProperty("java.io.tmpdir"), "testProvisioning");
delete(testFolder);
testFolder.mkdir();
final String profileId = "test";
try {
ProvisioningContext context = new ProvisioningContext(getAgent());
context.setArtifactRepositories(new URI[] {repoLoc});
context.setMetadataRepositories(new URI[] {repoLoc});
IEngine engine = getEngine();
// restrict the installation to 'linux & gtk & x86' to match the test repo
Map<String, String> props = new HashMap<>();
props.put(IProfile.PROP_ENVIRONMENTS, "osgi.ws=gtk,osgi.arch=x86,osgi.os=linux");
props.put(IProfile.PROP_INSTALL_FOLDER, testFolder.getAbsolutePath());
IProfile profile = createProfile(profileId, props);
// clean cached artifacts
IArtifactRepository artifactRepo = org.eclipse.equinox.internal.p2.touchpoint.eclipse.Util.getBundlePoolRepository(getAgent(), profile);
artifactRepo.removeAll(new NullProgressMonitor());
ProfileChangeRequest request = ProfileChangeRequest.createByProfileId(getAgent(), profile.getProfileId());
IQueryResult<IInstallableUnit> toBeInstalledIUs = getMetadataRepositoryManager().loadRepository(repoLoc, null).query(query, null);
assertFalse("Test case has problem to find IU to be installed.", toBeInstalledIUs.isEmpty());
request.addAll(toBeInstalledIUs.toSet());
IProvisioningPlan plan = getPlanner(getAgent()).getProvisioningPlan(request, context, null);
assertTrue("Provisioning plan can't be resolved.", plan.getStatus().isOK());
IStatus status = engine.perform(plan, phaseSet, monitor);
assertEquals("The reture code of provisioning is not expected.", expectedResult, status.getSeverity());
} finally {
delete(testFolder);
getProfileRegistry().removeProfile(profileId);
Util.getDownloadCacheRepo(getAgent()).removeAll(new NullProgressMonitor());
}
}
@Test
public void testPauseAndResumeMoreThanOnce() throws ProvisionException, InterruptedException {
// URI repoLoc = URI.create("http://download.eclipse.org/releases/indigo");
URI repoLoc = getTestData("Load test data.", "/testData/pausefeature").toURI();
final PhaseSet phaseSet = (PhaseSet) PhaseSetFactory.createDefaultPhaseSet();
final int threhold = 3;
class ResumeJob extends Job {
private PauseJob pauseJob;
private int count = 0;
public ResumeJob(String name, PauseJob pauseJob) {
super(name);
this.pauseJob = pauseJob;
}
@Override
protected IStatus run(IProgressMonitor monitor) {
pauseJob.setPause(false);
if (!phaseSet.resume())
return new Status(IStatus.INFO, TestActivator.PI_PROV_TESTS, "resume() failed.");
if (count++ < threhold)
pauseJob.schedule(10000);
return Status.OK_STATUS;
}
}
pause = new PauseJob("pause") {
@Override
protected IStatus run(IProgressMonitor monitor) {
if (!phaseSet.pause())
return new Status(IStatus.INFO, TestActivator.PI_PROV_TESTS, "pause() failed.");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
setPause(true);
if (resume == null)
resume = new ResumeJob("resume", this);
resume.schedule(10000);
return Status.OK_STATUS;
}
};
basicTest(repoLoc, phaseSet, pause, QueryUtil.createLatestQuery(QueryUtil.createIUQuery("org.eclipse.equinox.executable.feature.group")), IStatus.OK, null);
}
@Test
public void testCancelPausedProvisioing() throws ProvisionException, InterruptedException {
URI repoLoc = getTestData("Load test data.", "/testData/pausefeature").toURI();
final PhaseSet phaseSet = (PhaseSet) PhaseSetFactory.createDefaultPhaseSet();
class ProvListener implements ProvisioningListener {
boolean hasDownloadEvent = false;
@Override
public void notify(EventObject o) {
if (o instanceof DownloadProgressEvent)
hasDownloadEvent = true;
}
}
final ProvListener listener = new ProvListener();
getEventBus().addListener(listener);
try {
pause = new PauseJob("pause") {
@Override
protected IStatus run(IProgressMonitor monitor) {
while (!listener.hasDownloadEvent) {
try {
Thread.sleep(10);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
if (!phaseSet.pause())
return new Status(IStatus.ERROR, TestActivator.PI_PROV_TESTS, "pause() failed.");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// wait seconds
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
//
}
setPause(true);
return Status.OK_STATUS;
}
};
basicTest(repoLoc, phaseSet, pause, QueryUtil.createLatestQuery(QueryUtil.createIUQuery("org.eclipse.equinox.executable.feature.group")), IStatus.CANCEL, new NullProgressMonitor() {
@Override
public boolean isCanceled() {
return pause.isPaused();
}
});
} finally {
getEventBus().removeListener(listener);
}
}
}