Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Keller2015-05-26 17:49:54 +0000
committerMarkus Keller2015-05-26 17:49:54 +0000
commit18beb6714e3f702433eb9c54371fa9b57e83555c (patch)
treed1571049486cac1868cc392ea149698f0d501fee
parent521f380f74708f1b72e7b9ffabacf5bfbc3b90d0 (diff)
downloadeclipse.platform.ua-18beb6714e3f702433eb9c54371fa9b57e83555c.tar.gz
eclipse.platform.ua-18beb6714e3f702433eb9c54371fa9b57e83555c.tar.xz
eclipse.platform.ua-18beb6714e3f702433eb9c54371fa9b57e83555c.zip
Bug 468364: Add test for generated extension point and API docsI20150526-2010
-rw-r--r--org.eclipse.ua.tests.doc/src/org/eclipse/ua/tests/doc/AllTests.java10
-rw-r--r--org.eclipse.ua.tests.doc/src/org/eclipse/ua/tests/doc/internal/linkchecker/ApiDocTest.java270
2 files changed, 276 insertions, 4 deletions
diff --git a/org.eclipse.ua.tests.doc/src/org/eclipse/ua/tests/doc/AllTests.java b/org.eclipse.ua.tests.doc/src/org/eclipse/ua/tests/doc/AllTests.java
index 11d83ef63..6cc2b5a69 100644
--- a/org.eclipse.ua.tests.doc/src/org/eclipse/ua/tests/doc/AllTests.java
+++ b/org.eclipse.ua.tests.doc/src/org/eclipse/ua/tests/doc/AllTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009 IBM Corporation and others.
+ * Copyright (c) 2009, 2015 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
@@ -10,12 +10,13 @@
*******************************************************************************/
package org.eclipse.ua.tests.doc;
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
+import org.eclipse.ua.tests.doc.internal.linkchecker.ApiDocTest;
import org.eclipse.ua.tests.doc.internal.linkchecker.PrebuiltIndexChecker;
import org.eclipse.ua.tests.doc.internal.linkchecker.TocLinkChecker;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
/*
* Tests all user assistance functionality (automated).
*/
@@ -34,5 +35,6 @@ public class AllTests extends TestSuite {
public AllTests() {
addTestSuite(PrebuiltIndexChecker.class);
addTestSuite(TocLinkChecker.class);
+ addTestSuite(ApiDocTest.class);
}
}
diff --git a/org.eclipse.ua.tests.doc/src/org/eclipse/ua/tests/doc/internal/linkchecker/ApiDocTest.java b/org.eclipse.ua.tests.doc/src/org/eclipse/ua/tests/doc/internal/linkchecker/ApiDocTest.java
new file mode 100644
index 000000000..83a225d88
--- /dev/null
+++ b/org.eclipse.ua.tests.doc/src/org/eclipse/ua/tests/doc/internal/linkchecker/ApiDocTest.java
@@ -0,0 +1,270 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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.ua.tests.doc.internal.linkchecker;
+
+import java.net.URL;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.regex.Pattern;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.RegistryFactory;
+import org.eclipse.help.IHelpResource;
+import org.eclipse.help.IToc;
+import org.eclipse.help.IUAElement;
+import org.eclipse.help.internal.toc.TocContribution;
+import org.eclipse.help.internal.toc.TocFile;
+import org.eclipse.help.internal.toc.TocFileParser;
+import org.eclipse.osgi.service.resolver.ExportPackageDescription;
+import org.eclipse.osgi.service.resolver.PlatformAdmin;
+import org.eclipse.osgi.service.resolver.State;
+import org.eclipse.ua.tests.doc.internal.Activator;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import junit.framework.TestCase;
+
+public class ApiDocTest extends TestCase {
+
+ static class InternalExtensionFoundException extends SAXException {
+ private static final long serialVersionUID = 1L;
+ }
+
+ static class InternalExtensionFinder extends DefaultHandler {
+ /* Look for this pattern:
+ <element name="extension">
+ <annotation>
+ <appInfo>
+ <meta.element internal="true" />
+ */
+
+ int state = 0;
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+ switch (state) {
+ case 0:
+ if ("element".equalsIgnoreCase(qName) && "extension".equals(attributes.getValue("name")))
+ state = 1;
+ break;
+
+ case 1:
+ if ("annotation".equalsIgnoreCase(qName))
+ state = 2;
+ break;
+
+ case 2:
+ if ("appInfo".equalsIgnoreCase(qName))
+ state = 3;
+ break;
+
+ case 3:
+ if ("meta.element".equalsIgnoreCase(qName) && "true".equals(attributes.getValue("internal"))) {
+ throw new InternalExtensionFoundException();
+ }
+ break;
+ }
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ state = 0;
+ }
+ }
+
+ private static final String[] TOCS = {
+ "org.eclipse.platform.doc.isv",
+ "org.eclipse.jdt.doc.isv",
+ "org.eclipse.pde.doc.user",
+ };
+ private static final String TOPICS_REFERENCE_XML = "topics_Reference.xml";
+ private static final String REFERENCE_EXTENSION_POINTS = "reference/extension-points/";
+ private static final String REFERENCE_API = "reference/api/";
+ private static final Pattern NON_API_PACKAGES = Pattern.compile(".+\\.(?:internal|tests|examples)(?:\\..+)?");
+
+ /**
+ * Missing extension points / API packages currently don't make this test fail,
+ * since the list contains false positives (esp. when run locally). The test doesn't
+ * know which bundles eventually end up in the build, and which bundles are:
+ * <ul>
+ * <li>part of the test infrastructure</li>
+ * <li>dependencies (e.g. from Orbit)</li>
+ * <li>unrelated projects in the user's workspace that are not excluded in the launch configuration</li>
+ * </ul>
+ *
+ * However, the test prints potentially missing extension points / API packages to System.out.
+ *
+ * @throws Exception
+ */
+ public void testTopicsReference() throws Exception {
+ System.out.println("Running " + ApiDocTest.class.getName() + "#testTopicsReference()\n");
+
+ StringBuilder problems = new StringBuilder();
+
+ Set<String> extIds = new TreeSet<String>();
+ Set<String> packageIds = new TreeSet<String>();
+
+ TocFileParser parser = new TocFileParser();
+ for (String tocFile : TOCS) {
+ TocContribution contribution = parser.parse(new TocFile(tocFile, TOPICS_REFERENCE_XML, true, "en", null, null));
+ IToc toc = contribution.getToc();
+ IUAElement[] children = toc.getChildren();
+ for (IUAElement child : children) {
+ for (IUAElement child2 : child.getChildren()) {
+ if (child2 instanceof IHelpResource) {
+ IHelpResource topic = (IHelpResource) child2;
+ String href = topic.getHref();
+ if (href != null) {
+ if (href.startsWith(REFERENCE_EXTENSION_POINTS)) {
+ String id = topic.getLabel();
+ if (!extIds.add(id) ) {
+ problems.append("Extension point label '" + id + "' appears more than once in '" + TOPICS_REFERENCE_XML + "' files.\n");
+ continue;
+ }
+ String filename = href.substring(REFERENCE_EXTENSION_POINTS.length());
+ String expectedFileName = id.replace('.', '_') + ".html";
+ if (!expectedFileName.equals(filename)) {
+ problems.append("File name for extension point '" + id + "' expected: '" + expectedFileName + "' but was: '" + filename + "'\n");
+ }
+ } else if (href.startsWith(REFERENCE_API)) {
+ String id = topic.getLabel();
+ if (!packageIds.add(id) ) {
+ problems.append("API package label '" + id + "' appears more than once in '" + TOPICS_REFERENCE_XML + "' files.\n");
+ continue;
+ }
+ String filename = href.substring(REFERENCE_API.length());
+ String expectedFileName = id.replace('.', '/') + "/package-summary.html";
+ if (!expectedFileName.equals(filename)) {
+ problems.append("File name for package label '" + id + "' expected: '" + expectedFileName + "' but was: '" + filename + "'\n");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ checkExtensionPoints(extIds, problems);
+ checkPackages(packageIds, problems);
+
+ assertEquals("", problems.toString());
+ }
+
+ protected void checkExtensionPoints(Set<String> extIds, StringBuilder problems) throws Exception {
+ Set<String> registeredIds = new TreeSet<String>();
+
+ IExtensionRegistry registry = RegistryFactory.getRegistry();
+ IExtensionPoint[] extensionPoints = registry.getExtensionPoints();
+ for (IExtensionPoint extensionPoint : extensionPoints) {
+ String id = extensionPoint.getUniqueIdentifier();
+ String schemaReference = extensionPoint.getSchemaReference();
+ if (schemaReference == null) {
+ problems.append("Extension point missing a schema reference: " + id + "\n");
+ } else {
+ String contributor = extensionPoint.getContributor().getName();
+ Bundle bundle = Platform.getBundle(contributor);
+ URL schema = bundle.getEntry(schemaReference);
+ if (schema == null || schemaReference.isEmpty()) {
+ System.out.append("Extension point schema file not found for " + id + ": " + schemaReference + "\n");
+ continue;
+ }
+
+ SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+ SAXParser parser = parserFactory.newSAXParser();
+ InternalExtensionFinder handler = new InternalExtensionFinder();
+ try {
+ parser.parse(schema.toString(), handler);
+ } catch (InternalExtensionFoundException e) {
+ continue; // don't report internal extension points
+ }
+ }
+ registeredIds.add(id);
+ }
+
+ TreeSet<String> unexpectedTocIds = new TreeSet<String>(extIds);
+ unexpectedTocIds.removeAll(registeredIds);
+ if (!unexpectedTocIds.isEmpty()) {
+ problems.append("\n* Unexpected extension points in " + TOPICS_REFERENCE_XML + ":\n");
+ for (String unexpectedTocId : unexpectedTocIds) {
+ problems.append(unexpectedTocId).append('\n');
+ }
+ }
+
+ registeredIds.removeAll(extIds);
+ if (!registeredIds.isEmpty()) {
+ // these currently don't make the test fail, since the list contains false positives (esp. when run locally)
+ System.out.append("\n* Undocumented (non-internal) extension points:\n");
+ for (String registeredId : registeredIds) {
+ System.out.append(registeredId).append('\n');
+ }
+ }
+ }
+
+ protected void checkPackages(Set<String> packageIds, StringBuilder problems) {
+ Set<String> exportedPackageIds = new TreeSet<String>();
+
+ exportedPackageIds.add("org.eclipse.core.runtime.adaptor"); // not exported, but makes sense to document since accessible from outside of OSGi framework
+ exportedPackageIds.add("org.eclipse.swt.ole.win32"); // somehow missing from State#getExportedPackages(), maybe because it's declared in the fragment only
+
+ BundleContext context = Activator.getDefault().getBundle().getBundleContext();
+ ServiceReference<PlatformAdmin> platformAdminReference = context.getServiceReference(PlatformAdmin.class);
+ PlatformAdmin service = context.getService(platformAdminReference);
+ State state = service.getState(false);
+ ExportPackageDescription[] exportedPackages = state.getExportedPackages();
+ for (ExportPackageDescription exportPackageDescription : exportedPackages) {
+ String name = exportPackageDescription.getName();
+ if (!NON_API_PACKAGES.matcher(name).matches()) {
+ if (Boolean.TRUE.equals(exportPackageDescription.getDirective("x-internal"))
+ || exportPackageDescription.getDirective("x-friends") != null) {
+ continue;
+ }
+ exportedPackageIds.add(name);
+// Enumeration<String> packageChildren = exportPackageDescription.getSupplier().getBundle().getEntryPaths(name.replace('.', '/'));
+// while (packageChildren != null && packageChildren.hasMoreElements()) {
+// String child = packageChildren.nextElement();
+// if (child.endsWith(".class")) {
+// exportedPackageIds.add(name);
+// break pack;
+// }
+// }
+// System.out.append("Exported package without class files: ").append(name).append('\n');
+ }
+ }
+
+ TreeSet<String> unexpectedPackageIds = new TreeSet<String>(packageIds);
+ unexpectedPackageIds.removeAll(exportedPackageIds);
+ if (!unexpectedPackageIds.isEmpty()) {
+ problems.append("\n* Unexpected exported API packages in " + TOPICS_REFERENCE_XML + ":\n");
+ for (String unexpectedTocId : unexpectedPackageIds) {
+ problems.append(unexpectedTocId).append('\n');
+ }
+ }
+
+ exportedPackageIds.removeAll(packageIds);
+ if (!exportedPackageIds.isEmpty()) {
+ // these currently don't make the test fail, since the list contains false positives (esp. when run locally)
+ System.out.append("\n* Undocumented exported API package:\n");
+ for (String exportedPackageId : exportedPackageIds) {
+ System.out.append(exportedPackageId).append('\n');
+ }
+ }
+ }
+
+}

Back to the top