001/* Test for ChangeRequest. 002 003 Copyright (c) 1998-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.kernel.util.test.system; 029 030import java.util.Collections; 031import java.util.Enumeration; 032 033import ptolemy.actor.IORelation; 034import ptolemy.actor.Manager; 035import ptolemy.actor.TypedCompositeActor; 036import ptolemy.actor.lib.AddSubtract; 037import ptolemy.actor.lib.Const; 038import ptolemy.actor.lib.Recorder; 039import ptolemy.data.DoubleToken; 040import ptolemy.domains.sdf.kernel.SDFDirector; 041import ptolemy.domains.sdf.lib.SampleDelay; 042import ptolemy.kernel.ComponentRelation; 043import ptolemy.kernel.util.ChangeListener; 044import ptolemy.kernel.util.ChangeRequest; 045import ptolemy.kernel.util.IllegalActionException; 046import ptolemy.kernel.util.KernelException; 047import ptolemy.kernel.util.NameDuplicationException; 048 049/////////////////////////////////////////////////////////////////// 050//// ChangeRequestTest 051 052/** 053 Test for ChangeRequest. 054 055 This test is in the system directory because it uses packages outside 056 of kernel.util. 057 058 @author Edward A. Lee, Contributor: Christopher Hylands 059 @version $Id$ 060 @since Ptolemy II 10.0 061 @Pt.ProposedRating Red (eal) 062 @Pt.AcceptedRating Red (reviewmoderator) 063 @see ptolemy.kernel.util.ChangeRequest 064 065 */ 066public class ChangeRequestTest implements ChangeListener { 067 /** Constructor. 068 */ 069 public ChangeRequestTest() 070 throws IllegalActionException, NameDuplicationException { 071 _top = new TypedCompositeActor(); 072 _top.setName("top"); 073 _manager = new Manager(); 074 075 SDFDirector director = new SDFDirector(); 076 _top.setDirector(director); 077 _top.setManager(_manager); 078 079 _top.addChangeListener(this); 080 _const = new Const(_top, "const"); 081 _rec = new Recorder(_top, "rec"); 082 IORelation relation = (IORelation) _top.connect(_const.output, 083 _rec.input); 084 relation.setWidth(1); 085 } 086 087 /////////////////////////////////////////////////////////////////// 088 //// public methods //// 089 090 /** React to a change request has been successfully executed by 091 * doing nothing. This method is called after a change request 092 * has been executed successfully. In this class, we 093 * do nothing. 094 * @param change The change that has been executed, or null if 095 * the change was not done via a ChangeRequest. 096 */ 097 @Override 098 public void changeExecuted(ChangeRequest change) { 099 } 100 101 /** React to a change request that has resulted in an exception. 102 * This method is called after a change request was executed, 103 * but during the execution in an exception was thrown. 104 * This method throws a runtime exception with a description 105 * of the original exception. 106 * @param change The change that was attempted or null if 107 * the change was not done via a ChangeRequest. 108 * @param exception The exception that resulted. 109 */ 110 @Override 111 public void changeFailed(ChangeRequest change, Exception exception) { 112 // If we do not implement ChangeListener, then ChangeRequest 113 // will print any errors to stdout and continue. 114 // This causes no end of trouble with the test suite 115 // We can't throw and Exception here because this method in 116 // the base class does not throw Exception. 117 // In JDK1.4, we can construct exceptions from exceptions, but 118 // not in JDK1.3.1 119 //throw new RuntimeException(exception); 120 throw new RuntimeException(exception.toString()); 121 } 122 123 /** Finish a run. Return the results. 124 */ 125 public Enumeration finish() throws KernelException { 126 for (int i = 0; i < 4; i++) { 127 _manager.iterate(); 128 } 129 130 _manager.wrapup(); 131 return Collections.enumeration(_rec.getHistory(0)); 132 } 133 134 /** Insert a feedback loop. 135 */ 136 public void insertFeedback() { 137 // Create an anonymous inner class 138 ChangeRequest change = new ChangeRequest(this, "test2") { 139 @Override 140 protected void _execute() throws Exception { 141 _const.output.unlinkAll(); 142 _rec.input.unlinkAll(); 143 144 AddSubtract add = new AddSubtract(_top, "add"); 145 SampleDelay sampleDelay = new SampleDelay(_top, "sampleDelay"); 146 sampleDelay.initialOutputs.setExpression("{4, 5}"); 147 _top.connect(_const.output, add.plus); 148 149 ComponentRelation relation = _top.connect(add.output, 150 sampleDelay.input); 151 _rec.input.link(relation); 152 153 // Any pre-existing input port whose connections 154 // are modified needs to have this method called. 155 _rec.input.createReceivers(); 156 _top.connect(sampleDelay.output, add.plus); 157 } 158 }; 159 160 _top.requestChange(change); 161 } 162 163 /** Mutate. 164 */ 165 public void mutate() { 166 if (changeRequest == null) { 167 changeRequest = mutateConst2ChangeRequest(); 168 } 169 170 _top.requestChange(changeRequest); 171 } 172 173 public void waitForCompletionTask() { 174 Thread waitForCompletionThread = new Thread(new Runnable() { 175 @Override 176 public void run() { 177 System.out.println(Thread.currentThread().getName() 178 + " About to wait for completion"); 179 180 try { 181 changeRequest.waitForCompletion(); 182 } catch (Exception ex) { 183 System.out.println(ex); 184 } 185 186 System.out.println(Thread.currentThread().getName() 187 + " Done waiting for completion"); 188 } 189 }); 190 191 waitForCompletionThread.setName("waitForCompletionThread"); 192 waitForCompletionThread.start(); 193 } 194 195 /** Create a change request that always throws an exception. */ 196 public ChangeRequest mutateBadChangeRequest() { 197 // Create an anonymous inner class 198 changeRequest = new ChangeRequest(this, 199 "Change request that always throws an Exception") { 200 @Override 201 protected void _execute() throws Exception { 202 // Compare against true so that the code compiles. 203 if (true) { 204 throw new Exception("Always Thrown Exception"); 205 } 206 } 207 }; 208 return changeRequest; 209 } 210 211 /** Create a change request that sets const to 2.0. */ 212 public ChangeRequest mutateConst2ChangeRequest() { 213 // Create an anonymous inner class 214 changeRequest = new ChangeRequest(this, "Changing Const to 2.0") { 215 @Override 216 protected void _execute() throws Exception { 217 _const.value.setToken(new DoubleToken(2.0)); 218 } 219 }; 220 return changeRequest; 221 } 222 223 /** Start a run. 224 */ 225 public void start() throws KernelException { 226 _manager.initialize(); 227 _manager.iterate(); 228 } 229 230 /////////////////////////////////////////////////////////////////// 231 //// public variables //// 232 233 /** ChangeRequest that modifies the system. */ 234 public ChangeRequest changeRequest; 235 236 /////////////////////////////////////////////////////////////////// 237 //// private variables //// 238 private Manager _manager; 239 240 private Recorder _rec; 241 242 private Const _const; 243 244 private TypedCompositeActor _top; 245}