/** * Copyright (C) 2010-2017 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 <http://www.gnu.org/licenses/>. */ package org.evosuite.strategy; import org.evosuite.Properties; import org.evosuite.ShutdownTestWriter; import org.evosuite.Properties.Criterion; import org.evosuite.Properties.Strategy; import org.evosuite.Properties.TheReplacementFunction; import org.evosuite.TestGenerationContext; import org.evosuite.coverage.archive.ArchiveTestChromosomeFactory; import org.evosuite.coverage.archive.TestsArchive; import org.evosuite.coverage.branch.BranchPool; import org.evosuite.coverage.mutation.MutationTestPool; import org.evosuite.coverage.mutation.MutationTimeoutStoppingCondition; import org.evosuite.ga.ChromosomeFactory; import org.evosuite.ga.FitnessReplacementFunction; import org.evosuite.ga.MinimizeSizeSecondaryObjective; import org.evosuite.coverage.ibranch.IBranchSecondaryObjective; import org.evosuite.ga.SecondaryObjective; import org.evosuite.ga.metaheuristics.GeneticAlgorithm; import org.evosuite.ga.metaheuristics.RandomSearch; import org.evosuite.ga.metaheuristics.SPEA2; import org.evosuite.ga.metaheuristics.SteadyStateGA; import org.evosuite.ga.metaheuristics.NSGAII; import org.evosuite.ga.metaheuristics.mosa.MOSA; import org.evosuite.ga.metaheuristics.OnePlusOneEA; import org.evosuite.ga.metaheuristics.StandardGA; import org.evosuite.ga.metaheuristics.MonotonicGA; import org.evosuite.regression.RegressionTestChromosomeFactory; import org.evosuite.regression.RegressionTestSuiteChromosomeFactory; import org.evosuite.statistics.StatisticsListener; import org.evosuite.ga.operators.crossover.CrossOverFunction; import org.evosuite.ga.operators.crossover.SinglePointCrossOver; import org.evosuite.ga.operators.crossover.SinglePointFixedCrossOver; import org.evosuite.ga.operators.crossover.SinglePointRelativeCrossOver; import org.evosuite.ga.operators.selection.BinaryTournamentSelectionCrowdedComparison; import org.evosuite.ga.operators.selection.FitnessProportionateSelection; import org.evosuite.ga.operators.selection.RankSelection; import org.evosuite.ga.operators.selection.SelectionFunction; import org.evosuite.ga.operators.selection.TournamentSelection; import org.evosuite.ga.stoppingconditions.GlobalTimeStoppingCondition; import org.evosuite.ga.stoppingconditions.MaxTimeStoppingCondition; import org.evosuite.ga.stoppingconditions.RMIStoppingCondition; import org.evosuite.ga.stoppingconditions.SocketStoppingCondition; import org.evosuite.ga.stoppingconditions.StoppingCondition; import org.evosuite.ga.stoppingconditions.ZeroFitnessStoppingCondition; import org.evosuite.testcase.factories.AllMethodsTestChromosomeFactory; import org.evosuite.testcase.factories.JUnitTestCarvedChromosomeFactory; import org.evosuite.testcase.factories.RandomLengthTestFactory; import org.evosuite.testcase.localsearch.BranchCoverageMap; import org.evosuite.testsuite.secondaryobjectives.MinimizeAverageLengthSecondaryObjective; import org.evosuite.testsuite.secondaryobjectives.MinimizeExceptionsSecondaryObjective; import org.evosuite.testsuite.secondaryobjectives.MinimizeMaxLengthSecondaryObjective; import org.evosuite.testsuite.secondaryobjectives.MinimizeTotalLengthSecondaryObjective; import org.evosuite.testsuite.RelativeSuiteLengthBloatControl; import org.evosuite.testsuite.factories.SerializationSuiteChromosomeFactory; import org.evosuite.testsuite.TestSuiteChromosome; import org.evosuite.testsuite.factories.TestSuiteChromosomeFactory; import org.evosuite.testsuite.TestSuiteReplacementFunction; import org.evosuite.utils.ArrayUtil; import org.evosuite.utils.ResourceController; import sun.misc.Signal; /** * Factory for GA on test suites * * @author gordon * */ @SuppressWarnings("restriction") public class PropertiesSuiteGAFactory extends PropertiesSearchAlgorithmFactory<TestSuiteChromosome> { protected ChromosomeFactory<TestSuiteChromosome> getChromosomeFactory() { switch (Properties.STRATEGY) { case EVOSUITE: switch (Properties.TEST_FACTORY) { case ALLMETHODS: logger.info("Using all methods chromosome factory"); return new TestSuiteChromosomeFactory( new AllMethodsTestChromosomeFactory()); case RANDOM: logger.info("Using random chromosome factory"); return new TestSuiteChromosomeFactory(new RandomLengthTestFactory()); case ARCHIVE: logger.info("Using archive chromosome factory"); return new TestSuiteChromosomeFactory(new ArchiveTestChromosomeFactory()); case JUNIT: logger.info("Using seeding chromosome factory"); JUnitTestCarvedChromosomeFactory factory = new JUnitTestCarvedChromosomeFactory( new RandomLengthTestFactory()); return new TestSuiteChromosomeFactory(factory); case SERIALIZATION: logger.info("Using serialization seeding chromosome factory"); return new SerializationSuiteChromosomeFactory( new RandomLengthTestFactory()); default: throw new RuntimeException("Unsupported test factory: " + Properties.TEST_FACTORY); } case REGRESSION: return new RegressionTestSuiteChromosomeFactory(); case MOSUITE: return new TestSuiteChromosomeFactory(new RandomLengthTestFactory()); default: throw new RuntimeException("Unsupported test factory: " + Properties.TEST_FACTORY); } } protected GeneticAlgorithm<TestSuiteChromosome> getGeneticAlgorithm(ChromosomeFactory<TestSuiteChromosome> factory) { switch (Properties.ALGORITHM) { case ONEPLUSONEEA: logger.info("Chosen search algorithm: (1+1)EA"); { OnePlusOneEA<TestSuiteChromosome> ga = new OnePlusOneEA<TestSuiteChromosome>(factory); if (Properties.TEST_ARCHIVE) ga.setArchive(TestsArchive.instance); return ga; } case MONOTONICGA: logger.info("Chosen search algorithm: SteadyStateGA"); { MonotonicGA<TestSuiteChromosome> ga = new MonotonicGA<TestSuiteChromosome>(factory); if (Properties.TEST_ARCHIVE) ga.setArchive(TestsArchive.instance); if (Properties.REPLACEMENT_FUNCTION == TheReplacementFunction.FITNESSREPLACEMENT) { // user has explicitly asked for this replacement function ga.setReplacementFunction(new FitnessReplacementFunction()); } else { // use default ga.setReplacementFunction(new TestSuiteReplacementFunction()); } return ga; } case STEADYSTATEGA: logger.info("Chosen search algorithm: MuPlusLambdaGA"); { SteadyStateGA<TestSuiteChromosome> ga = new SteadyStateGA<>(factory); if (Properties.TEST_ARCHIVE) ga.setArchive(TestsArchive.instance); if (Properties.REPLACEMENT_FUNCTION == TheReplacementFunction.FITNESSREPLACEMENT) { // user has explicitly asked for this replacement function ga.setReplacementFunction(new FitnessReplacementFunction()); } else { // use default ga.setReplacementFunction(new TestSuiteReplacementFunction()); } return ga; } case RANDOM: logger.info("Chosen search algorithm: Random"); { RandomSearch<TestSuiteChromosome> ga = new RandomSearch<TestSuiteChromosome>(factory); if (Properties.TEST_ARCHIVE) ga.setArchive(TestsArchive.instance); return ga; } case NSGAII: logger.info("Chosen search algorithm: NSGAII"); return new NSGAII<TestSuiteChromosome>(factory); case SPEA2: logger.info("Chosen search algorithm: SPEA2"); return new SPEA2<TestSuiteChromosome>(factory); case MOSA: logger.info("Chosen search algorithm: MOSA"); return new MOSA<TestSuiteChromosome>(factory); default: logger.info("Chosen search algorithm: StandardGA"); { StandardGA<TestSuiteChromosome> ga = new StandardGA<TestSuiteChromosome>(factory); if (Properties.TEST_ARCHIVE) ga.setArchive(TestsArchive.instance); return ga; } } } protected SelectionFunction<TestSuiteChromosome> getSelectionFunction() { switch (Properties.SELECTION_FUNCTION) { case ROULETTEWHEEL: return new FitnessProportionateSelection<>(); case TOURNAMENT: return new TournamentSelection<>(); case BINARY_TOURNAMENT: return new BinaryTournamentSelectionCrowdedComparison<>(); default: return new RankSelection<>(); } } protected CrossOverFunction getCrossoverFunction() { switch (Properties.CROSSOVER_FUNCTION) { case SINGLEPOINTFIXED: return new SinglePointFixedCrossOver(); case SINGLEPOINTRELATIVE: return new SinglePointRelativeCrossOver(); case SINGLEPOINT: return new SinglePointCrossOver(); case COVERAGE: if (Properties.STRATEGY != Properties.Strategy.EVOSUITE) throw new RuntimeException( "Coverage crossover function requires test suite mode"); return new org.evosuite.ga.operators.crossover.CoverageCrossOver(); default: throw new RuntimeException("Unknown crossover function: " + Properties.CROSSOVER_FUNCTION); } } /** * <p> * getSecondarySuiteObjective * </p> * * @param name * a {@link java.lang.String} object. * @return a {@link org.evosuite.search.ga.SecondaryObjective} object. */ protected SecondaryObjective<TestSuiteChromosome> getSecondarySuiteObjective(String name) { if (name.equalsIgnoreCase("size")) return new MinimizeSizeSecondaryObjective<>(); else if (name.equalsIgnoreCase("ibranch")) return new IBranchSecondaryObjective(); else if (name.equalsIgnoreCase("archiveibranch")) return new IBranchSecondaryObjective(); else if (name.equalsIgnoreCase("maxlength")) return new MinimizeMaxLengthSecondaryObjective(); else if (name.equalsIgnoreCase("averagelength")) return new MinimizeAverageLengthSecondaryObjective(); else if (name.equalsIgnoreCase("exceptions")) return new MinimizeExceptionsSecondaryObjective(); else if (name.equalsIgnoreCase("totallength")) return new MinimizeTotalLengthSecondaryObjective(); else throw new RuntimeException("ERROR: asked for unknown secondary objective \"" + name + "\""); } protected void getSecondaryObjectives(GeneticAlgorithm<TestSuiteChromosome> algorithm) { String objectives = Properties.SECONDARY_OBJECTIVE; // check if there are no secondary objectives to optimize if (objectives == null || objectives.trim().length() == 0 || objectives.trim().equalsIgnoreCase("none")) return; for (String name : objectives.split(":")) { TestSuiteChromosome.addSecondaryObjective(getSecondarySuiteObjective(name.trim())); } } @Override public GeneticAlgorithm<TestSuiteChromosome> getSearchAlgorithm() { ChromosomeFactory<TestSuiteChromosome> factory = getChromosomeFactory(); // FIXXME GeneticAlgorithm<TestSuiteChromosome> ga = getGeneticAlgorithm(factory); if (Properties.NEW_STATISTICS) ga.addListener(new StatisticsListener()); // How to select candidates for reproduction SelectionFunction<TestSuiteChromosome> selectionFunction = getSelectionFunction(); selectionFunction.setMaximize(false); ga.setSelectionFunction(selectionFunction); // When to stop the search StoppingCondition stopping_condition = getStoppingCondition(); ga.setStoppingCondition(stopping_condition); // ga.addListener(stopping_condition); if (Properties.STOP_ZERO) { ga.addStoppingCondition(new ZeroFitnessStoppingCondition()); } if (!(stopping_condition instanceof MaxTimeStoppingCondition)) { ga.addStoppingCondition(new GlobalTimeStoppingCondition()); } if (ArrayUtil.contains(Properties.CRITERION, Criterion.MUTATION) || ArrayUtil.contains(Properties.CRITERION, Criterion.STRONGMUTATION)) { if (Properties.STRATEGY == Strategy.ONEBRANCH) ga.addStoppingCondition(new MutationTimeoutStoppingCondition()); else ga.addListener(new MutationTestPool()); // } else if (Properties.CRITERION == Criterion.DEFUSE) { // if (Properties.STRATEGY == Strategy.EVOSUITE) // ga.addListener(new DefUseTestPool()); } ga.resetStoppingConditions(); ga.setPopulationLimit(getPopulationLimit()); // How to cross over CrossOverFunction crossover_function = getCrossoverFunction(); ga.setCrossOverFunction(crossover_function); // What to do about bloat // MaxLengthBloatControl bloat_control = new MaxLengthBloatControl(); // ga.setBloatControl(bloat_control); if (Properties.CHECK_BEST_LENGTH) { RelativeSuiteLengthBloatControl bloat_control = new org.evosuite.testsuite.RelativeSuiteLengthBloatControl(); ga.addBloatControl(bloat_control); ga.addListener(bloat_control); } // ga.addBloatControl(new MaxLengthBloatControl()); getSecondaryObjectives(ga); // Some statistics //if (Properties.STRATEGY == Strategy.EVOSUITE) // ga.addListener(SearchStatistics.getInstance()); // ga.addListener(new MemoryMonitor()); // ga.addListener(MutationStatistics.getInstance()); // ga.addListener(BestChromosomeTracker.getInstance()); if (Properties.DYNAMIC_LIMIT) { // max_s = GAProperties.generations * getBranches().size(); // TODO: might want to make this dependent on the selected coverage // criterion // TODO also, question: is branchMap.size() really intended here? // I think BranchPool.getBranchCount() was intended Properties.SEARCH_BUDGET = Properties.SEARCH_BUDGET * (BranchPool.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()).getNumBranchlessMethods(Properties.TARGET_CLASS) + BranchPool.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()).getBranchCountForClass(Properties.TARGET_CLASS) * 2); stopping_condition.setLimit(Properties.SEARCH_BUDGET); logger.info("Setting dynamic length limit to " + Properties.SEARCH_BUDGET); } if (Properties.LOCAL_SEARCH_RESTORE_COVERAGE) { org.evosuite.ga.metaheuristics.SearchListener map = BranchCoverageMap.getInstance(); ga.addListener(map); } if (Properties.SHUTDOWN_HOOK) { // ShutdownTestWriter writer = new // ShutdownTestWriter(Thread.currentThread()); ShutdownTestWriter writer = new ShutdownTestWriter(); ga.addStoppingCondition(writer); RMIStoppingCondition rmi = RMIStoppingCondition.getInstance(); ga.addStoppingCondition(rmi); if (Properties.STOPPING_PORT != -1) { SocketStoppingCondition ss = new SocketStoppingCondition(); ss.accept(); ga.addStoppingCondition(ss); } // Runtime.getRuntime().addShutdownHook(writer); Signal.handle(new Signal("INT"), writer); } ga.addListener(new ResourceController()); return ga; } }