1 /*******************************************************************************
2  *  Copyright (c) 2008, 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.updatesite;
15 
16 import java.io.ByteArrayOutputStream;
17 import java.io.File;
18 import java.io.FileOutputStream;
19 import java.io.IOException;
20 import java.io.OutputStream;
21 import java.io.PrintStream;
22 import java.lang.reflect.Field;
23 import java.net.URI;
24 import java.net.URISyntaxException;
25 import java.util.Collection;
26 import java.util.Map;
27 import javax.xml.parsers.DocumentBuilder;
28 import javax.xml.parsers.DocumentBuilderFactory;
29 import junit.framework.Test;
30 import junit.framework.TestSuite;
31 import org.eclipse.core.runtime.IProgressMonitor;
32 import org.eclipse.core.runtime.IStatus;
33 import org.eclipse.core.runtime.NullProgressMonitor;
34 import org.eclipse.core.runtime.URIUtil;
35 import org.eclipse.equinox.internal.p2.artifact.repository.MirrorSelector;
36 import org.eclipse.equinox.internal.p2.artifact.repository.RawMirrorRequest;
37 import org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepository;
38 import org.eclipse.equinox.internal.p2.metadata.ArtifactKey;
39 import org.eclipse.equinox.internal.p2.metadata.IRequiredCapability;
40 import org.eclipse.equinox.internal.p2.updatesite.SiteFeature;
41 import org.eclipse.equinox.internal.p2.updatesite.UpdateSite;
42 import org.eclipse.equinox.internal.p2.updatesite.artifact.UpdateSiteArtifactRepository;
43 import org.eclipse.equinox.p2.core.ProvisionException;
44 import org.eclipse.equinox.p2.metadata.IArtifactKey;
45 import org.eclipse.equinox.p2.metadata.IInstallableUnit;
46 import org.eclipse.equinox.p2.metadata.IRequirement;
47 import org.eclipse.equinox.p2.metadata.ITouchpointData;
48 import org.eclipse.equinox.p2.metadata.ITouchpointInstruction;
49 import org.eclipse.equinox.p2.metadata.Version;
50 import org.eclipse.equinox.p2.metadata.VersionRange;
51 import org.eclipse.equinox.p2.query.IQuery;
52 import org.eclipse.equinox.p2.query.IQueryResult;
53 import org.eclipse.equinox.p2.query.QueryUtil;
54 import org.eclipse.equinox.p2.repository.IRepository;
55 import org.eclipse.equinox.p2.repository.IRepositoryManager;
56 import org.eclipse.equinox.p2.repository.artifact.ArtifactKeyQuery;
57 import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor;
58 import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
59 import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
60 import org.eclipse.equinox.p2.repository.artifact.spi.ArtifactDescriptor;
61 import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
62 import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
63 import org.eclipse.equinox.p2.repository.spi.AbstractRepository;
64 import org.eclipse.equinox.p2.tests.AbstractProvisioningTest;
65 import org.eclipse.equinox.p2.tests.StringBufferStream;
66 import org.w3c.dom.Document;
67 import org.w3c.dom.Element;
68 import org.w3c.dom.NodeList;
69 
70 /**
71  * @since 1.0
72  */
73 public class UpdateSiteTest extends AbstractProvisioningTest {
74 	/*
75 	 * Constructor for the class.
76 	 */
UpdateSiteTest(String name)77 	public UpdateSiteTest(String name) {
78 		super(name);
79 	}
80 
81 	/*
82 	 * Run all the tests in this class.
83 	 */
suite()84 	public static Test suite() {
85 		return new TestSuite(UpdateSiteTest.class);
86 	}
87 
testRelativeSiteURL()88 	public void testRelativeSiteURL() {
89 		File site = getTestData("0.1", "/testData/updatesite/siteurl");
90 		UpdateSite updatesite = null;
91 		try {
92 			updatesite = UpdateSite.load(site.toURI(), getTransport(), getMonitor());
93 		} catch (ProvisionException e) {
94 			fail("0.2", e);
95 		}
96 
97 		try {
98 			int featureCount = updatesite.loadFeatures(new NullProgressMonitor()).length;
99 			assertEquals(1, featureCount);
100 		} catch (ProvisionException e) {
101 			fail("0.4", e);
102 		}
103 	}
104 
testAbsoluteSiteURL()105 	public void testAbsoluteSiteURL() {
106 		File site = getTestData("0.1", "/testData/updatesite/siteurl2");
107 		File siteDirectory = getTestData("0.1", "/testData/updatesite/siteurl2/siteurl/");
108 		UpdateSite updatesite = null;
109 		try {
110 			updatesite = UpdateSite.load(site.toURI(), getTransport(), getMonitor());
111 			updatesite.getSite().setLocationURIString(siteDirectory.toURI().toString());
112 		} catch (ProvisionException e) {
113 			fail("0.2", e);
114 		}
115 
116 		try {
117 			int featureCount = updatesite.loadFeatures(new NullProgressMonitor()).length;
118 			assertEquals(1, featureCount);
119 		} catch (ProvisionException e) {
120 			fail("0.4", e);
121 		}
122 	}
123 
testDefaultDigestURL()124 	public void testDefaultDigestURL() {
125 		File site = getTestData("0.1", "/testData/updatesite/digest");
126 		UpdateSite updatesite = null;
127 		try {
128 			updatesite = UpdateSite.load(site.toURI(), getTransport(), getMonitor());
129 		} catch (ProvisionException e) {
130 			fail("0.2", e);
131 		}
132 
133 		try {
134 			int featureCount = updatesite.loadFeatures(new NullProgressMonitor()).length;
135 			assertEquals(1, featureCount);
136 		} catch (ProvisionException e) {
137 			fail("0.4", e);
138 		}
139 	}
140 
testZippedDefaultDigestURL()141 	public void testZippedDefaultDigestURL() throws URISyntaxException {
142 		File site = getTestData("0.1", "/testData/updatesite/digest/site.zip");
143 		URI siteURI = new URI("jar:" + site.toURI() + "!/");
144 		UpdateSite updatesite = null;
145 		try {
146 			updatesite = UpdateSite.load(siteURI, getTransport(), getMonitor());
147 		} catch (ProvisionException e) {
148 			fail("0.2", e);
149 		}
150 
151 		try {
152 			int featureCount = updatesite.loadFeatures(new NullProgressMonitor()).length;
153 			assertEquals(1, featureCount);
154 		} catch (ProvisionException e) {
155 			fail("0.4", e);
156 		}
157 	}
158 
testRelativeDigestURL()159 	public void testRelativeDigestURL() {
160 		File site = getTestData("0.1", "/testData/updatesite/digesturl");
161 		UpdateSite updatesite = null;
162 		try {
163 			updatesite = UpdateSite.load(site.toURI(), getTransport(), getMonitor());
164 		} catch (ProvisionException e) {
165 			fail("0.2", e);
166 		}
167 
168 		try {
169 			int featureCount = updatesite.loadFeatures(new NullProgressMonitor()).length;
170 			assertEquals(1, featureCount);
171 		} catch (ProvisionException e) {
172 			fail("0.4", e);
173 		}
174 	}
175 
testAbsoluteDigestURL()176 	public void testAbsoluteDigestURL() {
177 		File site = getTestData("0.1", "/testData/updatesite/digesturl2");
178 		File digestDirectory = getTestData("0.1", "/testData/updatesite/digesturl2/digesturl/");
179 		UpdateSite updatesite = null;
180 		try {
181 			updatesite = UpdateSite.load(site.toURI(), getTransport(), getMonitor());
182 			updatesite.getSite().setDigestURIString(digestDirectory.toURI().toString());
183 		} catch (ProvisionException e) {
184 			fail("0.2", e);
185 		}
186 
187 		try {
188 			int featureCount = updatesite.loadFeatures(new NullProgressMonitor()).length;
189 			assertEquals(1, featureCount);
190 		} catch (ProvisionException e) {
191 			fail("0.4", e);
192 		}
193 	}
194 
195 	/*
196 	 * Test in which we load an update site from a valid site.xml file. Handle
197 	 * all the variations in the file.
198 	 */
testNoDigestGoodSite()199 	public void testNoDigestGoodSite() {
200 		File site = getTestData("0.1", "/testData/updatesite/site");
201 		UpdateSite updatesite = null;
202 		try {
203 			updatesite = UpdateSite.load(site.toURI(), getTransport(), getMonitor());
204 		} catch (ProvisionException e) {
205 			fail("0.2", e);
206 		}
207 		try {
208 			int featureCount = updatesite.loadFeatures(new NullProgressMonitor()).length;
209 			assertEquals(1, featureCount);
210 		} catch (ProvisionException e) {
211 			fail("0.4", e);
212 		}
213 	}
214 
testNoEndingSlashURL()215 	public void testNoEndingSlashURL() {
216 		File base = getTestData("0.1", "/testData/updatesite");
217 		UpdateSite updatesite = null;
218 		try {
219 			URI siteURL = base.toURI().resolve("site");
220 			updatesite = UpdateSite.load(siteURL, getTransport(), getMonitor());
221 		} catch (ProvisionException e) {
222 			fail("0.2", e);
223 		}
224 		try {
225 			int featureCount = updatesite.loadFeatures(new NullProgressMonitor()).length;
226 			assertEquals(1, featureCount);
227 		} catch (ProvisionException e) {
228 			fail("0.4", e);
229 		}
230 	}
231 
testSiteXMLURL()232 	public void testSiteXMLURL() {
233 		File site = getTestData("0.1", "/testData/updatesite/site/site.xml");
234 		UpdateSite updatesite = null;
235 		try {
236 			updatesite = UpdateSite.load(site.toURI(), getTransport(), getMonitor());
237 		} catch (ProvisionException e) {
238 			fail("0.2", e);
239 		}
240 		try {
241 			int featureCount = updatesite.loadFeatures(getMonitor()).length;
242 			assertEquals(1, featureCount);
243 		} catch (ProvisionException e) {
244 			fail("0.4", e);
245 		}
246 	}
247 
testSiteWithSpaces()248 	public void testSiteWithSpaces() {
249 		File site = getTestData("0.1", "/testData/updatesite/site with spaces/");
250 		UpdateSite updatesite = null;
251 		try {
252 			updatesite = UpdateSite.load(site.toURI(), getTransport(), getMonitor());
253 		} catch (ProvisionException e) {
254 			fail("0.2", e);
255 		}
256 		try {
257 			int featureCount = updatesite.loadFeatures(new NullProgressMonitor()).length;
258 			assertEquals(1, featureCount);
259 		} catch (ProvisionException e) {
260 			fail("0.4", e);
261 		}
262 	}
263 
testXXXSiteXXXXMLURL()264 	public void testXXXSiteXXXXMLURL() {
265 		File site = getTestData("0.1", "/testData/updatesite/xxxsitexxx/xxxsitexxx.xml");
266 		UpdateSite updatesite = null;
267 		try {
268 			updatesite = UpdateSite.load(site.toURI(), getTransport(), getMonitor());
269 		} catch (ProvisionException e) {
270 			fail("0.2", e);
271 		}
272 		try {
273 			int featureCount = updatesite.loadFeatures(new NullProgressMonitor()).length;
274 			assertEquals(1, featureCount);
275 		} catch (ProvisionException e) {
276 			fail("0.4", e);
277 		}
278 	}
279 
testBadXXXSiteXXXXMLURL()280 	public void testBadXXXSiteXXXXMLURL() {
281 		File siteDir = getTestData("0.1", "/testData/updatesite/xxxsitexxx");
282 		File site = new File(siteDir, "site.xml");
283 		try {
284 			UpdateSite.load(site.toURI(), getTransport(), getMonitor());
285 			fail("0.2");
286 		} catch (ProvisionException e) {
287 			// expected
288 		}
289 	}
290 
testBadDigestGoodSite()291 	public void testBadDigestGoodSite() {
292 		File site = getTestData("0.1", "/testData/updatesite/baddigestgoodsite");
293 		UpdateSite updatesite = null;
294 		try {
295 			updatesite = UpdateSite.load(site.toURI(), getTransport(), getMonitor());
296 		} catch (ProvisionException e) {
297 			fail("0.2", e);
298 		}
299 		try {
300 			updatesite.loadFeatures(new NullProgressMonitor());
301 		} catch (ProvisionException e) {
302 			fail("0.4", e);
303 		}
304 	}
305 
testCorruptDigestGoodSite()306 	public void testCorruptDigestGoodSite() {
307 		File site = getTestData("0.1", "/testData/updatesite/corruptdigestgoodsite");
308 		UpdateSite updatesite = null;
309 		try {
310 			updatesite = UpdateSite.load(site.toURI(), getTransport(), getMonitor());
311 		} catch (ProvisionException e) {
312 			fail("0.2", e);
313 		}
314 		StringBuffer buffer = new StringBuffer();
315 		PrintStream out = System.out;
316 		try {
317 			System.setOut(new PrintStream(new StringBufferStream(buffer)));
318 			updatesite.loadFeatures(new NullProgressMonitor());
319 		} catch (ProvisionException e) {
320 			fail("0.4", e);
321 		} finally {
322 			System.setOut(out);
323 		}
324 		assertTrue(buffer.toString().contains("Content is not allowed in prolog."));
325 	}
326 
testBadDigestBadSite()327 	public void testBadDigestBadSite() {
328 		File site = getTestData("0.1", "/testData/updatesite/baddigestbadsite");
329 		try {
330 			UpdateSite.load(site.toURI(), getTransport(), getMonitor());
331 			fail("0.2");
332 		} catch (ProvisionException e) {
333 			// expected
334 		}
335 	}
336 
testBadSiteXML()337 	public void testBadSiteXML() {
338 		// handle the case where the site.xml doesn't parse correctly
339 		File site = getTestData("0.1", "/testData/updatesite/badSiteXML");
340 		try {
341 			UpdateSite.load(site.toURI(), getTransport(), getMonitor());
342 			fail("0.2");
343 		} catch (ProvisionException e) {
344 			// expected exception
345 		}
346 	}
347 
348 	/*
349 	 * Test the case where we don't have a digest or site.xml.
350 	 */
testNoSite()351 	public void testNoSite() {
352 		// ensure we have a validate, empty location
353 		File temp = getTempFolder();
354 		temp.mkdirs();
355 		try {
356 			UpdateSite.load(temp.toURI(), getTransport(), getMonitor());
357 			fail("0.2");
358 		} catch (ProvisionException e) {
359 			// we expect an exception
360 		}
361 	}
362 
testNullSite()363 	public void testNullSite() {
364 		try {
365 			assertNull("1.0", UpdateSite.load(null, getTransport(), getMonitor()));
366 		} catch (ProvisionException e) {
367 			fail("1.99", e);
368 		}
369 	}
370 
testBadFeatureURL()371 	public void testBadFeatureURL() {
372 		File site = getTestData("0.1", "/testData/updatesite/badfeatureurl");
373 		UpdateSite updatesite = null;
374 		try {
375 			updatesite = UpdateSite.load(site.toURI(), getTransport(), getMonitor());
376 		} catch (ProvisionException e) {
377 			fail("0.2", e);
378 		}
379 		StringBuffer buffer = new StringBuffer();
380 		PrintStream out = System.out;
381 		try {
382 			System.setOut(new PrintStream(new StringBufferStream(buffer)));
383 			int featureCount = updatesite.loadFeatures(new NullProgressMonitor()).length;
384 			assertEquals(0, featureCount);
385 		} catch (ProvisionException e) {
386 			fail("0.5");
387 
388 		} finally {
389 			System.setOut(out);
390 		}
391 		assertTrue(buffer.toString().contains("Error reading feature"));
392 	}
393 
testGoodFeatureURL()394 	public void testGoodFeatureURL() {
395 		File site = getTestData("0.1", "/testData/updatesite/goodfeatureurl");
396 		UpdateSite updatesite = null;
397 		try {
398 			updatesite = UpdateSite.load(site.toURI(), getTransport(), getMonitor());
399 		} catch (ProvisionException e) {
400 			fail("0.2", e);
401 		}
402 		try {
403 			int featureCount = updatesite.loadFeatures(new NullProgressMonitor()).length;
404 			assertEquals(1, featureCount);
405 		} catch (ProvisionException e) {
406 			fail("0.5");
407 		}
408 	}
409 
testZippedGoodFeatureURL()410 	public void testZippedGoodFeatureURL() throws URISyntaxException {
411 
412 		File site = getTestData("0.1", "/testData/updatesite/goodfeatureurl/site.zip");
413 		URI siteURI = new URI("jar:" + site.toURI() + "!/");
414 		UpdateSite updatesite = null;
415 		try {
416 			updatesite = UpdateSite.load(siteURI, getTransport(), getMonitor());
417 		} catch (ProvisionException e) {
418 			fail("0.2", e);
419 		}
420 
421 		try {
422 			int featureCount = updatesite.loadFeatures(new NullProgressMonitor()).length;
423 			assertEquals(1, featureCount);
424 		} catch (ProvisionException e) {
425 			fail("0.5");
426 		}
427 	}
428 
testIncludedFeature()429 	public void testIncludedFeature() {
430 		File site = getTestData("0.1", "/testData/updatesite/includedfeature");
431 		UpdateSite updatesite = null;
432 		try {
433 			updatesite = UpdateSite.load(site.toURI(), getTransport(), getMonitor());
434 		} catch (ProvisionException e) {
435 			fail("0.2", e);
436 		}
437 		try {
438 			int featureCount = updatesite.loadFeatures(new NullProgressMonitor()).length;
439 			assertEquals(2, featureCount);
440 		} catch (ProvisionException e) {
441 			fail("0.5");
442 		}
443 	}
444 
testIncludedFeatureArchive()445 	public void testIncludedFeatureArchive() {
446 		File site = getTestData("0.1", "/testData/updatesite/includedfeaturearchive");
447 		UpdateSite updatesite = null;
448 		try {
449 			updatesite = UpdateSite.load(site.toURI(), getTransport(), getMonitor());
450 		} catch (ProvisionException e) {
451 			fail("0.2", e);
452 		}
453 		try {
454 			int featureCount = updatesite.loadFeatures(new NullProgressMonitor()).length;
455 			assertEquals(2, featureCount);
456 		} catch (ProvisionException e) {
457 			fail("0.5");
458 		}
459 	}
460 
testBadIncludedFeatureArchive()461 	public void testBadIncludedFeatureArchive() {
462 		File site = getTestData("0.1", "/testData/updatesite/badincludedfeaturearchive");
463 		UpdateSite updatesite = null;
464 		try {
465 			updatesite = UpdateSite.load(site.toURI(), getTransport(), getMonitor());
466 		} catch (ProvisionException e) {
467 			fail("0.2", e);
468 		}
469 		StringBuffer buffer = new StringBuffer();
470 		PrintStream out = System.out;
471 		try {
472 			System.setOut(new PrintStream(new StringBufferStream(buffer)));
473 			int featureCount = updatesite.loadFeatures(new NullProgressMonitor()).length;
474 			assertEquals(1, featureCount);
475 		} catch (ProvisionException e) {
476 			fail("0.5");
477 		} finally {
478 			System.setOut(out);
479 		}
480 		assertTrue(buffer.toString().contains("Error reading feature"));
481 	}
482 
testNoFeatureIdAndVersion()483 	public void testNoFeatureIdAndVersion() {
484 		File site = getTestData("0.1", "/testData/updatesite/nofeatureidandversion");
485 		UpdateSite updatesite = null;
486 		try {
487 			updatesite = UpdateSite.load(site.toURI(), getTransport(), getMonitor());
488 		} catch (ProvisionException e) {
489 			fail("0.2", e);
490 		}
491 		try {
492 			int featureCount = updatesite.loadFeatures(new NullProgressMonitor()).length;
493 			assertEquals(2, featureCount);
494 		} catch (ProvisionException e) {
495 			fail("0.5");
496 		}
497 	}
498 
testSiteFeatureVersionEquals()499 	public void testSiteFeatureVersionEquals() {
500 		SiteFeature a = new SiteFeature();
501 		SiteFeature b = new SiteFeature();
502 		assertEquals("1.0", a, b);
503 		b.setFeatureVersion("1.0.0");
504 		a.setFeatureVersion("1.0.0");
505 		b.setFeatureVersion("1.0.0");
506 		assertEquals("1.1", a, b);
507 		b.setFeatureVersion("2.0.0");
508 		assertFalse("1.2", a.equals(b));
509 		b.setFeatureVersion(null);
510 		assertFalse("1.3", a.equals(b));
511 		assertFalse("1.4", b.equals(a));
512 	}
513 
testSiteFeatureLabelEquals()514 	public void testSiteFeatureLabelEquals() {
515 		SiteFeature a = new SiteFeature();
516 		SiteFeature b = new SiteFeature();
517 		assertEquals("1.0", a, b);
518 		a.setLabel("foo");
519 		b.setLabel("foo");
520 		assertEquals("1.1", a, b);
521 		b.setLabel("bar");
522 		assertFalse("1.2", a.equals(b));
523 		b.setLabel(null);
524 		assertFalse("1.3", a.equals(b));
525 		assertFalse("1.4", b.equals(a));
526 	}
527 
testSiteFeatureIDEquals()528 	public void testSiteFeatureIDEquals() {
529 		SiteFeature a = new SiteFeature();
530 		SiteFeature b = new SiteFeature();
531 		assertEquals("1.0", a, b);
532 		a.setFeatureIdentifier("org.foo");
533 		b.setFeatureIdentifier("org.foo");
534 		assertEquals("1.1", a, b);
535 		b.setFeatureIdentifier("org.bar");
536 		assertFalse("1.2", a.equals(b));
537 		b.setFeatureIdentifier(null);
538 		assertFalse("1.3", a.equals(b));
539 		assertFalse("1.4", b.equals(a));
540 	}
541 
testSiteFeatureEquals()542 	public void testSiteFeatureEquals() {
543 		SiteFeature a = new SiteFeature();
544 		SiteFeature b = new SiteFeature();
545 		assertEquals("1.0", a, b);
546 		a.setURLString("http://foo");
547 		assertFalse("1.1", a.equals(b));
548 		b.setURLString("http://foo");
549 		assertEquals("1.2", a, b);
550 		a.setURLString("http://FOO");
551 		assertEquals("1.3", a, b);
552 		a.setURLString("file://FOO");
553 		assertFalse("1.4", a.equals(b));
554 		a.setURLString(null);
555 		assertFalse("1.5", a.equals(b));
556 		assertFalse("1.6", b.equals(a));
557 	}
558 
testSiteFeatureHash()559 	public void testSiteFeatureHash() {
560 		SiteFeature a = new SiteFeature();
561 		SiteFeature b = new SiteFeature();
562 		assertEquals("1.0", a.hashCode(), b.hashCode());
563 		a.setURLString("http://foo");
564 		b.setURLString("http://foo");
565 		assertEquals("1.1", a.hashCode(), b.hashCode());
566 		a.setURLString("http://FOO/");
567 		assertEquals("1.2", a.hashCode(), b.hashCode());
568 		a.setURLString("foo");
569 		b.setURLString("FoO");
570 		assertEquals("1.3", a.hashCode(), b.hashCode());
571 	}
572 
testSiteFeatureNotEquals()573 	public void testSiteFeatureNotEquals() {
574 		SiteFeature a = new SiteFeature();
575 		SiteFeature b = new SiteFeature();
576 		assertEquals("1.0", a, b);
577 		a.setURLString("file:/c:/foo");
578 		assertFalse("1.1", a.equals(b));
579 		b.setURLString("file:/c:/bar");
580 		assertFalse("1.2", a.equals(b));
581 		assertFalse("1.3", b.equals(a));
582 		a.setURLString("http://foo");
583 		b.setURLString("http://bar/");
584 		assertFalse("1.4", b.equals(a));
585 	}
586 
testSiteFeatureFileURL()587 	public void testSiteFeatureFileURL() {
588 		SiteFeature a = new SiteFeature();
589 		SiteFeature b = new SiteFeature();
590 		assertEquals("1.0", a, b);
591 		a.setURLString("file:/c:/foo");
592 		b.setURLString("file:/c:/FOO");
593 		if (a.equals(b))
594 			assertEquals("1.1", a.hashCode(), b.hashCode());
595 		a.setURLString("FILE:/c:/foo");
596 		b.setURLString("file:/c:/FOO");
597 		if (a.equals(b))
598 			assertEquals("1.2", a.hashCode(), b.hashCode());
599 		a.setURLString("HTTP://example.com");
600 		b.setURLString("HTtP://example.com");
601 		if (a.equals(b))
602 			assertEquals("1.3", a.hashCode(), b.hashCode());
603 		a.setURLString("HTTP://eXaMpLe.com");
604 		b.setURLString("HTtP://example.com");
605 		if (a.equals(b))
606 			assertEquals("1.4", a.hashCode(), b.hashCode());
607 		a.setURLString("HTTP://eXaMpLe.com/");
608 		b.setURLString("HTtP://example.com");
609 		assertEquals(a, b);
610 		if (a.equals(b))
611 			assertEquals("1.5", a.hashCode(), b.hashCode());
612 		a.setURLString("http://localhost");
613 		b.setURLString("http://127.0.0.1");
614 		if (a.equals(b))
615 			assertEquals("1.6", a.hashCode(), b.hashCode());
616 	}
617 
testRepoWithFeatureWithNullUpdateURL()618 	public void testRepoWithFeatureWithNullUpdateURL() {
619 		IMetadataRepositoryManager repoMan = getAgent().getService(IMetadataRepositoryManager.class);
620 		assertNotNull(repoMan);
621 		File site = getTestData("Update site", "/testData/updatesite/missingUpdateURLFeature/");
622 		IMetadataRepository metadataRepo = null;
623 		StringBuffer buffer = new StringBuffer();
624 		PrintStream out = System.out;
625 		try {
626 			System.setOut(new PrintStream(new StringBufferStream(buffer)));
627 			metadataRepo = repoMan.loadRepository(site.toURI(), null);
628 		} catch (ProvisionException e) {
629 			fail("Can't load repository missingUpdateURLFeature");
630 		} finally {
631 			System.setOut(out);
632 		}
633 		assertTrue(buffer.toString().contains("Invalid site reference null in feature test.featurewithmissingupdateurl."));
634 		IQuery<IInstallableUnit> query = QueryUtil.createIUQuery("test.featurewithmissingupdateurl.feature.group", Version.create("1.0.0"));
635 		IQueryResult<IInstallableUnit> result = metadataRepo.query(query, null);
636 		assertEquals("1.0", 1, queryResultSize(result));
637 	}
638 
639 	/**
640 	 * Tests that a feature requiring a bundle with no range is converted correctly.
641 	 */
testBug243422()642 	public void testBug243422() {
643 		IMetadataRepositoryManager repoMan = getAgent().getService(IMetadataRepositoryManager.class);
644 		assertNotNull(repoMan);
645 		File site = getTestData("Update site", "/testData/updatesite/UpdateSite243422/");
646 		IMetadataRepository metadataRepo = null;
647 		try {
648 			metadataRepo = repoMan.loadRepository(site.toURI(), null);
649 		} catch (ProvisionException e) {
650 			fail("Can't load repository UpdateSite243422");
651 		}
652 		IQuery<IInstallableUnit> query = QueryUtil.createIUQuery("org.eclipse.jdt.astview.feature.feature.group", Version.create("1.0.1"));
653 		IQueryResult<IInstallableUnit> result = metadataRepo.query(query, null);
654 		assertEquals("1.0", 1, queryResultSize(result));
655 		IInstallableUnit featureIU = result.iterator().next();
656 		for (IRequirement requirement : featureIU.getRequirements()) {
657 			IRequiredCapability req = (IRequiredCapability) requirement;
658 			if (req.getName().equals("org.eclipse.ui.ide")) {
659 				assertEquals("2.0", VersionRange.emptyRange, req.getRange());
660 			}
661 		}
662 	}
663 
testShortenVersionNumberInFeature()664 	public void testShortenVersionNumberInFeature() {
665 		IArtifactRepositoryManager repoMan = getAgent().getService(IArtifactRepositoryManager.class);
666 		assertNotNull(repoMan);
667 		File site = getTestData("Update site", "/testData/updatesite/240121/UpdateSite240121/");
668 		IArtifactRepository artifactRepo = null;
669 		try {
670 			artifactRepo = repoMan.loadRepository(site.toURI(), null);
671 		} catch (ProvisionException e) {
672 			fail("Can't load repository UpdateSite240121");
673 		}
674 		IQueryResult<IArtifactKey> keys = artifactRepo.query(new ArtifactKeyQuery(null, "Plugin240121", null), null);
675 		assertEquals(1, queryResultSize(keys));
676 		IArtifactKey key = keys.iterator().next();
677 		IStatus status = artifactRepo.getArtifact(artifactRepo.getArtifactDescriptors(key)[0], new ByteArrayOutputStream(500), new NullProgressMonitor());
678 		if (!status.isOK())
679 			fail("Can't get the expected artifact:" + key);
680 	}
681 
682 	/**
683 	 * Tests that the feature jar IU has the appropriate touchpoint instruction for
684 	 * unzipping the feature on install.
685 	 */
testFeatureJarUnzipInstruction()686 	public void testFeatureJarUnzipInstruction() {
687 		IMetadataRepositoryManager repoMan = getAgent().getService(IMetadataRepositoryManager.class);
688 		File site = getTestData("0.1", "/testData/updatesite/site");
689 		URI location = null;
690 		location = site.toURI();
691 		IMetadataRepository repository;
692 		try {
693 			repository = repoMan.loadRepository(location, getMonitor());
694 		} catch (ProvisionException e) {
695 			fail("1.99", e);
696 			return;
697 		}
698 		IQueryResult<IInstallableUnit> result = repository.query(QueryUtil.createIUQuery("test.feature.feature.jar"), getMonitor());
699 		assertTrue("1.0", !result.isEmpty());
700 		IInstallableUnit unit = result.iterator().next();
701 		Collection<ITouchpointData> data = unit.getTouchpointData();
702 		assertEquals("1.1", 1, data.size());
703 		Map<String, ITouchpointInstruction> instructions = data.iterator().next().getInstructions();
704 		assertEquals("1.2", 1, instructions.size());
705 		assertEquals("1.3", "true", instructions.get("zipped").getBody());
706 	}
707 
708 	/**
709 	 * TODO Failing test, see bug 265528.
710 	 */
_testFeatureSiteReferences()711 	public void _testFeatureSiteReferences() throws ProvisionException, URISyntaxException {
712 		File site = getTestData("0.1", "/testData/updatesite/siteFeatureReferences");
713 		URI siteURI = site.toURI();
714 		URI testUpdateSite = new URI("http://download.eclipse.org/test/updatesite/");
715 		URI testDiscoverySite = new URI("http://download.eclipse.org/test/discoverysite");
716 
717 		IMetadataRepositoryManager manager = getAgent().getService(IMetadataRepositoryManager.class);
718 		assertNotNull(manager);
719 		manager.removeRepository(testUpdateSite);
720 		manager.removeRepository(testDiscoverySite);
721 		IMetadataRepository repository = manager.loadRepository(siteURI, 0, getMonitor());
722 		try {
723 			//wait for site references to be published asynchronously
724 			Thread.sleep(1000);
725 		} catch (InterruptedException e) {
726 			fail("4.99", e);
727 		}
728 		assertNotNull(repository);
729 		assertTrue("1.0", manager.contains(testUpdateSite));
730 		assertTrue("1.1", manager.contains(testDiscoverySite));
731 		assertFalse("1.2", manager.isEnabled(testUpdateSite));
732 		assertFalse("1.3", manager.isEnabled(testDiscoverySite));
733 	}
734 
testMetadataRepoCount()735 	public void testMetadataRepoCount() {
736 		File site = getTestData("0.1", "/testData/updatesite/site");
737 		URI siteURI = site.toURI();
738 
739 		IMetadataRepositoryManager metadataRepoMan = getAgent().getService(IMetadataRepositoryManager.class);
740 		assertNotNull(metadataRepoMan);
741 
742 		URI[] knownRepos = metadataRepoMan.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL);
743 		for (URI knownRepo : knownRepos) {
744 			if (siteURI.equals(knownRepo)) {
745 				metadataRepoMan.removeRepository(siteURI);
746 				knownRepos = metadataRepoMan.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL);
747 				break;
748 			}
749 		}
750 
751 		try {
752 			metadataRepoMan.loadRepository(site.toURI(), getMonitor());
753 		} catch (ProvisionException e) {
754 			fail("1.0", e);
755 			return;
756 		}
757 		URI[] afterKnownRepos = metadataRepoMan.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL);
758 		assertTrue("1.1", afterKnownRepos.length == knownRepos.length + 1);
759 	}
760 
testArtifactRepoCount()761 	public void testArtifactRepoCount() {
762 		File site = getTestData("0.1", "/testData/updatesite/site");
763 		URI siteURI = site.toURI();
764 
765 		IArtifactRepositoryManager artifactRepoMan = getAgent().getService(IArtifactRepositoryManager.class);
766 		assertNotNull(artifactRepoMan);
767 
768 		URI[] knownRepos = artifactRepoMan.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL);
769 		for (URI knownRepo : knownRepos) {
770 			if (siteURI.equals(knownRepo)) {
771 				artifactRepoMan.removeRepository(siteURI);
772 				knownRepos = artifactRepoMan.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL);
773 				break;
774 			}
775 		}
776 
777 		try {
778 			artifactRepoMan.loadRepository(site.toURI(), getMonitor());
779 		} catch (ProvisionException e) {
780 			fail("1.0", e);
781 			return;
782 		}
783 		URI[] afterKnownRepos = artifactRepoMan.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL);
784 		assertTrue("1.1", afterKnownRepos.length == knownRepos.length + 1);
785 	}
786 
testPack200()787 	public void testPack200() {
788 		File output = new File(getTempFolder(), getUniqueString());
789 		File site = getTestData("0.1", "/testData/updatesite/packedSiteWithMirror");
790 		URI siteURI = site.toURI();
791 
792 		IArtifactRepository repo = null;
793 		try {
794 			repo = getArtifactRepositoryManager().loadRepository(siteURI, new NullProgressMonitor());
795 		} catch (ProvisionException e) {
796 			fail("0.2", e);
797 		}
798 		IArtifactKey key = new ArtifactKey("org.eclipse.update.feature", "test.feature", Version.create("1.0.0"));
799 		IArtifactDescriptor[] descriptors = repo.getArtifactDescriptors(key);
800 
801 		// Should have a packed & canonical version
802 		assertEquals(2, descriptors.length);
803 		IArtifactDescriptor desc = IArtifactDescriptor.FORMAT_PACKED.equals(descriptors[0].getProperty(IArtifactDescriptor.FORMAT)) ? descriptors[0] : descriptors[1];
804 		try (OutputStream out = new FileOutputStream(output)) {
805 
806 			IStatus status = repo.getRawArtifact(desc, out, new NullProgressMonitor());
807 			// Transfer should succeed
808 			assertTrue(status.isOK());
809 			// Length should be as expected
810 			assertEquals(480, output.length());
811 		} catch (IOException e) {
812 			fail("Failed", e);
813 		} finally {
814 			getArtifactRepositoryManager().removeRepository(siteURI);
815 		}
816 	}
817 
testMirrors()818 	public void testMirrors() {
819 		String testDataLocation = "/testData/updatesite/packedSiteWithMirror";
820 		File targetLocation = null;
821 		URI siteURI = getTestData("0.1", testDataLocation).toURI();
822 		try {
823 			IArtifactKey key = new ArtifactKey("osgi.bundle", "test.fragment", Version.create("1.0.0"));
824 			// Load source repository
825 			IArtifactRepository sourceRepo = getArtifactRepositoryManager().loadRepository(siteURI, getMonitor());
826 
827 			// Hijack source repository's mirror selector
828 			new OrderedMirrorSelector(sourceRepo, testDataLocation);
829 
830 			// Create target repository
831 			targetLocation = File.createTempFile("target", ".repo");
832 			targetLocation.delete();
833 			targetLocation.mkdirs();
834 			IArtifactRepository targetRepository = new SimpleArtifactRepository(getAgent(), "TargetRepo", targetLocation.toURI(), null);
835 
836 			// Load the packed descriptor
837 			IArtifactDescriptor[] descriptors = sourceRepo.getArtifactDescriptors(key);
838 			IArtifactDescriptor descriptor = null;
839 			for (int i = 0; i < descriptors.length && descriptor == null; i++)
840 				if (IArtifactDescriptor.FORMAT_PACKED.equals(descriptors[i].getProperty(IArtifactDescriptor.FORMAT)))
841 					descriptor = descriptors[i];
842 
843 			if (descriptor == null)
844 				fail("0.3");
845 
846 			RawMirrorRequest mirror = new RawMirrorRequest(descriptor, new ArtifactDescriptor(descriptor), targetRepository, getTransport());
847 			mirror.perform(sourceRepo, getMonitor());
848 
849 			assertTrue(mirror.getResult().isOK());
850 			assertTrue(targetRepository.contains(key));
851 		} catch (Exception e) {
852 			fail("0.2", e);
853 		} finally {
854 			if (targetLocation != null)
855 				delete(targetLocation);
856 			getArtifactRepositoryManager().removeRepository(siteURI);
857 		}
858 	}
859 
860 	/*
861 	 * Special mirror selector for testing which chooses mirrors in order
862 	 */
863 	protected class OrderedMirrorSelector extends MirrorSelector {
864 		private URI repoLocation;
865 		int index = 0;
866 		MirrorInfo[] mirrors;
867 		IArtifactRepository repo;
868 
OrderedMirrorSelector(IArtifactRepository repo, String testDataLocation)869 		OrderedMirrorSelector(IArtifactRepository repo, String testDataLocation) throws Exception {
870 			super(repo, getTransport());
871 			this.repo = repo;
872 			// Alternatively we could use reflect to change "location" of the repo
873 			setRepoSelector();
874 			getRepoLocation();
875 			mirrors = computeMirrors("file:///" + getTestData("Mirror Location", testDataLocation + '/' + repo.getProperties().get(IRepository.PROP_MIRRORS_URL)).toString().replace('\\', '/'));
876 		}
877 
setRepoSelector()878 		private void setRepoSelector() throws Exception {
879 			Field delegate = UpdateSiteArtifactRepository.class.getDeclaredField("delegate");
880 			delegate.setAccessible(true);
881 			// Hijack the source repository's MirrorSelector with ours which provides mirrors in order.
882 			Field mirrorsField = SimpleArtifactRepository.class.getDeclaredField("mirrors");
883 			mirrorsField.setAccessible(true);
884 			mirrorsField.set(delegate.get(repo), this);
885 
886 			// Setting this property forces SimpleArtifactRepository to use mirrors despite being a local repo
887 			Field properties = AbstractRepository.class.getDeclaredField("properties");
888 			properties.setAccessible(true);
889 			((Map) properties.get(delegate.get(repo))).put(SimpleArtifactRepository.PROP_FORCE_THREADING, String.valueOf(true));
890 		}
891 
892 		// Overridden to prevent mirror sorting
893 		@Override
reportResult(String toDownload, IStatus result)894 		public synchronized void reportResult(String toDownload, IStatus result) {
895 			return;
896 		}
897 
898 		// We want to test each mirror once.
899 		@Override
hasValidMirror()900 		public synchronized boolean hasValidMirror() {
901 			return mirrors != null && index < mirrors.length;
902 		}
903 
904 		@Override
getMirrorLocation(URI inputLocation, IProgressMonitor monitor)905 		public synchronized URI getMirrorLocation(URI inputLocation, IProgressMonitor monitor) {
906 			return URIUtil.append(nextMirror(), repoLocation.relativize(inputLocation).getPath());
907 		}
908 
nextMirror()909 		private URI nextMirror() {
910 			Field mirrorLocation = null;
911 			try {
912 				mirrorLocation = MirrorInfo.class.getDeclaredField("locationString");
913 				mirrorLocation.setAccessible(true);
914 
915 				if (index < mirrors.length)
916 					return URIUtil.makeAbsolute(new URI((String) mirrorLocation.get(mirrors[index++])), repoLocation);
917 				return repoLocation;
918 			} catch (Exception e) {
919 				fail(Double.toString(0.4 + index), e);
920 				return null;
921 			}
922 		}
923 
getRepoLocation()924 		private synchronized void getRepoLocation() {
925 			Field locationField = null;
926 			try {
927 				locationField = UpdateSiteArtifactRepository.class.getDeclaredField("location");
928 				locationField.setAccessible(true);
929 				repoLocation = (URI) locationField.get(repo);
930 			} catch (Exception e) {
931 				fail("0.3", e);
932 			}
933 		}
934 
computeMirrors(String mirrorsURL)935 		private MirrorInfo[] computeMirrors(String mirrorsURL) {
936 			// Copied & modified from MirrorSelector
937 			try {
938 				DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
939 				DocumentBuilder builder = domFactory.newDocumentBuilder();
940 				Document document = builder.parse(mirrorsURL);
941 				if (document == null)
942 					return null;
943 				NodeList mirrorNodes = document.getElementsByTagName("mirror"); //$NON-NLS-1$
944 				int mirrorCount = mirrorNodes.getLength();
945 				MirrorInfo[] infos = new MirrorInfo[mirrorCount + 1];
946 				for (int i = 0; i < mirrorCount; i++) {
947 					Element mirrorNode = (Element) mirrorNodes.item(i);
948 					String infoURL = mirrorNode.getAttribute("url"); //$NON-NLS-1$
949 					infos[i] = new MirrorInfo(infoURL, i);
950 				}
951 				//p2: add the base site as the last resort mirror so we can track download speed and failure rate
952 				infos[mirrorCount] = new MirrorInfo(repoLocation.toString(), mirrorCount);
953 				return infos;
954 			} catch (Exception e) {
955 				// log if absolute url
956 				if (mirrorsURL != null && (mirrorsURL.startsWith("http://") //$NON-NLS-1$
957 						|| mirrorsURL.startsWith("https://") //$NON-NLS-1$
958 						|| mirrorsURL.startsWith("file://") //$NON-NLS-1$
959 						|| mirrorsURL.startsWith("ftp://") //$NON-NLS-1$
960 						|| mirrorsURL.startsWith("jar://"))) //$NON-NLS-1$
961 					fail("Error processing mirrors URL: " + mirrorsURL, e); //$NON-NLS-1$
962 				return null;
963 			}
964 		}
965 	}
966 }