org.evosuite.testcase.statements.EnumPrimitiveStatement Maven / Gradle / Ivy
/**
* Copyright (C) 2010-2018 Gordon Fraser, Andrea Arcuri and EvoSuite
* contributors
*
* This file is part of EvoSuite.
*
* EvoSuite is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3.0 of the License, or
* (at your option) any later version.
*
* EvoSuite is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with EvoSuite. If not, see .
*/
/**
*
*/
package org.evosuite.testcase.statements;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
import java.util.List;
import org.evosuite.testcase.TestCase;
import org.evosuite.testcase.execution.ExecutionTracer;
import org.evosuite.utils.generic.GenericClass;
import org.evosuite.utils.Randomness;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
/**
*
* EnumPrimitiveStatement class.
*
*
* @author Gordon Fraser
*/
public class EnumPrimitiveStatement> extends PrimitiveStatement {
private static final long serialVersionUID = -7027695648061887082L;
private transient T[] constants;
private transient Class enumClass;
/**
*
* Constructor for EnumPrimitiveStatement.
*
*
* @param tc
* a {@link org.evosuite.testcase.TestCase} object.
* @param clazz
* a {@link java.lang.Class} object.
* @param
* a T object.
*/
@SuppressWarnings("unchecked")
public EnumPrimitiveStatement(TestCase tc, Class clazz) {
super(tc, clazz, null);
enumClass = clazz;
boolean tracerEnabled = ExecutionTracer.isEnabled();
if (tracerEnabled)
ExecutionTracer.disable();
try {
if (clazz.getEnumConstants().length > 0) {
this.value = clazz.getEnumConstants()[0];
constants = clazz.getEnumConstants();
} else {
// Coping with empty enums is a bit of a mess
constants = (T[]) new Enum[0];
}
} catch (Throwable t) {
// Loading the Enum class might fail
constants = (T[]) new Enum[0];
}
if (tracerEnabled)
ExecutionTracer.enable();
}
/**
*
* Constructor for EnumPrimitiveStatement.
*
*
* @param tc
* a {@link org.evosuite.testcase.TestCase} object.
* @param value
* a T object.
*/
@SuppressWarnings("unchecked")
public EnumPrimitiveStatement(TestCase tc, T value) {
super(tc, value.getClass(), value);
boolean tracerEnabled = ExecutionTracer.isEnabled();
if (tracerEnabled)
ExecutionTracer.disable();
enumClass = (Class) retrieveEnumClass(value.getClass());
constants = (T[]) retrieveEnumClass(value.getClass()).getEnumConstants();
if (tracerEnabled)
ExecutionTracer.enable();
}
private static Class> retrieveEnumClass(Class> clazz) {
if (clazz.isEnum())
return clazz;
else if (clazz.getEnclosingClass() != null && clazz.getEnclosingClass().isEnum())
return clazz.getEnclosingClass();
else if (clazz.getDeclaringClass() != null && clazz.getDeclaringClass().isEnum())
return clazz.getDeclaringClass();
else
throw new RuntimeException("Cannot find enum class: " + clazz);
}
/**
*
* Getter for the field enumClass
.
*
*
* @return a {@link java.lang.Class} object.
*/
public Class getEnumClass() {
return enumClass;
}
/**
*
* getEnumValues
*
*
* @return a {@link java.util.List} object.
*/
public List getEnumValues() {
return Arrays.asList(constants);
}
/* (non-Javadoc)
* @see org.evosuite.testcase.PrimitiveStatement#delta()
*/
/** {@inheritDoc} */
@Override
public void delta() {
if (constants.length <= 1) {
return;
}
int pos = 0;
for (pos = 0; pos < constants.length; pos++) {
if (constants[pos].equals(value)) {
break;
}
}
boolean delta = Randomness.nextBoolean();
if (delta) {
pos++;
} else {
pos--;
}
if (pos >= constants.length) {
pos = 0;
} else if (pos < 0) {
pos = constants.length - 1;
}
value = constants[pos];
}
/* (non-Javadoc)
* @see org.evosuite.testcase.PrimitiveStatement#hasMoreThanOneValue()
*/
@Override
public boolean hasMoreThanOneValue() {
return constants.length > 1;
}
/* (non-Javadoc)
* @see org.evosuite.testcase.PrimitiveStatement#zero()
*/
/** {@inheritDoc} */
@Override
public void zero() {
if (constants.length == 0)
return;
value = constants[0];
}
/* (non-Javadoc)
* @see org.evosuite.testcase.PrimitiveStatement#randomize()
*/
/** {@inheritDoc} */
@Override
public void randomize() {
if (constants.length > 1) {
int pos = Randomness.nextInt(constants.length);
value = constants[pos];
}
}
/* (non-Javadoc)
* @see org.evosuite.testcase.StatementInterface#changeClassLoader(java.lang.ClassLoader)
*/
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override
public void changeClassLoader(ClassLoader loader) {
try {
int pos = 0;
for (pos = 0; pos < constants.length; pos++) {
if (constants[pos].equals(value)) {
break;
}
}
enumClass = (Class) loader.loadClass(enumClass.getName());
constants = enumClass.getEnumConstants(); // wtf
if (constants==null) {
/**
* I am not sure why, but sometimes it looks as getEnumConstants()
* returns a null value even when the enumClass is actually an enum
* with values. So, the hack I found was simply to retry this again.
*/
constants = enumClass.getEnumConstants();
}
//TODO: the hack above has a drawback: sometimes the new constant array doesn't contain the element at constants[pos]
if (constants.length > pos) {
value = constants[pos];
}
} catch (ClassNotFoundException e) {
logger.warn("Class not found - keeping old class loader ", e);
} catch (SecurityException e) {
logger.warn("Class not found - keeping old class loader ", e);
}
super.changeClassLoader(loader);
}
private void writeObject(ObjectOutputStream oos) throws IOException {
GenericClass currentClass = new GenericClass(enumClass);
oos.writeObject(currentClass);
int pos = 0;
for (pos = 0; pos < constants.length; pos++) {
if (constants[pos].equals(value)) {
break;
}
}
oos.writeInt(pos);
}
@SuppressWarnings("unchecked")
private void readObject(ObjectInputStream ois) throws ClassNotFoundException,
IOException {
GenericClass enumGenericClass = (GenericClass) ois.readObject();
int pos = ois.readInt();
enumClass = (Class) enumGenericClass.getRawClass();
try {
if (enumClass.getEnumConstants().length > 0) {
this.value = enumClass.getEnumConstants()[0];
constants = enumClass.getEnumConstants();
if(constants.length > 0)
value = constants[pos];
} else {
// Coping with empty enums is a bit of a mess
constants = (T[]) new Enum[0];
}
} catch (Throwable t) {
// Loading the Enum class might fail
constants = (T[]) new Enum[0];
}
}
}