package de.duehl.basics.system;

/*
 * Copyright 2020 Christian Dühl. All rights reserved.
 *
 * This program is free software. You can redistribute it and/or
 * modify it under the same terms as perl:
 *
 * general:  http://dev.perl.org/licenses/
 * GPL:      http://dev.perl.org/licenses/gpl1.html
 * artistic: http://dev.perl.org/licenses/artistic.html
 */

import static org.junit.Assert.*;

import java.util.List;

import org.junit.Test;

import de.duehl.basics.collections.CollectionsHelper;
import de.duehl.basics.text.Text;

public class ExceptionHelperTest {

    private static final List<String> LOWER_STACK_TRACE_ELEMENTS = CollectionsHelper.buildListFrom(
            "java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
            "java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)",
            "java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)",
            "java.base/java.lang.reflect.Method.invoke(Method.java:568)",
            "org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)",
            "org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)",
            "org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)",
            "org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)",
            "org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)",
            "org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)",
            "org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)",
            "org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)",
            "org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)",
            "org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)",
            "org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)",
            "org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)",
            "org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)",
            "org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)",
            "org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)",
            "org.junit.runners.ParentRunner.run(ParentRunner.java:413)",
            "org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:93)",
            "org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)",
            "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:596)",
            "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:824)",
            "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:494)",
            "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:225)"
            );

    private static final String LOWER_STACK_TRACE_PART = createLowerStackTracePartString();

    private static String createLowerStackTracePartString() {
        StringBuilder builder = new StringBuilder();
        int number = 1;

        for (String part : LOWER_STACK_TRACE_ELEMENTS) {
            builder
                    .append("    ")
                    .append(Text.fillWithSpacesAtFront(Integer.toString(++number), 2))
                    .append(": ")
                    .append(part)
                    .append(Text.LINE_BREAK)
                    ;
        }

        return builder.toString();
    }

    private static final String LOWER_STACK_TRACE_PART_HTML = createLowerStackTracePartHtml();

    private static String createLowerStackTracePartHtml() {
        StringBuilder builder = new StringBuilder();

        for (String part : LOWER_STACK_TRACE_ELEMENTS) {
            builder
                    .append("    <li>")
                    .append(part)
                    .append("</li>")
                    .append(Text.LINE_BREAK)
                    ;
        }

        return builder.toString();
    }

    @Test
    public void getDescriptionWithStackTraceNormalException() {
        Exception exception = new Exception("Da ist was passiert!");
        String actual = ExceptionHelper.getDescriptionWithStackTrace(exception);
        String expected = "Klassenname: java.lang.Exception" + Text.LINE_BREAK
                + "Nachricht  : Da ist was passiert!" + Text.LINE_BREAK
                + "Stack-Trace: " + Text.LINE_BREAK
                + "     1: de.duehl.basics.system.ExceptionHelperTest.getDescriptionWithStackTraceNormalException(ExceptionHelperTest.java:92)" + Text.LINE_BREAK
                + LOWER_STACK_TRACE_PART;
        assertEquals(expected, actual);
    }

    @Test
    public void getDescriptionWithStackTraceExceptionWithCause() {
        Exception exception = new Exception("Da ist was passiert!",
                new Exception("Da ist was anderes passiert!"));
        String actual = ExceptionHelper.getDescriptionWithStackTrace(exception);
        String expected = "Klassenname: java.lang.Exception" + Text.LINE_BREAK
                + "Nachricht  : Da ist was passiert!" + Text.LINE_BREAK
                + "Stack-Trace: " + Text.LINE_BREAK
                + "     1: de.duehl.basics.system.ExceptionHelperTest.getDescriptionWithStackTraceExceptionWithCause(ExceptionHelperTest.java:104)" + Text.LINE_BREAK
                + LOWER_STACK_TRACE_PART
                + "Cause      : " + Text.LINE_BREAK
                + "Klassenname: java.lang.Exception" + Text.LINE_BREAK
                + "Nachricht  : Da ist was anderes passiert!" + Text.LINE_BREAK
                + "Stack-Trace: " + Text.LINE_BREAK
                + "     1: de.duehl.basics.system.ExceptionHelperTest.getDescriptionWithStackTraceExceptionWithCause(ExceptionHelperTest.java:105)" + Text.LINE_BREAK
                + LOWER_STACK_TRACE_PART;
        assertEquals(expected, actual);
    }

