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 java.io.IOException;
045:
046: import com.sun.jdi.connect.IllegalConnectorArgumentsException;
047: import org.netbeans.api.debugger.DebuggerManager;
048: import org.netbeans.api.debugger.jpda.event.JPDABreakpointEvent;
049: import org.netbeans.api.debugger.jpda.event.JPDABreakpointListener;
050: import org.netbeans.junit.NbTestCase;
051:
052: /**
053: * Tests line breakpoints at various places.
054: *
055: * @author Maros Sandor, Jan Jancura
056: */
057: public class LineBreakpointTest extends NbTestCase {
058:
059: private static final String TEST_APP = Utils
060: .getURL(System.getProperty("test.dir.src")
061: + "org/netbeans/api/debugger/jpda/testapps/LineBreakpointApp.java");
062: private static final String TEST_APP_PATH = System
063: .getProperty("test.dir.src")
064: + "org/netbeans/api/debugger/jpda/testapps/LineBreakpointApp.java";
065:
066: private JPDASupport support;
067:
068: public LineBreakpointTest(String s) {
069: super (s);
070: }
071:
072: public void testConditionalBreakpoint() throws Exception {
073: Utils.BreakPositions bp = Utils
074: .getBreakPositions(TEST_APP_PATH);
075: doTestBreakpointComplete(bp.getStopLine("condition1"), "x==22",
076: JPDABreakpointEvent.CONDITION_FALSE);
077: doTestBreakpointComplete(bp.getStopLine("condition2"), "x==60",
078: JPDABreakpointEvent.CONDITION_TRUE);
079: }
080:
081: public void testMultipleLineBreakpoints() throws Exception {
082: try {
083: Utils.BreakPositions bp = Utils
084: .getBreakPositions(TEST_APP_PATH);
085: LineBreakpoint[] lb = bp.getBreakpoints().toArray(
086: new LineBreakpoint[0]);
087: {
088: LineBreakpoint b;
089: b = lb[4];
090: lb[4] = lb[2];
091: lb[2] = b;
092: }
093: /*
094: LineBreakpoint lb1 = LineBreakpoint.create (TEST_APP, 32);
095: LineBreakpoint lb2 = LineBreakpoint.create (TEST_APP, 37);
096: LineBreakpoint lb3 = LineBreakpoint.create (TEST_APP, 109);
097: lb3.setPreferredClassName("org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp$Inner");
098: LineBreakpoint lb4 = LineBreakpoint.create (TEST_APP, 92);
099: lb4.setPreferredClassName("org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp$InnerStatic");
100: LineBreakpoint lb5 = LineBreakpoint.create (TEST_APP, 41);
101: */
102: DebuggerManager dm = DebuggerManager.getDebuggerManager();
103: for (int i = 0; i < lb.length; i++) {
104: dm.addBreakpoint(lb[i]);
105: }
106:
107: TestBreakpointListener[] tb = new TestBreakpointListener[lb.length];
108: for (int i = 0; i < lb.length; i++) {
109: tb[i] = new TestBreakpointListener(lb[i]);
110: lb[i].addJPDABreakpointListener(tb[i]);
111: }
112: support = JPDASupport
113: .attach("org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp");
114: JPDADebugger debugger = support.getDebugger();
115:
116: for (int j = 0; j < lb.length; j++) {
117: support.waitState(JPDADebugger.STATE_STOPPED); // j-th breakpoint hit
118: assertEquals(
119: "Debugger stopped at wrong line for breakpoint "
120: + j, lb[j].getLineNumber(), debugger
121: .getCurrentCallStackFrame()
122: .getLineNumber(null));
123: for (int i = j + 1; i < tb.length; i++) {
124: tb[i].checkNotNotified();
125: }
126: if (j < lb.length - 1) {
127: support.doContinue();
128: }
129: }
130:
131: for (int i = 0; i < tb.length; i++) {
132: tb[i].checkResult();
133: }
134: for (int i = 0; i < tb.length; i++) {
135: dm.removeBreakpoint(lb[i]);
136: }
137: support.doContinue();
138: support.waitState(JPDADebugger.STATE_DISCONNECTED);
139: } finally {
140: if (support != null)
141: support.doFinish();
142: }
143: }
144:
145: public void testStaticBlockBreakpoint() throws Exception {
146: Utils.BreakPositions bp = Utils
147: .getBreakPositions(TEST_APP_PATH);
148: doTestBreakpointComplete(bp.getStopLine("staticx"));
149: doTestBreakpointComplete(bp.getStopLine("staticx2"));
150: }
151:
152: public void testStaticInnerClassBreakpoint() throws Exception {
153: Utils.BreakPositions bp = Utils
154: .getBreakPositions(TEST_APP_PATH);
155: doTestBreakpointComplete(bp.getStopLine("IS1"));
156: doTestBreakpointComplete(bp.getStopLine("IS2"));
157: doTestBreakpointComplete(bp.getStopLine("IS3"));
158: }
159:
160: public void testMainLineBreakpoint() throws Exception {
161: Utils.BreakPositions bp = Utils
162: .getBreakPositions(TEST_APP_PATH);
163: doTestBreakpointComplete(bp.getStopLine("M1"));
164: }
165:
166: public void testConstructorLineBreakpoint() throws Exception {
167: Utils.BreakPositions bp = Utils
168: .getBreakPositions(TEST_APP_PATH);
169: doTestBreakpointComplete(bp.getStopLine("C1"));
170: }
171:
172: public void testInnerLineBreakpoint() throws Exception {
173: Utils.BreakPositions bp = Utils
174: .getBreakPositions(TEST_APP_PATH);
175: doTestBreakpointComplete(bp.getStopLine("I1"));
176: doTestBreakpointComplete(bp.getStopLine("I2"));
177: doTestBreakpointComplete(bp.getStopLine("I3"));
178: }
179:
180: private void doTestBreakpointComplete(int line, String condition,
181: int conditionResult) throws IOException,
182: IllegalConnectorArgumentsException, DebuggerStartException {
183: try {
184: LineBreakpoint lb = doTestBreakpoint(line, condition,
185: conditionResult);
186: if (condition == null
187: || conditionResult == JPDABreakpointEvent.CONDITION_TRUE) {
188: support.doContinue();
189: support.waitState(JPDADebugger.STATE_DISCONNECTED);
190: }
191: DebuggerManager.getDebuggerManager().removeBreakpoint(lb);
192: } finally {
193: if (support != null)
194: support.doFinish();
195: }
196: }
197:
198: private void doTestBreakpointComplete(int line) throws IOException,
199: IllegalConnectorArgumentsException, DebuggerStartException {
200: doTestBreakpointComplete(line, null,
201: JPDABreakpointEvent.CONDITION_NONE);
202: }
203:
204: private LineBreakpoint doTestBreakpoint(int line, String condition,
205: int conditionResult) throws IOException,
206: IllegalConnectorArgumentsException, DebuggerStartException {
207: JPDASupport.removeAllBreakpoints();
208: LineBreakpoint lb = LineBreakpoint.create(TEST_APP, line);
209: /*
210: if (73 <= line && line <= 98) {
211: lb.setPreferredClassName("org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp$InnerStatic");
212: } else if (100 <= line && line <= 115) {
213: lb.setPreferredClassName("org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp$Inner");
214: }
215: */
216: lb.setCondition(condition);
217: TestBreakpointListener tbl = new TestBreakpointListener(lb,
218: conditionResult);
219: lb.addJPDABreakpointListener(tbl);
220: DebuggerManager.getDebuggerManager().addBreakpoint(lb);
221:
222: support = JPDASupport
223: .attach("org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp");
224:
225: if (condition == null
226: || conditionResult == JPDABreakpointEvent.CONDITION_TRUE) {
227: support.waitState(JPDADebugger.STATE_STOPPED);
228: } else {
229: support.waitState(JPDADebugger.STATE_DISCONNECTED);
230: }
231:
232: tbl.checkResult();
233: return lb;
234: }
235:
236: /**
237: * Tests debugger's ability to make difference between different projects
238: * with the same classes while getting the locations during class-loaded event.
239: *
240: * 1. The user creates 2 classes: ${test.dir.src}/.../LineBreakpointApp.java
241: * and ${test.dir.src_2}/.../LineBreakpointApp.java
242: * 2. Then set a breakpoint in ${test.dir.src_2}/.../LineBreakpointApp.java.
243: *
244: * Debugger should stop _only_ in the second project. If debugger stopped in
245: * the first one, then assertion violation would arise because of source path
246: * equality test.
247: */
248: public void testBreakpointUnambiguity1() throws Exception {
249: try {
250: Utils.BreakPositions bp = Utils
251: .getBreakPositions(System
252: .getProperty("test.dir.src")
253: + "org/netbeans/api/debugger/jpda/testapps/LineBreakpointApp.java");
254: LineBreakpoint lb1 = LineBreakpoint.create(TEST_APP, bp
255: .getStopLine("condition1"));
256: // lb1.setSourceRoot(System.getProperty ("test.dir.src"));
257: DebuggerManager dm = DebuggerManager.getDebuggerManager();
258: dm.addBreakpoint(lb1);
259:
260: TestBreakpointListener tb1 = new TestBreakpointListener(lb1);
261: lb1.addJPDABreakpointListener(tb1);
262:
263: support = JPDASupport
264: .attach("org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp");
265: JPDADebugger debugger = support.getDebugger();
266:
267: support.waitState(JPDADebugger.STATE_STOPPED); // breakpoint hit, the source root is correct
268: assertEquals("Debugger stopped at wrong line", lb1
269: .getLineNumber(), debugger
270: .getCurrentCallStackFrame().getLineNumber(null));
271:
272: tb1.checkResult();
273: support.doContinue();
274: support.waitState(JPDADebugger.STATE_DISCONNECTED);
275: dm.removeBreakpoint(lb1);
276: support.doFinish();
277: /*
278: // Second run - BP should not be hit with a different source root - viz testBreakpointUnambiguity2()
279: support = null;
280: lb1 = LineBreakpoint.create (TEST_APP, 39);
281: lb1.setSourceRoot(System.getProperty ("test.dir.src")+"_2");
282: dm = DebuggerManager.getDebuggerManager ();
283: dm.addBreakpoint (lb1);
284:
285: tb1 = new TestBreakpointListener (lb1);
286: lb1.addJPDABreakpointListener (tb1);
287:
288: support = JPDASupport.attach (
289: "org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp"
290: );
291: debugger = support.getDebugger();
292:
293: support.waitState (JPDADebugger.STATE_STOPPED); // Stopped or disconnected
294: assertEquals(
295: "Debugger should not stop on BP with faked source root",
296: debugger.getState(),
297: JPDADebugger.STATE_DISCONNECTED
298: );
299: tb1.checkNotNotified();
300: dm.removeBreakpoint (lb1);
301: */
302: } finally {
303: if (support != null)
304: support.doFinish();
305: }
306: }
307:
308: /**
309: * Tests debugger's ability to make difference between different projects
310: * with the same classes while getting the locations during class-loaded event.
311: *
312: * 1. The user creates 2 classes: ${test.dir.src}/.../LineBreakpointApp.java
313: * and ${test.dir.src_2}/.../LineBreakpointApp.java
314: * 2. Then set a breakpoint in ${test.dir.src_2}/.../LineBreakpointApp.java.
315: *
316: * Debugger should stop _only_ in the second project. If debugger stopped in
317: * the first one, then assertion violation would arise because of source path
318: * equality test.
319: */
320: public void testBreakpointUnambiguity2() throws Exception {
321: try {
322: Utils.BreakPositions bp = Utils
323: .getBreakPositions(System
324: .getProperty("test.dir.src")
325: + "org/netbeans/api/debugger/jpda/testapps/LineBreakpointApp.java");
326: LineBreakpoint lb1 = LineBreakpoint
327: .create(
328: Utils
329: .getURL(System
330: .getProperty("user.home")
331: + // intentionally bad path
332: java.io.File.separator
333: + "org/netbeans/api/debugger/jpda/testapps/LineBreakpointApp.java"),
334: bp.getStopLine("condition1"));
335: //lb1.setSourceRoot(System.getProperty ("test.dir.src") + "_2");
336: DebuggerManager dm = DebuggerManager.getDebuggerManager();
337: dm.addBreakpoint(lb1);
338:
339: TestBreakpointListener tb1 = new TestBreakpointListener(lb1);
340: lb1.addJPDABreakpointListener(tb1);
341:
342: support = JPDASupport
343: .attach("org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp");
344: JPDADebugger debugger = support.getDebugger();
345:
346: support.waitState(JPDADebugger.STATE_STOPPED); // Stopped or disconnected
347: assertEquals(
348: "Debugger should not stop on BP with faked source root",
349: debugger.getState(),
350: JPDADebugger.STATE_DISCONNECTED);
351:
352: tb1.checkNotNotified();
353: dm.removeBreakpoint(lb1);
354: } finally {
355: if (support != null)
356: support.doFinish();
357: }
358: }
359:
360: // innerclasses ............................................................
361:
362: private class TestBreakpointListener implements
363: JPDABreakpointListener {
364:
365: private LineBreakpoint lineBreakpoint;
366: private int conditionResult;
367:
368: private JPDABreakpointEvent event;
369: private AssertionError failure;
370:
371: public TestBreakpointListener(LineBreakpoint lineBreakpoint) {
372: this (lineBreakpoint, JPDABreakpointEvent.CONDITION_NONE);
373: }
374:
375: public TestBreakpointListener(LineBreakpoint lineBreakpoint,
376: int conditionResult) {
377: this .lineBreakpoint = lineBreakpoint;
378: this .conditionResult = conditionResult;
379: }
380:
381: public void breakpointReached(JPDABreakpointEvent event) {
382: try {
383: checkEvent(event);
384: } catch (AssertionError e) {
385: failure = e;
386: } catch (Throwable e) {
387: failure = new AssertionError(e);
388: }
389: }
390:
391: private void checkEvent(JPDABreakpointEvent event) {
392: this .event = event;
393: assertEquals("Breakpoint event: Wrong source breakpoint",
394: lineBreakpoint, event.getSource());
395: assertNotNull("Breakpoint event: Context thread is null",
396: event.getThread());
397:
398: int result = event.getConditionResult();
399: if (result == JPDABreakpointEvent.CONDITION_FAILED
400: && conditionResult != JPDABreakpointEvent.CONDITION_FAILED)
401: failure = new AssertionError(event
402: .getConditionException());
403: else if (result != conditionResult)
404: failure = new AssertionError(
405: "Unexpected breakpoint condition result: "
406: + result);
407: }
408:
409: public void checkResult() {
410: if (event == null) {
411: CallStackFrame f = support.getDebugger()
412: .getCurrentCallStackFrame();
413: int ln = -1;
414: if (f != null) {
415: ln = f.getLineNumber(null);
416: }
417: throw new AssertionError(
418: "Breakpoint was not hit (listener was not notified) "
419: + ln);
420: }
421: if (failure != null)
422: throw failure;
423: }
424:
425: public void checkNotNotified() {
426: if (event != null) {
427: JPDAThread t = event.getThread();
428: throw new AssertionError(
429: "Breakpoint was hit (listener was notified) in thread "
430: + t);
431: }
432: if (failure != null)
433: throw failure;
434: }
435: }
436: }
|