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.core;
043:
044: import java.awt.Dialog;
045: import java.io.File;
046: import java.io.FileInputStream;
047: import java.io.FileOutputStream;
048: import java.io.IOException;
049: import java.lang.reflect.InvocationTargetException;
050: import java.util.MissingResourceException;
051: import java.util.logging.Level;
052: import java.util.logging.LogManager;
053: import java.util.logging.Logger;
054: import javax.swing.JDialog;
055: import javax.swing.SwingUtilities;
056: import junit.framework.Test;
057: import org.netbeans.core.startup.TopLogging;
058: import org.netbeans.junit.MockServices;
059: import org.netbeans.junit.NbTestCase;
060: import org.netbeans.junit.NbTestSuite;
061: import org.openide.DialogDescriptor;
062: import org.openide.DialogDisplayer;
063: import org.openide.ErrorManager;
064: import org.openide.NotifyDescriptor;
065: import org.openide.util.Exceptions;
066: import org.xml.sax.SAXParseException;
067:
068: /**
069: * Test the core error manager impl.
070: * @author Jesse Glick
071: * @see "#18141"
072: */
073: public final class NbErrorManagerTest extends NbTestCase {
074: public NbErrorManagerTest(String s) {
075: super (s);
076: }
077:
078: public static Test suite() {
079: //return new NbErrorManagerTest("testNestedThrowables");
080: return new NbTestSuite(NbErrorManagerTest.class);
081: }
082:
083: private ErrorManager err;
084:
085: protected void setUp() throws Exception {
086: clearWorkDir();
087:
088: MockServices.setServices(MockDD.class);
089:
090: System.setProperty("netbeans.user", getWorkDirPath());
091: // init the whole system
092: TopLogging.initializeQuietly();
093:
094: err = ErrorManager.getDefault();
095: assertNotNull("One Error manager found", err);
096: }
097:
098: public void testIsLoggable() {
099: assertFalse(ErrorManager.getDefault().isLoggable(
100: ErrorManager.INFORMATIONAL));
101: assertFalse(ErrorManager.getDefault().isLoggable(
102: ErrorManager.INFORMATIONAL + 1));
103: assertTrue(ErrorManager.getDefault().isLoggable(
104: ErrorManager.WARNING + 1));
105: }
106:
107: public void testBasicNotify() throws Exception {
108: assertTrue(err.isNotifiable(ErrorManager.EXCEPTION));
109: NullPointerException npe = new NullPointerException("unloc msg");
110: err.notify(ErrorManager.INFORMATIONAL, npe);
111: String s = readLog();
112: assertTrue(s
113: .indexOf("java.lang.NullPointerException: unloc msg") != -1);
114: assertTrue(s.indexOf("testBasicNotify") != -1);
115: }
116:
117: public void testLog() throws Exception {
118: assertFalse(err.isLoggable(ErrorManager.INFORMATIONAL));
119: err.log("some msg");
120: String s = readLog();
121: assertTrue(s.indexOf("some msg") == -1);
122: assertTrue(err.isLoggable(ErrorManager.WARNING));
123: err.log(ErrorManager.WARNING, "another msg");
124: s = readLog();
125: assertTrue(s.indexOf("another msg") != -1);
126: ErrorManager err2 = err.getInstance("foo.bar.baz");
127: assertFalse(err2.isLoggable(ErrorManager.INFORMATIONAL));
128: err2.log("sub msg #1");
129: s = readLog();
130: assertTrue(s.indexOf("sub msg #1") == -1);
131: System.setProperty("quux.hoho.level", "0");
132:
133: LogManager.getLogManager().readConfiguration();
134:
135: err2 = err.getInstance("quux.hoho.yaya");
136: assertTrue(err2.isLoggable(ErrorManager.INFORMATIONAL));
137: err2.log("sub msg #2");
138: s = readLog();
139: assertTrue(s, s.indexOf("sub msg #2") != -1);
140: assertTrue(s, s.indexOf("quux.hoho.yaya") != -1);
141: }
142:
143: /** @see "#15611" */
144: public void testNestedThrowables() throws Exception {
145: NullPointerException npe = new NullPointerException("unloc msg");
146: ClassNotFoundException cnfe = new ClassNotFoundException(
147: "other msg", npe);
148: err.notify(ErrorManager.INFORMATIONAL, cnfe);
149: String s = readLog();
150: assertTrue(s
151: .indexOf("java.lang.NullPointerException: unloc msg") != -1);
152: assertTrue(s.indexOf("java.lang.ClassNotFoundException") != -1);
153: npe = new NullPointerException("msg1");
154: IOException ioe = new IOException("msg2");
155: ioe.initCause(npe); // only works in right order with initCause, not ErrorManager.annotate
156: InvocationTargetException ite = new InvocationTargetException(
157: ioe, "msg3");
158: IllegalStateException ise = new IllegalStateException("msg4");
159: ise.initCause(ite);
160: err.notify(ErrorManager.INFORMATIONAL, ise);
161: s = readLog();
162: assertTrue(s,
163: s.indexOf("java.lang.NullPointerException: msg1") != -1);
164: assertTrue(s, s.indexOf("java.io.IOException: msg2") != -1);
165: assertTrue(s.indexOf("msg3") != -1);
166: assertTrue(s, s
167: .indexOf("java.lang.IllegalStateException: msg4") != -1);
168: // #91541: check that stack traces are printed in a pleasant order.
169: assertTrue(s,
170: s.indexOf("java.lang.NullPointerException: msg1") < s
171: .indexOf("java.io.IOException: msg2"));
172: assertTrue(s, s.indexOf("java.io.IOException: msg2") < s
173: .indexOf("msg3"));
174: assertTrue(s, s.indexOf("msg3") < s
175: .indexOf("java.lang.IllegalStateException: msg4"));
176: }
177:
178: public void testNotifyWithAnnotations() throws Exception {
179: NullPointerException npe = new NullPointerException("unloc msg");
180: err.annotate(npe, "loc msg #1");
181: err.notify(ErrorManager.INFORMATIONAL, npe);
182: String s = readLog();
183: assertTrue(s
184: .indexOf("java.lang.NullPointerException: unloc msg") != -1);
185: assertTrue(s, s.indexOf("loc msg #1") != -1);
186: npe = new NullPointerException("unloc msg");
187: err.annotate(npe, ErrorManager.UNKNOWN, "extra unloc msg",
188: null, null, null);
189: err.notify(ErrorManager.INFORMATIONAL, npe);
190: s = readLog();
191: assertTrue(s.indexOf("extra unloc msg") != -1);
192: npe = new NullPointerException("new unloc msg");
193: IOException ioe = new IOException("something bad");
194: err.annotate(ioe, npe);
195: err.notify(ErrorManager.INFORMATIONAL, ioe);
196: s = readLog();
197: assertTrue(s
198: .indexOf("java.lang.NullPointerException: new unloc msg") != -1);
199: assertTrue(s.indexOf("java.io.IOException: something bad") != -1);
200: }
201:
202: public void testDeepAnnotations() throws Exception {
203: Exception e1 = new Exception("msg1");
204: // #19114: deeply nested loc msgs should be used
205: err.annotate(e1, "some loc msg");
206: Exception e2 = new Exception("msg2");
207: err.annotate(e2, e1);
208: Exception e3 = new Exception("msg3");
209: err.annotate(e3, e2);
210: Exception e4 = new Exception("msg4");
211: err.annotate(e3, e4);
212: err.notify(ErrorManager.INFORMATIONAL, e3);
213: String s = readLog();
214: assertTrue(s, s.indexOf("java.lang.Exception: msg1") != -1);
215: assertTrue(s.indexOf("java.lang.Exception: msg2") != -1);
216: assertTrue(s.indexOf("java.lang.Exception: msg3") != -1);
217: assertTrue(s.indexOf("java.lang.Exception: msg4") != -1);
218: assertTrue(s.indexOf("some loc msg") != -1);
219: }
220:
221: /** @see "#19487" */
222: public void testLoops() throws Exception {
223: Exception e1 = new Exception("msg1");
224: Exception e2 = new Exception("msg2");
225: err.annotate(e2, e1);
226: Exception e3 = new Exception("msg3");
227: err.annotate(e3, e2);
228: err.annotate(e1, e3);
229: err.notify(ErrorManager.INFORMATIONAL, e1);
230: String s = readLog();
231: assertTrue(s.indexOf("java.lang.Exception: msg1") != -1);
232: assertTrue(s, s.indexOf("java.lang.Exception: msg2") != -1);
233: assertTrue(s.indexOf("java.lang.Exception: msg3") != -1);
234: // warning from NBEM itself:
235: assertTrue(s.indexOf("cyclic") != -1);
236: }
237:
238: public void testAddedInfo() throws Exception {
239: MissingResourceException mre = new MissingResourceException(
240: "msg1", "the.class.Name", "the-key");
241: err.notify(ErrorManager.INFORMATIONAL, mre);
242: String s = readLog();
243: assertTrue(s
244: .indexOf("java.util.MissingResourceException: msg1") != -1);
245: assertTrue(s.indexOf("the.class.Name") != -1);
246: assertTrue(s.indexOf("the-key") != -1);
247: SAXParseException saxpe = new SAXParseException("msg2",
248: "pub-id", "sys-id", 313, 424);
249: err.notify(ErrorManager.INFORMATIONAL, saxpe);
250: s = readLog();
251: assertTrue(s.indexOf("org.xml.sax.SAXParseException: msg2") != -1);
252: assertTrue(s.indexOf("pub-id") != -1);
253: assertTrue(s.indexOf("sys-id") != -1);
254: assertTrue(s.indexOf("313") != -1);
255: assertTrue(s.indexOf("424") != -1);
256: }
257:
258: /**
259: * Actually just tests the same code used when running NE.
260: */
261: public void testNotifyException() throws Exception {
262: IOException ioe = new IOException("unloc msg");
263: err.annotate(ioe, "loc msg");
264: NbErrorManager.Exc x = NbErrorManager.createExc(ioe,
265: Level.INFO, null);
266: assertEquals(Level.INFO, x.getSeverity());
267: assertEquals("loc msg", x.getLocalizedMessage());
268: assertTrue(x.isLocalized());
269: // could do more here...
270: }
271:
272: /**
273: * Check that UNKNOWN works.
274: * @see "#30947"
275: */
276: public void testUnknownSeverity() throws Exception {
277:
278: // Simple exception is EXCEPTION.
279: Throwable t = new IOException("unloc msg");
280: NbErrorManager.Exc x = NbErrorManager.createExc(t, null, null);
281: assertEquals(Level.WARNING, x.getSeverity());
282: assertEquals("unloc msg", x.getMessage());
283: assertEquals("unloc msg", x.getLocalizedMessage());
284: assertFalse(x.isLocalized());
285:
286: // Same when there is unloc debug info attached.
287: t = new IOException("unloc msg");
288: err.annotate(t, ErrorManager.UNKNOWN, "some debug info", null,
289: null, null);
290: x = NbErrorManager.createExc(t, null, null);
291: assertEquals(Level.WARNING, x.getSeverity());
292: assertEquals("unloc msg", x.getMessage());
293: assertEquals("unloc msg", x.getLocalizedMessage());
294: assertFalse(x.isLocalized());
295:
296: // Nested exceptions don't necessarily change anything severity-wise.
297: t = new IOException("unloc msg");
298: Throwable t2 = new IOException("unloc msg #2");
299: err.annotate(t, ErrorManager.UNKNOWN, null, null, t2, null);
300: x = NbErrorManager.createExc(t, null, null);
301: assertEquals(Level.WARNING, x.getSeverity());
302: assertEquals("unloc msg", x.getMessage());
303: assertEquals("unloc msg", x.getLocalizedMessage());
304: assertFalse(x.isLocalized());
305:
306: // But annotations at a particular severity level (usually localized) do
307: // set the severity for the exception.
308: t = new IOException("unloc msg");
309: err.annotate(t, ErrorManager.USER, null, "loc msg", null, null);
310: x = NbErrorManager.createExc(t, null, null);
311: assertEquals(1973, x.getSeverity().intValue());
312: assertEquals("unloc msg", x.getMessage());
313: assertEquals("loc msg", x.getLocalizedMessage());
314: assertTrue(x.isLocalized());
315:
316: // And that works even if you are just rethrowing someone else's exception.
317: t = new IOException("unloc msg");
318: t2 = new IOException("unloc msg #2");
319: err
320: .annotate(t2, ErrorManager.USER, null, "loc msg", null,
321: null);
322: err.annotate(t, ErrorManager.UNKNOWN, null, null, t2, null);
323: x = NbErrorManager.createExc(t, null, null);
324: assertEquals(1973, x.getSeverity().intValue());
325: assertEquals("unloc msg", x.getMessage());
326: assertEquals("loc msg", x.getLocalizedMessage());
327: assertTrue(x.isLocalized());
328:
329: // Almost the same test, but to mimic #31254 message == localizedMessage:
330: t2 = new IOException("loc msg");
331: err
332: .annotate(t2, ErrorManager.USER, null, "loc msg", null,
333: null);
334: t = new IOException("loc msg");
335: err.annotate(t, ErrorManager.USER, null, null, t2, null);
336: x = NbErrorManager.createExc(t, null, null);
337: assertEquals(1973, x.getSeverity().intValue());
338: assertEquals("loc msg", x.getMessage());
339: assertEquals("loc msg", x.getLocalizedMessage());
340: // Note that it is stil considered localized even though the messages
341: // are equals: there is a localized annotation.
342: assertTrue(x.isLocalized());
343:
344: }
345:
346: public void testPerPetrKuzelsRequestInIssue62836() throws Exception {
347: class My extends Exception {
348: public My() {
349: super ("Ahoj");
350: }
351: }
352:
353: My my = new My();
354:
355: err.notify(err.INFORMATIONAL, my);
356: err.notify(err.USER, my);
357:
358: String output = readLog();
359: // wait for a dialog to be shown
360: waitEQ();
361:
362: int report = output.indexOf("My: Ahoj");
363: assertTrue("There is one exception reported: " + output,
364: report > 0);
365: int next = output.indexOf("My: Ahoj", report + 1);
366: assertEquals("No next exceptions there (after " + report
367: + "):\n" + output, -1, next);
368: }
369:
370: private void waitEQ() throws InterruptedException,
371: InvocationTargetException {
372: SwingUtilities.invokeAndWait(new Runnable() {
373: public void run() {
374: }
375: });
376: }
377:
378: public void testErrorManagerCompatibilityAsDescribedInIssue79227()
379: throws Exception {
380: MockDD.lastDescriptor = null;
381:
382: Exception ex = new ClassNotFoundException();
383: ErrorManager em = ErrorManager.getDefault();
384: String msg = "LocMsg";
385: em.annotate(ex, msg);
386: em.notify(ErrorManager.USER, ex); // Issue 65116 - don't show the exception to the user
387:
388: waitEQ();
389: assertNotNull("Mock descriptor called", MockDD.lastDescriptor);
390: assertEquals("Info msg", NotifyDescriptor.INFORMATION_MESSAGE,
391: MockDD.lastDescriptor.getMessageType());
392: }
393:
394: public void testUIExceptionsTriggersTheDialog() throws Exception {
395: MockDD.lastDescriptor = null;
396:
397: Exception ex = new IOException();
398: ErrorManager em = ErrorManager.getDefault();
399: em.annotate(ex, ErrorManager.USER, "bla", "blaLoc", null, null);
400: Exceptions.printStackTrace(ex);
401:
402: waitEQ();
403: assertNotNull("Mock descriptor called", MockDD.lastDescriptor);
404: assertEquals("Info msg", NotifyDescriptor.INFORMATION_MESSAGE,
405: MockDD.lastDescriptor.getMessageType());
406: }
407:
408: public void testUIExceptionsTriggersNoDialogIssue118408()
409: throws Exception {
410: MockDD.lastDescriptor = null;
411:
412: Exception iex = new IllegalStateException();
413: String msg = "Thread '";
414: ErrorManager.getDefault().notify(
415: ErrorManager.getDefault().annotate(iex, msg));
416:
417: waitEQ();
418: assertNotNull("Mock descriptor called", MockDD.lastDescriptor);
419: assertEquals("Warning msg as the exception has been localized",
420: NotifyDescriptor.WARNING_MESSAGE, MockDD.lastDescriptor
421: .getMessageType());
422: }
423:
424: public void testUIExceptionsTriggersTheDialogWithWarningPlus1()
425: throws Exception {
426: MockDD.lastDescriptor = null;
427:
428: Exception ex = new IOException();
429: ErrorManager em = ErrorManager.getDefault();
430: em.annotate(ex, ErrorManager.USER, "bla", "blaLoc", null, null);
431: Logger.global.log(OwnLevel.UNKNOWN, "someerror", ex);
432:
433: waitEQ();
434: assertNotNull("Mock descriptor called", MockDD.lastDescriptor);
435: assertEquals("Info msg", NotifyDescriptor.INFORMATION_MESSAGE,
436: MockDD.lastDescriptor.getMessageType());
437: }
438:
439: // Noticed as part of analysis of #59807 stack trace: Throwable.initCause tricky!
440: public void testCatchMarker() throws Exception {
441: try {
442: m1();
443: fail();
444: } catch (IOException e) {
445: err.notify(ErrorManager.INFORMATIONAL, e);
446: String s = readLog();
447: assertTrue("added [catch] marker in simple cases: " + s, s
448: .indexOf("[catch] at "
449: + NbErrorManagerTest.class.getName()
450: + ".testCatchMarker") != -1);
451: }
452: try {
453: m3();
454: fail();
455: } catch (IOException e) {
456: err.notify(ErrorManager.INFORMATIONAL, e);
457: String s = readLog();
458: assertTrue("added [catch] marker in compound exception: "
459: + s, s.indexOf("[catch] at "
460: + NbErrorManagerTest.class.getName()
461: + ".testCatchMarker") != -1);
462: }
463: try {
464: m5();
465: fail();
466: } catch (InterruptedException e) {
467: err.notify(ErrorManager.INFORMATIONAL, e);
468: String s = readLog();
469: assertTrue(
470: "added [catch] marker in multiply compound exception: "
471: + s, s.indexOf("[catch] at "
472: + NbErrorManagerTest.class.getName()
473: + ".testCatchMarker") != -1);
474: }
475: try {
476: throw new IOException(
477: "main line\ndata 1\ndata 2\ndata 3\ndata 4");
478: } catch (IOException e) {
479: err.notify(ErrorManager.INFORMATIONAL, e);
480: String s = readLog();
481: assertTrue(
482: "added [catch] marker in an actual stack trace line: "
483: + s, s.indexOf("[catch] at "
484: + NbErrorManagerTest.class.getName()
485: + ".testCatchMarker") != -1);
486: }
487: }
488:
489: private static void m1() throws IOException {
490: m2();
491: }
492:
493: private static void m2() throws IOException {
494: throw new IOException();
495: }
496:
497: private static void m3() throws IOException {
498: try {
499: m4();
500: } catch (ClassNotFoundException e) {
501: throw (IOException) new IOException().initCause(e);
502: }
503: }
504:
505: private static void m4() throws ClassNotFoundException {
506: throw new ClassNotFoundException();
507: }
508:
509: private static void m5() throws InterruptedException {
510: try {
511: m3();
512: } catch (IOException e) {
513: throw (InterruptedException) new InterruptedException()
514: .initCause(e);
515: }
516: }
517:
518: private String readLog() throws IOException {
519: LogManager.getLogManager().readConfiguration();
520:
521: File log = new File(new File(new File(getWorkDir(), "var"),
522: "log"), "messages.log");
523: assertTrue("Log file exists: " + log, log.canRead());
524:
525: FileInputStream is = new FileInputStream(log);
526:
527: byte[] arr = new byte[(int) log.length()];
528: int r = is.read(arr);
529: assertEquals("all read", arr.length, r);
530: is.close();
531:
532: new FileOutputStream(log).close(); // truncate
533:
534: return "---%<--- [start log of " + getName() + "]\n"
535: + new String(arr).replaceFirst("\0+", "")
536: + "\n---%<--- [end log of " + getName() + "]\n";
537: }
538:
539: public static final class MockDD extends DialogDisplayer {
540: static NotifyDescriptor lastDescriptor;
541:
542: public Object notify(NotifyDescriptor descriptor) {
543: lastDescriptor = descriptor;
544: return null;
545: }
546:
547: public Dialog createDialog(DialogDescriptor descriptor) {
548: lastDescriptor = descriptor;
549: return new JDialog() {
550: @SuppressWarnings("deprecation")
551: public void show() {
552: }
553: };
554: }
555:
556: }
557:
558: private static final class OwnLevel extends Level {
559: public static final Level UNKNOWN = new OwnLevel("UNKNOWN",
560: Level.WARNING.intValue() + 1); // NOI18N
561:
562: private OwnLevel(String s, int i) {
563: super (s, i);
564: }
565: } // end of UserLevel
566: }
|