/******************************************************************************* * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation from Oracle TopLink ******************************************************************************/ package org.eclipse.persistence.tools.workbench.test.mappingsmodel.spi.meta; import java.io.File; import java.util.Iterator; import java.util.Map; import junit.framework.TestCase; import org.eclipse.persistence.tools.workbench.mappingsmodel.spi.meta.ExternalClass; import org.eclipse.persistence.tools.workbench.mappingsmodel.spi.meta.ExternalClassDescription; import org.eclipse.persistence.tools.workbench.mappingsmodel.spi.meta.ExternalClassRepository; import org.eclipse.persistence.tools.workbench.mappingsmodel.spi.meta.ExternalClassRepositoryFactory; import org.eclipse.persistence.tools.workbench.mappingsmodel.spi.meta.ExternalField; import org.eclipse.persistence.tools.workbench.mappingsmodel.spi.meta.ExternalMethod; import org.eclipse.persistence.tools.workbench.test.utility.TestTools; import org.eclipse.persistence.tools.workbench.utility.ClassTools; import org.eclipse.persistence.tools.workbench.utility.CollectionTools; import org.eclipse.persistence.tools.workbench.utility.io.IndentingPrintWriter; import org.eclipse.persistence.tools.workbench.utility.iterators.TransformationIterator; public abstract class ExternalClassRepositoryTests extends TestCase { protected ExternalClassRepositoryFactory factory; protected ExternalClassRepositoryTests(String name) { super(name); } protected void setUp() throws Exception { super.setUp(); this.factory = this.buildFactory(); } protected abstract ExternalClassRepositoryFactory buildFactory(); protected abstract ExternalClassRepository systemClasspathRepository() throws Exception; protected abstract ExternalClassRepository buildExternalClassRepository(File[] classpath); protected abstract ExternalClassRepository systemRepositoryFor(ExternalClassRepository repository) throws Exception; protected void tearDown() throws Exception { TestTools.clear(this); super.tearDown(); } // public void testPerformance() throws Exception { // ExternalClassRepository repository = this.systemClasspathRepository(); // // long start, finish; // start = new Date().getTime(); // repository.getExternalClassDescriptions(); // finish = new Date().getTime(); // long actual = finish - start; // // should take more than half a second; or we missed something... // long expected = 500; // assertTrue("Probably too fast - expected: " + expected + " actual: " + actual, actual > expected); // // should take less than 8 seconds // expected = 8000; // assertTrue("Possibly too slow - expected: " + expected + " actual: " + actual, actual < expected); // // start = new Date().getTime(); // repository.getExternalClassDescriptions(); // finish = new Date().getTime(); // actual = finish - start; // // now it should take less than 0.005 seconds // expected = 50; // assertTrue("Possibly too slow - expected: " + expected + " actual: " + actual, actual < expected); // } // public void testSystemClasspath() throws Exception { ExternalClassRepository repository = this.systemClasspathRepository(); ExternalClassDescription[] externalClassDescriptions = repository.getClassDescriptions(); // jdk 1.4.2 has over 9000 classes in rt.jar... assertTrue("missing system entries", externalClassDescriptions.length > 5000); this.verifyClass(externalClassDescriptions, int.class); this.verifyClass(externalClassDescriptions, void.class); this.verifyClass(externalClassDescriptions, java.lang.Object.class); this.verifyClass(externalClassDescriptions, java.lang.Class.class); } public void testTypeIdentity() throws Exception { ExternalClassRepository repository = this.systemClasspathRepository(); ExternalClassDescription type1 = this.descriptionFor(repository.getClassDescriptions(), java.lang.String.class); ExternalClassDescription type2 = this.descriptionFor(repository.getClassDescriptions(), java.lang.String.class); assertTrue("bungled type identity", type1 == type2); } public void testSystemArrayTypes() throws Exception { ExternalClassRepository repository = this.systemClasspathRepository(); ExternalClassDescription[] externalClassDescriptions = repository.getClassDescriptions(); ExternalClassRepository systemRepository = this.systemRepositoryFor(repository); Class arrayType = (new byte[0]).getClass(); // array types should not be returned directly this.verifyInvalidType(externalClassDescriptions, arrayType); // the array type comes from the "system" repository Map arrayClassDescriptions = (Map) ClassTools.getFieldValue(systemRepository, "arrayClassDescriptions"); assertTrue("internal attribute test", arrayClassDescriptions.isEmpty()); arrayClassDescriptions = (Map) ClassTools.getFieldValue(repository, "arrayClassDescriptions"); assertTrue("internal attribute test", arrayClassDescriptions.isEmpty()); ExternalClass exClass = this.descriptionFor(externalClassDescriptions, java.lang.String.class).getExternalClass(); ExternalMethod exMethod = SPIMetaTestTools.zeroArgumentMethodNamed(exClass, "getBytes"); ExternalClassDescription type1 = exMethod.getReturnType(); exMethod = SPIMetaTestTools.oneArgumentMethodNamed(exClass, "getBytes", "java.lang.String"); ExternalClassDescription type2 = exMethod.getReturnType(); assertTrue("bungled array type identity", type1 == type2); this.verifyInvalidType(externalClassDescriptions, arrayType); // the array type comes from the "system" repository arrayClassDescriptions = (Map) ClassTools.getFieldValue(systemRepository, "arrayClassDescriptions"); assertTrue("internal attribute test", ! arrayClassDescriptions.isEmpty()); this.verifyArrayTypesContains(arrayClassDescriptions, arrayType); // hacking... maybe test should be moved to subclasses... if (systemRepository != repository) { arrayClassDescriptions = (Map) ClassTools.getFieldValue(repository, "arrayClassDescriptions"); assertTrue("internal attribute test", arrayClassDescriptions.isEmpty()); } } public void testProjectArrayTypes() throws Exception { // add an array instance variable to the source code final String testArrayName = "testArray"; final Class testArrayType = (new Object[0]).getClass(); ClasspathTestTool tool = new ClasspathTestTool(ClassTools.shortClassNameForObject(this) + "." + this.getName()) { protected SourceExtender buildSourceExtender() { return new SourceExtender() { public void extendSourceOn(IndentingPrintWriter pw, int version) { pw.print("public " + testArrayType.getComponentType().getName() + "[] " + testArrayName + ";"); } }; } }; tool.setUp(); ExternalClassRepository repository = this.buildExternalClassRepository(new File[] {tool.subdir1}); ExternalClassDescription[] externalClassDescriptions = repository.getClassDescriptions(); ExternalClassRepository systemRepository = this.systemRepositoryFor(repository); // array types should not be returned directly this.verifyInvalidType(externalClassDescriptions, testArrayType); // the array comes from the "project" repository Map arrayClassDescriptions = (Map) ClassTools.getFieldValue(systemRepository, "arrayClassDescriptions"); assertTrue("internal attribute test", arrayClassDescriptions.isEmpty()); arrayClassDescriptions = (Map) ClassTools.getFieldValue(repository, "arrayClassDescriptions"); assertTrue("internal attribute test", arrayClassDescriptions.isEmpty()); ExternalClass exClass = this.descriptionForClassNamed(externalClassDescriptions, ClasspathTestTool.TEST_CLASS_NAME).getExternalClass(); ExternalField exField = SPIMetaTestTools.fieldNamed(exClass, testArrayName); ExternalClassDescription type1 = exField.getType(); exField = SPIMetaTestTools.fieldNamed(exClass, testArrayName); ExternalClassDescription type2 = exField.getType(); assertTrue("bungled array type identity", type1 == type2); this.verifyInvalidType(externalClassDescriptions, testArrayType); // hacking... maybe test should be moved to subclasses... if (systemRepository != repository) { // the array comes from the "project" repository arrayClassDescriptions = (Map) ClassTools.getFieldValue(systemRepository, "arrayClassDescriptions"); assertTrue("internal attribute test", arrayClassDescriptions.isEmpty()); } arrayClassDescriptions = (Map) ClassTools.getFieldValue(repository, "arrayClassDescriptions"); assertTrue("internal attribute test", ! arrayClassDescriptions.isEmpty()); this.verifyArrayTypesContains(arrayClassDescriptions, testArrayType); tool.tearDown(); } public void testProjectClasspathOrder() throws Exception { ClasspathTestTool tool = new ClasspathTestTool(ClassTools.shortClassNameForObject(this) + "." + this.getName()); tool.setUp(); ExternalClassRepository repository = this.buildExternalClassRepository(new File[] {tool.subdir1, tool.subdir2}); ExternalClass exClass = repository.getClassDescription(ClasspathTestTool.TEST_CLASS_NAME).getExternalClass(); ExternalField exField = SPIMetaTestTools.fieldNamed(exClass, ClasspathTestTool.VERSION_MEMBER_PREFIX + "1"); assertNotNull("wrong class loaded", exField); // now, swap the subdirs repository = this.buildExternalClassRepository(new File[] {tool.subdir2, tool.subdir1}); exClass = repository.getClassDescription(ClasspathTestTool.TEST_CLASS_NAME).getExternalClass(); exField = SPIMetaTestTools.fieldNamed(exClass, ClasspathTestTool.VERSION_MEMBER_PREFIX + "2"); assertNotNull("wrong class loaded", exField); tool.tearDown(); } public void testProjectClasspath() throws Exception { ClasspathTestTool tool = new ClasspathTestTool(ClassTools.shortClassNameForObject(this) + "." + this.getName()); tool.setUp(); this.verifyProjectClasspathEntry(tool.subdir1, ClasspathTestTool.TEST_CLASS_NAME); this.verifyProjectClasspathEntry(tool.subdir2, ClasspathTestTool.TEST_CLASS_NAME); this.verifyProjectClasspathEntry(tool.jarFile1, ClasspathTestTool.TEST_CLASS_NAME); this.verifyProjectClasspathEntry(tool.jarFile1, ClasspathTestTool.TEST_CLASS_NAME); this.verifyProjectClasspathEntry(tool.zipFile1, ClasspathTestTool.TEST_CLASS_NAME); this.verifyProjectClasspathEntry(tool.zipFile1, ClasspathTestTool.TEST_CLASS_NAME); tool.tearDown(); } protected abstract void verifyArrayTypesContains(Map arrayClassDescriptions, Class arrayType); private void verifyInvalidType(ExternalClassDescription[] externalClassDescriptions, Class invalidJavaClass) { boolean exCaught = false; try { this.descriptionFor(externalClassDescriptions, invalidJavaClass); } catch (IllegalArgumentException ex) { exCaught = true; } assertTrue("IllegalArgumentException not thrown", exCaught); } private void verifyProjectClasspathEntry(File classpathEntry, String className) { ExternalClassRepository repository = this.buildExternalClassRepository(new File[] {classpathEntry}); ExternalClassDescription[] externalClassDescriptions = repository.getClassDescriptions(); // first verify that the system entries are also OK this.verifyClass(externalClassDescriptions, java.lang.Object.class); // then check the project entry this.verifyClassNamed(externalClassDescriptions, className); } private void verifyClass(ExternalClassDescription[] externalClassDescriptions, Class javaClass) { this.verifyClassNamed(externalClassDescriptions, javaClass.getName()); } private void verifyClassNamed(ExternalClassDescription[] externalClassDescriptions, String className) { assertTrue("missing external class: " + className, CollectionTools.contains(this.classNames(externalClassDescriptions), className)); } private Iterator classNames(Iterator externalClassDescriptions) { return new TransformationIterator(externalClassDescriptions) { protected Object transform(Object next) { return ((ExternalClassDescription) next).getName(); } }; } private Iterator classNames(ExternalClassDescription[] externalClassDescriptions) { return this.classNames(CollectionTools.iterator(externalClassDescriptions)); } protected ExternalClassDescription descriptionFor(ExternalClassDescription[] externalClassDescriptions, Class javaClass) { return this.descriptionForClassNamed(externalClassDescriptions, javaClass.getName()); } protected ExternalClassDescription descriptionForClassNamed(ExternalClassDescription[] externalClassDescriptions, String className) { for (int i = externalClassDescriptions.length; i-- > 0; ) { if (externalClassDescriptions[i].getName().equals(className)) { return externalClassDescriptions[i]; } } throw new IllegalArgumentException(className); } }