All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.evosuite.testcarver.testcase.EvoTestCaseCodeGenerator 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.testcarver.testcase;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;

import org.apache.commons.lang3.reflect.FieldUtils;
import org.evosuite.Properties;
import org.evosuite.TestGenerationContext;
import org.evosuite.classpath.ResourceList;
import org.evosuite.testcarver.capture.CaptureLog;
import org.evosuite.testcarver.capture.CaptureUtil;
import org.evosuite.testcarver.codegen.ICodeGenerator;
import org.evosuite.testcase.variable.ArrayIndex;
import org.evosuite.testcase.variable.ArrayReference;
import org.evosuite.testcase.variable.FieldReference;
import org.evosuite.testcase.variable.NullReference;
import org.evosuite.testcase.TestCase;
import org.evosuite.testcase.variable.VariableReference;
import org.evosuite.testcase.statements.ArrayStatement;
import org.evosuite.testcase.statements.AssignmentStatement;
import org.evosuite.testcase.statements.ClassPrimitiveStatement;
import org.evosuite.testcase.statements.ConstructorStatement;
import org.evosuite.testcase.statements.FieldStatement;
import org.evosuite.testcase.statements.ImmutableStringPrimitiveStatement;
import org.evosuite.testcase.statements.MethodStatement;
import org.evosuite.testcase.statements.NullStatement;
import org.evosuite.testcase.statements.PrimitiveStatement;
import org.evosuite.utils.generic.GenericConstructor;
import org.evosuite.utils.generic.GenericField;
import org.evosuite.utils.generic.GenericMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class EvoTestCaseCodeGenerator implements ICodeGenerator {
	
	private static final Logger logger = LoggerFactory.getLogger(EvoTestCaseCodeGenerator.class);
	//--- source generation
	private TestCase testCase;

	private final Map oidToVarRefMap;

	public EvoTestCaseCodeGenerator() {
		this.oidToVarRefMap = new HashMap<>();
	}
	
	@Override
	public boolean isMaximumLengthReached() {
		return testCase.size() > Properties.CHROMOSOME_LENGTH;
	}

	@Override
	public void createMethodCallStmt(final CaptureLog log, final int logRecNo) {
		if(log == null)
			throw new IllegalArgumentException("captured log must not be null");
		if(logRecNo <= -1)
			throw new IllegalArgumentException("log record number is invalid: " + logRecNo);
		if(isMaximumLengthReached())
			return;
		
		// assumption: all necessary statements are created and there is one variable for each referenced object
		final int oid = log.objectIds.get(logRecNo);
		final Object[] methodArgs = log.params.get(logRecNo);
		final String methodName = log.methodNames.get(logRecNo);
		Class type;
		try {
			final String typeName = log.getTypeName(oid);
			type = getClassForName(typeName);

			logger.debug("Creating method call statement for call to method {}.{}", typeName, methodName);

			final Class[] methodParamTypeClasses = getMethodParamTypeClasses(log, logRecNo);
			final ArrayList args = getArguments(methodArgs,
					methodParamTypeClasses);


			if (CaptureLog.OBSERVED_INIT.equals(methodName)) {
				// Person var0 = new Person();
				final ConstructorStatement constStmt = new ConstructorStatement(
						testCase,
						new GenericConstructor(
								type.getDeclaredConstructor(methodParamTypeClasses), type),
						args);

				this.oidToVarRefMap.put(oid, testCase.addStatement(constStmt));
			} else {
				//------------------ handling for ordinary method calls e.g. var1 = var0.doSth();
				final Object returnValue = log.returnValues.get(logRecNo);

				if (CaptureLog.RETURN_TYPE_VOID.equals(returnValue)) {

					GenericMethod genericMethod = new GenericMethod(
							this.getDeclaredMethod(type, methodName,
									methodParamTypeClasses)
							, type);

					MethodStatement m = new MethodStatement(testCase, genericMethod,
							this.oidToVarRefMap.get(oid), args);

					testCase.addStatement(m);
				} else {
					// final org.objectweb.asm.Type returnType = org.objectweb.asm.Type.getReturnType(methodDesc);
					logger.debug("Callee: {} ({})", this.oidToVarRefMap.get(oid), this.oidToVarRefMap.keySet());
					// Person var0 = var.getPerson();
					final MethodStatement m = new MethodStatement(
							testCase,
							new GenericMethod(
									this.getDeclaredMethod(type, methodName,
											methodParamTypeClasses), type),

							this.oidToVarRefMap.get(oid),
							args);
					final Integer returnValueOID = (Integer) returnValue;
					this.oidToVarRefMap.put(returnValueOID, testCase.addStatement(m));
				}
			}
		} catch(NoSuchMethodException e) {
			logger.info("Method not found; this may happen e.g. if an exception is thrown in the constructor");
			return;
		} catch (final Exception e) {
			logger.info("Error at log record number {}: {}", logRecNo, e.toString());
			logger.info("Test case so far: "+testCase.toCode());
			logger.info(log.toString());

			CodeGeneratorException.propagateError(e, "[logRecNo = %s] - an unexpected error occurred while creating method call stmt for %s.", logRecNo, methodName);
		}
	}

	private Class[] getMethodParamTypeClasses(CaptureLog log, int logRecNo) {
		final String methodDesc = log.descList.get(logRecNo);
		final org.objectweb.asm.Type[] methodParamTypes = org.objectweb.asm.Type.getArgumentTypes(methodDesc);

		final Class[] methodParamTypeClasses = new Class[methodParamTypes.length];
		for (int i = 0; i < methodParamTypes.length; i++) {
			methodParamTypeClasses[i] = getClassFromType(methodParamTypes[i]);
		}
		return methodParamTypeClasses;
	}

	private ArrayList getArguments(final Object[] methodArgs,
	        final Class[] methodParamTypeClasses) throws IllegalArgumentException {

		ArrayList args = new ArrayList();

		Integer argOID; // is either an oid or null
		for (int i = 0; i < methodArgs.length; i++) {
			argOID = (Integer) methodArgs[i];
			if (argOID == null) {
				args.add(testCase.addStatement(new NullStatement(testCase,
				        methodParamTypeClasses[i])));
			} else {
				VariableReference ref = this.oidToVarRefMap.get(argOID);
				if (ref == null) {
					throw new RuntimeException("VariableReference is null for argOID "
					        + argOID+"; have oids: "+this.oidToVarRefMap.keySet());
				} else {
					args.add(ref);
				}
			}
		}
		return args;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public void createPlainInitStmt(CaptureLog log, int logRecNo) {
		// NOTE: PLAIN INIT: has always one non-null param
		// TODO: use primitives
		final int oid = log.objectIds.get(logRecNo);

		if (this.oidToVarRefMap.containsKey(oid)) {
			// TODO this might happen because of Integer.valueOf(), for example. . Is this approach ok?
			return;
		}

		final String type = log.getTypeName(oid);
		final Object value = log.params.get(logRecNo)[0];

		final VariableReference varRef;

		if (value instanceof Class) {
			// final PrimitiveStatement cps = ClassPrimitiveStatement.getPrimitiveStatement(testCase, getClassForName(type));
			final PrimitiveStatement cps = new ClassPrimitiveStatement(testCase,
			        getClassForName(type));
			cps.setValue(value);

			varRef = testCase.addStatement(cps);
		} else {
			final PrimitiveStatement primitiveValue = PrimitiveStatement.getPrimitiveStatement(testCase,
			                                                                                   getClassForName(type));
			primitiveValue.setValue(value);

			varRef = testCase.addStatement(primitiveValue);
		}

		this.oidToVarRefMap.put(oid, varRef);
	}

	@SuppressWarnings({ "rawtypes" })
	@Override
	public void createUnobservedInitStmt(CaptureLog log, int logRecNo) {

		// NOTE: PLAIN INIT: has always one non-null param
		// TODO: use primitives
		final int oid = log.objectIds.get(logRecNo);

		try {

			final Object value = log.params.get(logRecNo)[0];
			final PrimitiveStatement stringRep = new ImmutableStringPrimitiveStatement(testCase, (String)value);
			final VariableReference stringRepRef = testCase.addStatement(stringRep);

			final MethodStatement m = new MethodStatement(testCase, new GenericMethod(EvoSuiteXStream.class.getMethod("fromString", new Class[] {String.class}), EvoSuiteXStream.class), null, Arrays.asList(stringRepRef));
			this.oidToVarRefMap.put(oid, testCase.addStatement(m));
		} catch (final Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public void createFieldWriteAccessStmt(CaptureLog log, int logRecNo) {
		// assumption: all necessary statements are created and there is one variable for each referenced object

		final Object[] methodArgs = log.params.get(logRecNo);
		final int oid = log.objectIds.get(logRecNo);
		final int captureId = log.captureIds.get(logRecNo);

		final String fieldName = log.getNameOfAccessedFields(captureId);
		final String typeName = log.getTypeName(oid);

		try {
			final Class type = getClassForName(typeName);

			final String fieldDesc = log.descList.get(logRecNo);
			final Class fieldType = CaptureUtil.getClassFromDesc(fieldDesc);

			final FieldReference targetFieldRef = new FieldReference(testCase,
			        new GenericField(this.getDeclaredField(type, fieldName), type), this.oidToVarRefMap.get(oid));

			final AssignmentStatement assignment;

			final Integer arg = (Integer) methodArgs[0];
			if (arg == null) {
				final NullStatement nullStmt = new NullStatement(testCase, fieldType);
				final VariableReference nullReference = testCase.addStatement(nullStmt);

				assignment = new AssignmentStatement(testCase, targetFieldRef,
				        nullReference);
			} else {
				assignment = new AssignmentStatement(testCase, targetFieldRef,
				        this.oidToVarRefMap.get(arg));
			}
			final VariableReference varRef = testCase.addStatement(assignment);
			logger.debug("Adding assignment statement: "+assignment.getCode());
			if (arg != null) {
				this.oidToVarRefMap.put(arg, varRef);
			}
		} catch (final Exception e) {
			CodeGeneratorException.propagateError(e, "[logRecNo = %s] - an unexpected error occurred while creating field write access stmt. Log: %s", logRecNo, log);
		}
	}

	@Override
	public void createFieldReadAccessStmt(CaptureLog log, int logRecNo) {
		// assumption: all necessary statements are created and there is one variable for reach referenced object
		final int oid = log.objectIds.get(logRecNo);
		final int captureId = log.captureIds.get(logRecNo);

		final Object returnValue = log.returnValues.get(logRecNo);
		if (!CaptureLog.RETURN_TYPE_VOID.equals(returnValue)) // TODO necessary?
		{
			Integer returnValueOID = (Integer) returnValue;
//			final String descriptor = log.descList.get(logRecNo);
//			final org.objectweb.asm.Type fieldTypeType = org.objectweb.asm.Type.getType(descriptor);
			final String typeName = log.getTypeName(oid);
			final String fieldName = log.getNameOfAccessedFields(captureId);

			try {
//				final Class fieldType = getClassFromType(fieldTypeType);
				final Class type = getClassForName(typeName);

//				final FieldReference valueRef = new FieldReference(testCase,
//				        new GenericField(getDeclaredField(type, fieldName), type));
//				final VariableReference targetVar = new VariableReferenceImpl(testCase,
//				        fieldType);

				final FieldStatement fieldStatement = new FieldStatement(testCase, new GenericField(FieldUtils.getField(type, fieldName, true), type), this.oidToVarRefMap.get(oid));
				//final AssignmentStatement assignment = new AssignmentStatement(testCase,
				//        targetVar, valueRef);
				// VariableReference varRef = testCase.addStatement(assignment);
				VariableReference varRef = testCase.addStatement(fieldStatement);

				this.oidToVarRefMap.put(returnValueOID, varRef);

			} catch (final Exception e) {
				logger.debug("Error while trying to get field "
				                                          + fieldName + " of class "
				                                          + getClassForName(typeName)+": "+e);
				CodeGeneratorException.propagateError(e, "[logRecNo = %s] - an unexpected error occurred while creating field read access stmt. Log: %s", logRecNo, log);
			}
		}
	}

	private final Class getClassFromType(final org.objectweb.asm.Type type) {

		if (type.equals(org.objectweb.asm.Type.BOOLEAN_TYPE)) {
			return Boolean.TYPE;
		} else if (type.equals(org.objectweb.asm.Type.BYTE_TYPE)) {
			return Byte.TYPE;
		} else if (type.equals(org.objectweb.asm.Type.CHAR_TYPE)) {
			return Character.TYPE;
		} else if (type.equals(org.objectweb.asm.Type.DOUBLE_TYPE)) {
			return Double.TYPE;
		} else if (type.equals(org.objectweb.asm.Type.FLOAT_TYPE)) {
			return Float.TYPE;
		} else if (type.equals(org.objectweb.asm.Type.INT_TYPE)) {
			return Integer.TYPE;
		} else if (type.equals(org.objectweb.asm.Type.LONG_TYPE)) {
			return Long.TYPE;
		} else if (type.equals(org.objectweb.asm.Type.SHORT_TYPE)) {
			return Short.TYPE;
		} else if (type.getSort() == org.objectweb.asm.Type.ARRAY) {
			final org.objectweb.asm.Type elementType = type.getElementType();
			int[] dimensions = new int[type.getDimensions()];
			
			if (elementType.equals(org.objectweb.asm.Type.BOOLEAN_TYPE)) {
				return Array.newInstance(boolean.class, dimensions).getClass();
			} else if (elementType.equals(org.objectweb.asm.Type.BYTE_TYPE)) {
				return Array.newInstance(byte.class, dimensions).getClass();
			} else if (elementType.equals(org.objectweb.asm.Type.CHAR_TYPE)) {
				return Array.newInstance(char.class, dimensions).getClass();
			} else if (elementType.equals(org.objectweb.asm.Type.DOUBLE_TYPE)) {
				return Array.newInstance(double.class, dimensions).getClass();
			} else if (elementType.equals(org.objectweb.asm.Type.FLOAT_TYPE)) {
				return Array.newInstance(float.class, dimensions).getClass();
			} else if (elementType.equals(org.objectweb.asm.Type.INT_TYPE)) {
				return Array.newInstance(int.class, dimensions).getClass();
			} else if (elementType.equals(org.objectweb.asm.Type.LONG_TYPE)) {
				return Array.newInstance(long.class, dimensions).getClass();
			} else if (elementType.equals(org.objectweb.asm.Type.SHORT_TYPE)) {
				return Array.newInstance(short.class, dimensions).getClass();
			}
		}

		//		try 
		//		{
		return getClassForName(type.getClassName());
		//			return Class.forName(type.getClassName(), true, StaticTestCluster.classLoader);
		//		} 
		//		catch (final ClassNotFoundException e) 
		//		{
		//			throw new RuntimeException(e);
		//		}
	}

	private final Class getClassForName(String type) {
		try {
			if (type.equals("boolean") || type.equals("java.lang.Boolean")) {
				return Boolean.TYPE;
			} else if (type.equals("byte") || type.equals("java.lang.Byte")) {
				return Byte.TYPE;
			} else if (type.equals("char") || type.equals("java.lang.Character")) {
				return Character.TYPE;
			} else if (type.equals("double") || type.equals("java.lang.Double")) {
				return Double.TYPE;
			} else if (type.equals("float") || type.equals("java.lang.Float")) {
				return Float.TYPE;
			} else if (type.equals("int") || type.equals("java.lang.Integer")) {
				return Integer.TYPE;
			} else if (type.equals("long") || type.equals("java.lang.Long")) {
				return Long.TYPE;
			} else if (type.equals("short") || type.equals("java.lang.Short")) {
				return Short.TYPE;
			} else if (type.equals("String")) {
				return Class.forName("java.lang." + type, true,
				                     TestGenerationContext.getInstance().getClassLoaderForSUT());
			}

			if (type.endsWith("[]")) {
				// see http://stackoverflow.com/questions/3442090/java-what-is-this-ljava-lang-object
				
				final StringBuilder arrayTypeNameBuilder = new StringBuilder(30);
				
				int index = 0;
				while((index = type.indexOf('[', index)) != -1)
				{
					arrayTypeNameBuilder.append('[');
					index++;
				}
				
				arrayTypeNameBuilder.append('L'); // always needed for Object arrays
				
				// remove bracket from type name get array component type
				type = type.replace("[]", "");
				arrayTypeNameBuilder.append(type);

				arrayTypeNameBuilder.append(';'); // finalize object array name
				
				return Class.forName(arrayTypeNameBuilder.toString(), true,
				                     TestGenerationContext.getInstance().getClassLoaderForSUT());
			} else {
				return Class.forName(ResourceList.getClassNameFromResourcePath(type), true,
				                     TestGenerationContext.getInstance().getClassLoaderForSUT());
			}
		} catch (final ClassNotFoundException e) {
			throw new RuntimeException(e);
		}
	}

	private Field getDeclaredField(final Class clazz, final String fieldName)
	        throws NoSuchFieldException {
		if (clazz == null || Object.class.equals(clazz)) {
			throw new NoSuchFieldException(fieldName);
		}

		try {
			final Field field = clazz.getDeclaredField(fieldName);
			field.setAccessible(true);
			return field;
		} catch (final NoSuchFieldException e) {
			return getDeclaredField(clazz.getSuperclass(), fieldName);
		}
	}

	private Method getDeclaredMethod(final Class clazz, final String methodName,
	        Class[] paramTypes) throws NoSuchMethodException {
		// logger.info("Trying to get method "+methodName +" from class "+clazz+" with parameters "+Arrays.asList(paramTypes));
		if (clazz == null || Object.class.equals(clazz)) {
			throw new NoSuchMethodException(methodName + "(" + Arrays.toString(paramTypes)
			        + ")");
		}

		try {
			final Method m = clazz.getDeclaredMethod(methodName, paramTypes);
			m.setAccessible(true);
			return m;
		} catch (final NoSuchMethodException e) {			
			//logger.info("Not found {}, available methods: {}", methodName, Arrays.asList(clazz.getDeclaredMethods()));
			return getDeclaredMethod(clazz.getSuperclass(), methodName, paramTypes);
		}
	}

	@Override
	public void createArrayInitStmt(final CaptureLog log, final int logRecNo) {
		final int oid = log.objectIds.get(logRecNo);

		final Object[] params = log.params.get(logRecNo);
		final String arrTypeName = log.getTypeName(oid);
		final Class arrType = getClassForName(arrTypeName);

		// --- create array instance creation e.g. int[] var = new int[10];

		final ArrayReference arrRef;

		// create array only once
		if (this.oidToVarRefMap.containsKey(oid)) {
			arrRef = (ArrayReference) this.oidToVarRefMap.get(oid);
		} else {
			arrRef = new ArrayReference(testCase, arrType);
			final ArrayStatement arrStmt = new ArrayStatement(testCase, arrRef);
			arrStmt.setSize(params.length);
			testCase.addStatement(arrStmt);
			this.oidToVarRefMap.put(oid, arrRef);
		}

		final Class arrCompClass = arrType.getComponentType();

		AssignmentStatement assignStmt;
		ArrayIndex arrIndex;
		VariableReference valueRef;
		Integer argOID; // is either an oid or null
		for (int i = 0; i < params.length; i++) {
			argOID = (Integer) params[i];
			if (argOID == null) {
				valueRef = testCase.addStatement(new NullStatement(testCase, arrCompClass));
			} else {
				valueRef = this.oidToVarRefMap.get(argOID);
				if(valueRef == null) {
					logger.info("ValueREF is NULL for "+argOID);
					continue;
				}
			}

			arrIndex = new ArrayIndex(testCase, arrRef, i);
			assignStmt = new AssignmentStatement(testCase, arrIndex, valueRef);
			testCase.addStatement(assignStmt);
			logger.debug("Adding assignment (array): "+assignStmt.getCode());
		}
	}

	private boolean hasDefaultConstructor(final Class clazz) {
		for (final Constructor c : clazz.getConstructors()) {
			if (c.getParameterTypes().length == 0 && Modifier.isPublic(c.getModifiers())) {
				return true;
			}
		}

		return false;
	}

	@Override
	public void createCollectionInitStmt(final CaptureLog log, final int logRecNo) {
		try 
		{
			final int oid = log.objectIds.get(logRecNo);
			final Object[] params = log.params.get(logRecNo);
			String collTypeName = log.getTypeName(oid);
			Class collType = getClassForName(collTypeName);

			// -- determine if an alternative collection must be used for code generation
			final boolean isPublic = java.lang.reflect.Modifier.isPublic(collType.getModifiers());
			if (! isPublic || !hasDefaultConstructor(collType)) {
				if (Set.class.isAssignableFrom(collType)) {
					collTypeName = HashSet.class.getName();
					collType = HashSet.class;
				} else if (List.class.isAssignableFrom(collType)) {
					collTypeName = ArrayList.class.getName();
					collType = ArrayList.class;
				} else if (Queue.class.isAssignableFrom(collType)) {
					collTypeName = ArrayDeque.class.getName();
					collType = ArrayDeque.class;
				} else {
					CodeGeneratorException.propagateError("[logRecNo = %s] - collection %s is not supported", logRecNo, collType);
				}
			}

			// -- create code for instantiating collection

			final List noParams = Collections.emptyList();
			final ConstructorStatement constrStmt = new ConstructorStatement(testCase,
			        new GenericConstructor(collType.getConstructor(new Class[0]),
			                collType), noParams);

			final VariableReference collRef = testCase.addStatement(constrStmt);
			this.oidToVarRefMap.put(oid, collRef);

			// --- fill collection

			MethodStatement methodStmt;
			Integer argOID; // is either an oid or null
			ArrayList paramList;
			Method method;

			for (int i = 0; i < params.length; i++) 
			{
				paramList = new ArrayList(1);
				argOID = (Integer) params[i];
				if (argOID == null || !this.oidToVarRefMap.containsKey(argOID)) {
					VariableReference var = testCase.addStatement(new NullStatement(testCase,
					        Object.class));
					paramList.add(var);
				} else {
					VariableReference var = this.oidToVarRefMap.get(argOID); 
					paramList.add(var);
				}

				method = collType.getMethod("add", Object.class);
				methodStmt = new MethodStatement(testCase, new GenericMethod(method,
				        collType), collRef, paramList);
				testCase.addStatement(methodStmt);
			}
		} 
		catch (final Exception e) {
			CodeGeneratorException.propagateError("[logRecNo = %s] - an unexpected error occurred while creating collection init stmt", logRecNo,  e);
		}
	}

	private void replaceNullWithNullReferences(List paramList, Class ... paramTypes)
	{
		CodeGeneratorException.check(paramList.size() == paramTypes.length, "[paramList = %s, paramTypes] - number of params does not correspond number of paramTypes", paramList, Arrays.toString(paramTypes));
		
		Object v;
		for(int j = 0; j < paramList.size(); j++)
		{
			v = paramList.get(j);
			if(v == null)
			{
				paramList.set(j, new NullReference(testCase, paramTypes[j]));
			}
		}

	}
	
	@Override
	public void createMapInitStmt(final CaptureLog log, final int logRecNo) {
		try {
			final int oid = log.objectIds.get(logRecNo);
			final Object[] params = log.params.get(logRecNo);
			String collTypeName = log.getTypeName(oid);
			Class collType = getClassForName(collTypeName);

			// -- determine if an alternative collection must be used for code generation
			final boolean isPublic= java.lang.reflect.Modifier.isPublic(collType.getModifiers());
			if (!isPublic|| !hasDefaultConstructor(collType)) {
				collType = HashMap.class;
			}

			// -- create code for instantiating collection

			final List noParams = Collections.emptyList();
			final ConstructorStatement constrStmt = new ConstructorStatement(testCase,
			        new GenericConstructor(collType.getConstructor(new Class[0]),
			                collType), noParams);

			final VariableReference collRef = testCase.addStatement(constrStmt);
			this.oidToVarRefMap.put(oid, collRef);

			// --- fill collection

			MethodStatement methodStmt;
			Integer argOID; // is either an oid or null
			ArrayList paramList = new ArrayList();

			for (int i = 0; i < params.length; i++) {
				argOID = (Integer) params[i];
				if (argOID == null) {
										
					paramList.add(testCase.addStatement(new NullStatement(testCase,
					        Object.class)));
					
				} else {
					paramList.add(this.oidToVarRefMap.get(argOID));
				}

				if (i % 2 == 1) {

					final Method method = collType.getMethod("put", Object.class,
					                                         Object.class);
					
					replaceNullWithNullReferences(paramList, Object.class, Object.class);
					
					methodStmt = new MethodStatement(testCase, new GenericMethod(method,
					        collType), collRef, paramList);
					testCase.addStatement(methodStmt);
					paramList = new ArrayList(2);
				}

			}
		} catch (final Exception e) {
			CodeGeneratorException.propagateError( e, "[logRecNo = %s] - an unexpected error occurred while creating map init stmt", logRecNo);
		}
	}

	@Override
	public void before(CaptureLog log) {
		this.testCase = new CarvedTestCase();
	}

	@Override
	public void after(CaptureLog log) {
	}

	@Override
	public TestCase getCode() {
		return this.testCase;
	}

	@Override
	public void clear() {
		this.testCase = null;
		this.oidToVarRefMap.clear();
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy