package io.github.yurloc.autostring;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.Test;

/**
 * Specifies behavior of {@link AutoStringBuilder} in corner cases.
 */
public class CornerCasesSpecificationTest {

    /**
     * Field with null value should be converted to {@code "null"} string.
     */
    @Test
    public void nullValueDisplayedAsNull() {
        assertThat(new HasFieldWithNullValue().toString()).isEqualTo("HasFieldWithNullValue[nullField=null]");
    }

    /**
     * Passing null to AutoStringBuilder is wrong.
     */
    @Test(expected = IllegalArgumentException.class)
    public void nullArgumentThrowsException() {
        new PassesNullArgument().toString();
    }

    @Test(expected = TestException.class)
    public void shouldNotSwallowRuntimeExceptions() {
        new ThrowsRuntimeException().toString();
    }

    @Test(expected = TestError.class)
    public void shouldNotSwallowErrors() {
        new ThrowsError().toString();
    }

    @Test
    public void emptyBracketsForClassWithNoAutoStringFields() {
        assertThat(new HasNoAutoStringFields().toString()).isEqualTo("HasNoAutoStringFields[]");
    }

    @Test
    public void emptyBracketsForClassWithNoFields() {
        assertThat(new HasNoFields().toString()).isEqualTo("HasNoFields[]");
    }

    private static class HasFieldWithNullValue {

        @AutoString
        private final String nullField = null;

        @Override
        public String toString() {
            return AutoStringBuilder.build(this);
        }
    }

    private static class PassesNullArgument {

        @Override
        public String toString() {
            return AutoStringBuilder.build(null);
        }
    }

    private static class TestException extends RuntimeException {

        private static final long serialVersionUID = 1L;

    }

    private static class ThrowsRuntimeException {

        @AutoString
        private Object field = new Object() {

            @Override
            public String toString() {
                throw new TestException();
            }
        };

        @Override
        public String toString() {
            return AutoStringBuilder.build(this);
        }
    }

    private static class TestError extends Error {

        private static final long serialVersionUID = 1L;

    }

    private static class ThrowsError {

        @AutoString
        private Object field = new Object() {

            @Override
            public String toString() {
                throw new TestError();
            }
        };

        @Override
        public String toString() {
            return AutoStringBuilder.build(this);
        }
    }

    private static class HasNoAutoStringFields {

        private final String value = "/";

        public String getValue() {
            return value;
        }

        @Override
        public String toString() {
            return AutoStringBuilder.build(this);
        }
    }

    private static class HasNoFields {

        public void butSomeMethod() {
            // that does nothing
        }

        @Override
        public String toString() {
            return AutoStringBuilder.build(this);
        }
    }
}

@@ -989,32 +989,89 @@
 tring();%0A    %7D%0A%0A
+    /**%0A     * Not intended but should not fail.%0A     */%0A
     @Test%0A    pu
@@ -1056,32 +1056,32 @@
    */%0A    @Test%0A
-
     public void 
@@ -1224,32 +1224,89 @@
 lds%5B%5D%22);%0A    %7D%0A%0A
+    /**%0A     * Not intended but should not fail.%0A     */%0A
     @Test%0A    pu
@@ -1345,32 +1345,32 @@
 ithNoFields() %7B%0A
-
         assertTh
@@ -1429,32 +1429,246 @@
 lds%5B%5D%22);%0A    %7D%0A%0A
+    /**%0A     * Not intended but should not fail.%0A     */%0A    @Test%0A    public void shouldNotFailWhenArgumentIsString() %7B%0A        assertThat(new PassesStringInsteadOfThis().toString()).isEqualTo(%22String%5B%5D%22);%0A    %7D%0A%0A
     private stat
@@ -3551,11 +3551,188 @@
  %7D%0A    %7D
+%0A%0A    private static class PassesStringInsteadOfThis %7B%0A%0A        @Override%0A        public String toString() %7B%0A            return AutoStringBuilder.build(%22hello%22);%0A        %7D%0A    %7D
 %0A%7D%0A

Should not fail if argument is String