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}