/** * 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 openjava.mop.*; import openjava.ptree.*; import java.io.*; /** * <p>Generate ABS (Absolute Value Insertion), AOR (Arithmetic Operator Replacement), * LCR (Logical Operator Replacement), ROR (Relational Operator Replacement), * and UOI (Unary Operator Insertion) mutants. * </p> * <p> * -- <i>ABS</i> modifies each arithmetic expression by the function <i>abs()</i>, * <i>negAbs()</i>, and <i>failOnZero()</i> <br /> * -- <i>AOR</i> replaces each occurrence of one of the arithmetic operators +, -, *, /, * and % by each of the other operators <br /> * -- <i>LCR</i> replaces each occurrence of each bitwise logical operator * (bitwise and - &, bitwise or - |, exclusive or - ^) by each of * the other operators <br /> * -- <i>ROR</i> replaces each occurrence of one of the relational operators * (<, <=, >, >=, =, <>) by each of the other operators and by * <i>falseOp</i> which assigns a <i>false</i> value to a predicate, and * <i>trueOp</i> which assigns a <i>true</i> value to a predicate <br /> * -- <i>UOI</i> inserts each unary operator (arithmetic +, arithmetic -, conditional !, * logical ~) before each expression of the correct type * </p> * @author Yu-Seung Ma * @version 1.0 */ public class ABS_AOR_LCR_ROR_UOI extends mujava.op.util.Mutator { boolean mutant_possible = true; boolean absFlag = true; boolean aorFlag = true; boolean lcrFlag = true; boolean rorFlag = true; boolean uoiFlag = true; public ABS_AOR_LCR_ROR_UOI(FileEnvironment file_env, ClassDeclaration cdecl, CompilationUnit comp_unit) { super( file_env, comp_unit ); } /** * Set ABS flag to a given predicate * @param b */ public void setABSFlag(boolean b) { absFlag = b; } /** * Set AOR flag to a given predicate * @param b */ public void setAORFlag(boolean b) { aorFlag = b; } /** * Set LCR flag to a given predicate * @param b */ public void setLCRFlag(boolean b) { lcrFlag = b; } /** * Set ROR flag to a given predicate * @param b */ public void setRORFlag(boolean b) { rorFlag = b; } /** * Set UOI flag to a given predicate * @param b */ public void setUOIFlag(boolean b) { uoiFlag = b; } public void visit( FieldDeclaration p ) throws ParseTreeException { mutant_possible = false; super.visit(p); mutant_possible = true; } public void visit( MethodCall p ) throws ParseTreeException { try { OJClass type = getType(p); if (mutant_possible) { if ( type == OJSystem.INT || type == OJSystem.DOUBLE || type == OJSystem.FLOAT || type == OJSystem.LONG || type == OJSystem.SHORT) { if (absFlag) absMutantGen(p); } else if ( type == OJSystem.BOOLEAN) { if (uoiFlag) uoi_boolean_MutantGen(p); } } mutant_possible = true; super.visit(p); } catch (Exception e) { // do nothing } } public void visit( BinaryExpression p ) throws ParseTreeException { OJClass type = getType(p); // arithmetic expression // for ABS, UOI operator if ( type == OJSystem.INT || type == OJSystem.DOUBLE || type == OJSystem.FLOAT || type == OJSystem.LONG || type == OJSystem.SHORT) { if (absFlag) absMutantGen(p); } Expression lexpr = p.getLeft(); lexpr.accept( this ); int op_type = p.getOperator(); switch (op_type) { // for AOR mutation operator // 5 Arithmetic Operators : TIMES, DIVIDE, MOD, PLUS, MONUS case BinaryExpression.TIMES : if (aorFlag) aorMutantGen(p,BinaryExpression.TIMES); break; case BinaryExpression.DIVIDE : if (aorFlag) aorMutantGen(p,BinaryExpression.DIVIDE); break; case BinaryExpression.MOD : if (aorFlag) aorMutantGen(p,BinaryExpression.MOD); break; case BinaryExpression.PLUS : if (aorFlag) aorMutantGen(p,BinaryExpression.PLUS); break; case BinaryExpression.MINUS : if (aorFlag) aorMutantGen(p,BinaryExpression.MINUS); break; // for ROR mutation operator // 7 Relational Operators : LESS,GREATER,LESSEQUAL,GREATEREQUAL, // EQUAL,NOTEQUAL case BinaryExpression.LESS : if (rorFlag) rorMutantGen(p,BinaryExpression.LESS); break; case BinaryExpression.GREATER : if (rorFlag) rorMutantGen(p,BinaryExpression.GREATER); break; case BinaryExpression.LESSEQUAL : if (rorFlag) rorMutantGen(p,BinaryExpression.LESSEQUAL); break; case BinaryExpression.GREATEREQUAL : if (rorFlag) rorMutantGen(p,BinaryExpression.GREATEREQUAL); break; case BinaryExpression.EQUAL : if (rorFlag) rorMutantGen(p,BinaryExpression.EQUAL); break; case BinaryExpression.NOTEQUAL : if (rorFlag) rorMutantGen(p,BinaryExpression.NOTEQUAL); break; // for LCR mutation operator // 3 Logical Operators : AND, OR, XOR case BinaryExpression.LOGICAL_AND : if (lcrFlag) lcrMutantGen(p,BinaryExpression.LOGICAL_AND); break; case BinaryExpression.LOGICAL_OR : if (lcrFlag) lcrMutantGen(p,BinaryExpression.LOGICAL_OR); break; case BinaryExpression.XOR : if (lcrFlag) lcrMutantGen(p,BinaryExpression.XOR); break; } Expression rexpr = p.getRight(); rexpr.accept( this ); } public void visit( StatementList p ) throws ParseTreeException { mutant_possible = true; super.visit(p); } public void visit( Parameter p ) throws ParseTreeException { mutant_possible = false; super.visit(p); mutant_possible = true; } public void visit( VariableDeclaration p ) throws ParseTreeException { mutant_possible = false; super.visit(p); mutant_possible = true; } public void visit( ExpressionStatement p ) throws ParseTreeException { Expression exp = p.getExpression(); if (exp instanceof MethodCall) { mutant_possible = false; super.visit(p); mutant_possible = true; } else { super.visit(p); } } public void visit( CaseGroup p ) throws ParseTreeException { mutant_possible = false; super.visit(p); mutant_possible = true; } public void visit( Variable p ) throws ParseTreeException { OJClass type = getType(p); if ( mutant_possible) { // arithmetic expression // for ABS, UOI operator if ( type == OJSystem.INT || type == OJSystem.DOUBLE || type == OJSystem.FLOAT || type == OJSystem.LONG || type == OJSystem.SHORT) { if (mutant_possible) { if (absFlag) absMutantGen(p); if (uoiFlag) uoi_arithmetic_MutantGen(p); } } else if (type == OJSystem.BOOLEAN) { if (mutant_possible) { if (uoiFlag) uoi_boolean_MutantGen(p); } } } super.visit(p); } public void visit( UnaryExpression p ) throws ParseTreeException { OJClass type = getType(p); if (type == OJSystem.BOOLEAN) { lcr_outputToFile(p); } //-------------------------------------- mutant_possible = false; Expression newp = this.evaluateDown( p ); if (newp != p) { p.replace( newp ); return; } p.childrenAccept( this ); newp = this.evaluateUp( p ); if (newp != p) p.replace( newp ); mutant_possible = true; } public void visit( AssignmentExpression p ) throws ParseTreeException { //mutant_possible = false; //Expression left = p.getLeft(); //super.visit( p ); //FieldAccess fldac = (FieldAccess) left; //Expression refexpr = fldac.getReferenceExpr(); //TypeName reftype = fldac.getReferenceType(); mutant_possible = true; Expression value = p.getRight(); /* custom version of visit() skipping the field */ Expression newp; newp = this.evaluateDown( p ); if (newp != p) { p.replace( newp ); newp.accept( this ); return; } value.accept( this ); newp = this.evaluateUp( p ); if (newp != p) p.replace( newp ); } private void lcrMutantGen(BinaryExpression exp, int op) { if (op != BinaryExpression.LOGICAL_AND) { lcr_outputToFile(exp,BinaryExpression.LOGICAL_AND); } if (op != BinaryExpression.LOGICAL_OR) { lcr_outputToFile(exp,BinaryExpression.LOGICAL_OR); } if (op != BinaryExpression.XOR) { lcr_outputToFile(exp,BinaryExpression.XOR); } } private void absMutantGen(MethodCall exp) { abs_zero_outputToFile(exp); abs_negative_outputToFile(exp); } private void absMutantGen(BinaryExpression exp) { abs_zero_outputToFile(exp); abs_negative_outputToFile(exp); } private void absMutantGen(Variable var) { abs_zero_outputToFile(var); abs_negative_outputToFile(var); } private void uoi_boolean_MutantGen(Variable exp) { uoi_outputToFile(exp,UnaryExpression.NOT); } private void uoi_boolean_MutantGen(MethodCall exp) { uoi_outputToFile(exp,UnaryExpression.NOT); } private void uoi_arithmetic_MutantGen(Variable exp) { uoi_outputToFile(exp,UnaryExpression.POST_DECREMENT); uoi_outputToFile(exp,UnaryExpression.POST_INCREMENT); uoi_outputToFile(exp,UnaryExpression.PRE_DECREMENT); uoi_outputToFile(exp,UnaryExpression.PRE_INCREMENT); } private void aorMutantGen(BinaryExpression exp, int op) { if (op != BinaryExpression.TIMES) { aor_outputToFile(exp,BinaryExpression.TIMES); } if (op != BinaryExpression.DIVIDE) { aor_outputToFile(exp,BinaryExpression.DIVIDE); } if (op != BinaryExpression.MOD) { aor_outputToFile(exp,BinaryExpression.MOD); } if (op != BinaryExpression.PLUS) { aor_outputToFile(exp,BinaryExpression.PLUS); } if (op != BinaryExpression.MINUS) { aor_outputToFile(exp,BinaryExpression.MINUS); } } private void rorMutantGen(BinaryExpression exp, int op) { if (op != BinaryExpression.LESS) { ror_outputToFile(exp,BinaryExpression.LESS); } if (op != BinaryExpression.GREATER) { ror_outputToFile(exp,BinaryExpression.GREATER); } if (op != BinaryExpression.LESSEQUAL) { ror_outputToFile(exp,BinaryExpression.LESSEQUAL); } if (op != BinaryExpression.GREATEREQUAL) { ror_outputToFile(exp,BinaryExpression.GREATEREQUAL); } if (op != BinaryExpression.EQUAL) { ror_outputToFile(exp,BinaryExpression.EQUAL); } if (op != BinaryExpression.NOTEQUAL) { ror_outputToFile(exp,BinaryExpression.NOTEQUAL); } } /** * Output UOI mutants to files * @param original * @param mutant_op */ public void uoi_outputToFile(Variable original, int mutant_op) { if (comp_unit == null) return; String f_name; num++; f_name = getSourceName("UOI"); String mutant_dir = getMuantID("UOI"); try { PrintWriter out = getPrintWriter(f_name); UOI_Writer writer = new UOI_Writer(mutant_dir, out); writer.setMutant(original, mutant_op); 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(); } } /** * Output UOI mutants to files * @param original * @param mutant_op */ public void uoi_outputToFile(MethodCall original, int mutant_op) { if (comp_unit == null) return; String f_name; num++; f_name = getSourceName("UOI"); String mutant_dir = getMuantID("UOI"); try { PrintWriter out = getPrintWriter(f_name); UOI_Writer writer = new UOI_Writer(mutant_dir, out); writer.setMutant(original, mutant_op); 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(); } } public void aor_outputToFile(BinaryExpression original, int mutant_op) { if (comp_unit == null) return; String f_name; num++; f_name = getSourceName("AOR"); String mutant_dir = getMuantID("AOR"); try { PrintWriter out = getPrintWriter(f_name); AOR_Writer writer = new AOR_Writer(mutant_dir, out); writer.setMutant(original, mutant_op); 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(); } } /** * Output LCR mutants to files * @param original * @param mutant_op */ public void lcr_outputToFile(BinaryExpression original, int mutant_op) { if (comp_unit == null) return; String f_name; num++; f_name = getSourceName("LCR"); String mutant_dir = getMuantID("LCR"); try { PrintWriter out = getPrintWriter(f_name); LCR_Writer writer = new LCR_Writer(mutant_dir, out); writer.setMutant(original, mutant_op); 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(); } } /** * Output LCR mutants to files * @param original */ public void lcr_outputToFile(UnaryExpression original) { if (comp_unit == null) return; String f_name; num++; f_name = getSourceName("LCR"); String mutant_dir = getMuantID("LCR"); try { PrintWriter out = getPrintWriter(f_name); LCR_Writer writer = new LCR_Writer(mutant_dir, out); writer.setMutant(original); 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(); } } /** * Output ABS (<i>failOnZero()</i> on expression) mutants to files * @param original */ public void abs_zero_outputToFile(BinaryExpression original) { if (comp_unit == null) return; String f_name; num++; f_name = getSourceName("ABS"); String mutant_dir = getMuantID("ABS"); try { PrintWriter out = getPrintWriter(f_name); ABS_Writer writer = new ABS_Writer(mutant_dir, out); writer.setZeroFlag(original); 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(); } } /** * Output ABS (<i>absNeg()</i> on expression) mutants to files * @param original */ public void abs_negative_outputToFile(BinaryExpression original) { if (comp_unit == null) return; String f_name; num++; f_name = getSourceName("ABS"); String mutant_dir = getMuantID("ABS"); try { PrintWriter out = getPrintWriter(f_name); ABS_Writer writer = new ABS_Writer(mutant_dir, out); writer.setNegativeFlag(original); 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(); } } /** * Output ABS (<i>failOnZero()</i> (on method call) mutants to files * @param original */ public void abs_zero_outputToFile(MethodCall original) { if (comp_unit == null) return; String f_name; num++; f_name = getSourceName("ABS"); String mutant_dir = getMuantID("ABS"); try { PrintWriter out = getPrintWriter(f_name); ABS_Writer writer = new ABS_Writer(mutant_dir, out); writer.setZeroFlag(original); 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(); } } /** * Output ABS (<i>absNeg()</i> on method call) mutants to files * @param original */ public void abs_negative_outputToFile(MethodCall original) { if (comp_unit == null) return; String f_name; num++; f_name = getSourceName("ABS"); String mutant_dir = getMuantID("ABS"); try { PrintWriter out = getPrintWriter(f_name); ABS_Writer writer = new ABS_Writer(mutant_dir, out); writer.setNegativeFlag(original); 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(); } } /** * Output ABS (<i>failOnZero()</i> (on variable) mutants to files * @param original */ public void abs_zero_outputToFile(Variable original) { if (comp_unit == null) return; String f_name; num++; f_name = getSourceName("ABS"); String mutant_dir = getMuantID("ABS"); try { PrintWriter out = getPrintWriter(f_name); ABS_Writer writer = new ABS_Writer(mutant_dir, out); writer.setZeroFlag(original); 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(); } } /** * Output ABS (<i>absNeg()</i> on variable) mutants to files * @param original */ public void abs_negative_outputToFile(Variable original) { if (comp_unit == null) return; String f_name; num++; f_name = getSourceName("ABS"); String mutant_dir = getMuantID("ABS"); try { PrintWriter out = getPrintWriter(f_name); ABS_Writer writer = new ABS_Writer(mutant_dir, out); writer.setNegativeFlag(original); 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(); } } /** * Output ROR mutants to files * @param original * @param mutant_op */ public void ror_outputToFile(BinaryExpression original, int mutant_op) { if (comp_unit == null) return; String f_name; num++; f_name = getSourceName("ROR"); String mutant_dir = getMuantID("ROR"); try { PrintWriter out = getPrintWriter(f_name); ROR_Writer writer = new ROR_Writer(mutant_dir, out); writer.setMutant(original,mutant_op); 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(); } } }