package org.datacite.mds.web.api.controller;

import static org.easymock.EasyMock.*;
import static org.junit.Assert.assertEquals;

import org.datacite.mds.service.DoiService;
import org.datacite.mds.validation.ValidationException;
import org.junit.Before;
import org.junit.Test;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockHttpServletRequest;

public class DoiApiControllerTest {
    
    DoiApiController doiApiController = new DoiApiController();
    DoiService mockDoiService;
    
    String doi = "10.5072/1111";
    String url = "http://example.com";

    @Before
    public void setUp() throws Exception {
        mockDoiService = createMock(DoiService.class);
        doiApiController.doiService = this.mockDoiService;
    }    

    @Test
    public void testCreateOrUpdatePost() throws Exception {
        expectDoiServiceCreate();
        HttpStatus statusCode = post(doi + "\n" + url, false);
        assertEquals(HttpStatus.CREATED, statusCode);
    }
    
    @Test
    public void testCreateOrUpdatePut() throws Exception {
        expectDoiServiceCreate();
        HttpStatus statusCode = post(doi + "\n" + url, false);
        assertEquals(HttpStatus.CREATED, statusCode);
        
        reset(mockDoiService);
        expectDoiServiceUpdate();
        statusCode = put(doi + "\n" + url, false);
	assertEquals(HttpStatus.OK, statusCode);
    }        
    
    @Test(expected = ValidationException.class)
    public void testCreateOrUpdateNonValid() throws Exception {
        post("", null);
    }
    
    @Test(expected = ValidationException.class)
    public void testCreateOrUpdateNonValid2() throws Exception {
        post("\n", null);
    }

    @Test(expected = ValidationException.class)
    public void testCreateOrUpdateNonValid2a() throws Exception {
        post("\n\n", null);
    }
    
    @Test(expected = ValidationException.class)
    public void testCreateOrUpdateNonValid3() throws Exception {
        post(doi + "\n", null);
    }

    @Test(expected = ValidationException.class)
    public void testCreateOrUpdateNonValid4() throws Exception {
        post("\n" + url, true);
    }
    
    private void expectDoiServiceCreate() throws Exception {
        expect(mockDoiService.create(eq(doi), eq(url), anyBoolean())).andStubReturn(null);
        replay(mockDoiService);
    }

    private void expectDoiServiceUpdate() throws Exception {
        expect(mockDoiService.update(eq(doi), eq(url), anyBoolean())).andStubReturn(null);
        replay(mockDoiService);
    }

    private HttpStatus post(String body, Boolean testMode) throws Exception {
        return request("POST", body, testMode);
    }
    
    private HttpStatus put(String body, Boolean testMode) throws Exception {
        return request("PUT", body, testMode);
    }
    
    private HttpStatus request(String method, String body, Boolean testMode) throws Exception {
        MockHttpServletRequest request = new MockHttpServletRequest();
        request.setMethod(method);
        ResponseEntity<? extends Object> response = doiApiController.createOrUpdate(body, testMode, request);
        verify(mockDoiService);
        return response.getStatusCode();
    }
}

@@ -1038,36 +1038,516 @@
 tusCode);%0A    %7D%0A
+%0A
     
+@Test%0A    public void testCreateOrUpdatePostCRLF() throws Exception %7B%0A        expectDoiServiceCreate();%0A        HttpStatus statusCode = post(doi + %22%5Cr%5Cn%22 + url, false);%0A        assertEquals(HttpStatus.CREATED, statusCode);%0A    %7D%0A%0A    @Test%0A    public void testCreateOrUpdatePostTrailingNewLine() throws Exception %7B%0A        expectDoiServiceCreate();%0A        HttpStatus statusCode = post(doi + %22%5Cn%22 + url + %22%5Cn%22, false);%0A        assertEquals(HttpStatus.CREATED, statusCode);%0A    %7D%0A
 %0A    @Test%0A    p
@@ -2019,24 +2019,25 @@
 OrUpdate
-NonValid
+EmptyBody
 () throw
@@ -2167,25 +2167,27 @@
 OrUpdate
-NonValid2
+EmptyLines1
 () throw
@@ -2319,18 +2319,19 @@
 date
-NonValid2a
+EmptyLines2
 () t
@@ -2473,17 +2473,16 @@
 date
-NonValid3
+EmptyUrl
 () t
@@ -2624,17 +2624,180 @@
 date
-NonValid4
+EmptyDoi() throws Exception %7B%0A        post(%22%5Cn%22 + url, true);%0A    %7D%0A%0A    @Test(expected = ValidationException.class)%0A    public void testCreateOrUpdateIntermediateEmptyLine
 () t
@@ -2819,33 +2819,41 @@
  %7B%0A        post(
-%22
+doi + %22%5Cn
 %5Cn%22 + url, true)
@@ -2852,36 +2852,403 @@
 l, true);%0A    %7D%0A
+%0A
     
+@Test(expected = ValidationException.class)%0A    public void testCreateOrUpdateBodyWithManyTrailingNewlines() throws Exception %7B%0A        post(doi + %22%5Cn%22 + url + %22%5Cn%5Cn%22, true);%0A    %7D%0A%0A    @Test(expected = ValidationException.class)%0A    public void testCreateOrUpdateBodyWithThreeLines() throws Exception %7B%0A        post(doi + %22%5Cn%22 + url + %22%5Cn%22 + %22foobar%22, true);%0A    %7D%0A
 %0A    private voi
@@ -3388,40 +3388,8 @@
 l);%0A
-        replay(mockDoiService);%0A
     
@@ -3547,40 +3547,8 @@
 l);%0A
-        replay(mockDoiService);%0A
     
@@ -3910,32 +3910,64 @@
 ows Exception %7B%0A
+        replay(mockDoiService);%0A
         MockHttp

add some (failing) tests