/* * Copyright 2007 Wishnu Prasetya. * * This file is part of T2. * T2 is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License (GPL) as published by the * Free Software Foundation; either version 3 of the License, or any * later version. * * T2 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 General Public License * for more details. * * A copy of the GNU General Public License can be found in T2 distribution. * If it is missing, see http://www.gnu.org/licenses. */ package Sequenic.T2.Engines; import java.lang.reflect.Method; import Sequenic.T2.Seq.* ; /** * An abstract class representing a plugable sequence generator for * {@link BaseEngine}. Such a generator offers two primitive methods, one to * generate the initial meta-step (for creating the target object that * starts a test sequence), and one to generate a test step. It has a * link to the {@link BaseEngine} it is attached to, so it can access the * engine's setup and runtime state. * *

The engine basically just repeatedly calls those two primitives to * construct the sequences. The engine controls e.g. how many sequences * to generate, and their lengths. The generator controls the exact steps * to generate, thus ultimately the traces. A default implementation is * provided as an * {@link BaseEngine.RandomSequenceGenerator internal class} of * {@link BaseEngine}. This default implementation generates the steps randomly. * *

The class below already includes code-template for implementing the * "search-mode" feature. * */ abstract public class BaseEngineSeqGenerator { /** * A reference to the engine using this sequence generator, so that it * is possible for the generator to read the engine's properties and * state. */ public BaseEngine engine ; /** * A method to initialize the generator. */ public void init() { } /** * To generate the (meta) step that would create a target object. This * step is used to begin a test sequence. It returns a null if it can't * come up with a step. */ abstract public MkValStep META_mkTargetObject(Class C) ; /** * To generate a (meta) test step. Return null if it can't come up with a * step. */ abstract public TraceStep META_mkTestStep(Sequenic.T2.Seq.Trace sigma) ; /** * This notifies the generator that the given sigma fails due to violation * to a pre-condition or other assumptions. This generator may then decide to * redo the sequence, but with some slight variation. The code below, simply * "saves" the sigma, and leaves it to the implementation of this engine to * decide what to do with it. */ public void notify_asmfailing_trace(Sequenic.T2.Seq.Trace sigma) { // Search mode is off: if (engine.searchMode<=0) return ; if (number_of_trace_retries >= engine.searchMode) { sigma_to_redo = null ; return ; } // This does not back track; turned off // //sigma_to_redo = sigma ; //sigma.trace.removeLast() ; //number_of_trace_retries++ ; // Ok, so we haven't tried enough; try to redo/regenerate the current step: sigma_to_redo = sigma ; sigma_to_redo.trace.removeLast() ; int MaxNumberOfRetries_perStep = engine.searchMode / Math.max(1,engine.maxExecLength - 1) ; if (number_of_step_retries >= MaxNumberOfRetries_perStep) { // We have retried this step enough; so, backtrack one step further: number_of_step_retries = 0 ; if (sigma_to_redo.trace.isEmpty()) sigma_to_redo = null ; // can't backtrack further // Else do the back-track : else sigma_to_redo.trace.removeLast() ; } number_of_trace_retries++ ; number_of_step_retries++ ; } /** * This notify that a full trace has been generated that does not violate * any assumption. */ public void notify_non_asmfailing_trace() { sigma_to_redo = null ; number_of_trace_retries=0 ; number_of_step_retries=0 ; } /** * This is part of the "search-mode" feature. When set to non-null, * it is used to signal to this engine that it needs to redo the * given sigma. This typically entails generating new last step * to that sigma. */ protected Sequenic.T2.Seq.Trace sigma_to_redo = null ; /** * This is to keep track of the number of times a sigma has been retried. * Also part of the "search-mode" feature. */ protected int number_of_trace_retries = 0 ; /** * This is to keep track of the number of times the current trace step has been retried. * Also part of the "search-mode" feature. */ protected int number_of_step_retries = 0 ; /** * Return true if the generator is exhausted (it can't generate no further * step). */ abstract public boolean isExhausted() ; /** * Used to keep track of the method we're working on so the META_mkObject * can use that info to get possible annotations from the method. */ private Method currentMethod; public Method getCurrentMethod() { return currentMethod; } protected void setCurrentMethod(Method m) { currentMethod = m; } }