1 /*******************************************************************************
2  *  Copyright (c) 2007, 2017 IBM Corporation and others.
3  *
4  *  This program and the accompanying materials
5  *  are made available under the terms of the Eclipse Public License 2.0
6  *  which accompanies this distribution, and is available at
7  *  https://www.eclipse.org/legal/epl-2.0/
8  *
9  *  SPDX-License-Identifier: EPL-2.0
10  *
11  *  Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.equinox.p2.tests.engine;
15 
16 import java.io.File;
17 import java.io.IOException;
18 import java.util.*;
19 import org.eclipse.core.runtime.*;
20 import org.eclipse.equinox.internal.p2.engine.*;
21 import org.eclipse.equinox.internal.p2.engine.phases.Collect;
22 import org.eclipse.equinox.internal.provisional.p2.core.eventbus.ProvisioningListener;
23 import org.eclipse.equinox.p2.engine.*;
24 import org.eclipse.equinox.p2.engine.spi.ProvisioningAction;
25 import org.eclipse.equinox.p2.metadata.*;
26 import org.eclipse.equinox.p2.query.QueryUtil;
27 import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
28 import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
29 import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
30 import org.eclipse.equinox.p2.tests.AbstractProvisioningTest;
31 
32 /**
33  * Simple test of the engine API.
34  */
35 public class PhaseTest extends AbstractProvisioningTest {
36 	public static class TestPhaseSet extends PhaseSet {
37 
TestPhaseSet()38 		public TestPhaseSet() {
39 			super(new Phase[] {new TestPhase()});
40 		}
41 
TestPhaseSet(Phase phase)42 		public TestPhaseSet(Phase phase) {
43 			super(new Phase[] {phase});
44 		}
45 
TestPhaseSet(Phase[] phases)46 		public TestPhaseSet(Phase[] phases) {
47 			super(phases);
48 		}
49 	}
50 
51 	public static class TestPhase extends InstallableUnitPhase {
52 
53 		public boolean initializePhase;
54 		public boolean completePhase;
55 		public boolean initializeOperand;
56 		public boolean completeOperand;
57 
TestPhase()58 		protected TestPhase() {
59 			super("test", 1);
60 		}
61 
TestPhase(String phaseId, int weight)62 		protected TestPhase(String phaseId, int weight) {
63 			super(phaseId, weight);
64 		}
65 
66 		@Override
completeOperand(IProfile profile, InstallableUnitOperand operand, Map<String, Object> parameters, IProgressMonitor monitor)67 		protected IStatus completeOperand(IProfile profile, InstallableUnitOperand operand, Map<String, Object> parameters, IProgressMonitor monitor) {
68 			completeOperand = true;
69 			return super.completeOperand(profile, operand, parameters, monitor);
70 		}
71 
72 		@Override
initializeOperand(IProfile profile, InstallableUnitOperand operand, Map<String, Object> parameters, IProgressMonitor monitor)73 		protected IStatus initializeOperand(IProfile profile, InstallableUnitOperand operand, Map<String, Object> parameters, IProgressMonitor monitor) {
74 			parameters.put("TestPhase.initializeOperand", "true");
75 			initializeOperand = true;
76 			return super.initializeOperand(profile, operand, parameters, monitor);
77 		}
78 
79 		@Override
completePhase(IProgressMonitor monitor, IProfile profile, Map<String, Object> parameters)80 		protected IStatus completePhase(IProgressMonitor monitor, IProfile profile, Map<String, Object> parameters) {
81 			completePhase = true;
82 			return super.completePhase(monitor, profile, parameters);
83 		}
84 
85 		@Override
initializePhase(IProgressMonitor monitor, IProfile profile, Map<String, Object> parameters)86 		protected IStatus initializePhase(IProgressMonitor monitor, IProfile profile, Map<String, Object> parameters) {
87 			parameters.put("TestPhase.initializePhase", "true");
88 			initializePhase = true;
89 			return super.initializePhase(monitor, profile, parameters);
90 		}
91 
92 		@Override
getActions(InstallableUnitOperand operand)93 		protected List<ProvisioningAction> getActions(InstallableUnitOperand operand) {
94 			IInstallableUnit unit = operand.second();
95 			List<ProvisioningAction> parsedActions = getActions(unit, phaseId);
96 			if (parsedActions != null)
97 				return parsedActions;
98 
99 			ITouchpointType type = unit.getTouchpointType();
100 			if (type == null || type == ITouchpointType.NONE)
101 				return null;
102 
103 			String actionId = getActionManager().getTouchpointQualifiedActionId(phaseId, type);
104 			ProvisioningAction action = getActionManager().getAction(actionId, null);
105 			if (action == null) {
106 				throw new IllegalArgumentException("action not found: " + phaseId);
107 			}
108 			return Collections.singletonList(action);
109 		}
110 	}
111 
112 	private IEngine engine;
113 
PhaseTest(String name)114 	public PhaseTest(String name) {
115 		super(name);
116 	}
117 
PhaseTest()118 	public PhaseTest() {
119 		super("");
120 	}
121 
122 	@Override
setUp()123 	protected void setUp() throws Exception {
124 		engine = getEngine();
125 	}
126 
127 	@Override
tearDown()128 	protected void tearDown() throws Exception {
129 		super.tearDown();
130 		engine = null;
131 	}
132 
testNullPhaseId()133 	public void testNullPhaseId() {
134 		try {
135 			new TestPhase(null, 1);
136 		} catch (IllegalArgumentException expected) {
137 			return;
138 		}
139 		fail();
140 	}
141 
testEmptyPhaseId()142 	public void testEmptyPhaseId() {
143 		try {
144 			new TestPhase("", 1);
145 		} catch (IllegalArgumentException expected) {
146 			return;
147 		}
148 		fail();
149 	}
150 
testNegativeWeight()151 	public void testNegativeWeight() {
152 		try {
153 			new TestPhase("xyz", -1);
154 		} catch (IllegalArgumentException expected) {
155 			return;
156 		}
157 		fail();
158 	}
159 
testZeroWeight()160 	public void testZeroWeight() {
161 		try {
162 			new TestPhase("xyz", 0);
163 		} catch (IllegalArgumentException expected) {
164 			return;
165 		}
166 		fail();
167 	}
168 
testPerform()169 	public void testPerform() {
170 		PhaseSet phaseSet = new TestPhaseSet(new TestPhase());
171 		IProfile profile = createProfile("PhaseTest");
172 
173 		engine.perform(engine.createPlan(profile, null), phaseSet, new NullProgressMonitor());
174 	}
175 
testInitCompletePhase()176 	public void testInitCompletePhase() {
177 		TestPhase phase = new TestPhase() {
178 			@Override
179 			protected IStatus initializePhase(IProgressMonitor monitor, IProfile profile, Map<String, Object> parameters) {
180 				assertFalse(parameters.containsKey("TestPhase.initializePhase"));
181 				assertFalse(completePhase);
182 				super.initializePhase(monitor, profile, parameters);
183 				assertTrue(parameters.containsKey("TestPhase.initializePhase"));
184 				assertFalse(completePhase);
185 				return null;
186 			}
187 
188 			@Override
189 			protected IStatus completePhase(IProgressMonitor monitor, IProfile profile, Map<String, Object> parameters) {
190 				assertTrue(parameters.containsKey("TestPhase.initializePhase"));
191 				assertFalse(completePhase);
192 				super.completePhase(monitor, profile, parameters);
193 				assertTrue(parameters.containsKey("TestPhase.initializePhase"));
194 				assertTrue(completePhase);
195 				return null;
196 			}
197 		};
198 		PhaseSet phaseSet = new TestPhaseSet(phase);
199 		IProfile profile = createProfile("PhaseTest");
200 		IInstallableUnit unit = createIU("unit");
201 		IProvisioningPlan plan = engine.createPlan(profile, null);
202 		plan.addInstallableUnit(unit);
203 		engine.perform(plan, phaseSet, new NullProgressMonitor());
204 		assertTrue(phase.initializePhase);
205 		assertTrue(phase.completePhase);
206 	}
207 
testInitCompleteOperand()208 	public void testInitCompleteOperand() {
209 		TestPhase phase = new TestPhase() {
210 			@Override
211 			protected IStatus completeOperand(IProfile profile, Operand operand, Map<String, Object> parameters, IProgressMonitor monitor) {
212 				assertTrue(parameters.containsKey("TestPhase.initializeOperand"));
213 				assertFalse(completeOperand);
214 				super.completeOperand(profile, operand, parameters, monitor);
215 				assertTrue(parameters.containsKey("TestPhase.initializeOperand"));
216 				assertTrue(completeOperand);
217 				return null;
218 			}
219 
220 			@Override
221 			protected IStatus initializeOperand(IProfile profile, Operand operand, Map<String, Object> parameters, IProgressMonitor monitor) {
222 				assertFalse(parameters.containsKey("TestPhase.initializeOperand"));
223 				assertFalse(completeOperand);
224 				super.initializeOperand(profile, operand, parameters, monitor);
225 				assertTrue(parameters.containsKey("TestPhase.initializeOperand"));
226 				assertFalse(completeOperand);
227 				return null;
228 			}
229 		};
230 		PhaseSet phaseSet = new TestPhaseSet(phase);
231 		IProfile profile = createProfile("PhaseTest");
232 		IInstallableUnit unit = createIU("testInitCompleteOperand");
233 
234 		IProvisioningPlan plan = engine.createPlan(profile, null);
235 		plan.addInstallableUnit(unit);
236 		engine.perform(plan, phaseSet, new NullProgressMonitor());
237 		assertTrue(phase.initializeOperand);
238 		assertTrue(phase.completeOperand);
239 	}
240 
testGetProfileDataArea()241 	public void testGetProfileDataArea() {
242 		TestPhase phase = new TestPhase() {
243 			@Override
244 			protected IStatus initializePhase(IProgressMonitor monitor, IProfile profile, Map<String, Object> parameters) {
245 				File profileDataArea = (File) parameters.get("profileDataDirectory");
246 				assertTrue(profileDataArea.isDirectory());
247 				File test = new File(profileDataArea, "test");
248 				assertFalse(test.exists());
249 				try {
250 					test.createNewFile();
251 				} catch (IOException e) {
252 					fail(e.getMessage());
253 				}
254 				assertTrue(test.exists());
255 				return super.initializePhase(monitor, profile, parameters);
256 			}
257 
258 			@Override
259 			protected IStatus completePhase(IProgressMonitor monitor, IProfile profile, Map<String, Object> parameters) {
260 				File profileDataArea = (File) parameters.get("profileDataDirectory");
261 				assertTrue(profileDataArea.isDirectory());
262 				File test = new File(profileDataArea, "test");
263 				assertTrue(test.exists());
264 				test.delete();
265 				assertFalse(test.exists());
266 				return super.completePhase(monitor, profile, parameters);
267 			}
268 		};
269 		PhaseSet phaseSet = new TestPhaseSet(phase);
270 		IProfile profile = createProfile("PhaseTest");
271 		IInstallableUnit unit = createIU("testGetProfileDataArea");
272 
273 		IProvisioningPlan plan = engine.createPlan(profile, null);
274 		plan.addInstallableUnit(unit);
275 		engine.perform(plan, phaseSet, new NullProgressMonitor());
276 		assertTrue(phase.initializePhase);
277 		assertTrue(phase.completePhase);
278 	}
279 
280 	public static class TestAction extends ProvisioningAction {
281 
282 		@Override
execute(Map<String, Object> parameters)283 		public IStatus execute(Map<String, Object> parameters) {
284 			return null;
285 		}
286 
287 		@Override
undo(Map<String, Object> parameters)288 		public IStatus undo(Map<String, Object> parameters) {
289 			return null;
290 		}
291 	}
292 
testGetAction()293 	public void testGetAction() {
294 		final ArrayList<ProvisioningAction> actionsList1 = new ArrayList<>();
295 		InstallableUnitPhase phase1 = new InstallableUnitPhase("test", 1) {
296 			@Override
297 			protected List<ProvisioningAction> getActions(InstallableUnitOperand operand) {
298 				List<ProvisioningAction> actions = getActions(operand.second(), "test1");
299 				actionsList1.addAll(actions);
300 				return actions;
301 			}
302 		};
303 		final ArrayList<ProvisioningAction> actionsList2 = new ArrayList<>();
304 		InstallableUnitPhase phase2 = new InstallableUnitPhase("test", 1) {
305 			@Override
306 			protected List<ProvisioningAction> getActions(InstallableUnitOperand operand) {
307 				List<ProvisioningAction> actions = getActions(operand.second(), "test2");
308 				actionsList2.addAll(actions);
309 				return actions;
310 			}
311 		};
312 
313 		PhaseSet phaseSet = new TestPhaseSet(new Phase[] {phase1, phase2});
314 		IProfile profile = createProfile("PhaseTest");
315 
316 		Map<String, Object> instructions = new HashMap<>();
317 		instructions.put("test1", MetadataFactory.createTouchpointInstruction("test1.test()", null));
318 		instructions.put("test2", MetadataFactory.createTouchpointInstruction("test2.test()", null));
319 		ITouchpointData touchpointData = MetadataFactory.createTouchpointData(instructions);
320 		IInstallableUnit unit = createIU("test", Version.create("1.0.0"), null, NO_REQUIRES, new IProvidedCapability[0], NO_PROPERTIES, ITouchpointType.NONE, touchpointData, false);
321 		IProvisioningPlan plan = engine.createPlan(profile, null);
322 		plan.addInstallableUnit(unit);
323 		IStatus status = engine.perform(plan, phaseSet, new NullProgressMonitor());
324 		if (!status.isOK()) {
325 			fail(status.toString());
326 		}
327 
328 		assertEquals(TestAction.class, ((ParameterizedProvisioningAction) actionsList1.get(0)).getAction().getClass());
329 		assertEquals(TestAction.class, ((ParameterizedProvisioningAction) actionsList2.get(0)).getAction().getClass());
330 	}
331 
testCancelHappenBeforeCompleteCollectPhase()332 	public void testCancelHappenBeforeCompleteCollectPhase() {
333 		final String testDataLocation = "testData/mirror/mirrorSourceRepo3";
334 		Set<IInstallableUnit> ius = null;
335 		try {
336 			IArtifactRepositoryManager mgr = getArtifactRepositoryManager();
337 			mgr.loadRepository((getTestData("test artifact repo", testDataLocation).toURI()), null);
338 			IMetadataRepositoryManager metaManager = getMetadataRepositoryManager();
339 			IMetadataRepository metaRepo = metaManager.loadRepository((getTestData("test metadata repo", testDataLocation).toURI()), null);
340 			ius = metaRepo.query(QueryUtil.ALL_UNITS, null).toUnmodifiableSet();
341 		} catch (Exception e) {
342 			fail("1.0", e);
343 		}
344 		class MyCollect extends Collect {
345 			boolean isCancelled = false;
346 			int progress = 0;
347 			final static int THREHOLD = 2;
348 
349 			public MyCollect(int weight) {
350 				super(weight);
351 			}
352 
353 			@Override
354 			protected List<ProvisioningAction> getActions(InstallableUnitOperand operand) {
355 				List<ProvisioningAction> actions = super.getActions(operand);
356 				if (actions != null)
357 					progress++;
358 				if (progress > THREHOLD)
359 					isCancelled = true;
360 				return actions;
361 			}
362 		}
363 		final MyCollect collect = new MyCollect(100);
364 		PhaseSet phaseSet = new TestPhaseSet(new Phase[] {collect});
365 		IProfile profile = createProfile("PhaseTest");
366 		IProvisioningPlan plan = engine.createPlan(profile, null);
367 		for (IInstallableUnit iu : ius)
368 			plan.addInstallableUnit(iu);
369 		class TestListener implements ProvisioningListener {
370 			boolean collectEvent = false;
371 
372 			@Override
373 			public void notify(EventObject o) {
374 				if (o instanceof CollectEvent)
375 					collectEvent = true;
376 			}
377 
378 		}
379 		TestListener listener = new TestListener();
380 		getEventBus().addListener(listener);
381 		try {
382 			IStatus status = engine.perform(plan, phaseSet, new NullProgressMonitor() {
383 				@Override
384 				public boolean isCanceled() {
385 					return collect.isCancelled;
386 				}
387 			});
388 			if (!status.matches(IStatus.CANCEL)) {
389 				fail(status.toString());
390 			}
391 			assertFalse("Collect actually happened!", listener.collectEvent);
392 		} finally {
393 			getEventBus().removeListener(listener);
394 		}
395 	}
396 }
397