/*
 * Copyright (c) 2017 Mockito contributors
 * This program is made available under the terms of the MIT License.
 */
package org.mockitousage;

import static org.mockito.BDDMockito.*;

import org.junit.Before;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

public class CompilationWarningsTest {

    @Before
    public void pay_attention_to_compilation_warnings_and_JDK_version() {}

    @Test
    public void no_warnings_for_most_common_api() throws Exception {
        doReturn(null).when(mock(IMethods.class)).objectReturningMethodNoArgs();
        doReturn("a", 12).when(mock(IMethods.class)).objectReturningMethodNoArgs();
        doReturn(1000).when(mock(IMethods.class)).objectReturningMethodNoArgs();
        doThrow(new NullPointerException())
                .when(mock(IMethods.class))
                .objectReturningMethodNoArgs();
        doThrow(new NullPointerException(), new IllegalArgumentException())
                .when(mock(IMethods.class))
                .objectReturningMethodNoArgs();
        doThrow(NullPointerException.class)
                .when(mock(IMethods.class))
                .objectReturningMethodNoArgs();

        doAnswer(ignore()).doReturn(null).when(mock(IMethods.class)).objectReturningMethodNoArgs();
        doAnswer(ignore())
                .doReturn("a", 12)
                .when(mock(IMethods.class))
                .objectReturningMethodNoArgs();
        doAnswer(ignore()).doReturn(1000).when(mock(IMethods.class)).objectReturningMethodNoArgs();
        doAnswer(ignore())
                .doThrow(new NullPointerException())
                .when(mock(IMethods.class))
                .objectReturningMethodNoArgs();
        doAnswer(ignore())
                .doThrow(new NullPointerException(), new IllegalArgumentException())
                .when(mock(IMethods.class))
                .objectReturningMethodNoArgs();
        doAnswer(ignore())
                .doThrow(NullPointerException.class)
                .when(mock(IMethods.class))
                .objectReturningMethodNoArgs();

        when(mock(IMethods.class).objectReturningMethodNoArgs()).thenReturn(null);
        when(mock(IMethods.class).objectReturningMethodNoArgs()).thenReturn("a", 12L);
        when(mock(IMethods.class).objectReturningMethodNoArgs()).thenReturn(1000);
        when(mock(IMethods.class).objectReturningMethodNoArgs())
                .thenThrow(new NullPointerException());
        when(mock(IMethods.class).objectReturningMethodNoArgs())
                .thenThrow(new NullPointerException(), new IllegalArgumentException());
        when(mock(IMethods.class).objectReturningMethodNoArgs())
                .thenThrow(NullPointerException.class);

        when(mock(IMethods.class).objectReturningMethodNoArgs()).then(ignore()).thenReturn(null);
        when(mock(IMethods.class).objectReturningMethodNoArgs())
                .then(ignore())
                .thenReturn("a", 12L);
        when(mock(IMethods.class).objectReturningMethodNoArgs()).then(ignore()).thenReturn(1000);
        when(mock(IMethods.class).objectReturningMethodNoArgs())
                .then(ignore())
                .thenThrow(new NullPointerException());
        when(mock(IMethods.class).objectReturningMethodNoArgs())
                .then(ignore())
                .thenThrow(new NullPointerException(), new IllegalArgumentException());
        when(mock(IMethods.class).objectReturningMethodNoArgs())
                .then(ignore())
                .thenThrow(NullPointerException.class);

        willReturn(null).given(mock(IMethods.class)).objectReturningMethodNoArgs();
        willReturn("a", 12).given(mock(IMethods.class)).objectReturningMethodNoArgs();
        willReturn(1000).given(mock(IMethods.class)).objectReturningMethodNoArgs();
        willThrow(new NullPointerException())
                .given(mock(IMethods.class))
                .objectReturningMethodNoArgs();
        willThrow(new NullPointerException(), new IllegalArgumentException())
                .given(mock(IMethods.class))
                .objectReturningMethodNoArgs();
        willThrow(NullPointerException.class)
                .given(mock(IMethods.class))
                .objectReturningMethodNoArgs();

        willAnswer(ignore())
                .willReturn(null)
                .given(mock(IMethods.class))
                .objectReturningMethodNoArgs();
        willAnswer(ignore())
                .willReturn("a", 12)
                .given(mock(IMethods.class))
                .objectReturningMethodNoArgs();
        willAnswer(ignore())
                .willReturn(1000)
                .given(mock(IMethods.class))
                .objectReturningMethodNoArgs();
        willAnswer(ignore())
                .willThrow(new NullPointerException())
                .given(mock(IMethods.class))
                .objectReturningMethodNoArgs();
        willAnswer(ignore())
                .willThrow(new NullPointerException(), new IllegalArgumentException())
                .given(mock(IMethods.class))
                .objectReturningMethodNoArgs();
        willAnswer(ignore())
                .willThrow(NullPointerException.class)
                .given(mock(IMethods.class))
                .objectReturningMethodNoArgs();

        given(mock(IMethods.class).objectReturningMethodNoArgs()).willReturn(null);
        given(mock(IMethods.class).objectReturningMethodNoArgs()).willReturn("a", 12L);
        given(mock(IMethods.class).objectReturningMethodNoArgs()).willReturn(1000);
        given(mock(IMethods.class).objectReturningMethodNoArgs())
                .willThrow(new NullPointerException());
        given(mock(IMethods.class).objectReturningMethodNoArgs())
                .willThrow(new NullPointerException(), new IllegalArgumentException());
        given(mock(IMethods.class).objectReturningMethodNoArgs())
                .willThrow(NullPointerException.class);

        given(mock(IMethods.class).objectReturningMethodNoArgs()).will(ignore()).willReturn(null);
        given(mock(IMethods.class).objectReturningMethodNoArgs())
                .will(ignore())
                .willReturn("a", 12L);
        given(mock(IMethods.class).objectReturningMethodNoArgs()).will(ignore()).willReturn(1000);
        given(mock(IMethods.class).objectReturningMethodNoArgs())
                .will(ignore())
                .willThrow(new NullPointerException());
        given(mock(IMethods.class).objectReturningMethodNoArgs())
                .will(ignore())
                .willThrow(new NullPointerException(), new IllegalArgumentException());
        given(mock(IMethods.class).objectReturningMethodNoArgs())
                .will(ignore())
                .willThrow(NullPointerException.class);
    }

