/** * 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; import openjava.mop.*; import openjava.ptree.*; import java.io.*; import mujava.op.*; import mujava.op.util.*; import mujava.util.Debug; /** * <p>Generate class mutants according to selected * class mutation operator(s) from gui.GenMutantsMain. * The original version is loaded, mutated, and compiled. * Outputs (mutated source and class files) are in the * class-mutants folder. </p> * * <p> Currently available class mutation operators: * (1) AMC: Access modifier change, * (2) IHD: Hiding variable deletion, * (3) IHI: Hiding variable insertion, * (4) IOD: Overriding method deletion, * (5) IOP: Overriding method calling position change, * (6) IOR: Overriding method rename, * (7) ISI: Super keyword insertion, * (8) ISD: Super keyword deletion, * (9) IPC: Explicit call to parent's constructor deletion, * (10) PNC: New method call with child class type, * (11) PMD: Member variable declaration with parent class type, * (12) PPD: Parameter variable declaration with child class type, * (13) PCI: Type cast operator insertion, * (14) PCC: Cast type change, * (15) PCD: Type cast operator deletion, * (16) PRV: Reference assignment with other compatible variable, * (17) OMR: Overloading method contents replace, * (18) OMD: Overloading method deletion, * (19) OAN: Arguments of overloading method call change, * (20) JTI: Java-specific this keyword insertion, * (21) JTD: Java-specific this keyword deletion, * (22) JSI: Java-specific static modifier insertion, * (23) JSD: Java-specific static modifier deletion, * (24) JID: Java-specific member variable initialization deletion, * (25) JDC: Java-supported default constructor creation, * (26) EOA: Java-specific reference assignment and content assignment replacement, * (27) EOC: Java-specific reference comparison and content assignment replacement, * (28) EAM: Java-specific accessor method change, * (29) EMM: Java-specific modifier method change * </p> * @author Yu-Seung Ma * @version 1.0 */ public class ClassMutantsGenerator extends MutantsGenerator { boolean existIHD = false; String[] classOp; public ClassMutantsGenerator (File f) { super(f); classOp = MutationSystem.cm_operators; } public ClassMutantsGenerator (File f, boolean debug) { super(f, debug); classOp = MutationSystem.cm_operators; } public ClassMutantsGenerator (File f, String[] cOP) { super(f); classOp = cOP; } /** * Verify if the target Java source and class files exist, * generate class mutants */ void genMutants() { if (comp_unit == null) { System.err.println(original_file + " is skipped."); } ClassDeclarationList cdecls = comp_unit.getClassDeclarations(); if (cdecls == null || cdecls.size() == 0) return; if (classOp != null && classOp.length > 0) { Debug.println("* Generating class mutants"); MutationSystem.clearPreviousClassMutants(); MutationSystem.MUTANT_PATH = MutationSystem.CLASS_MUTANT_PATH; CodeChangeLog.openLogFile(); genClassMutants(cdecls); CodeChangeLog.closeLogFile(); } } /** * Apply selected class mutation operators * @param cdecls */ void genClassMutants (ClassDeclarationList cdecls) { genClassMutants1(cdecls); genClassMutants2(cdecls); } /** * Apply selected class mutation operators: IHD, IHI, IOD, OMR, OMD, JDC * @param cdecls */ void genClassMutants2 (ClassDeclarationList cdecls) { for (int j=0; j<cdecls.size(); ++j) { ClassDeclaration cdecl = cdecls.get(j); if (cdecl.getName().equals(MutationSystem.CLASS_NAME)) { DeclAnalyzer mutant_op; if (hasOperator(classOp, "IHD")) { Debug.println(" Applying IHD ... ... "); mutant_op = new IHD(file_env, null, cdecl); generateMutant(mutant_op); if ( ( (IHD)mutant_op).getTotal() > 0 ) existIHD = true; } if (hasOperator(classOp, "IHI")) { Debug.println(" Applying IHI ... ... "); mutant_op = new IHI(file_env, null, cdecl); generateMutant(mutant_op); } if (hasOperator(classOp, "IOD")) { Debug.println(" Applying IOD ... ... "); mutant_op = new IOD(file_env, null, cdecl); generateMutant(mutant_op); } if (hasOperator(classOp, "OMR")) { Debug.println(" Applying OMR ... ... "); mutant_op = new OMR(file_env, null, cdecl); generateMutant(mutant_op); } if (hasOperator(classOp, "OMD")) { Debug.println(" Applying OMD ... ... "); mutant_op = new OMD(file_env, null, cdecl); generateMutant(mutant_op); } if (hasOperator(classOp, "JDC")) { Debug.println(" Applying JDC ... ... "); mutant_op = new JDC(file_env, null, cdecl); generateMutant(mutant_op); } } } } /** * Apply selected class mutation operators: * AMC, IOR, ISD, IOP, IPC, PNC, PMD, PPD, * PRV, PCI, PCC, PCD, JSD, JSI, JTD, JTI, * JID, OAN, EOA, EOC, EAM, EMM * @param cdecls */ void genClassMutants1(ClassDeclarationList cdecls) { for (int j=0; j<cdecls.size(); ++j) { ClassDeclaration cdecl = cdecls.get(j); if (cdecl.getName().equals(MutationSystem.CLASS_NAME)) { String qname = file_env.toQualifiedName(cdecl.getName()); try { mujava.op.util.Mutator mutant_op; if (hasOperator(classOp, "AMC")) { Debug.println(" Applying AMC ... ... "); mutant_op = new AMC(file_env, cdecl, comp_unit); comp_unit.accept(mutant_op); } if (hasOperator(classOp, "IOR")) { Debug.println(" Applying IOR ... ... "); try { Class parent_class = Class.forName(qname).getSuperclass(); if ( !(parent_class.getName().equals("java.lang.Object")) ) { String temp_str = parent_class.getName(); String result_str = ""; for (int k=0; k<temp_str.length(); k++) { char c = temp_str.charAt(k); if (c == '.') { result_str = result_str + "/"; } else { result_str = result_str + c; } } File f = new File(MutationSystem.SRC_PATH, result_str + ".java"); if (f.exists()) { CompilationUnit[] parent_comp_unit = new CompilationUnit[1]; FileEnvironment[] parent_file_env = new FileEnvironment[1]; this.generateParseTree(f, parent_comp_unit, parent_file_env); this.initParseTree(parent_comp_unit, parent_file_env); mutant_op = new IOR(file_env, cdecl, comp_unit); ((IOR)mutant_op).setParentEnv(parent_file_env[0], parent_comp_unit[0]); comp_unit.accept(mutant_op); } } } catch (ClassNotFoundException e) { System.out.println(" Exception at generating IOR mutant. file : AllMutantsGenerator.java "); } catch (NullPointerException e1) { System.out.print(" IOP ^^; "); } } if (hasOperator(classOp, "ISD")) { Debug.println(" Applying ISD ... ... "); mutant_op = new ISD( file_env, cdecl, comp_unit ); comp_unit.accept(mutant_op); } if (hasOperator(classOp, "IOP")) { Debug.println(" Applying IOP ... ... "); mutant_op = new IOP(file_env, cdecl, comp_unit); comp_unit.accept(mutant_op); } if (hasOperator(classOp, "IPC")) { Debug.println(" Applying IPC ... ... "); mutant_op = new IPC( file_env, cdecl, comp_unit ); comp_unit.accept(mutant_op); } if (hasOperator(classOp, "PNC")) { Debug.println(" Applying PNC ... ... "); mutant_op = new PNC( file_env, cdecl, comp_unit ); comp_unit.accept(mutant_op); } if (hasOperator(classOp, "PMD")) { Debug.println(" Applying PMD ... ... "); //if(existIHD){ mutant_op = new PMD( file_env, cdecl, comp_unit ); comp_unit.accept(mutant_op); //} } if (hasOperator(classOp, "PPD")) { Debug.println(" Applying PPD ... ... "); // if(existIHD){ mutant_op = new PPD( file_env, cdecl, comp_unit ); comp_unit.accept(mutant_op); //} } if (hasOperator(classOp, "PRV")) { Debug.println(" Applying PRV ... ... "); mutant_op = new PRV( file_env, cdecl, comp_unit ); comp_unit.accept(mutant_op); } if (hasOperator(classOp, "PCI")) { Debug.println(" Applying PCI ... ... "); mutant_op = new PCI( file_env, cdecl, comp_unit ); comp_unit.accept(mutant_op); } if (hasOperator(classOp, "PCC")) { Debug.println(" Applying PCC ... ... "); mutant_op = new PCC( file_env, cdecl, comp_unit ); comp_unit.accept(mutant_op); } if (hasOperator(classOp, "PCD")) { Debug.println(" Applying PCD ... ... "); mutant_op = new PCD( file_env, cdecl, comp_unit ); comp_unit.accept(mutant_op); } if (hasOperator(classOp, "JSD")) { Debug.println(" Applying JSC ... ... "); mutant_op = new JSD( file_env, cdecl, comp_unit ); comp_unit.accept(mutant_op); } if (hasOperator(classOp, "JSI")) { Debug.println(" Applying JSI ... ... "); mutant_op = new JSI( file_env, cdecl, comp_unit ); comp_unit.accept(mutant_op); } if (hasOperator(classOp, "JTD")) { Debug.println(" Applying JTD ... ... "); mutant_op = new JTD( file_env, cdecl, comp_unit ); comp_unit.accept(mutant_op); } if (hasOperator(classOp, "JTI")) { Debug.println(" Applying JTI ... ... "); mutant_op = new JTI( file_env, cdecl, comp_unit ); comp_unit.accept(mutant_op); } if (hasOperator(classOp, "JID")) { Debug.println(" Applying JID ... ... "); mutant_op = new JID( file_env, cdecl, comp_unit ); comp_unit.accept(mutant_op); } if (hasOperator(classOp, "OAN")) { Debug.println(" Applying OAN ... ... "); mutant_op = new OAN( file_env, cdecl, comp_unit ); comp_unit.accept(mutant_op); } if (hasOperator(classOp, "EOA")) { Debug.println(" Applying EOA ... ... "); mutant_op = new EOA( file_env, cdecl, comp_unit ); comp_unit.accept(mutant_op); } if (hasOperator(classOp, "EOC")) { Debug.println(" Applying EOC ... ... "); mutant_op = new EOC( file_env, cdecl, comp_unit ); comp_unit.accept(mutant_op); } if (hasOperator(classOp, "EAM")) { Debug.println(" Applying EAM ... ... "); mutant_op = new EAM( file_env, cdecl, comp_unit ); comp_unit.accept(mutant_op); } if (hasOperator(classOp, "EMM")) { Debug.println(" Applying EMM ... ... "); mutant_op = new EMM( file_env, cdecl, comp_unit ); comp_unit.accept(mutant_op); } } catch (ParseTreeException e ) { System.err.println( "Encountered errors during generating mutants." ); e.printStackTrace(); } } } } /** * Compile class mutants into bytecode */ public void compileMutants() { if (classOp != null && classOp.length > 0) { Debug.println("* Compiling class mutants into bytecode"); MutationSystem.MUTANT_PATH = MutationSystem.CLASS_MUTANT_PATH; super.compileMutants(); } } }