package com.bitmoving.util;


import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.encoder.LayoutWrappingEncoder;
import ch.qos.logback.core.status.Status;
import ch.qos.logback.core.status.StatusListenerAsList;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.LoggerFactory;

import java.util.List;

import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertTrue;

public class FlowdockLoggerIntegrationTest {

    private static final LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();

    @Test
    public void status_stored_on_error_while_sending() {
        LoggerContext context = new LoggerContext();
        StatusListenerAsList statusListener = trackStatusWithListener(context);

        FlowdockAppender appender = new FlowdockAppender();
        appender.setApiEndpoint("http://localhost:7800");
        appender.setFlowToken("token");
        appender.setAuthor("author");
        appender.setEncoder(createEncoder(context));
        appender.setName("FLOWDOCK");
        appender.setContext(context);
        appender.start();

        Logger logger = loggerWithAppender(appender);
        logger.error("message", new RuntimeException("ouch"));

        List<Status> statusList = statusListener.getStatusList();
        assertThat(statusList.size(), equalTo(1));

        Status status = statusList.get(0);
        assertTrue(status.getOrigin().getClass() == FlowdockAppender.class);
        assertThat(status.getMessage(), containsString("Could not send message"));
    }

    @Test
    public void do_not_start_appender_if_author_is_missing() {
        LoggerContext context = new LoggerContext();
        StatusListenerAsList statusListener = trackStatusWithListener(context);

        FlowdockAppender appender = new FlowdockAppender();
        appender.setEncoder(createEncoder(context));
        appender.setName("FLOWDOCK");
        appender.setContext(context);
        appender.start();

        assertThat(appender.isStarted(), is(false));

        Logger logger = loggerWithAppender(appender);
        logger.error("message");

        List < Status > statusList = statusListener.getStatusList();
        assertThat(statusList.size(), equalTo(2));

        Status status = statusList.get(0);
        assertTrue(status.getOrigin().getClass() == FlowdockAppender.class);
        assertThat(status.getMessage(), containsString("No author set"));
    }

    private FlowdockAppender startAppender(String endpoint, LoggerContext context) {
        FlowdockAppender appender = new FlowdockAppender();
        appender.setApiEndpoint(endpoint);
        appender.setFlowToken("token");
        appender.setAuthor("author");
        appender.setEncoder(createEncoder(context));
        appender.setName("FLOWDOCK");
        appender.setContext(context);
        appender.start();
        return appender;
    }

    private Logger loggerWithAppender(Appender<ILoggingEvent> appender) {
        Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("test1");
        logger.addAppender(appender);
        logger.setLevel(Level.DEBUG);
        logger.setAdditive(false);
        return logger;
    }

    private StatusListenerAsList trackStatusWithListener(LoggerContext context) {
        StatusListenerAsList statusListener = new StatusListenerAsList();
        context.getStatusManager().add(statusListener);
        return statusListener;
    }

    private LayoutWrappingEncoder createEncoder(LoggerContext context) {
        PatternLayoutEncoder encoder = new PatternLayoutEncoder();
        encoder.setContext(context);
        encoder.setPattern("[%thread] %-5level %logger{40} - %msg %n");
        encoder.start();
        return encoder;
    }
}

@@ -456,24 +456,55 @@
 ort 
-org.junit.Ignore
+com.google.common.util.concurrent.MoreExecutors
 ;%0Aim
@@ -771,109 +771,8 @@
  %7B%0A%0A
-    private static final LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();%0A%0A
     
@@ -827,24 +827,52 @@
 le_sending()
+ throws InterruptedException
  %7B%0A        L
@@ -1340,32 +1340,199 @@
 ender.start();%0A%0A
+        // execute the request threads on same thread as JUnit test%0A        appender.getMessageSender().setExecutorService(MoreExecutors.newDirectExecutorService());%0A%0A
         Logger l
@@ -1950,24 +1950,49 @@
 message%22));%0A
+        appender.stop();%0A
     %7D%0A%0A    @
@@ -2874,455 +2874,27 @@
     
-%7D%0A%0A    private FlowdockAppender startAppender(String endpoint, LoggerContext context) %7B%0A        FlowdockAppender appender = new FlowdockAppender();%0A        appender.setApiEndpoint(endpoint);%0A        appender.setFlowToken(%22token%22);%0A        appender.setAuthor(%22author%22);%0A        appender.setEncoder(createEncoder(context));%0A        appender.setName(%22FLOWDOCK%22);%0A        appender.setContext(context);%0A        appender.start();%0A        return appender
+    appender.stop()
 ;%0A  

Stop appenders, and let the message sender execute the requests on the same thread as the unit test runs