    @Test
    public void getDescriptionWithStackTraceExceptionWithTwoCauseses() {
        Exception exception = new Exception("Da ist was passiert!",
                new Exception("Da ist was anderes passiert!",
                        new Exception("Da ist was noch etwas anderes passiert!")));
        String actual = ExceptionHelper.getDescriptionWithStackTrace(exception);
        String expected = "Klassenname: java.lang.Exception" + Text.LINE_BREAK
                + "Nachricht  : Da ist was passiert!" + Text.LINE_BREAK
                + "Stack-Trace: " + Text.LINE_BREAK
                + "     1: de.duehl.basics.system.ExceptionHelperTest.getDescriptionWithStackTraceExceptionWithTwoCauseses(ExceptionHelperTest.java:123)" + Text.LINE_BREAK
                + LOWER_STACK_TRACE_PART
                + "Cause      : " + Text.LINE_BREAK
                + "Klassenname: java.lang.Exception" + Text.LINE_BREAK
                + "Nachricht  : Da ist was anderes passiert!" + Text.LINE_BREAK
                + "Stack-Trace: " + Text.LINE_BREAK
                + "     1: de.duehl.basics.system.ExceptionHelperTest.getDescriptionWithStackTraceExceptionWithTwoCauseses(ExceptionHelperTest.java:124)" + Text.LINE_BREAK
                + LOWER_STACK_TRACE_PART
                + "Cause      : " + Text.LINE_BREAK
                + "Klassenname: java.lang.Exception" + Text.LINE_BREAK
                + "Nachricht  : Da ist was noch etwas anderes passiert!" + Text.LINE_BREAK
                + "Stack-Trace: " + Text.LINE_BREAK
                + "     1: de.duehl.basics.system.ExceptionHelperTest.getDescriptionWithStackTraceExceptionWithTwoCauseses(ExceptionHelperTest.java:125)" + Text.LINE_BREAK
                + LOWER_STACK_TRACE_PART;
        assertEquals(expected, actual);
    }

    @Test
    public void getExceptionNameAndMessageNormalException() {
        Exception exception = new Exception("Da ist was passiert!");
        String actual = ExceptionHelper.getExceptionNameAndMessage(exception);
        String expected = "Klasse der Ausnahme: java.lang.Exception, "
                + "Fehlermeldung der Ausnahme: Da ist was passiert!";
        assertEquals(expected, actual);
    }

    @Test
    public void getExceptionNameAndMessageExceptionWithCause() {
        Exception exception = new Exception("Da ist was passiert!",
                new Exception("Da ist was anderes passiert!"));
        String actual = ExceptionHelper.getExceptionNameAndMessage(exception);
        String expected = "Klasse der Ausnahme: java.lang.Exception, "
                + "Fehlermeldung der Ausnahme: Da ist was passiert! "
                + "(caused by: Klasse der Ausnahme: java.lang.Exception, "
                + "Fehlermeldung der Ausnahme: Da ist was anderes passiert!)";
        assertEquals(expected, actual);
    }

    @Test
    public void getExceptionNameAndMessageExceptionWithTwoCauseses() {
        Exception exception = new Exception("Da ist was passiert!",
                new Exception("Da ist was anderes passiert!",
                        new Exception("Da ist was noch etwas anderes passiert!")));
        String actual = ExceptionHelper.getExceptionNameAndMessage(exception);
        String expected = "Klasse der Ausnahme: java.lang.Exception, "
                + "Fehlermeldung der Ausnahme: Da ist was passiert! "
                + "(caused by: Klasse der Ausnahme: java.lang.Exception, "
                + "Fehlermeldung der Ausnahme: Da ist was anderes passiert! "
                + "(caused by: Klasse der Ausnahme: java.lang.Exception, "
                + "Fehlermeldung der Ausnahme: Da ist was noch etwas anderes passiert!))";
        assertEquals(expected, actual);
    }

