View Javadoc
1   /*
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2023, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.core.blackbox.appender;
15  
16  import ch.qos.logback.core.Appender;
17  import ch.qos.logback.core.ConsoleAppender;
18  import ch.qos.logback.core.Context;
19  import ch.qos.logback.core.ContextBase;
20  
21  import ch.qos.logback.core.testUtil.DummyEncoder;
22  import ch.qos.logback.core.testUtil.XTeeOutputStream;
23  import org.fusesource.jansi.AnsiConsole;
24  import org.fusesource.jansi.AnsiPrintStream;
25  import org.junit.jupiter.api.AfterEach;
26  import org.junit.jupiter.api.Assertions;
27  import org.junit.jupiter.api.BeforeEach;
28  import org.junit.jupiter.api.Test;
29  
30  import java.io.FilterOutputStream;
31  import java.io.OutputStream;
32  import java.io.PrintStream;
33  import java.lang.reflect.Field;
34  
35  /**
36   * Redirecting System.out is quite messy. Disable this test in Maven but not in
37   * Package.class
38   */
39  public class JansiConsoleAppenderTest {
40      Context context = new ContextBase();
41      ConsoleAppender<Object> ca = new ConsoleAppender<Object>();
42  
43      XTeeOutputStream teeOut;
44      XTeeOutputStream teeErr;
45      PrintStream originalOut;
46      PrintStream originalErr;
47  
48      @BeforeEach
49      public void setUp() {
50          originalOut = System.out;
51          originalErr = System.err;
52          // teeOut will output bytes on System out but it will also
53          // collect them so that the output can be compared against
54          // some expected output data
55          // teeOut = new TeeOutputStream(originalOut);
56  
57          // keep the console quiet
58          teeOut = new XTeeOutputStream(null);
59          teeErr = new XTeeOutputStream(null);
60  
61          // redirect System.out to teeOut and System.err to teeErr
62          replace(AnsiConsole.out(), teeOut);
63          replace(AnsiConsole.err(), teeErr);
64      }
65  
66      @AfterEach
67      public void tearDown() {
68          System.setOut(originalOut);
69          replace(AnsiConsole.out(), originalOut);
70          System.setErr(originalErr);
71          replace(AnsiConsole.err(), originalErr);
72          AnsiConsole.systemUninstall();
73      }
74  
75      private void replace(AnsiPrintStream ansiPrintStream, OutputStream os) {
76          try {
77              Field field = FilterOutputStream.class.getDeclaredField("out");
78              field.setAccessible(true);
79              OutputStream oldOs = (OutputStream) field.get(ansiPrintStream);
80              field.set(ansiPrintStream, os);
81          } catch (Throwable t) {
82              throw new IllegalStateException("Unable to initialize Jansi for testing", t);
83          }
84      }
85  
86      public Appender<Object> getAppender() {
87          return new ConsoleAppender<>();
88      }
89  
90      @Test
91      public void jansiSystemOut() {
92  
93          DummyEncoder<Object> dummyEncoder = new DummyEncoder<>();
94          ca.setEncoder(dummyEncoder);
95          ca.setTarget("System.out");
96          ca.setContext(context);
97          ca.setWithJansi(true);
98          ca.start();
99          Assertions.assertTrue(ca.getOutputStream() instanceof AnsiPrintStream);
100         ca.doAppend(new Object());
101         // broken in Jansi 2.x as it uses java.io.FileDescriptor instead of System.out
102         Assertions.assertEquals("dummy", teeOut.toString().trim());
103     }
104 
105     @Test
106     public void jansiSystemErr() {
107         DummyEncoder<Object> dummyEncoder = new DummyEncoder<>();
108         ca.setEncoder(dummyEncoder);
109         ca.setTarget("System.err");
110         ca.setContext(context);
111         ca.setWithJansi(true);
112         ca.start();
113         Assertions.assertTrue(ca.getOutputStream() instanceof AnsiPrintStream);
114         ca.doAppend(new Object());
115         // broken in Jansi 2.x as it uses java.io.FileDescriptor instead of System.err
116         Assertions.assertEquals("dummy", teeErr.toString().trim());
117     }
118 }