package net.kencochrane.raven.connection;

import mockit.Injectable;
import mockit.Mock;
import mockit.MockUp;
import net.kencochrane.raven.Raven;
import net.kencochrane.raven.event.Event;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.io.IOException;
import java.util.concurrent.locks.ReentrantLock;

import static mockit.Deencapsulation.setField;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.verify;

public class AbstractConnectionTest {
    private final String publicKey = "9bcf4a8c-f353-4f25-9dda-76a873fff905";
    private final String secretKey = "56a9d05e-9032-4fdd-8f67-867d526422f9";
    private AbstractConnection abstractConnection;
    //Spying with mockito as jMockit doesn't support mocks of ReentrantLock
    @Spy
    private ReentrantLock reentrantLock = new ReentrantLock();

    @BeforeMethod
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        setField(Raven.class, "NAME", "Raven-Java/Test");
        abstractConnection = new DummyAbstractConnection(publicKey, secretKey);
        setField(abstractConnection, "lock", reentrantLock);
    }

    @Test
    public void testAuthHeader() throws Exception {
        String authHeader = abstractConnection.getAuthHeader();

        assertThat(authHeader, is("Sentry sentry_version=5,"
                + "sentry_client=Raven-Java/Test,"
                + "sentry_key=" + publicKey + ","
                + "sentry_secret=" + secretKey));
    }

    @Test
    public void testSuccessfulSendCallsDoSend(@Injectable final Event mockEvent) throws Exception {
        new MockUp<DummyAbstractConnection>() {
            @SuppressWarnings("unused")
            @Mock(invocations = 1)
            protected void doSend(Event event) throws ConnectionException {
            }
        };

        abstractConnection.send(mockEvent);
    }

    @Test
    public void testExceptionOnSendStartLockDown(@Injectable final Event mockEvent) throws Exception {
        new MockUp<DummyAbstractConnection>() {
            @SuppressWarnings("unused")
            @Mock
            protected void doSend(Event event) throws ConnectionException {
                throw new ConnectionException();
            }
        };

        abstractConnection.send(mockEvent);

        verify(reentrantLock).tryLock();
        verify(reentrantLock).unlock();
    }

    private static final class DummyAbstractConnection extends AbstractConnection {
        public DummyAbstractConnection(String publicKey, String secretKey) {
            super(publicKey, secretKey);
        }

        @Override
        protected void doSend(Event event) throws ConnectionException {
        }

        @Override
        public void close() throws IOException {
        }
    }
}

@@ -80,34 +80,80 @@
 kit.
-Mock;%0Aimport mockit.MockUp
+NonStrictExpectations;%0Aimport mockit.Tested;%0Aimport mockit.Verifications
 ;%0Aim
@@ -376,36 +376,8 @@
 t;%0A%0A
-import java.io.IOException;%0A
 impo
@@ -643,16 +643,32 @@
 nTest %7B%0A
+    @Injectable%0A
     priv
@@ -736,16 +736,32 @@
 ff905%22;%0A
+    @Injectable%0A
     priv
@@ -829,16 +829,28 @@
 422f9%22;%0A
+    @Tested%0A
     priv
@@ -1208,149 +1208,8 @@
 %22);%0A
-        abstractConnection = new DummyAbstractConnection(publicKey, secretKey);%0A        setField(abstractConnection, %22lock%22, reentrantLock);%0A
     
@@ -1679,197 +1679,136 @@
     
-new MockUp%3CDummyAbstractConnection%3E() %7B%0A            @SuppressWarnings(%22unused%22)%0A            @Mock(invocations = 1)%0A            protected void doSend(Event event) throws ConnectionException 
+setField(abstractConnection, %22lock%22, reentrantLock);%0A%0A        abstractConnection.send(mockEvent);%0A%0A        new Verifications() %7B
 %7B%0A  
@@ -1816,35 +1816,13 @@
     
- 
-    %7D%0A        %7D;%0A%0A
      
-   
 abst
@@ -1828,33 +1828,35 @@
 tractConnection.
-s
+doS
 end(mockEvent);%0A
@@ -1855,16 +1855,28 @@
 Event);%0A
+        %7D%7D;%0A
     %7D%0A%0A 
@@ -1999,181 +1999,151 @@
     
-new MockUp%3CDummyAbstractConnection%3E() %7B%0A            @SuppressWarnings(%22unused%22)%0A            @Mock%0A            protected void 
+setField(abstractConnection, %22lock%22, reentrantLock);%0A        new NonStrictExpectations() %7B%7B%0A            abstractConnection.
 doSend(
+(
 Event
- event) throws ConnectionException %7B
+) any);
 %0A   
@@ -2155,17 +2155,16 @@
     
-    throw
+result =
  new
@@ -2199,22 +2199,9 @@
     
- 
-   %7D%0A        
+%7D
 %7D;%0A%0A
@@ -2335,405 +2335,7 @@
    %7D
-%0A%0A    private static final class DummyAbstractConnection extends AbstractConnection %7B%0A        public DummyAbstractConnection(String publicKey, String secretKey) %7B%0A            super(publicKey, secretKey);%0A        %7D%0A%0A        @Override%0A        protected void doSend(Event event) throws ConnectionException %7B%0A        %7D%0A%0A        @Override%0A        public void close() throws IOException %7B%0A        %7D%0A    %7D
 %0A%7D%0A

Use Tested rather than creating dummy implementations