1   /*
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2026, 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 v2.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          //System.setOut(new PrintStream(teeOut));
62          //System.setErr(new PrintStream(teeErr));
63  
64          // redirect System.out to teeOut and System.err to teeErr
65          //replace(originalOut, teeOut);
66          //replace(originalErr, teeErr);
67      }
68  
69      @AfterEach
70      public void tearDown() {
71          AnsiConsole.systemUninstall();
72          System.setOut(originalOut);
73          //replace(AnsiConsole.out(), originalOut);
74          System.setErr(originalErr);
75          //replace(AnsiConsole.err(), originalErr);
76  
77      }
78  
79      private void replace(AnsiPrintStream ansiPrintStream, OutputStream os) {
80          try {
81              Field field = FilterOutputStream.class.getDeclaredField("out");
82              field.setAccessible(true);
83              OutputStream oldOs = (OutputStream) field.get(ansiPrintStream);
84              field.set(ansiPrintStream, os);
85          } catch (Throwable t) {
86              throw new IllegalStateException("Unable to initialize Jansi for testing", t);
87          }
88      }
89  
90      public Appender<Object> getAppender() {
91          return new ConsoleAppender<>();
92      }
93  
94      @Test
95      public void jansiSystemOut() {
96  
97          DummyEncoder<Object> dummyEncoder = new DummyEncoder<>();
98          ca.setEncoder(dummyEncoder);
99          ca.setTarget("System.out");
100         ca.setContext(context);
101         ca.setWithJansi(true);
102         ca.start();
103         Assertions.assertTrue(ca.getOutputStream() instanceof AnsiPrintStream);
104         ca.doAppend(new Object());
105         // broken in Jansi 2.x as it uses java.io.FileDescriptor instead of System.out
106         //Assertions.assertEquals("dummy", teeOut.toString().trim());
107     }
108 
109     @Test
110     public void jansiSystemErr() {
111         DummyEncoder<Object> dummyEncoder = new DummyEncoder<>();
112         ca.setEncoder(dummyEncoder);
113         ca.setTarget("System.err");
114         ca.setContext(context);
115         ca.setWithJansi(true);
116         ca.start();
117         Assertions.assertTrue(ca.getOutputStream() instanceof AnsiPrintStream);
118         ca.doAppend(new Object());
119         // broken in Jansi 2.x as it uses java.io.FileDescriptor instead of System.err
120         //Assertions.assertEquals("dummy", teeErr.toString().trim());
121     }
122 }