/** * 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.continuous.job.schedule; import java.util.LinkedList; import java.util.List; import org.evosuite.continuous.job.JobDefinition; import org.evosuite.continuous.job.JobScheduler; import org.evosuite.continuous.project.ProjectStaticData; import org.evosuite.continuous.project.ProjectStaticData.ClassInfo; /** * Root class for the different kinds of schedule. * * <p> * TODO: memory based on number of branches, as we can/should use larger population size, longer * test cases, larger test suites, etc. These latter are an initial proof-of-concept of a more * general optimized tuning. * * <p> * TODO: handle schedule that is specific for the SVN/Git changes (ie only recently modified classes used for search). * Would be interesting to analyze how often there are commits (how many classes are modified) in open source / industrial projects. * If in last commit there were added/modified a set X of classes, not only we might * want to focus on those, but also on the others that take them as input. * Furthermore, we can look at the history: if CTG has been run for weeks/months, * and then new classes are added, those should have much higher priority than old, * heavily tested classes * * <p> * TODO: we should also consider what version of EvoSuite has been used. * If a new version of EvoSuite is introduced during CTG, it would make sense * to re-generate test cases for all CUTs, as new version might achieve higher * coverage * * @author arcuri * */ public abstract class ScheduleType { protected final JobScheduler scheduler; protected ScheduleType(JobScheduler scheduler){ this.scheduler = scheduler; } protected boolean enoughBudgetForAll(){ int totalBudget = 60 * scheduler.getConfiguration().timeInMinutes * scheduler.getConfiguration().getNumberOfUsableCores(); int maximumNumberOfJobs = totalBudget / (60 * scheduler.getConfiguration().minMinutesPerJob) ; return maximumNumberOfJobs >= scheduler.getProjectData().getTotalNumberOfTestableCUTs(); } /** * Create a new partial/complete schedule if there is still search budget left * * @return * @throws IllegalStateException */ public abstract List<JobDefinition> createNewSchedule() throws IllegalStateException; /** * <p> * When we get a schedule, the scheduler might decide to do not use the entire * budget. Reason? It might decide to generate some test cases first, and then * use those as seeding for a new round of execution. * </p> * * <p> * Once the budget is finished, this schedule cannot be reused. A new * instance needs to be created. * </p> * * @return */ public abstract boolean canExecuteMore(); /** * if there is not enough search budget, then try * to target as many CUTs as possible * @return */ protected List<JobDefinition> createScheduleForWhenNotEnoughBudget(){ ProjectStaticData data = scheduler.getProjectData(); int totalBudget = 60 * scheduler.getConfiguration().timeInMinutes * scheduler.getConfiguration().getNumberOfUsableCores(); List<JobDefinition> jobs = new LinkedList<JobDefinition>(); /* * TODO: when starting schedule, check how many classes we do already have test cases from previous runs. * If from previous run we have some classes, then prioritize the others */ //not enough budget for(ClassInfo info : data.getClassInfos()){ if(!info.isTestable()){ continue; } JobDefinition job = new JobDefinition( 60 * scheduler.getConfiguration().minMinutesPerJob, scheduler.getConfiguration().getConstantMemoryPerJob(), info.getClassName(), 0, null, null); jobs.add(job); totalBudget -= (60 * scheduler.getConfiguration().minMinutesPerJob); if(totalBudget <= 0){ break; } } return jobs; } }