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}