/*******************************************************************************
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.apache.kato.tests.junit;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.tools.diagnostics.image.CorruptData;
import javax.tools.diagnostics.image.CorruptDataException;
import javax.tools.diagnostics.image.ImagePointer;
import javax.tools.diagnostics.image.MemoryAccessException;
import javax.tools.diagnostics.runtime.java.JavaClass;
import javax.tools.diagnostics.runtime.java.JavaClassLoader;
import javax.tools.diagnostics.runtime.java.JavaField;
import javax.tools.diagnostics.runtime.java.JavaMethod;
import javax.tools.diagnostics.runtime.java.JavaObject;
import javax.tools.diagnostics.runtime.java.JavaReference;
import org.apache.kato.tests.scenarios.ArrayletTest;
public class JavaClassTest extends AbstractImageTestcase
{
public class Super {
int superField1 = 3;
String superField2 = "Ciao";
}
public class Sub extends Super {
long subField1 = 100;
char[] subField2 = new char[]{'c','c'};
public Sub() {
System.out.println("Sub instantiated");
}
}
private JavaClass _testClass;
private JavaObject _arrayInstance; //array classes aren't loaded like normal classes and only come into existence when an array object is created
private static Sub _subClassObject = null;
private static ArrayletTest _testDeadlock = null;
protected void setUp() throws Exception
{
try {
_testClass = defaultJavaClass();
_arrayInstance = defaultJavaObject(true);
super.setUp();
} catch (TestNotImplementedException e) {
throw e;
}
}
public void configureDeclareFieldsNotInherited() {
_subClassObject = new Sub();
}
public void configureArraylets() {
_testDeadlock = new ArrayletTest();
}
/*
* Test method for 'javax.tools.diagnostics.runtime.java.JavaClass.getObject()'
*/
public void testGetObject()
{
try {
JavaObject object = _testClass.getObject();
assertNotNull(object);
/* validate that the object is an instance of java/lang/Class */
JavaClass javaLangClass = object.getJavaClass();
assertNotNull(javaLangClass);
assertEquals(javaLangClass.getName(), "java/lang/Class");
} catch (CorruptDataException e) {
//allowed by the spec
} catch (Exception e) {
//if we caught anything else, this is an error
fail();
}
}
/*
* Test method for 'javax.tools.diagnostics.runtime.java.JavaClass.getClassLoader()'
*/
public void testGetClassLoader()
{
try {
JavaClassLoader loader = _testClass.getClassLoader();
assertNotNull(loader);
} catch (CorruptDataException e) {
//allowed by the spec
} catch (Exception e) {
//if we caught anything else, this is an error
fail();
}
}
/*
* Test method for 'javax.tools.diagnostics.runtime.java.JavaClass.getName()'
*/
public void testGetName()
{
try {
String name = _testClass.getName();
assertNotNull(name);
} catch (CorruptDataException e) {
//allowed by the spec
} catch (Exception e) {
//if we caught anything else, this is an error
fail();
}
}
/*
* Test method for 'javax.tools.diagnostics.runtime.java.JavaClass.getSuperclass()'
*/
public void testGetSuperclass()
{
try {
JavaClass superClass = _testClass.getSuperclass();
assertNotNull(superClass);
} catch (CorruptDataException e) {
//allowed by the spec
} catch (Exception e) {
//if we caught anything else, this is an error
fail();
}
}
/*
* Test method for 'javax.tools.diagnostics.runtime.java.JavaClass.getInterfaces()'
*/
public void testGetInterfaces()
{
try {
List iter = _testClass.getInterfaces();
assertNotNull(iter);
} catch (Exception e) {
//if we caught anything else, this is an error
fail();
}
}
/*
* Test method for 'javax.tools.diagnostics.runtime.java.JavaClass.getModifiers()'
*/
public void testGetModifiers()
{
try {
_testClass.getModifiers();
//fill in any checks that could be used for validity here
} catch (CorruptDataException e) {
//allowed by the spec
} catch (Exception e) {
//if we caught anything else, this is an error
fail();
}
}
/*
* Test method for 'javax.tools.diagnostics.runtime.java.JavaClass.isArray()'
*/
public void testIsArray()
{
//any result is safe so long as it doesn't throw something unexpected
try {
_testClass.isArray();
} catch (CorruptDataException e) {
//allowed by the spec
} catch (Exception e) {
//if we caught anything else, this is an error
fail();
}
}
/**
* Test method for 'javax.tools.diagnostics.runtime.java.JavaClass.getComponentType()'
*
* Ensures that we get a non-null component type which has a non-null, non-empty length
*/
public void testGetComponentType()
{
JavaClass arrayClass = null;
JavaClass component = null;
try {
arrayClass = _arrayInstance.getJavaClass();
component = arrayClass.getComponentType();
} catch (CorruptDataException e) {
//allowed by the spec
}
assertNotNull(component);
String name=null;
try {
name = component.getName();
} catch (CorruptDataException e) {
}
assertNotNull(name);
assertTrue(name.length() > 0);
}
/**
* Test method for 'javax.tools.diagnostics.runtime.java.JavaClass.getDeclaredFields()'
*
* Ensures that we get a non-null iterator and anything in the iterator is an instance
* of JavaField or CorruptData
*/
public void testGetDeclaredFields()
{
try {
Iterator fields = _testClass.getDeclaredFields().iterator();
assertNotNull(fields);
while (fields.hasNext()) {
Object element = fields.next();
assertTrue((element instanceof JavaField) || (element instanceof CorruptData));
}
} catch (Exception e) {
//if we caught anything else, this is an error
fail();
}
}
/**
* Test method for 'javax.tools.diagnostics.runtime.java.JavaClass.getDeclaredMethods()'
*
* Ensures that the declared methods iterator is non-null and any methods in it
* are either JavaMethod or CorruptData
*/
public void testGetDeclaredMethods()
{
try {
Iterator methods = _testClass.getDeclaredMethods().iterator();
assertNotNull(methods);
while (methods.hasNext()) {
Object instance = methods.next();
assertTrue((instance instanceof JavaMethod) || (instance instanceof CorruptData));
}
} catch (Exception e) {
//if we caught anything else, this is an error
fail();
}
}
/**
* Test method for 'javax.tools.diagnostics.runtime.java.JavaClass.getConstantPoolReferences()'
*
* Ensures that the test class returns a non-null iterator and that any elements
* in it are either JavaObject or CorruptData
*/
public void testGetConstantPoolReferences()
{
try {
Iterator references = _testClass.getConstantPoolReferences().iterator();
assertNotNull(references);
while (references.hasNext()) {
Object instance = references.next();
assertTrue((instance instanceof JavaObject) || (instance instanceof CorruptData));
if (instance instanceof JavaObject) {
// ensure that these are valid objects by reading the class
JavaObject object = (JavaObject)instance;
JavaClass clazz = object.getJavaClass();
assertNotNull(clazz);
}
}
} catch (Exception e) {
//if we caught anything else, this is an error
fail();
}
}
/**
* Test method for 'javax.tools.diagnostics.runtime.java.JavaClass.getID()'
*
* Ensures that the pointer is non-null and that the underlying address is non-zero
*/
public void testGetID()
{
try {
ImagePointer id = _testClass.getID();
assertNotNull(id);
assertTrue(0 != id.getAddress());
} catch (Exception e) {
//if we caught anything else, this is an error
fail();
}
}
/**
* Test method for 'javax.tools.diagnostics.runtime.java.JavaClass.getReferences()'
*
* Ensures that the test class returns a non-null iterator, that any elements in it are
* either JavaReference or CorruptData, and that any JavaReference objects have a non-null
* description.
*/
public void testGetReferences()
{
try {
Iterator references = _testClass.getReferences().iterator();
assertNotNull(references);
while (references.hasNext()) {
Object instance = references.next();
assertTrue((instance instanceof JavaReference) || (instance instanceof CorruptData));
if (instance instanceof JavaReference) {
// sniff these objects by getting the description
JavaReference object = (JavaReference)instance;
String description = object.getDescription();
assertNotNull(description);
}
}
} catch (Exception e) {
// if we caught anything else, this is a failure
fail();
}
}
/**
* Verify that the equals call doesn't throw
*/
public void testEquals()
{
try{
assertTrue(_testClass.equals(_testClass));
} catch (Throwable t) {
//if we fail internally, we want to flag that as a test failure, not just an error
t.printStackTrace();
fail();
}
}
/**
* Verify that hashCode() doesn't throw and returns non-zero (technically zero is ok but it will be
* flagged here to ensure that we aren't doing anything bad to create the hashcode)
*/
public void testHashCode()
{
try {
assertTrue(0 != _testClass.hashCode());
} catch (Exception e) {
//if we caught anything else, this is an error
fail();
}
}
public void testDeclaredFieldsNotInherited()
{
try {
//search all the loaders for a class which we know we had in the address space
String candidateClass = this.getClass().getName()+"$Sub";
candidateClass = candidateClass.replace('.', '/');
JavaClass subclass = _findClassForName(candidateClass);
if (null == subclass) {
//not finding this testing class makes this test useless
//note that this can also happen if we are working with a corrupt core file
throw new TestNotImplementedException();
}
JavaClass superclass = null;
try {
superclass = subclass.getSuperclass();
} catch (CorruptDataException e) {
//even though this would be valid, it isn't helpful for our case
throw new TestNotImplementedException();
}
if (null == superclass) {
//not finding this testing class makes this test useless
throw new TestNotImplementedException();
}
//now make sure that none of the fields in subclass are in superclass
Iterator subfields = subclass.getDeclaredFields().iterator();
while (subfields.hasNext()) {
Object subtest = subfields.next();
Iterator superfields = superclass.getDeclaredFields().iterator();
while (superfields.hasNext()) {
Object supertest = superfields.next();
assertFalse(supertest.equals(subtest));
}
}
} catch (TestNotImplementedException t) {
//we wanted this exception to break the test case with error instead of failure so re-throw
throw t;
} catch (Exception e) {
//if we caught anything else, this is an error
fail();
}
}
private JavaClass _findClassForName(String candidateClass)
{
Iterator allLoaders = defaultJavaRuntime().getJavaClassLoaders().iterator();
JavaClass subclass = null;
while (allLoaders.hasNext() && (null == subclass)) {
JavaClassLoader loader = (JavaClassLoader) allLoaders.next();
Iterator classes = loader.getDefinedClasses().iterator();
while (classes.hasNext() && (null == subclass)) {
JavaClass oneClass = (JavaClass) classes.next();
try {
if (oneClass.getName().equals(candidateClass)) {
subclass = oneClass;
break;
}
} catch (CorruptDataException e) {
//even though this would be valid, it isn't helpful for our case
throw new TestNotImplementedException();
}
}
}
return subclass;
}
/**
* This test should eventually be moved out to a stand-alone high-level test since it is looking for a specific
* field to verify that arraycopy and arraylets (in the RTJ case) work properly.
*/
public void testArraylets()
{
String staticSizeName = "DTFJ_ARRAYLET_LENGTH";
String staticName = "DTFJ_ARRAYLET_TEST_INSTANCE";
JavaClass candidateClass = _findClassForName("org/apache/kato/tests/scenarios/ArrayletTest");
if (null != candidateClass) {
int size = 0;
JavaObject container = null;
Iterator fields = candidateClass.getDeclaredFields().iterator();
try {
while (fields.hasNext()) {
JavaField field = (JavaField) fields.next();
String fieldName = field.getName();
if (fieldName.equals(staticSizeName)) {
size = field.getInt(null);
} else if (fieldName.equals(staticName)) {
container = (JavaObject) field.get(null);
}
}
//now ensure that we actually have something to test with
if ((0 != size) && (null != container)) {
//now, pull apart the fields of the container
JavaClass containerClass = container.getJavaClass();
Iterator theseFields = containerClass.getDeclaredFields().iterator();
while (theseFields.hasNext()) {
JavaField oneField = (JavaField) theseFields.next();
if (oneField.getName().equals("DTFJ_ARRAYLET_INTS")) {
//run the int test
JavaObject array = (JavaObject) oneField.get(container);
int remote[] = new int[size];
int whole[] = new int[size];
for (int i = 0; i < size; i++) {
array.arraycopy(i, remote, i, 1);
assertTrue(remote[i] == (size -i));
}
array.arraycopy(0, whole, 0, size);
assertTrue(Arrays.equals(whole, remote));
} else if (oneField.getName().equals("DTFJ_ARRAYLET_BYTES")) {
//run the byte test
JavaObject array = (JavaObject) oneField.get(container);
byte remote[] = new byte[size];
byte whole[] = new byte[size];
for (int i = 0; i < size; i++) {
array.arraycopy(i, remote, i, 1);
assertTrue(remote[i] == ((byte)(size -i)));
}
array.arraycopy(0, whole, 0, size);
assertTrue(Arrays.equals(whole, remote));
} else if (oneField.getName().equals("DTFJ_ARRAYLET_STRINGCONTAINER")) {
//run the byte test
JavaObject array = (JavaObject) oneField.get(container);
JavaObject whole[] = new JavaObject[size];
array.arraycopy(0, whole, 0, size);
JavaField stringField = null;
Iterator iter = whole[0].getJavaClass().getDeclaredFields().iterator();
while(iter.hasNext()) {
JavaField testField = (JavaField) iter.next();
if (testField.getName().equals("_stringField")) {
//this is the field
stringField = testField;
}
}
assertNotNull(stringField);
//now extract the string fields
for (int i = 0; i < whole.length; i++) {
String stringContent = stringField.getString(whole[i]);
assertTrue(stringContent.equals(Integer.toString(size-i)));
}
}
}
} else {
//we are missing something required to run the test
throw new TestNotImplementedException();
}
} catch (CorruptDataException e) {
//if anything went wrong, we can't run the test
throw new TestNotImplementedException();
} catch (MemoryAccessException e) {
assertNotNull(e.getPointer());
//if anything went wrong, we can't run the test
throw new TestNotImplementedException();
} catch (Exception e) {
//if we caught anything else, this is an error
fail();
}
} else {
//the class isn't there so say we can't run the test
throw new TestNotImplementedException();
}
}
/**
* Test method for 'javax.tools.diagnostics.runtime.java.JavaClass.toString()'
*
*/
public void testToString()
{
String theString = _testClass.toString();
assertNotNull(theString);
assertTrue(theString.length() >= 0 );
}
}