/** * 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.statistics; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import org.evosuite.Properties; import org.evosuite.coverage.exception.ExceptionCoverageSuiteFitness; import org.evosuite.ga.Chromosome; import org.evosuite.ga.metaheuristics.GeneticAlgorithm; import org.evosuite.ga.metaheuristics.SearchListener; import org.evosuite.ga.stoppingconditions.MaxStatementsStoppingCondition; import org.evosuite.ga.stoppingconditions.MaxTestsStoppingCondition; import org.evosuite.rmi.ClientServices; import org.evosuite.runtime.sandbox.Sandbox; import org.evosuite.testsuite.TestSuiteChromosome; /** * Client-side listener that transmits data to master * * @author gordon * */ public class StatisticsListener implements SearchListener { private volatile BlockingQueue<Chromosome> individuals = new LinkedBlockingQueue<Chromosome>(); private volatile boolean done = false; private volatile double bestFitness = Double.MAX_VALUE; private volatile boolean minimizing = true; private int numFitnessEvaluations = 0; private volatile Thread notifier; /** * When did we send an individual due to a new generation iteration? */ private volatile long timeFromLastGenerationUpdate = 0; public StatisticsListener() { notifier = new Thread() { @Override public void run() { // Wait for new element in queue // If there is a new element, then send it to master through RMI while(!done || !individuals.isEmpty()) { Chromosome individual; try { individual = individuals.take(); StatisticsSender.sendIndividualToMaster(individual); } catch (InterruptedException e) { done = true; } } } }; Sandbox.addPrivilegedThread(notifier); notifier.start(); } @Override public void iteration(GeneticAlgorithm<?> algorithm) { long elapsed = System.currentTimeMillis() - timeFromLastGenerationUpdate; if(elapsed > Properties.TIMELINE_INTERVAL){ /* * We do not send an individual to Master at each new generation, because * for fast CUTs we could have far too many generations. * As this info is only used for time interval values, there * is no point in sending too many */ timeFromLastGenerationUpdate = System.currentTimeMillis(); // Enqueue current best individual individuals.offer(algorithm.getBestIndividual()); // send timeline variable directly ClientServices.getInstance().getClientNode().trackOutputVariable(RuntimeVariable.TotalExceptionsTimeline, ExceptionCoverageSuiteFitness.getMaxExceptionsCovered()); } } @Override public void searchFinished(GeneticAlgorithm<?> algorithm) { // If the search is finished, we may want to clear the queue and just send the final element? //individuals.clear(); // TODO: Maybe have a check on size individuals.offer(algorithm.getBestIndividual()); ClientServices.getInstance().getClientNode().trackOutputVariable(RuntimeVariable.Statements_Executed, MaxStatementsStoppingCondition.getNumExecutedStatements()); ClientServices.getInstance().getClientNode().trackOutputVariable(RuntimeVariable.Tests_Executed, MaxTestsStoppingCondition.getNumExecutedTests()); ClientServices.getInstance().getClientNode().trackOutputVariable(RuntimeVariable.Generations, algorithm.getAge()); ClientServices.getInstance().getClientNode().trackOutputVariable(RuntimeVariable.Fitness_Evaluations, numFitnessEvaluations); ClientServices.getInstance().getClientNode().trackOutputVariable(RuntimeVariable.TotalExceptionsTimeline, ExceptionCoverageSuiteFitness.getMaxExceptionsCovered()); if(algorithm.getBestIndividual() instanceof TestSuiteChromosome) { reportTestSuiteResult((TestSuiteChromosome) algorithm.getBestIndividual()); } done = true; try { notifier.join(3000); } catch (InterruptedException e) { notifier.interrupt(); Thread.currentThread().interrupt();//interrupted flag was reset } } private void reportTestSuiteResult(TestSuiteChromosome testSuite) { } @Override public void searchStarted(GeneticAlgorithm<?> algorithm) { done = false; if(algorithm.getFitnessFunction().isMaximizationFunction()) { bestFitness = 0.0; minimizing = false; } else { bestFitness = Double.MAX_VALUE; minimizing = true; } } @Override public void fitnessEvaluation(Chromosome individual) { numFitnessEvaluations++; double fitness = individual.getFitness(); if(minimizing) { if(fitness < bestFitness) { bestFitness = fitness; individuals.offer(individual); } } else { if(fitness > bestFitness) { bestFitness = fitness; individuals.offer(individual); } } } @Override public void modification(Chromosome individual) { // Nothing to do } }