001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.core.appender; 015 016import ch.qos.logback.core.Appender; 017import ch.qos.logback.core.ConsoleAppender; 018import ch.qos.logback.core.CoreConstants; 019import ch.qos.logback.core.encoder.DummyEncoder; 020import ch.qos.logback.core.encoder.EchoEncoder; 021import ch.qos.logback.core.encoder.NopEncoder; 022import ch.qos.logback.core.layout.DummyLayout; 023import ch.qos.logback.core.status.Status; 024import ch.qos.logback.core.testUtil.StatusChecker; 025 026import org.junit.After; 027import org.junit.Before; 028import org.junit.Test; 029 030import java.io.PrintStream; 031import java.io.UnsupportedEncodingException; 032import java.nio.charset.Charset; 033 034import static org.junit.Assert.assertEquals; 035import static org.junit.Assert.assertFalse; 036 037/** 038 * Redirecting System.out is quite messy. Disable this test in Maven bu not in Package.class 039 */ 040public class ConsoleAppenderTest extends AbstractAppenderTest<Object> { 041 042 XTeeOutputStream tee; 043 PrintStream original; 044 045 @Before 046 public void setUp() { 047 original = System.out; 048 // tee will output bytes on System out but it will also 049 // collect them so that the output can be compared against 050 // some expected output data 051 // tee = new TeeOutputStream(original); 052 053 // keep the console quiet 054 tee = new XTeeOutputStream(null); 055 056 // redirect System.out to tee 057 System.setOut(new PrintStream(tee)); 058 } 059 060 @After 061 public void tearDown() { 062 System.setOut(original); 063 } 064 065 @Override 066 public Appender<Object> getAppender() { 067 return new ConsoleAppender<Object>(); 068 } 069 070 protected Appender<Object> getConfiguredAppender() { 071 ConsoleAppender<Object> ca = new ConsoleAppender<Object>(); 072 ca.setEncoder(new NopEncoder<Object>()); 073 ca.start(); 074 return ca; 075 } 076 077 @Test 078 public void smoke() { 079 ConsoleAppender<Object> ca = (ConsoleAppender<Object>) getAppender(); 080 ca.setEncoder(new DummyEncoder<Object>()); 081 ca.start(); 082 ca.doAppend(new Object()); 083 assertEquals(DummyLayout.DUMMY, tee.toString()); 084 } 085 086 @Test 087 public void open() { 088 ConsoleAppender<Object> ca = (ConsoleAppender<Object>) getAppender(); 089 DummyEncoder<Object> dummyEncoder = new DummyEncoder<Object>(); 090 dummyEncoder.setFileHeader("open"); 091 ca.setEncoder(dummyEncoder); 092 ca.start(); 093 ca.doAppend(new Object()); 094 ca.stop(); 095 assertEquals("open" + CoreConstants.LINE_SEPARATOR + DummyLayout.DUMMY, tee.toString()); 096 } 097 098 @Test 099 public void testClose() { 100 ConsoleAppender<Object> ca = (ConsoleAppender<Object>) getAppender(); 101 DummyEncoder<Object> dummyEncoder = new DummyEncoder<Object>(); 102 dummyEncoder.setFileFooter("CLOSED"); 103 ca.setEncoder(dummyEncoder); 104 ca.start(); 105 ca.doAppend(new Object()); 106 ca.stop(); 107 // ConsoleAppender must keep the underlying stream open. 108 // The console is not ours to close. 109 assertFalse(tee.isClosed()); 110 assertEquals(DummyLayout.DUMMY + "CLOSED", tee.toString()); 111 } 112 113 // See http://jira.qos.ch/browse/LBCORE-143 114 @Test 115 public void changeInConsole() { 116 ConsoleAppender<Object> ca = (ConsoleAppender<Object>) getAppender(); 117 EchoEncoder<Object> encoder = new EchoEncoder<Object>(); 118 ca.setEncoder(encoder); 119 ca.start(); 120 ca.doAppend("a"); 121 assertEquals("a" + CoreConstants.LINE_SEPARATOR, tee.toString()); 122 123 XTeeOutputStream newTee = new XTeeOutputStream(null); 124 System.setOut(new PrintStream(newTee)); 125 ca.doAppend("b"); 126 assertEquals("b" + CoreConstants.LINE_SEPARATOR, newTee.toString()); 127 } 128 129 @Test 130 public void testUTF16BE() throws UnsupportedEncodingException { 131 ConsoleAppender<Object> ca = (ConsoleAppender<Object>) getAppender(); 132 DummyEncoder<Object> dummyEncoder = new DummyEncoder<Object>(); 133 Charset utf16BE = Charset.forName("UTF-16BE"); 134 dummyEncoder.setCharset(utf16BE); 135 ca.setEncoder(dummyEncoder); 136 ca.start(); 137 ca.doAppend(new Object()); 138 assertEquals(DummyLayout.DUMMY, new String(tee.toByteArray(), utf16BE)); 139 } 140 141 @Test 142 public void wrongTarget() { 143 ConsoleAppender<Object> ca = (ConsoleAppender<Object>) getAppender(); 144 EchoEncoder<Object> encoder = new EchoEncoder<Object>(); 145 encoder.setContext(context); 146 ca.setContext(context); 147 ca.setTarget("foo"); 148 ca.setEncoder(encoder); 149 ca.start(); 150 ca.doAppend("a"); 151 StatusChecker checker = new StatusChecker(context); 152 // 21:28:01,246 + WARN in ch.qos.logback.core.ConsoleAppender[null] - [foo] should be one of [System.out, 153 // System.err] 154 // 21:28:01,246 |-WARN in ch.qos.logback.core.ConsoleAppender[null] - Using previously set target, System.out by 155 // default. 156 // StatusPrinter.print(context); 157 158 checker.assertContainsMatch(Status.WARN, "\\[foo\\] should be one of \\[System.out, System.err\\]"); 159 160 } 161 162}