001/* Handle exceptions thrown in tests.
002
003 Copyright (c) 2006-2014 The Regents of the University of California.
004 All rights reserved.
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the above
008 copyright notice and the following two paragraphs appear in all copies
009 of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION_2
025 COPYRIGHTENDKEY
026
027 */
028package ptolemy.actor.lib;
029
030import ptolemy.actor.TypedAtomicActor;
031import ptolemy.actor.parameters.SharedParameter;
032import ptolemy.data.BooleanToken;
033import ptolemy.data.expr.StringParameter;
034import ptolemy.data.type.BaseType;
035import ptolemy.kernel.CompositeEntity;
036import ptolemy.kernel.util.ExceptionHandler;
037import ptolemy.kernel.util.IllegalActionException;
038import ptolemy.kernel.util.NameDuplicationException;
039import ptolemy.kernel.util.NamedObj;
040import ptolemy.util.MessageHandler;
041
042///////////////////////////////////////////////////////////////////
043//// TestExceptionHandler
044
045/**
046 This actor tests for exceptions that are expected to occur when
047 running a test model. When an exception is
048 thrown by the model, this actor is invoked. It has two
049 working modes, training mode and non-training mode. If in training mode,
050 this actor handles an exception by recording the exception message. If
051 not in training mode, this actor first compares the previously stored
052 (assumed correct) message to the exception message and then throws an
053 exception if the two messages are not the same.
054 Also, if a test runs to completion without throwing an exception, this actor
055 throws an exception in its wrapup() method. An exception is expected.
056
057 @author Haiyang Zheng
058 @deprecated Use {@link TestExceptionAttribute} instead.
059 @version $Id$
060 @since Ptolemy II 5.2
061 @Pt.ProposedRating Yellow (hyzheng)
062 @Pt.AcceptedRating Yellow (hyzheng)
063 */
064@Deprecated
065public class TestExceptionHandler extends TypedAtomicActor
066        implements ExceptionHandler {
067
068    /** Create a new actor in the specified container with the specified
069     *  name.  The name must be unique within the container or an exception
070     *  is thrown. The container argument must not be null, or a
071     *  NullPointerException will be thrown.
072     *
073     *  @param container The container.
074     *  @param name The name of this actor within the container.
075     *  @exception IllegalActionException If this actor cannot be contained
076     *   by the proposed container (see the setContainer() method).
077     *  @exception NameDuplicationException If the name coincides with
078     *   an entity already in the container.
079     */
080    public TestExceptionHandler(CompositeEntity container, String name)
081            throws NameDuplicationException, IllegalActionException {
082        super(container, name);
083        correctExceptionMessage = new StringParameter(this,
084                "correctExceptionMessage");
085        correctExceptionMessage.setExpression("");
086        trainingMode = new SharedParameter(this, "trainingMode", getClass(),
087                "false");
088        trainingMode.setTypeEquals(BaseType.BOOLEAN);
089        _invoked = false;
090    }
091
092    ///////////////////////////////////////////////////////////////////
093    ////                          parameters                       ////
094
095    /** If true, then collect the exception message and set the
096     *  correctExceptionMessage parameter with the content of the
097     *  exception. This parameter is a boolean, and it defaults to false.
098     *  It is a shared parameter, meaning
099     *  that changing it for any one instance in a model will change
100     *  it for all instances in the model.
101     */
102    public SharedParameter trainingMode;
103
104    /** The correct exception message to be compared against. */
105    public StringParameter correctExceptionMessage;
106
107    ///////////////////////////////////////////////////////////////////
108    ////                         public methods                    ////
109
110    /** Initialize. */
111    @Override
112    public void initialize() throws IllegalActionException {
113        super.initialize();
114        _invoked = false;
115    }
116
117    /** Handle an exception thrown in a test. If in training
118     *  mode, simply record the exception message. If not in training mode,
119     *  first compare the stored good message against the exception message.
120     *  If they are the same, do nothing. Otherwise, throw the exception again.
121     *  @param context The object in which the error occurred.
122     *  @param exception The exception to be handled.
123     *  @return True if the exception message is the same as the saved message.
124     *  @exception IllegalActionException If cannot get a valid token from
125     *  the trainingMode parameter or the exception message is not the same as
126     *  the stored message.
127     */
128    @Override
129    public boolean handleException(NamedObj context, Throwable exception)
130            throws IllegalActionException {
131        _invoked = true;
132        boolean training = ((BooleanToken) trainingMode.getToken())
133                .booleanValue();
134        if (training) {
135            correctExceptionMessage.setExpression(exception.getMessage());
136            correctExceptionMessage.setPersistent(true);
137        } else {
138            if (!exception.getMessage()
139                    .equals(correctExceptionMessage.stringValue())) {
140                throw new IllegalActionException(this, exception,
141                        "Expected:\n" + correctExceptionMessage.stringValue()
142                                + "\nBut got:\n" + exception.getMessage());
143            }
144        }
145        return true;
146    }
147
148    /** Call the super.wrapup() method. Check whether this actor has
149     *  been invoked to handle exceptions. If not, throw an exception.
150     *  Otherwise, do nothing.
151     *  @exception IllegalActionException If this actor has not been
152     *   invoked to handle exceptions.
153     */
154    @Override
155    public void wrapup() throws IllegalActionException {
156        super.wrapup();
157        if (((BooleanToken) trainingMode.getToken()).booleanValue()) {
158            if (MessageHandler.isNonInteractive()) {
159                throw new IllegalActionException(this,
160                        TRAINING_MODE_ERROR_MESSAGE);
161            } else {
162                System.err.println("Warning: '" + getFullName()
163                        + "' is in training mode, set the trainingMode "
164                        + "parameter to false before checking in");
165            }
166        }
167        if (!_invoked) {
168            throw new IllegalActionException(this, " should "
169                    + "have handled an exception but did not see any.");
170        } else {
171            _invoked = false;
172        }
173    }
174
175    ///////////////////////////////////////////////////////////////////
176    ////                         public variables                  ////
177
178    /** Exception message that is used if we are running under
179     *  the nightly build and the trainingMode parameter is true.
180     */
181    public static final String TRAINING_MODE_ERROR_MESSAGE = "Training Mode set for test actor and isRunningNightlyBuild()\n"
182            + "  returned true, indicating that the\n"
183            + "  ptolemy.ptII.isRunningNightlyBuild property is set.\n"
184            + "  The trainingMode parameter should not be set in files\n"
185            + "  that are checked into the nightly build!"
186            + "  To run the tests in nightly build mode, use"
187            + "     make nightly";
188
189    ///////////////////////////////////////////////////////////////////
190    ////                         private variables                 ////
191
192    private boolean _invoked = false;
193}