/**
* Copyright (C) 2015 the original author or authors.
*
* 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 mujava.op;
import java.io.*;
import openjava.mop.*;
import openjava.ptree.*;
/**
* <p>Generate IOP (Overriding method calling position change) mutants --
* move each call to an overridden method to the first and last
* statements of the method and up and down one statement
* </p>
* @author Yu-Seung Ma
* @version 1.0
*/
public class IOP extends mujava.op.util.Mutator implements IOP_Helper
{
MethodDeclaration containing_method = null;
public IOP(FileEnvironment file_env, ClassDeclaration cdecl, CompilationUnit comp_unit)
{
super( file_env,comp_unit );
}
public void visit(MethodDeclaration p) throws ParseTreeException
{
if (p.getName().equals("main"))
return;
containing_method = p;
super.visit(p);
}
boolean compatibleParameters( ExpressionList args, ParameterList plist)
{
if (args.size() != plist.size())
return false;
OJClass type = null;
for (int i=0; i<args.size(); i++)
{
try
{
type = getType(args.get(i));
} catch (ParseTreeException e)
{
type = null;
}
if (!(type.getName().equals(plist.get(i).getTypeSpecifier().getName())))
return false;
}
return true;
}
boolean isOverridingMethodCallWithSameName(MethodCall p)
{
Expression lexp = p.getReferenceExpr();
if (lexp == null)
return false;
if ( !(lexp instanceof SelfAccess))
return false;
if ( !(((SelfAccess)lexp).getAccessType()==SelfAccess.SUPER) )
return false;
if ( !(p.getName().equals(containing_method.getName())))
return false;
if (!compatibleParameters(p.getArguments(),containing_method.getParameters()) )
return false;
return true;
}
/**
* Write mutants to files and log mutated line
*/
public void visit( StatementList p ) throws ParseTreeException
{
this.evaluateDown( p );
for (int i=0; i<p.size(); i++)
{
Statement stmt = p.get(i);
if (stmt instanceof ExpressionStatement)
{
Expression exp = ((ExpressionStatement)stmt).getExpression();
if (exp instanceof MethodCall)
{
if (isOverridingMethodCallWithSameName((MethodCall)exp))
{
int[] change_mod = getChangeType(p.size(), i);
if (change_mod == null)
continue;
for (int h=0; h<change_mod.length; h++)
{
outputToFile(comp_unit, p, i, change_mod[h]);
}
}
}
}
}
this.evaluateUp( p );
}
/**
* Output IOP mutants to files
* @param comp_unit
* @param stmt_list
* @param index
* @param mod
*/
public void outputToFile(CompilationUnit comp_unit, StatementList stmt_list, int index,int mod)
{
if (comp_unit == null)
return;
String f_name;
num++;
f_name = getSourceName(this);
String mutant_dir = getMuantID();
try
{
PrintWriter out = getPrintWriter(f_name);
IOP_Writer writer = new IOP_Writer( mutant_dir, out );
writer.setMutant(stmt_list, index, mod);
comp_unit.accept( writer );
out.flush(); out.close();
} catch ( IOException e )
{
System.err.println( "fails to create " + f_name );
} catch ( ParseTreeException e )
{
System.err.println( "errors during printing " + f_name );
e.printStackTrace();
}
}
static int[] getChangeType(int stmt_num, int index)
{
int[] result = null;
switch (stmt_num)
{
case 0: break;
case 1: break;
case 2: result = new int[1];
if (index == 0)
result[0] = LAST;
else
result[0] = FIRST;
break;
case 3: result = new int[2];
if (index == 0)
{
result[0] = LAST;
result[1] = DOWN;
}
else if (index == 1)
{
result[0] = FIRST;
result[1] = LAST;
}
else if (index == 2)
{
result[0] = FIRST;
result[1] = UP;
}
break;
default:
if (index == 0)
{
result = new int[2];
result[0] = LAST;
result[1] = DOWN;
}
else if (index == 1)
{
result = new int[3];
result[0] = FIRST;
result[1] = LAST;
result[2] = DOWN;
}
else if (index == stmt_num-2)
{
result = new int[3];
result[0] = FIRST;
result[1] = LAST;
result[2] = UP;
}
else if (index == stmt_num-1)
{
result = new int[2];
result[0] = FIRST;
result[1] = UP;
}
else
{
result = new int[4];
result[0] = FIRST;
result[1] = LAST;
result[2] = UP;
result[3] = DOWN;
}
}
return result;
}
}