| /******************************************************************************* |
| * 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); |
| } |
| } |
| } |