/* * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com), * Yves Roos (yroos@lifl.fr) and others. * * 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 rationals.transductions.testing; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.LinkedList; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import rationals.State; import rationals.Automaton; import rationals.Transition; import rationals.transductions.DeterministicTransducer; import rationals.transductions.TransducerRelation; import rationals.transductions.Transducer; import rationals.transductions.TransductionException; /** * Testing FSM with UIO sequences, basic method. Test suite is generated for * each transition <code>(qi,i/o,qj)</code> by concatenating : * <ul> * <li>A reset input</li> * <li>A shortest sequence from <code>q0</code> to <code>qi</code></li> * <li>The input <code>i</code></li> * <li>The UIO for <code>qj</code></li> * </ul> * * This method is proposed in * <p> * <em>"A new technique for generating protocol tests"</em>, Sabnani and * Dahbura, 1985 * </p> * * @author nono * @version $Id: UTestGenerator.java 2 2006-08-24 14:41:48Z oqube $ */ public class UTestGenerator implements TransducerTestGenerator { /** * */ public UTestGenerator() { super(); } /* * (non-Javadoc) * * @see rationals.transductions.testing.TransducerTester#testSequence(rationals.transductions.Transducer) */ public Set testSuite(DeterministicTransducer t) throws TransductionException { Set ret = new HashSet(); /* construct UIO set */ Map m = t.makeUIOSet(); /* transform into input sequences */ Map im = new HashMap(); for(Iterator i= m.entrySet().iterator();i.hasNext();) { Map.Entry me = (Map.Entry)i.next(); List l = (List)me.getValue(); List il = new ArrayList(l.size()); for(Iterator i2=l.iterator();i2.hasNext();) { il.add(((TransducerRelation)i2.next()).getIn()); } im.put(me.getKey(),il); } /* construct shortest path for each state - use Dijkstra algorithm */ Map sp = new HashMap(); makeShortestPathMap(t, sp); /* compute test set */ for(Iterator i=t.delta().iterator();i.hasNext();) { Transition tr = (Transition)i.next(); TransducerRelation rel = (TransducerRelation)tr.label(); State from = tr.start(); State to = tr.end(); Object lbl = rel.getIn(); List l = from.isInitial() ? new ArrayList() : (List)sp.get(from); l.add(lbl); l.addAll((List)im.get(to)); ret.add(l.toArray()); } return ret; } /** * @param t * @param sp * @throws TransductionException */ private void makeShortestPathMap(Transducer t, Map sp) throws TransductionException { Set s = t.initials(); if (s.size() != 1) throw new TransductionException( "Transducer appears not deterministic or has no starting states"); State init = (State) s.iterator().next(); // create list of all states in bf order List vis = breadthFirstOrder(init,t); sp.put(init, new ArrayList()); for (Iterator it = vis.iterator(); it.hasNext();) { State st = (State) it.next(); if (st == init) continue; List word = null; /* find an already visited state that is a parent of this states */ sti: for (Iterator iter = sp.keySet().iterator(); iter.hasNext();) { State par = (State) iter.next(); Set trans = t.delta(par); for (Iterator iterator = trans.iterator(); iterator.hasNext();) { Transition tr = (Transition) iterator.next(); TransducerRelation rel = (TransducerRelation)tr.label(); if (tr.end() == st) { word = new ArrayList((List) sp.get(par)); word .add(rel.getIn()); break sti; } } } sp.put(st,word); } } private List /* < State > */ breadthFirstOrder(State start, Automaton a) { LinkedList todo = new LinkedList(); Set done = new LinkedHashSet(a.states().size()); todo.add(start); while(!todo.isEmpty()) { State st = (State)todo.removeFirst(); if(done.contains(st)) continue; done.add(st); /* add successors */ for(Iterator i=a.delta(st).iterator();i.hasNext();) { Transition tr = (Transition)i.next(); if(tr.end() != st) todo.add(tr.end()); } } return new ArrayList(done); } }