001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.api.debugger.jpda;
043:
044: import com.sun.jdi.ArrayReference;
045: import com.sun.jdi.StringReference;
046: import com.sun.jdi.Value;
047: import java.io.BufferedReader;
048: import java.io.InputStreamReader;
049: import java.net.URL;
050: import java.util.ArrayList;
051: import java.util.List;
052: import junit.framework.AssertionFailedError;
053: import org.netbeans.api.debugger.DebuggerManager;
054: import org.netbeans.junit.NbTestCase;
055: import org.netbeans.modules.debugger.jpda.expr.JDIVariable;
056:
057: /**
058: * Tests evaluation of various expressions.
059: * Automatically parses the expressions from the test methods and compares
060: * their evaluations with test methods calls.
061: *
062: * @author Martin Entlicher
063: */
064: public class EvaluatorTest extends NbTestCase {
065:
066: private JPDASupport support;
067: private URL source;
068:
069: public EvaluatorTest(String s) {
070: super (s);
071: }
072:
073: protected void setUp() throws Exception {
074: super .setUp();
075: System.setProperty("debugger.evaluator2", "true");
076: JPDASupport.removeAllBreakpoints();
077: Utils.BreakPositions bp = Utils
078: .getBreakPositions(System.getProperty("test.dir.src")
079: + "org/netbeans/api/debugger/jpda/testapps/EvaluatorApp.java");
080: LineBreakpoint lb = bp.getLineBreakpoints().get(0);
081: source = new URL(lb.getURL());
082: DebuggerManager.getDebuggerManager().addBreakpoint(lb);
083: support = JPDASupport
084: .attach("org.netbeans.api.debugger.jpda.testapps.EvaluatorApp");
085: support.waitState(JPDADebugger.STATE_STOPPED);
086: }
087:
088: public void testStaticEvaluation() throws Exception {
089: try {
090: List<Method> methods = getMethods(true);
091: AssertionFailedError te = null;
092: AssertionFailedError ex = null;
093: for (Method m : methods) {
094: try {
095: checkEval(m);
096: } catch (AssertionFailedError e) {
097: if (te == null) {
098: te = ex = e;
099: } else {
100: ex.initCause(e);
101: ex = e;
102: }
103: }
104: }
105: if (te != null) {
106: throw te;
107: }
108: //checkEvalFails ("this");
109: checkEvalFails("NoSuchClass.class");
110: } finally {
111: support.doFinish();
112: }
113: }
114:
115: public void testInstanceEvaluation() throws Exception {
116: try {
117: Utils.BreakPositions bp = Utils
118: .getBreakPositions(System
119: .getProperty("test.dir.src")
120: + "org/netbeans/api/debugger/jpda/testapps/EvaluatorApp.java");
121: LineBreakpoint lb = bp.getLineBreakpoints().get(1);
122: DebuggerManager.getDebuggerManager().addBreakpoint(lb);
123: support.doContinue();
124: support.waitState(JPDADebugger.STATE_STOPPED);
125:
126: List<Method> methods = getMethods(false);
127: AssertionFailedError te = null;
128: AssertionFailedError ex = null;
129: for (Method m : methods) {
130: try {
131: checkEval(m);
132: } catch (AssertionFailedError e) {
133: if (te == null) {
134: te = ex = e;
135: } else {
136: ex.initCause(e);
137: ex = e;
138: }
139: }
140: }
141: if (te != null) {
142: throw te;
143: }
144: } finally {
145: support.doFinish();
146: }
147: }
148:
149: private void checkEvalFails(String expression) {
150: try {
151: Variable var = support.getDebugger().evaluate(expression);
152: fail("Evaluation of expression was unexpectedly successful: "
153: + expression + " = " + var.getValue());
154: } catch (InvalidExpressionException e) {
155: // its ok
156: return;
157: }
158: }
159:
160: private void checkEval(Method m) {
161: try {
162: Variable eMethod = support.getDebugger().evaluate(
163: m.getName() + "()");
164: String undo = m.getUndo();
165: if (undo != null) {
166: support.getDebugger().evaluate(undo + "()");
167: }
168: Variable eVal = support.getDebugger().evaluate(
169: m.getExpression());
170: if (undo != null) {
171: support.getDebugger().evaluate(undo + "()");
172: }
173: /*System.err.println(" eMethod = "+eMethod);
174: System.err.println(" eVal = "+eVal);
175: System.err.println(" equals = "+eMethod.equals(eVal));*/
176: Value eMethodJDIValue = ((JDIVariable) eMethod)
177: .getJDIValue();
178: Value eValJDIValue = ((JDIVariable) eVal).getJDIValue();
179: /*System.err.println(" eMethod JDI Value = "+eMethodJDIValue);
180: System.err.println(" eVal JDI Value = "+eValJDIValue);
181: System.err.println(" equals = "+eMethodJDIValue.equals(eValJDIValue));*/
182: if (eMethod != null) {
183: assertEquals("Evaluation of expression '"
184: + m.getExpression() + "' of method '"
185: + m.getName()
186: + "()' produced a wrong type of result:",
187: eMethod.getType(), eVal.getType());
188: }
189: assertEquals("Evaluation of expression '"
190: + m.getExpression() + "' of method '" + m.getName()
191: + "()' produced a wrong value:", new JDIValue(
192: eMethodJDIValue), new JDIValue(eValJDIValue));
193: System.err.println(" Method " + m.getName()
194: + "() evaluated successfully.");
195: } catch (InvalidExpressionException e) {
196: e.printStackTrace();
197: fail("Evaluation of expression was unsuccessful: " + e);
198: }
199: }
200:
201: private List<Method> getMethods(boolean staticMethods)
202: throws Exception {
203: List<Method> methods = new ArrayList<Method>();
204: BufferedReader r = new BufferedReader(new InputStreamReader(
205: source.openStream()));
206: try {
207: Method m = null;
208: String line;
209: while ((line = r.readLine()) != null) {
210: line = line.trim();
211: if (line.startsWith("*"))
212: continue;
213: if (m != null) {
214: int rt = line.indexOf("return");
215: if (rt != 0) {
216: continue;
217: }
218: String expression;
219: try {
220: expression = line.substring(rt + 7, line
221: .lastIndexOf(';'));
222: } catch (RuntimeException rex) {
223: System.err.println("line = '" + line
224: + "', rt = " + rt
225: + ", lastIndexOf(';') = "
226: + line.lastIndexOf(';'));
227: rex.printStackTrace();
228: throw rex;
229: }
230: expression = expression.trim();
231: m.setExpression(expression);
232: methods.add(m);
233: m = null;
234: continue;
235: }
236: if (line.indexOf(" test") < 0 || line.indexOf("()") < 0) {
237: continue;
238: }
239: if (staticMethods != line.indexOf("static") >= 0) {
240: continue;
241: }
242: String name = line.substring(line.indexOf("test"), line
243: .indexOf("()"));
244: if (name.endsWith("_undo")) {
245: String origName = name.substring(0, name.length()
246: - "_undo".length());
247: for (Method om : methods) {
248: if (om.getName().equals(origName)) {
249: om.setUndo(name);
250: break;
251: }
252: }
253: } else {
254: m = new Method(name);
255: }
256: }
257: } finally {
258: r.close();
259: }
260: return methods;
261: }
262:
263: private static class Method {
264:
265: private String name;
266: private String undoName;
267: private String expression;
268:
269: public Method(String name) {
270: this .name = name;
271: }
272:
273: public String getName() {
274: return name;
275: }
276:
277: public void setUndo(String undoName) {
278: this .undoName = undoName;
279: }
280:
281: public String getUndo() {
282: return undoName;
283: }
284:
285: public void setExpression(String expression) {
286: this .expression = expression;
287: }
288:
289: public String getExpression() {
290: return expression;
291: }
292: }
293:
294: private static class JDIValue {
295:
296: private Value value;
297:
298: public JDIValue(Value value) {
299: this .value = value;
300: }
301:
302: @Override
303: public boolean equals(Object obj) {
304: if (!(obj instanceof JDIValue))
305: return false;
306: Value v = ((JDIValue) obj).value;
307: if (value == null)
308: return v == null;
309: if (value instanceof StringReference) {
310: if (!(v instanceof StringReference))
311: return false;
312: return ((StringReference) value).value().equals(
313: ((StringReference) v).value());
314: }
315: if (value instanceof ArrayReference) {
316: if (!(v instanceof ArrayReference))
317: return false;
318: ArrayReference a1 = (ArrayReference) value;
319: ArrayReference a2 = (ArrayReference) v;
320: if (!a1.type().equals(a2.type()))
321: return false;
322: if (a1.length() != a2.length())
323: return false;
324: int n = a1.length();
325: for (int i = 0; i < n; i++) {
326: if (!new JDIValue(a1.getValue(i))
327: .equals(new JDIValue(a2.getValue(i)))) {
328: return false;
329: }
330: }
331: return true;
332: }
333: return value.equals(v);
334: }
335:
336: @Override
337: public int hashCode() {
338: if (value == null)
339: return 0;
340: else
341: return value.hashCode();
342: }
343:
344: @Override
345: public String toString() {
346: return "" + value;
347: }
348:
349: }
350: }
|