/* * (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.HashSet; import java.util.Iterator; import java.util.Set; import rationals.Automaton; import rationals.properties.AreEquivalent; import rationals.properties.TraceEquivalence; import rationals.transductions.DeterministicTransducer; import rationals.transductions.Transduction; /** * A class for testing transducers. * This class is used to check conformance of finite state machines * whose structure is unknown against a specification. It uses two * {@see rationals.transductions.Transduction} objects and, given * a set of input words, check that output from both objects * matches. * * @author nono * @version $Id: TransducerTester.java 2 2006-08-24 14:41:48Z oqube $ */ public class TransducerTester { /** * Base method for testing. * This method returns properly if the <code>suite</code> is passed, that is * the output of <code>implem</code> for each word in suite is the same * as the output of <code>specif</code>. Same mean that they are the same * languages. This method is expensive as it needs to determinize each resulting * automaton from {@see rationals.transduction.Transduction.image(List)} * to check equivalence. <p> * When implementation is known to be a {@see rationals.transductions.RationalFunction}, * use method {@see testDeterministic}. * * * @param specif a specification transduction * @param implem implementation under test * @param suite a Set of List of input letters. * @throws TestFailure if some test is not passed. The object * thrown contains the faulty test case. */ public void test(Transduction specif, Transduction implem, Set suite) throws TestFailure { Set failures = new HashSet(); AreEquivalent equiv = new AreEquivalent(new TraceEquivalence()); for (Iterator it = suite.iterator(); it.hasNext();) { Object[] l = (Object[]) it.next(); Automaton expect = specif.image(l); Automaton real = implem.image(l); if (!equiv.test(expect, real)) failures.add(l); } if (!failures.isEmpty()) throw new TestFailure(failures); } /** * Method for testing deterministic implementations and specifications. * This method works like {@see test(rationals.transductions.Transduction,rationals.transductions.Transduction,java.util.Set)}. * * @param specif a specification function * @param implem implementation under test * @param suite a Set of arrays of input letters. * @throws TestFailure if some test is not passed. The object * thrown contains the faulty test case. */ public void testDeterministic(DeterministicTransducer specif, DeterministicTransducer implem, Set suite) throws TestFailure { Set failures = new HashSet(); for (Iterator it = suite.iterator(); it.hasNext();) { Object[] l = (Object[]) it.next(); Object[] expect = specif.imageWord(l); Object[] real = implem.imageWord(l); // System.err.println("expect ="+ expect+", real = "+real); /* basic tests */ if (expect == null && real == null) continue; if ((expect == null && real != null) || (expect != null && real == null) || (expect.length != real.length)) { failures.add(l); continue; } /* real test */ for (int i = 0; i < expect.length; i++) if (expect[i] == null ? real[i] != null : !expect[i] .equals(real[i])) failures.add(l); } if (!failures.isEmpty()) throw new TestFailure(failures); } }