1 /* 2 * Copyright the original author or authors. 3 * 4 * Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.mozilla.org/MPL/MPL-1.1.html 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 import org.as2lib.env.except.IllegalArgumentException; 18 import org.as2lib.env.reflect.MethodInfo; 19 import org.as2lib.env.reflect.ConstructorInfo; 20 import org.as2lib.env.reflect.ClassInfo; 21 import org.as2lib.test.speed.TestResult; 22 import org.as2lib.test.speed.AbstractTestResult; 23 24 /** 25 * {@code MethodInvocation} reflects a profiled method invocation. 26 * 27 * @author Simon Wacker 28 */ 29 class org.as2lib.test.speed.MethodInvocation extends AbstractTestResult implements TestResult { 30 31 /** Designates an unknown type in the type signature. */ 32 public static var UNKNOWN:String = "[unknown]"; 33 34 /** Designates type {@code Void} in the type signature. */ 35 public static var VOID:String = "Void"; 36 37 /** Invoked method. */ 38 private var method:MethodInfo; 39 40 /** Caller of this method invocation. */ 41 private var caller:MethodInvocation; 42 43 /** Time needed for this method invocation. */ 44 private var time:Number; 45 46 /** Arguments used for this method invocation. */ 47 private var args:Array; 48 49 /** Return value of this method invocation. */ 50 private var returnValue; 51 52 /** Exception thrown during this method invocation. */ 53 private var exception; 54 55 /** The previous method invocation. */ 56 private var previousMethodInvocation:MethodInvocation; 57 58 /** 59 * Constructs a new {@code MethodInvocation} instance. 60 * 61 * @param method the invoked method 62 * @throws IllegalArgumentException if {@code method} is {@code null} or 63 * {@code undefined} 64 */ 65 public function MethodInvocation(method:MethodInfo) { 66 if (!method) { 67 throw new IllegalArgumentException("Argument 'method' [" + method + "] must not be 'null' nor 'undefined'.", this, arguments); 68 } 69 this.method = method; 70 } 71 72 /** 73 * Returns the invoked method. 74 * 75 * @return the invoked method 76 */ 77 public function getMethod(Void):MethodInfo { 78 return this.method; 79 } 80 81 /** 82 * Returns the name of this method invocation. This is the method's name plus the 83 * signature of this method invocation. 84 * 85 * @return the name of this method invocation 86 * @see #getMethodName 87 * @see #getMethodSignature 88 */ 89 public function getName(Void):String { 90 return (getMethodName() + getSignature()); 91 } 92 93 /** 94 * Returns the full name of the invoked method. 95 * 96 * @return the full name of the invoked method 97 */ 98 public function getMethodName(Void):String { 99 return this.method.getFullName(); 100 } 101 102 /** 103 * Returns the signature of this method invocation. 104 * 105 * <p>If any information needed to generate the signature is not defined, 106 * {@link #UNKNOWN} is used as placeholder. 107 * 108 * @return this method invocation's signature 109 */ 110 public function getSignature(Void):String { 111 var result:String = "("; 112 if (this.args.length > 0) { 113 for (var i:Number = 0; i < this.args.length; i++) { 114 if (i != 0) { 115 result += ", "; 116 } 117 result += getFullTypeName(args[i]); 118 } 119 } else { 120 result += "Void"; 121 } 122 if (this.method instanceof ConstructorInfo) { 123 result += ")"; 124 } else { 125 result += "):"; 126 if (this.returnValue === undefined) { 127 result += VOID; 128 } else { 129 result += getFullTypeName(this.returnValue); 130 } 131 } 132 if (!wasSuccessful()) { 133 result += " throws "; 134 result += getFullTypeName(this.exception); 135 } 136 return result; 137 } 138 139 /** 140 * Returns the fully qualified type name for the passed-in {@code instance}. 141 * 142 * @param instance the instance to return the type name for 143 * @return the fully qualified type name for the passed-in {@code instance}. 144 */ 145 private function getFullTypeName(instance):String { 146 if (instance == null) return UNKNOWN; 147 var typeName:String = ClassInfo.forInstance(instance).getFullName(); 148 if (typeName == null) { 149 return UNKNOWN; 150 } else { 151 return typeName; 152 } 153 } 154 155 /** 156 * Returns the time in milliseconds needed for this method invocation. 157 * 158 * @return the time in milliseconds needed for this method invocation 159 */ 160 public function getTime(Void):Number { 161 return this.time; 162 } 163 164 /** 165 * Sets the time in milliseconds needed for this method invocation. 166 * 167 * @param time the time in milliseconds needed for this method invocation 168 */ 169 public function setTime(time:Number):Void { 170 this.time = time; 171 } 172 173 /** 174 * Returns the arguments used for this method invocation. 175 * 176 * @return the arguments used for this method invocation 177 */ 178 public function getArguments(Void):Array { 179 return this.args; 180 } 181 182 /** 183 * Sets the arguments used for this method invocation. 184 * 185 * @param args the arguments used for this method invocation 186 */ 187 public function setArguments(args:Array):Void { 188 this.args = args; 189 } 190 191 /** 192 * Returns this method invocation's return value. 193 * 194 * @return this method invocation's return value 195 */ 196 public function getReturnValue(Void) { 197 return this.returnValue; 198 } 199 200 /** 201 * Sets the return value of this method invocation. 202 * 203 * @param returnValue the return value of this method invocation 204 */ 205 public function setReturnValue(returnValue):Void { 206 this.exception = undefined; 207 this.returnValue = returnValue; 208 } 209 210 /** 211 * Returns the exception thrown during this method invocation. 212 * 213 * @return the exception thrown during this method invocation 214 */ 215 public function getException(Void) { 216 return this.exception; 217 } 218 219 /** 220 * Sets the exception thrown during this method invocation. 221 * 222 * @param exception the exception thrown during this method invocation 223 */ 224 public function setException(exception):Void { 225 this.returnValue = undefined; 226 this.exception = exception; 227 } 228 229 /** 230 * Returns whether this method invocation was successful. Successful means that it 231 * returned a proper return value and did not throw an exception. 232 * 233 * @return {@code true} if this method invocation was successful else {@code false} 234 */ 235 public function wasSuccessful(Void):Boolean { 236 return (this.exception === undefined); 237 } 238 239 /** 240 * Returns the method invocation that called the method that resulted in this 241 * method invocation. 242 * 243 * @return the method invocation that called the method that resulted in this 244 * method. 245 */ 246 public function getCaller(Void):MethodInvocation { 247 return this.caller; 248 } 249 250 /** 251 * Sets the method invocation that called the method that resulted in this method 252 * invocation. 253 * 254 * @param caller the method invocation that called the method that resulted in this 255 * method invocation. 256 */ 257 public function setCaller(caller:MethodInvocation):Void { 258 this.caller = caller; 259 } 260 261 /** 262 * Returns the previous method invocation. 263 * 264 * @return the previous method invocation 265 */ 266 public function getPreviousMethodInvocation(Void):MethodInvocation { 267 return this.previousMethodInvocation; 268 } 269 270 /** 271 * Sets the previous method invocation. 272 * 273 * @param previousMethodInvocation the previous method invocation 274 */ 275 public function setPreviousMethodInvocation(previousMethodInvocation:MethodInvocation):Void { 276 this.previousMethodInvocation = previousMethodInvocation; 277 } 278 279 /** 280 * Checks whether this method invocation was invoked before the passed-in 281 * {@code methodInvocation}. 282 * 283 * @param methodInvocation the method invocation to make the check upon 284 * @return {@code true} if this method invocation was invoked previously to the 285 * passed-in {@code methodInvocation} else {@code false} 286 */ 287 public function isPreviousMethodInvocation(methodInvocation:MethodInvocation):Boolean { 288 if (methodInvocation == this) return false; 289 var previousMethodInvocation:MethodInvocation = methodInvocation.getPreviousMethodInvocation(); 290 while (previousMethodInvocation) { 291 if (previousMethodInvocation == this) return true; 292 previousMethodInvocation = previousMethodInvocation.getPreviousMethodInvocation(); 293 } 294 return false; 295 } 296 297 /** 298 * Returns the string representation of this method invocation. 299 * 300 * @param rootTestResult test result that holds the total values needed for 301 * percentage calculations 302 * @return the string representation of this method invocation 303 */ 304 public function toString():String { 305 var rootTestResult:TestResult = arguments[0]; 306 if (!rootTestResult) rootTestResult = getThis(); 307 var result:String = getTimePercentage(rootTestResult.getTime()) + "%"; 308 result += ", " + getThis().getTime() + " ms"; 309 result += " - " + getName(); 310 return result; 311 } 312 313 }