1   /*
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2024, 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  
15  package ch.qos.logback.core.issue.lbcore258;
16  
17  
18  import java.io.IOException;
19  import java.io.OutputStream;
20  
21  
22  import ch.qos.logback.core.OutputStreamAppender;
23  import ch.qos.logback.core.encoder.EncoderBase;
24  import org.junit.jupiter.api.Test;
25  
26  /**
27   * Provided by Alexander Kudrevatykh in LOGBACK-1362
28   */
29  public class Logback1362 {
30  
31      long startNanos = System.nanoTime();
32      long DELAY = 20;
33      long getNanos() {
34          return (System.nanoTime() - startNanos);
35      }
36  
37      @Test
38      public void testAppender() throws InterruptedException {
39  
40          OutputStreamAppender<Object> appender = new OutputStreamAppender<Object>() {
41              @Override
42              public void addError(String msg, Throwable ex) {
43                  throw new RuntimeException(getNanos()+"  "+msg, ex);
44              }
45          };
46  
47          appender.setEncoder(new EncoderBase<Object>() {
48  
49              @Override
50              public byte[] headerBytes() {
51                  return null;
52              }
53  
54              @Override
55              public byte[] encode(Object event) {
56                  delay(DELAY*2);
57                  return new byte[]{'A'};
58              }
59  
60              @Override
61              public byte[] footerBytes() {
62                  // TODO Auto-generated method stub
63                  return null;
64              }
65          });
66          appender.setOutputStream(new OutputStream() {
67  
68              @Override
69              public void write(int b) throws IOException {
70                  throw new RuntimeException("not closed appender");
71              }
72          });
73  
74          System.out.println(getNanos() + " About to call appender.start()");
75          appender.start();
76          System.out.println(getNanos() + " After call to appender.start()");
77  
78          Thread t = new Thread(new Runnable() {
79              @Override
80              public void run() {
81                  delay(DELAY);
82                  System.out.println(getNanos() + " About to call appender.stop()");
83                  appender.stop();
84                  System.out.println(getNanos() + " After call to appender.stop()");
85              }
86          });
87          t.start();
88          System.out.println(getNanos() + " Calling appender.doAppend(new Object());");
89          appender.doAppend(new Object());
90          System.out.println("xxxxxxxxxxxxxxxxxxxxxx");
91          System.out.println(getNanos()+ " After call to appender.doAppender(new Object())");
92          t.join();
93      }
94  
95      private void delay(long delayInMillis) {
96          try {
97              Thread.sleep(delayInMillis);
98          } catch (InterruptedException e) {
99              // TODO Auto-generated catch block
100             e.printStackTrace();
101         }
102     }
103 
104 }
105