    @Test
    @SuppressWarnings("unchecked")
    public void
            heap_pollution_JDK7plus_warning_avoided_BUT_now_unchecked_generic_array_creation_warnings_ON_JDK5plus_environment()
                    throws Exception {
        doThrow(NullPointerException.class, IllegalArgumentException.class)
                .when(mock(IMethods.class))
                .objectReturningMethodNoArgs();
        when(mock(IMethods.class).objectReturningMethodNoArgs())
                .thenThrow(NullPointerException.class, IllegalArgumentException.class);
        doAnswer(ignore())
                .doThrow(NullPointerException.class, IllegalArgumentException.class)
                .when(mock(IMethods.class))
                .objectReturningMethodNoArgs();

        willThrow(NullPointerException.class, IllegalArgumentException.class)
                .given(mock(IMethods.class))
                .objectReturningMethodNoArgs();
        given(mock(IMethods.class).objectReturningMethodNoArgs())
                .willThrow(NullPointerException.class, IllegalArgumentException.class);
        willAnswer(ignore())
                .willThrow(NullPointerException.class, IllegalArgumentException.class)
                .given(mock(IMethods.class))
                .objectReturningMethodNoArgs();
    }

    @Test
    public void unchecked_confusing_null_argument_warnings() throws Exception {
        doReturn(null, (Object[]) null).when(mock(IMethods.class)).objectReturningMethodNoArgs();
        doAnswer(ignore())
                .doReturn(null, (Object[]) null)
                .when(mock(IMethods.class))
                .objectReturningMethodNoArgs();
        when(mock(IMethods.class).objectReturningMethodNoArgs()).thenReturn(null, (Object[]) null);
        when(mock(IMethods.class).objectReturningMethodNoArgs())
                .then(ignore())
                .thenReturn(null, (Object[]) null);
        willReturn(null, (Object[]) null).given(mock(IMethods.class)).objectReturningMethodNoArgs();
        given(mock(IMethods.class).objectReturningMethodNoArgs()).willReturn(null, (Object[]) null);
        willAnswer(ignore())
                .willReturn(null, (Object[]) null)
                .given(mock(IMethods.class))
                .objectReturningMethodNoArgs();
        given(mock(IMethods.class).objectReturningMethodNoArgs())
                .will(ignore())
                .willReturn(null, (Object[]) null);
    }

    private static Answer<?> ignore() {
        return new Answer<Object>() {
            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                return null;
            }
        };
    }
}
