package org.eclipse.recommenders.internal.types.rcp; import static org.hamcrest.Matchers.*; import static org.junit.Assert.assertThat; import java.io.File; import java.io.IOException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.recommenders.testing.CodeBuilder; import org.eclipse.recommenders.testing.rcp.completion.rules.TemporaryProject; import org.eclipse.recommenders.testing.rcp.completion.rules.TemporaryWorkspace; import org.eclipse.recommenders.utils.names.ITypeName; import org.eclipse.recommenders.utils.names.VmTypeName; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableSet; public class ProjectTypesIndexTest { private static final String SUPER_CLASS = "SuperClass"; private static final String SUB_CLASS = "SubClass"; private static final String SUB_SUB_CLASS = "SubSubClass"; private static final String INTERFACE_A = "IInterfaceA"; private static final String INTERFACE_B = "IInterfaceB"; private static final String IMPLEMENTATION = "Implementation"; private static final String OBJECT = "Object"; private static final ITypeName SUPER_CLASS_TYPE = VmTypeName.get(SUPER_CLASS); private static final ITypeName INTERFACE_A_TYPE = VmTypeName.get(INTERFACE_A); private static final ITypeName INTERFACE_B_TYPE = VmTypeName.get(INTERFACE_B); private static final IProgressMonitor PROGRESS = null; @ClassRule public static final TemporaryWorkspace WORKSPACE = new TemporaryWorkspace(); @Rule public TemporaryFolder indexDir = new TemporaryFolder(); @Test public void testUnseenProjectNeedsRebuild() throws Exception { TemporaryProject dependency = WORKSPACE.createProject(); dependency.createFile(classDeclaration(SUPER_CLASS, OBJECT)); TemporaryProject project = WORKSPACE.createProject(); project.withDependencyOnJarOf(dependency); ProjectTypesIndex sut = createSut(project, dependency); assertThat(sut.needsRebuild(), is(true)); } @Test public void testIndexedProjectNeedsNoRebuild() throws Exception { TemporaryProject dependency = WORKSPACE.createProject(); dependency.createFile(classDeclaration(SUPER_CLASS, OBJECT)); TemporaryProject project = WORKSPACE.createProject(); project.withDependencyOnJarOf(dependency); ProjectTypesIndex sut = createSut(project, dependency); sut.rebuild(PROGRESS); assertThat(sut.needsRebuild(), is(false)); } @Test public void testSimpleSuperclass() throws Exception { TemporaryProject dependency = WORKSPACE.createProject(); dependency.createFile(classDeclaration(SUPER_CLASS, OBJECT)); dependency.createFile(classDeclaration(SUB_CLASS, SUPER_CLASS)); TemporaryProject project = WORKSPACE.createProject(); project.withDependencyOnJarOf(dependency); ProjectTypesIndex sut = createSut(project, dependency); sut.rebuild(PROGRESS); ImmutableSet<String> subtypes = sut.doSubtypes(SUPER_CLASS_TYPE); assertThat(subtypes, containsInAnyOrder(SUPER_CLASS, SUB_CLASS)); assertThat(subtypes, hasSize(2)); } @Test public void testSuperclassChain() throws Exception { TemporaryProject dependency = WORKSPACE.createProject(); dependency.createFile(classDeclaration(SUPER_CLASS, OBJECT)); dependency.createFile(classDeclaration(SUB_CLASS, SUPER_CLASS)); dependency.createFile(classDeclaration(SUB_SUB_CLASS, SUB_CLASS)); TemporaryProject project = WORKSPACE.createProject(); project.withDependencyOnJarOf(dependency); ProjectTypesIndex sut = createSut(project, dependency); sut.rebuild(PROGRESS); ImmutableSet<String> subtypes = sut.doSubtypes(SUPER_CLASS_TYPE); assertThat(subtypes, containsInAnyOrder(SUPER_CLASS, SUB_CLASS, SUB_SUB_CLASS)); assertThat(subtypes, hasSize(3)); } @Test public void testSimpleInterface() throws Exception { TemporaryProject dependency = WORKSPACE.createProject(); dependency.createFile(interfaceDeclaration(INTERFACE_A, OBJECT)); dependency.createFile(classDeclaration(IMPLEMENTATION, OBJECT, INTERFACE_A)); TemporaryProject project = WORKSPACE.createProject(); project.withDependencyOnJarOf(dependency); ProjectTypesIndex sut = createSut(project, dependency); sut.rebuild(PROGRESS); ImmutableSet<String> subtypes = sut.doSubtypes(INTERFACE_A_TYPE); assertThat(subtypes, containsInAnyOrder(INTERFACE_A, IMPLEMENTATION)); assertThat(subtypes, hasSize(2)); } @Test public void testInterfaceChain() throws Exception { TemporaryProject dependency = WORKSPACE.createProject(); dependency.createFile(interfaceDeclaration(INTERFACE_A, OBJECT)); dependency.createFile(interfaceDeclaration(INTERFACE_B, INTERFACE_A)); dependency.createFile(classDeclaration(IMPLEMENTATION, OBJECT, INTERFACE_B)); TemporaryProject project = WORKSPACE.createProject(); project.withDependencyOnJarOf(dependency); ProjectTypesIndex sut = createSut(project, dependency); sut.rebuild(PROGRESS); ImmutableSet<String> subtypes = sut.doSubtypes(INTERFACE_A_TYPE); assertThat(subtypes, containsInAnyOrder(INTERFACE_A, INTERFACE_B, IMPLEMENTATION)); assertThat(subtypes, hasSize(3)); } @Test public void testMultipleInterfaces() throws Exception { TemporaryProject dependency = WORKSPACE.createProject(); dependency.createFile(interfaceDeclaration(INTERFACE_A, OBJECT)); dependency.createFile(interfaceDeclaration(INTERFACE_B, OBJECT)); dependency.createFile(classDeclaration(IMPLEMENTATION, OBJECT, INTERFACE_A, INTERFACE_B)); TemporaryProject project = WORKSPACE.createProject(); project.withDependencyOnJarOf(dependency); ProjectTypesIndex sut = createSut(project, dependency); sut.rebuild(PROGRESS); ImmutableSet<String> subtypesOfInterfaceA = sut.doSubtypes(INTERFACE_A_TYPE); assertThat(subtypesOfInterfaceA, containsInAnyOrder(INTERFACE_A, IMPLEMENTATION)); assertThat(subtypesOfInterfaceA, hasSize(2)); ImmutableSet<String> subtypesOfInterfaceB = sut.doSubtypes(INTERFACE_B_TYPE); assertThat(subtypesOfInterfaceB, containsInAnyOrder(INTERFACE_B, IMPLEMENTATION)); assertThat(subtypesOfInterfaceB, hasSize(2)); } @Test public void testUpdatedJarNeedsRebuild() throws Exception { TemporaryProject dependency = WORKSPACE.createProject(); dependency.createFile(classDeclaration(SUPER_CLASS, OBJECT)); dependency.createFile(classDeclaration(SUB_CLASS, SUPER_CLASS)); TemporaryProject project = WORKSPACE.createProject(); project.withDependencyOnJarOf(dependency); ProjectTypesIndex sut = createSut(project, dependency); sut.rebuild(PROGRESS); File jar = new File(dependency.getJarPath()); jar.setLastModified(jar.lastModified() + 1000); assertThat(sut.needsRebuild(), is(true)); } @Test public void testExpectedTypeNull() throws Exception { TemporaryProject dependency = WORKSPACE.createProject(); dependency.createFile(classDeclaration(SUPER_CLASS, OBJECT)); TemporaryProject project = WORKSPACE.createProject(); project.withDependencyOnJarOf(dependency); ProjectTypesIndex sut = createSut(project, dependency); ImmutableSet<String> subtypes = sut.doSubtypes(null); assertThat(subtypes, is(empty())); } private ProjectTypesIndex createSut(TemporaryProject project, TemporaryProject dependency) throws IOException { ProjectTypesIndex sut = new ProjectTypesIndex(project.getJavaProject(), indexDir.newFolder(), new File(dependency.getJarPath())); sut.initialize(); return sut; } private static CharSequence classDeclaration(String name, String superClass, String... interfaces) { return declaration("class", name, superClass, interfaces); } private static CharSequence interfaceDeclaration(String name, String superClass, String... interfaces) { return declaration("interface", name, superClass, interfaces); } private static CharSequence declaration(String kind, String name, String superClass, String... interfaces) { StringBuilder sb = new StringBuilder(); sb.append(kind); sb.append(' '); sb.append(name); if (!superClass.isEmpty()) { sb.append(" extends "); sb.append(superClass); } if (interfaces.length > 0) { sb.append(" implements "); } sb.append(Joiner.on(',').join(interfaces)); return CodeBuilder.classDeclaration(sb.toString(), ""); } }