blob: ea63d84be3c257a7b05170c0874521e5de857ad7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.pde.api.tools.util.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.filebuffers.ITextFileBufferManager;
import org.eclipse.core.filebuffers.LocationKind;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.TagElement;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.pde.api.tools.internal.ApiBaselineManager;
import org.eclipse.pde.api.tools.internal.model.ApiModelFactory;
import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
import org.eclipse.pde.api.tools.internal.provisional.Factory;
import org.eclipse.pde.api.tools.internal.provisional.IApiAnnotations;
import org.eclipse.pde.api.tools.internal.provisional.IApiBaselineManager;
import org.eclipse.pde.api.tools.internal.provisional.IApiDescription;
import org.eclipse.pde.api.tools.internal.provisional.RestrictionModifiers;
import org.eclipse.pde.api.tools.internal.provisional.VisibilityModifiers;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiBaseline;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent;
import org.eclipse.pde.api.tools.internal.util.Signatures;
import org.eclipse.pde.api.tools.model.tests.TestSuiteHelper;
import org.eclipse.pde.api.tools.tests.AbstractApiTest;
import org.eclipse.pde.api.tools.tests.util.FileUtils;
import org.eclipse.pde.api.tools.tests.util.ProjectUtils;
import org.eclipse.pde.core.project.IBundleClasspathEntry;
import org.eclipse.pde.core.project.IBundleProjectDescription;
import org.eclipse.pde.core.project.IBundleProjectService;
import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.TextEdit;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* Tests the {@link ApiBaselineManager} without the framework running
*/
@SuppressWarnings("unchecked")
public class ApiBaselineManagerTests extends AbstractApiTest {
static final String THREE = "three"; //$NON-NLS-1$
static final String TESTDEFAULT = "testdefault"; //$NON-NLS-1$
static final String ADDTEST = "addtest"; //$NON-NLS-1$
class SourceChangeVisitor extends ASTVisitor {
String name = null;
String signature = null;
String tagname = null;
ASTRewrite rewrite = null;
boolean remove = false;
public SourceChangeVisitor(String name, String signature, String tagname, boolean remove, ASTRewrite rewrite) {
this.name = name;
this.signature = signature;
this.tagname = tagname;
this.rewrite = rewrite;
this.remove = remove;
}
@Override
public boolean visit(FieldDeclaration node) {
if (signature != null) {
return false;
}
List<VariableDeclarationFragment> fields = node.fragments();
VariableDeclarationFragment fragment = null;
for (Iterator<VariableDeclarationFragment> iter = fields.iterator(); iter.hasNext();) {
fragment = iter.next();
if (fragment.getName().getFullyQualifiedName().equals(name)) {
break;
}
}
if (fragment != null) {
updateTag(node);
}
return false;
}
@Override
public boolean visit(MethodDeclaration node) {
if (name.equals(node.getName().getFullyQualifiedName())) {
if (signature.equals(Signatures.getMethodSignatureFromNode(node, true))) {
updateTag(node);
}
}
return false;
}
@Override
public boolean visit(TypeDeclaration node) {
if (name.equals(node.getName().getFullyQualifiedName())) {
updateTag(node);
return false;
}
return true;
}
/**
* Updates a javadoc tag, by either adding a new one or removing an
* existing one
*
* @param body
*/
private void updateTag(BodyDeclaration body) {
Javadoc docnode = body.getJavadoc();
AST ast = body.getAST();
if (docnode == null) {
docnode = ast.newJavadoc();
rewrite.set(body, body.getJavadocProperty(), docnode, null);
}
ListRewrite lrewrite = rewrite.getListRewrite(docnode, Javadoc.TAGS_PROPERTY);
if (remove) {
List<TagElement> tags = (List<TagElement>) docnode.getStructuralProperty(Javadoc.TAGS_PROPERTY);
if (tags != null) {
TagElement tag = null;
for (TagElement tag2 : tags) {
tag = tag2;
if (tagname.equals(tag.getTagName())) {
lrewrite.remove(tag, null);
}
}
}
} else {
TagElement newtag = ast.newTagElement();
newtag.setTagName(tagname);
lrewrite.insertLast(newtag, null);
}
}
}
private IPath SRC_LOC = TestSuiteHelper.getPluginDirectoryPath().append("test-source").append("a").append("b").append("c"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
private IPath PLUGIN_LOC = TestSuiteHelper.getPluginDirectoryPath().append("test-plugins"); //$NON-NLS-1$
private IApiBaselineManager fPMmanager = ApiPlugin.getDefault().getApiBaselineManager();
private final String TESTING_PACKAGE = "a.b.c"; //$NON-NLS-1$
/**
* @return the {@link IApiDescription} for the testing project
*/
private IApiDescription getTestProjectApiDescription() throws CoreException {
IApiBaseline baseline = getWorkspaceBaseline();
assertNotNull("the workspace baseline must exist", baseline); //$NON-NLS-1$
IApiComponent component = baseline.getApiComponent(TESTING_PLUGIN_PROJECT_NAME);
if (component != null) {
return component.getApiDescription();
}
return null;
}
/**
* Creates and returns a test baseline with the given id. Also adds it to
* the baseline manager
*
* @param id
* @return
*/
protected IApiBaseline getTestBaseline(String id) {
IApiBaseline baseline = ApiModelFactory.newApiBaseline(id);
fPMmanager.addApiBaseline(baseline);
return baseline;
}
/**
* Tests trying to get the workspace baseline without the framework running
*/
@Test
public void testGetWorkspaceComponent() {
IApiBaseline baseline = getWorkspaceBaseline();
assertNotNull("the workspace baseline must not be null", baseline); //$NON-NLS-1$
}
/**
* Tests that an API baseline can be added and retrieved successfully
*/
@Test
public void testAddBaseline() {
IApiBaseline baseline = getTestBaseline(ADDTEST);
assertNotNull("the test baseline must have been created", baseline); //$NON-NLS-1$
assertTrue("the testadd baseline must be in the manager", fPMmanager.removeApiBaseline(ADDTEST)); //$NON-NLS-1$
}
/**
* Tests that an API baseline can be added/removed successfully
*/
@Test
public void testRemoveBaseline() {
IApiBaseline baseline = getTestBaseline("removetest"); //$NON-NLS-1$
assertNotNull("the testremove baseline must exist", baseline); //$NON-NLS-1$
baseline = fPMmanager.getApiBaseline("removetest"); //$NON-NLS-1$
assertNotNull("the testremove baseline must be in the manager", baseline); //$NON-NLS-1$
assertTrue("the testremove baseline should have been removed", fPMmanager.removeApiBaseline("removetest")); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Tests that the default baseline can be set/retrieved
*/
@Test
public void testSetDefaultBaseline() {
try {
IApiBaseline baseline = getTestBaseline(TESTDEFAULT);
assertNotNull("the testdefault baseline must exist", baseline); //$NON-NLS-1$
fPMmanager.setDefaultApiBaseline(TESTDEFAULT);
baseline = fPMmanager.getDefaultApiBaseline();
assertNotNull("the default baseline must be the testdefault baseline", baseline); //$NON-NLS-1$
} finally {
fPMmanager.removeApiBaseline(TESTDEFAULT);
}
}
/**
* Tests that all baselines added to the manager can be retrieved
*/
@Test
public void testGetAllBaselines() {
try {
fPMmanager.addApiBaseline(getTestBaseline(ADDTEST));
fPMmanager.addApiBaseline(getTestBaseline(TESTDEFAULT));
fPMmanager.addApiBaseline(getTestBaseline(THREE));
IApiBaseline[] baselines = fPMmanager.getApiBaselines();
assertEquals("there should be three baselines", 3, baselines.length); //$NON-NLS-1$
} finally {
fPMmanager.removeApiBaseline(ADDTEST);
fPMmanager.removeApiBaseline(TESTDEFAULT);
fPMmanager.removeApiBaseline(THREE);
}
}
/**
* Tests that all of the baselines have been removed
*/
@Test
public void testCleanUpMmanager() {
try {
fPMmanager.addApiBaseline(getTestBaseline(ADDTEST));
fPMmanager.addApiBaseline(getTestBaseline(TESTDEFAULT));
fPMmanager.addApiBaseline(getTestBaseline(THREE));
IApiBaseline[] baselines = fPMmanager.getApiBaselines();
assertEquals("there should be three baselines", 3, baselines.length); //$NON-NLS-1$
assertTrue("the testadd baseline should have been removed", fPMmanager.removeApiBaseline(ADDTEST)); //$NON-NLS-1$
assertTrue("the testdefault baseline should have been removed", fPMmanager.removeApiBaseline(TESTDEFAULT)); //$NON-NLS-1$
assertTrue("the three baseline should have been removed", fPMmanager.removeApiBaseline(THREE)); //$NON-NLS-1$
assertEquals("There sould be no more baselines", 0, fPMmanager.getApiBaselines().length); //$NON-NLS-1$
} finally {
fPMmanager.removeApiBaseline(ADDTEST);
fPMmanager.removeApiBaseline(TESTDEFAULT);
fPMmanager.removeApiBaseline(THREE);
}
}
/**
* Adds the given source to the given package in the given fragment root
*
* @param root the root to add the source to
* @param packagename the name of the package e.g. a.b.c
* @param sourcename the name of the source file without an extension e.g.
* TestClass1
*/
public void assertTestSource(IPackageFragmentRoot root, String packagename, String sourcename) throws InvocationTargetException, IOException {
IPackageFragment fragment = root.getPackageFragment(packagename);
FileUtils.importFileFromDirectory(SRC_LOC.append(sourcename + ".java").toFile(), fragment.getPath(), new NullProgressMonitor()); //$NON-NLS-1$
}
/**
* Adds the package with the given name to the given package fragment root
*
* @param the project to add the package to
* @param srcroot the absolute path to the package fragment root to add the
* new package to
* @param packagename the name of the new package
* @return the new {@link IPackageFragment} or <code>null</code>
*/
public IPackageFragment assertTestPackage(IJavaProject project, IPath srcroot, String packagename) throws JavaModelException {
IPackageFragment fragment = null;
IPackageFragmentRoot root = project.findPackageFragmentRoot(srcroot);
assertNotNull("the 'src' package fragment root must exist", root); //$NON-NLS-1$
fragment = root.createPackageFragment(packagename, true, new NullProgressMonitor());
assertNotNull("the new package '" + packagename + "' should have been created", fragment); //$NON-NLS-1$ //$NON-NLS-2$
return fragment;
}
/**
* Adds a test library with the given name to the test projects' class path.
* The library is imported from the {@link #PLUGIN_LOC} location.
*
* @param project the project to add the library classpath entry to
* @param folderpath the path in the project where the library should be
* imported to
* @param libname the name of the library
*/
public IFolder assertTestLibrary(IJavaProject project, IPath folderpath, String libname) throws CoreException, InvocationTargetException, IOException {
IFolder folder = null;
// import library
folder = project.getProject().getFolder(folderpath);
if (!folder.exists()) {
folder.create(false, true, null);
}
FileUtils.importFileFromDirectory(PLUGIN_LOC.append(libname).toFile(), folder.getFullPath(), null);
IPath libPath = folder.getFullPath().append(libname);
// add to manifest bundle classpath
ProjectUtils.addBundleClasspathEntry(project.getProject(), ProjectUtils.getBundleProjectService().newBundleClasspathEntry(null, null, libPath.removeFirstSegments(1)));
waitForAutoBuild();
return folder;
}
/**
* Asserts if the given restriction is on the specified source
*
* @param packagename
* @param sourcename
*/
public void assertSourceResctriction(String packagename, String sourcename, int restriction) throws CoreException {
IApiDescription desc = getTestProjectApiDescription();
assertNotNull("the testing project api description must exist", desc); //$NON-NLS-1$
IApiAnnotations annot = desc.resolveAnnotations(Factory.typeDescriptor(packagename + "." + sourcename)); //$NON-NLS-1$
assertNotNull("the annotations for " + packagename + "." + sourcename + " cannot be null", annot); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertEquals("there must be a noinstantiate setting for TestClass1", annot.getRestrictions(), restriction); //$NON-NLS-1$
}
/**
* Tests that closing an API aware project causes the workspace description
* to be updated
*/
@Test
public void testWPUpdateProjectClosed() throws Exception {
IJavaProject project = getTestingProject();
assertNotNull("The testing project must exist", project); //$NON-NLS-1$
assertNotNull("the workspace baseline must not be null", getWorkspaceBaseline()); //$NON-NLS-1$
IApiComponent component = getWorkspaceBaseline().getApiComponent(TESTING_PLUGIN_PROJECT_NAME);
assertNotNull("the change project api component must exist in the workspace baseline", component); //$NON-NLS-1$
project.getProject().close(new NullProgressMonitor());
component = getWorkspaceBaseline().getApiComponent(TESTING_PLUGIN_PROJECT_NAME);
assertNull("the test project api component should no longer exist in the workspace baseline", component); //$NON-NLS-1$
}
/**
* Tests that opening an API aware project causes the workspace description
* to be updated
*/
@Test
public void testWPUpdateProjectOpen() throws Exception {
IJavaProject project = getTestingProject();
assertNotNull("The testing project must exist", project); //$NON-NLS-1$
if (project.getProject().isAccessible()) {
project.getProject().close(new NullProgressMonitor());
}
project.getProject().open(new NullProgressMonitor());
IApiBaseline baseline = getWorkspaceBaseline();
assertNotNull("the workspace baseline must not be null", baseline); //$NON-NLS-1$
IApiComponent component = baseline.getApiComponent(TESTING_PLUGIN_PROJECT_NAME);
assertNotNull("the test project api component must exist in the workspace baseline", component); //$NON-NLS-1$
}
/**
* Tests that adding a source file to an API aware project causes the
* workspace description to be updated This test adds
* <code>a.b.c.TestClass1</code> to the plug-in project
*/
@Test
public void testWPUpdateSourceAdded() throws Exception {
IJavaProject project = getTestingProject();
assertNotNull("The testing project must exist", project); //$NON-NLS-1$
IPackageFragmentRoot root = project.findPackageFragmentRoot(new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute().makeAbsolute());
assertNotNull("the 'src' package fragment root must exist", root); //$NON-NLS-1$
assertTestSource(root, TESTING_PACKAGE, "TestClass1"); //$NON-NLS-1$
assertSourceResctriction(TESTING_PACKAGE, "TestClass1", RestrictionModifiers.NO_INSTANTIATE); //$NON-NLS-1$
}
/**
* Tests that removing a source file from an API aware project causes the
* workspace description to be updated
*/
@Test
public void testWPUpdateSourceRemoved() throws Exception {
IJavaProject project = getTestingProject();
assertNotNull("The testing project must exist", project); //$NON-NLS-1$
IPackageFragmentRoot root = project.findPackageFragmentRoot(new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute());
assertNotNull("the 'src' package fragment root must exist", root); //$NON-NLS-1$
assertTestSource(root, TESTING_PACKAGE, "TestClass1"); //$NON-NLS-1$
IJavaElement element = project.findElement(new Path("a/b/c/TestClass1.java")); //$NON-NLS-1$
assertNotNull("the class a.b.c.TestClass1 must exist in the project", element); //$NON-NLS-1$
element.getResource().delete(true, new NullProgressMonitor());
IApiDescription desc = getTestProjectApiDescription();
assertNotNull("the testing project api description must exist", desc); //$NON-NLS-1$
IApiAnnotations annot = desc.resolveAnnotations(Factory.typeDescriptor("a.b.c.TestClass1")); //$NON-NLS-1$
assertNull("the annotations for a.b.c.TestClass1 should no longer be present", annot); //$NON-NLS-1$
}
/**
* Adds the specified tag to the source member defined by the member name
* and signature
*
* @param unit
* @param membername
* @param signature
* @param tagname
* @param remove
* @throws CoreException
* @throws MalformedTreeException
* @throws BadLocationException
*/
private void updateTagInSource(ICompilationUnit unit, String membername, String signature, String tagname, boolean remove) throws CoreException, MalformedTreeException, BadLocationException {
ASTParser parser = ASTParser.newParser(AST.JLS_Latest);
parser.setSource(unit);
CompilationUnit cunit = (CompilationUnit) parser.createAST(new NullProgressMonitor());
assertNotNull("the ast compilation unit cannot be null", cunit); //$NON-NLS-1$
cunit.recordModifications();
ASTRewrite rewrite = ASTRewrite.create(cunit.getAST());
cunit.accept(new SourceChangeVisitor(membername, signature, tagname, remove, rewrite));
ITextFileBufferManager bm = FileBuffers.getTextFileBufferManager();
IPath path = cunit.getJavaElement().getPath();
try {
bm.connect(path, LocationKind.IFILE, null);
ITextFileBuffer tfb = bm.getTextFileBuffer(path, LocationKind.IFILE);
IDocument document = tfb.getDocument();
TextEdit edits = rewrite.rewriteAST(document, null);
edits.apply(document);
tfb.commit(new NullProgressMonitor(), true);
} finally {
bm.disconnect(path, LocationKind.IFILE, null);
}
}
/**
* Tests that making Javadoc changes to the source file TestClass2 cause the
* workspace baseline to be updated.
*
* This test adds a @noinstantiate tag to the source file TestClass2
*/
@Test
public void testWPUpdateSourceTypeChanged() throws Exception {
IJavaProject project = getTestingProject();
assertNotNull("The testing project must exist", project); //$NON-NLS-1$
IPackageFragmentRoot root = project.findPackageFragmentRoot(new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute());
assertNotNull("the 'src' package fragment root must exist", root); //$NON-NLS-1$
NullProgressMonitor monitor = new NullProgressMonitor();
IPackageFragment fragment = root.getPackageFragment("a.b.c"); //$NON-NLS-1$
FileUtils.importFileFromDirectory(SRC_LOC.append("TestClass2.java").toFile(), fragment.getPath(), monitor); //$NON-NLS-1$
ICompilationUnit element = (ICompilationUnit) project.findElement(new Path("a/b/c/TestClass2.java")); //$NON-NLS-1$
assertNotNull("TestClass2 must exist in the test project", element); //$NON-NLS-1$
updateTagInSource(element, "TestClass2", null, "@noinstantiate", false); //$NON-NLS-1$ //$NON-NLS-2$
IApiDescription desc = getTestProjectApiDescription();
assertNotNull("the testing project api description must exist", desc); //$NON-NLS-1$
IApiAnnotations annot = desc.resolveAnnotations(Factory.typeDescriptor("a.b.c.TestClass2")); //$NON-NLS-1$
assertNotNull("the annotations for a.b.c.TestClass2 cannot be null", annot); //$NON-NLS-1$
assertTrue("there must be a noinstantiate setting for TestClass2", (annot.getRestrictions() & RestrictionModifiers.NO_INSTANTIATE) != 0); //$NON-NLS-1$
assertTrue("there must be a noextend setting for TestClass2", (annot.getRestrictions() & RestrictionModifiers.NO_EXTEND) != 0); //$NON-NLS-1$
}
/**
* Tests that tags updated on an inner type are updated in the workspace
* description.
*
* This test adds a @noinstantiate tag to an inner class in TestClass3
*/
@Test
public void testWPUpdateSourceInnerTypeChanged() throws Exception {
IJavaProject project = getTestingProject();
assertNotNull("The testing project must exist", project); //$NON-NLS-1$
IPackageFragmentRoot root = project.findPackageFragmentRoot(new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute());
assertNotNull("the 'src' package fragment root must exist", root); //$NON-NLS-1$
assertTestSource(root, TESTING_PACKAGE, "TestClass3"); //$NON-NLS-1$
ICompilationUnit element = (ICompilationUnit) project.findElement(new Path("a/b/c/TestClass3.java")); //$NON-NLS-1$
assertNotNull("TestClass3 must exist in the test project", element); //$NON-NLS-1$
updateTagInSource(element, "InnerTestClass3", null, "@noinstantiate", false); //$NON-NLS-1$ //$NON-NLS-2$
IApiDescription desc = getTestProjectApiDescription();
assertNotNull("the testing project api description must exist", desc); //$NON-NLS-1$
IApiAnnotations annot = desc.resolveAnnotations(Factory.typeDescriptor("a.b.c.TestClass3$InnerTestClass3")); //$NON-NLS-1$
assertNotNull("the annotations for a.b.c.TestClass3$InnerTestClass3 cannot be null", annot); //$NON-NLS-1$
assertFalse("there must not be a noinstantiate setting for TestClass3$InnerTestClass3", (annot.getRestrictions() & RestrictionModifiers.NO_INSTANTIATE) != 0); //$NON-NLS-1$
assertFalse("there must not be a noextend setting for TestClass3$InnerTestClass3", (annot.getRestrictions() & RestrictionModifiers.NO_EXTEND) != 0); //$NON-NLS-1$
}
/**
* Tests that changing the javadoc for a method updates the workspace
* baseline
*
* This test adds a @noextend tag to the method foo() in TestClass1
*/
@Test
public void testWPUpdateSourceMethodChanged() throws Exception {
IJavaProject project = getTestingProject();
assertNotNull("The testing project must exist", project); //$NON-NLS-1$
IPackageFragmentRoot root = project.findPackageFragmentRoot(new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute());
assertNotNull("the 'src' package fragment root must exist", root); //$NON-NLS-1$
assertTestSource(root, TESTING_PACKAGE, "TestClass1"); //$NON-NLS-1$
ICompilationUnit element = (ICompilationUnit) project.findElement(new Path("a/b/c/TestClass1.java")); //$NON-NLS-1$
assertNotNull("TestClass1 must exist in the test project", element); //$NON-NLS-1$
updateTagInSource(element, "foo", "()V", "@nooverride", false); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
IApiDescription desc = getTestProjectApiDescription();
assertNotNull("the testing project api description must exist", desc); //$NON-NLS-1$
IApiAnnotations annot = desc.resolveAnnotations(Factory.methodDescriptor("a.b.c.TestClass1", "foo", "()V")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertNotNull("the annotations for foo() cannot be null", annot); //$NON-NLS-1$
assertTrue("there must be a nooverride setting for foo()", (annot.getRestrictions() & RestrictionModifiers.NO_OVERRIDE) != 0); //$NON-NLS-1$
}
/**
* Tests that changing the javadoc for a field updates the workspace
* baseline
*
* This test adds a @noextend tag to the field 'field' in TestField9
*/
@Test
public void testWPUpdateSourceFieldChanged() throws Exception {
IJavaProject project = getTestingProject();
assertNotNull("The testing project must exist", project); //$NON-NLS-1$
IPackageFragmentRoot root = project.findPackageFragmentRoot(new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute());
assertNotNull("the 'src' package fragment root must exist", root); //$NON-NLS-1$
assertTestSource(root, TESTING_PACKAGE, "TestField9"); //$NON-NLS-1$
ICompilationUnit element = (ICompilationUnit) project.findElement(new Path("a/b/c/TestField9.java")); //$NON-NLS-1$
assertNotNull("TestField9 must exist in the test project", element); //$NON-NLS-1$
updateTagInSource(element, "field", null, "@noreference", false); //$NON-NLS-1$ //$NON-NLS-2$
IApiDescription desc = getTestProjectApiDescription();
assertNotNull("the testing project api description must exist", desc); //$NON-NLS-1$
IApiAnnotations annot = desc.resolveAnnotations(Factory.fieldDescriptor("a.b.c.TestField9", "field")); //$NON-NLS-1$ //$NON-NLS-2$
assertNotNull("the annotations for 'field' cannot be null", annot); //$NON-NLS-1$
assertTrue("there must be a noreference setting for 'field'", (annot.getRestrictions() & RestrictionModifiers.NO_REFERENCE) != 0); //$NON-NLS-1$
}
/**
* Tests that removing a tag from a method updates the workspace baseline
*
* This test removes a @noextend tag to the method foo() in TestClass1
*/
@Test
public void testWPUpdateSourceMethodRemoveTag() throws Exception {
IJavaProject project = getTestingProject();
assertNotNull("The testing project must exist", project); //$NON-NLS-1$
IPackageFragmentRoot root = project.findPackageFragmentRoot(new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute());
assertNotNull("the 'src' package fragment root must exist", root); //$NON-NLS-1$
assertTestSource(root, TESTING_PACKAGE, "TestClass1"); //$NON-NLS-1$
ICompilationUnit element = (ICompilationUnit) project.findElement(new Path("a/b/c/TestClass1.java")); //$NON-NLS-1$
assertNotNull("TestClass1 must exist in the test project", element); //$NON-NLS-1$
updateTagInSource(element, "foo", "()V", "@nooverride", true); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
IApiDescription desc = getTestProjectApiDescription();
assertNotNull("the testing project api description must exist", desc); //$NON-NLS-1$
IApiAnnotations annot = desc.resolveAnnotations(Factory.methodDescriptor("a.b.c.TestClass1", "foo", "()V")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertNotNull("the annotations for foo() cannot be null", annot); //$NON-NLS-1$
assertTrue("there must be no restrictions for foo()", annot.getRestrictions() == 0); //$NON-NLS-1$
}
/**
* Tests that removing a tag from a type updates the workspace baseline
*
* This test removes a @noinstantiate tag to an inner class in TestClass3
*/
@Test
public void testWPUpdateSourceTypeRemoveTag() throws Exception {
IJavaProject project = getTestingProject();
assertNotNull("The testing project must exist", project); //$NON-NLS-1$
IPackageFragmentRoot root = project.findPackageFragmentRoot(new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute());
assertNotNull("the 'src' package fragment root must exist", root); //$NON-NLS-1$
assertTestSource(root, TESTING_PACKAGE, "TestClass3"); //$NON-NLS-1$
ICompilationUnit element = (ICompilationUnit) project.findElement(new Path("a/b/c/TestClass3.java")); //$NON-NLS-1$
assertNotNull("TestClass3 must exist in the test project", element); //$NON-NLS-1$
updateTagInSource(element, "InnerTestClass3", null, "@noextend", true); //$NON-NLS-1$ //$NON-NLS-2$
IApiDescription desc = getTestProjectApiDescription();
assertNotNull("the testing project api description must exist", desc); //$NON-NLS-1$
IApiAnnotations annot = desc.resolveAnnotations(Factory.typeDescriptor("a.b.c.TestClass3$InnerTestClass3")); //$NON-NLS-1$
assertNotNull("the annotations for 'InnerTestClass3' cannot be null", annot); //$NON-NLS-1$
assertTrue("there must be a no restrictions for 'InnerTestClass3'", (annot.getRestrictions() & RestrictionModifiers.NO_INSTANTIATE) == 0); //$NON-NLS-1$
}
/**
* Tests that removing a tag from a field updates the workspace baseline
*
* This test adds a @noextend tag to the field 'field' in TestField9
*/
@Test
public void testWPUpdateSourceFieldRemoveTag() throws Exception {
IJavaProject project = getTestingProject();
assertNotNull("The testing project must exist", project); //$NON-NLS-1$
IPackageFragmentRoot root = project.findPackageFragmentRoot(new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute());
assertNotNull("the 'src' package fragment root must exist", root); //$NON-NLS-1$
assertTestSource(root, TESTING_PACKAGE, "TestField9"); //$NON-NLS-1$
ICompilationUnit element = (ICompilationUnit) project.findElement(new Path("a/b/c/TestField9.java")); //$NON-NLS-1$
assertNotNull("TestField9 must exist in the test project", element); //$NON-NLS-1$
updateTagInSource(element, "field1", null, "@noreference", true); //$NON-NLS-1$ //$NON-NLS-2$
IApiDescription desc = getTestProjectApiDescription();
assertNotNull("the testing project api description must exist", desc); //$NON-NLS-1$
IApiAnnotations annot = desc.resolveAnnotations(Factory.fieldDescriptor("a.b.c.TestField9", "field")); //$NON-NLS-1$ //$NON-NLS-2$
assertNotNull("the annotations for 'field' cannot be null", annot); //$NON-NLS-1$
assertTrue("there must be a no restrictions for 'field'", annot.getRestrictions() == 0); //$NON-NLS-1$
}
/**
* Tests that a library added to the build and bundle class path of a
* project causes the class file containers for the project to need to be
* recomputed
*
* @throws IOException
* @throws InvocationTargetException
* @throws CoreException
*/
@Test
public void testWPUpdateLibraryAddedToClasspath() throws Exception {
IFolder folder = null;
try {
IJavaProject project = getTestingProject();
assertNotNull("The testing project must exist", project); //$NON-NLS-1$
IApiComponent component = getWorkspaceBaseline().getApiComponent(project.getElementName());
assertNotNull("the workspace component must exist", component); //$NON-NLS-1$
int before = component.getApiTypeContainers().length;
// add to classpath
folder = assertTestLibrary(project, new Path("libx"), "component.a_1.0.0.jar"); //$NON-NLS-1$ //$NON-NLS-2$
assertNotNull("The new library path should not be null", folder); //$NON-NLS-1$
// re-retrieve updated component
component = getWorkspaceBaseline().getApiComponent(project.getElementName());
assertTrue("there must be more containers after the addition", before < component.getApiTypeContainers().length); //$NON-NLS-1$
} finally {
if (folder != null) {
FileUtils.delete(folder);
}
}
}
/**
* Tests removing a library from the classpath of a project
*/
@Test
public void testWPUpdateLibraryRemovedFromClasspath() throws Exception {
IPath libPath = null;
try {
IJavaProject project = getTestingProject();
assertNotNull("The testing project must exist", project); //$NON-NLS-1$
// add to classpath
IFolder folder = assertTestLibrary(project, new Path("libx"), "component.a_1.0.0.jar"); //$NON-NLS-1$ //$NON-NLS-2$
IApiComponent component = getWorkspaceBaseline().getApiComponent(project.getElementName());
assertNotNull("the workspace component must exist", component); //$NON-NLS-1$
int before = component.getApiTypeContainers().length;
libPath = folder.getFullPath().append("component.a_1.0.0.jar"); //$NON-NLS-1$
// remove classpath entry
ProjectUtils.removeFromClasspath(project, JavaCore.newLibraryEntry(libPath, null, null));
waitForAutoBuild();
// remove from bundle class path
IBundleProjectService service = ProjectUtils.getBundleProjectService();
IBundleProjectDescription description = service.getDescription(project.getProject());
description.setBundleClasspath(new IBundleClasspathEntry[] { service.newBundleClasspathEntry(new Path(ProjectUtils.SRC_FOLDER), null, null) });
description.apply(null);
waitForAutoBuild();
// retrieve updated component
component = getWorkspaceBaseline().getApiComponent(project.getElementName());
assertTrue("there must be less containers after the removal", before > component.getApiTypeContainers().length); //$NON-NLS-1$
} finally {
if (libPath != null) {
FileUtils.delete(libPath.toOSString());
}
}
}
/**
* Tests that changing the output folder settings for a project cause the
* class file containers to be updated
*/
@Test
public void testWPUpdateDefaultOutputFolderChanged() throws Exception {
IJavaProject project = getTestingProject();
assertNotNull("The testing project must exist", project); //$NON-NLS-1$
IContainer container = ProjectUtils.addFolderToProject(project.getProject(), "bin2"); //$NON-NLS-1$
assertNotNull("the new output folder cannot be null", container); //$NON-NLS-1$
IApiComponent component = getWorkspaceBaseline().getApiComponent(project.getElementName());
assertNotNull("the workspace component must exist", component); //$NON-NLS-1$
int before = component.getApiTypeContainers().length;
project.setOutputLocation(container.getFullPath(), new NullProgressMonitor());
waitForAutoBuild();
assertTrue("there must be the same number of containers after the change", before == component.getApiTypeContainers().length); //$NON-NLS-1$
assertTrue("the new output location should be 'bin2'", "bin2".equalsIgnoreCase(project.getOutputLocation().toFile().getName())); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Tests that the output folder settings for a source folder cause the class
* file containers to be updated
*/
@Test
public void testWPUpdateOutputFolderSrcFolderChanged() throws Exception {
IJavaProject project = getTestingProject();
IApiComponent component = getWorkspaceBaseline().getApiComponent(project.getElementName());
assertNotNull("the workspace component must exist", component); //$NON-NLS-1$
int before = component.getApiTypeContainers().length;
ProjectUtils.addFolderToProject(project.getProject(), "bin3"); //$NON-NLS-1$
IContainer container = ProjectUtils.addFolderToProject(project.getProject(), "src2"); //$NON-NLS-1$
// add to bundle class path
IBundleProjectService service = ProjectUtils.getBundleProjectService();
IBundleClasspathEntry next = service.newBundleClasspathEntry(new Path("src2"), new Path("bin3"), new Path("next.jar")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
ProjectUtils.addBundleClasspathEntry(project.getProject(), next);
waitForAutoBuild();
// retrieve updated component
component = getWorkspaceBaseline().getApiComponent(project.getElementName());
assertTrue("there must be one more container after the change", before < component.getApiTypeContainers().length); //$NON-NLS-1$
IPackageFragmentRoot root = project.getPackageFragmentRoot(container);
assertTrue("the class file container for src2 must be 'bin3'", "bin3".equals(root.getRawClasspathEntry().getOutputLocation().toFile().getName())); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Tests that adding a package does not update the workspace baseline
*/
@Test
public void testWPUpdatePackageAdded() throws Exception {
IJavaProject project = getTestingProject();
assertNotNull("The testing project must exist", project); //$NON-NLS-1$
// add the package
assertTestPackage(project, new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute(), "a.test1.c.d"); //$NON-NLS-1$
IApiDescription desc = getTestProjectApiDescription();
assertNotNull("the testing project api description must exist", desc); //$NON-NLS-1$
IApiAnnotations annot = desc.resolveAnnotations(Factory.packageDescriptor("a.test1.c.d")); //$NON-NLS-1$
assertNotNull("the annotations for package " + TESTING_PACKAGE + " should exist", annot); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Tests that removing a package updates the workspace baseline This test
* removes the a.b.c package being used in all tests thus far, and should be
* run last
*/
@Test
public void testWPUpdatePackageRemoved() throws Exception {
IJavaProject project = getTestingProject();
assertNotNull("The testing project must exist", project); //$NON-NLS-1$
// add the package
IPath srcroot = new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute();
IPackageFragment fragment = assertTestPackage(project, srcroot, "a.test2"); //$NON-NLS-1$
assertNotNull("the package " + TESTING_PACKAGE + " must exist", fragment); //$NON-NLS-1$ //$NON-NLS-2$
// remove the package
fragment.delete(true, new NullProgressMonitor());
IApiDescription desc = getTestProjectApiDescription();
assertNotNull("the testing project api description must exist", desc); //$NON-NLS-1$
IApiAnnotations annot = desc.resolveAnnotations(Factory.packageDescriptor("a.test2")); //$NON-NLS-1$
assertNull("the annotations for package " + TESTING_PACKAGE + " should not exist", annot); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Tests that an exported package addition in the PDE model is reflected in
* the workspace api baseline
*/
@Test
public void testWPUpdateExportPackageAdded() throws Exception {
IJavaProject project = getTestingProject();
assertNotNull("The testing project must exist", project); //$NON-NLS-1$
// add package
assertTestPackage(project, new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute(), "export1"); //$NON-NLS-1$
// update
setPackageToApi(project, "export1"); //$NON-NLS-1$
IApiAnnotations annot = getTestProjectApiDescription().resolveAnnotations(Factory.packageDescriptor("export1")); //$NON-NLS-1$
assertNotNull("there must be an annotation for the new exported package", annot); //$NON-NLS-1$
assertTrue("the newly exported package must be API visibility", annot.getVisibility() == VisibilityModifiers.API); //$NON-NLS-1$
}
/**
* Tests that changing a directive to x-internal on an exported package
* causes the workspace api baseline to be updated
*/
@Test
public void testWPUPdateExportPackageDirectiveChangedToInternal() throws Exception {
IJavaProject project = getTestingProject();
assertNotNull("The testing project must exist", project); //$NON-NLS-1$
// add package
assertTestPackage(project, new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute(), "export1"); //$NON-NLS-1$
// export the package
ProjectUtils.addExportedPackage(project.getProject(), "export1", true, null); //$NON-NLS-1$
// check the description
IApiAnnotations annot = getTestProjectApiDescription().resolveAnnotations(Factory.packageDescriptor("export1")); //$NON-NLS-1$
assertNotNull("there must be an annotation for the new exported package", annot); //$NON-NLS-1$
assertTrue("the changed exported package must be PRIVATE visibility", annot.getVisibility() == VisibilityModifiers.PRIVATE); //$NON-NLS-1$
}
/**
* Tests that an exported package removal in the PDE model is reflected in
* the workspace api baseline
*/
@Test
public void testWPUpdateExportPackageRemoved() throws Exception {
IJavaProject project = getTestingProject();
assertNotNull("The testing project must exist", project); //$NON-NLS-1$
// add package
assertTestPackage(project, new Path(project.getElementName()).append(ProjectUtils.SRC_FOLDER).makeAbsolute(), "export1"); //$NON-NLS-1$
setPackageToApi(project, "export1"); //$NON-NLS-1$
IApiAnnotations annot = getTestProjectApiDescription().resolveAnnotations(Factory.packageDescriptor("export1")); //$NON-NLS-1$
assertNotNull("there must be an annotation for the new exported package", annot); //$NON-NLS-1$
assertTrue("the newly exported package must be API visibility", annot.getVisibility() == VisibilityModifiers.API); //$NON-NLS-1$
// remove exported packages
IBundleProjectService service = ProjectUtils.getBundleProjectService();
IBundleProjectDescription description = service.getDescription(project.getProject());
description.setPackageExports(null);
description.apply(null);
// check the API description
annot = getTestProjectApiDescription().resolveAnnotations(Factory.packageDescriptor("export1")); //$NON-NLS-1$
assertNotNull("should still be an annotation for the package", annot); //$NON-NLS-1$
assertTrue("unexported package must be private", VisibilityModifiers.isPrivate(annot.getVisibility())); //$NON-NLS-1$
}
/**
* sets the given package name to be an Exported-Package
*
* @param name
*/
private void setPackageToApi(IJavaProject project, String name) throws CoreException {
ProjectUtils.addExportedPackage(project.getProject(), name, false, null);
}
IJavaProject getTestingProject() {
return JavaCore.create(ResourcesPlugin.getWorkspace().getRoot().getProject(TESTING_PLUGIN_PROJECT_NAME));
}
@Before
public void setUp() throws Exception {
createProject(TESTING_PLUGIN_PROJECT_NAME, new String[] { TESTING_PACKAGE });
setPackageToApi(getTestingProject(), TESTING_PACKAGE);
}
@After
public void tearDown() throws Exception {
deleteProject(TESTING_PLUGIN_PROJECT_NAME);
getWorkspaceBaseline().dispose();
}
}