    @Test
    public void getExceptionNameAndMessageExceptionWithThreeCauseses() {
        Exception exception = new Exception("Da ist was passiert!",
                new Exception("Da ist was anderes passiert!",
                        new Exception("Da ist was noch etwas anderes passiert!",
                                new Exception("Da ist was noch etwas ganz anderes passiert!"))));
        String actual = ExceptionHelper.getExceptionNameAndMessage(exception);
        String expected = "Klasse der Ausnahme: java.lang.Exception, "
                + "Fehlermeldung der Ausnahme: Da ist was passiert! "
                + "(caused by: Klasse der Ausnahme: java.lang.Exception, "
                + "Fehlermeldung der Ausnahme: Da ist was anderes passiert! "
                + "(caused by: Klasse der Ausnahme: java.lang.Exception, "
                + "Fehlermeldung der Ausnahme: Da ist was noch etwas anderes passiert! "
                + "(caused by: Klasse der Ausnahme: java.lang.Exception, "
                + "Fehlermeldung der Ausnahme: Da ist was noch etwas ganz anderes passiert!)))";
        assertEquals(expected, actual);
    }

    @Test
    public void getDescriptionWithStackTraceExceptionHtmlWithTwoCauseses() {
        Exception exception = new Exception("Da ist was passiert!",
                new Exception("Da ist was anderes passiert!",
                        new Exception("Da ist was noch etwas anderes passiert!")));
        String actual = ExceptionHelper.getDescriptionWithStackTraceHtml(exception);
        String expected = "<p>Klassenname: java.lang.Exception</p>" + Text.LINE_BREAK
                + "<p>Nachricht  : Da ist was passiert!</p>" + Text.LINE_BREAK
                + "<p>Stack-Trace:</p>" + Text.LINE_BREAK
                + "<ol>" + Text.LINE_BREAK
                + "    <li>de.duehl.basics.system.ExceptionHelperTest.getDescriptionWithStackTraceExceptionHtmlWithTwoCauseses(ExceptionHelperTest.java:203)</li>" + Text.LINE_BREAK
                + LOWER_STACK_TRACE_PART_HTML
                + "</ol>" + Text.LINE_BREAK
                + "<p>Cause      :</p>" + Text.LINE_BREAK
                + "<p>Klassenname: java.lang.Exception</p>" + Text.LINE_BREAK
                + "<p>Nachricht  : Da ist was anderes passiert!</p>" + Text.LINE_BREAK
                + "<p>Stack-Trace:</p>" + Text.LINE_BREAK
                + "<ol>" + Text.LINE_BREAK
                + "    <li>de.duehl.basics.system.ExceptionHelperTest.getDescriptionWithStackTraceExceptionHtmlWithTwoCauseses(ExceptionHelperTest.java:204)</li>" + Text.LINE_BREAK
                + LOWER_STACK_TRACE_PART_HTML
                + "</ol>" + Text.LINE_BREAK
                + "<p>Cause      :</p>" + Text.LINE_BREAK
                + "<p>Klassenname: java.lang.Exception</p>" + Text.LINE_BREAK
                + "<p>Nachricht  : Da ist was noch etwas anderes passiert!</p>" + Text.LINE_BREAK
                + "<p>Stack-Trace:</p>" + Text.LINE_BREAK
                + "<ol>" + Text.LINE_BREAK
                + "    <li>de.duehl.basics.system.ExceptionHelperTest.getDescriptionWithStackTraceExceptionHtmlWithTwoCauseses(ExceptionHelperTest.java:205)</li>" + Text.LINE_BREAK
                + LOWER_STACK_TRACE_PART_HTML
                + "</ol>" + Text.LINE_BREAK;
        assertEquals(expected, actual);
    }

}
