org.cruk.genologics.api.GenologicsAPIBatchOperationTest.java Source code

Java tutorial

Introduction

Here is the source code for org.cruk.genologics.api.GenologicsAPIBatchOperationTest.java

Source

/*
 * CRUK-CI Genologics REST API Java Client.
 * Copyright (C) 2013 Cancer Research UK Cambridge Institute.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.cruk.genologics.api;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.output.NullOutputStream;
import org.easymock.EasyMock;
import org.junit.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.web.client.RestTemplate;

import com.genologics.ri.LimsLink;
import com.genologics.ri.Link;
import com.genologics.ri.Links;
import com.genologics.ri.artifact.Artifact;
import com.genologics.ri.artifact.ArtifactBatchFetchResult;
import com.genologics.ri.artifact.ArtifactLink;

@SuppressWarnings("deprecation")
public class GenologicsAPIBatchOperationTest {
    private ConfigurableApplicationContext appContext;

    private GenologicsAPI api;
    private RestTemplate restTemplate;
    private Jaxb2Marshaller marshaller;

    public GenologicsAPIBatchOperationTest() throws MalformedURLException {
        // Need a separate application context because of the mock HttpClients

        appContext = new ClassPathXmlApplicationContext("/org/cruk/genologics/api/genologics-client-context.xml");

        api = appContext.getBean("genologicsAPI", GenologicsAPI.class);
        restTemplate = appContext.getBean("genologicsRestTemplate", RestTemplate.class);
        marshaller = appContext.getBean("genologicsJaxbMarshaller", Jaxb2Marshaller.class);

        // Only needed as a mock.
        api.setServer(new URL("http://limsdev.cri.camres.org:8080"));
    }

    @Override
    protected void finalize() {
        appContext.close();
    }

    @Test
    public void testArtifactBatchDuplicate() throws Exception {
        List<LimsLink<Artifact>> links = new ArrayList<LimsLink<Artifact>>();

        links.add(new ArtifactLink(new URI("http://limsdev.cri.camres.org:8080/api/v2/artifacts/2-1000624")));
        links.add(new ArtifactLink(
                new URI("http://limsdev.cri.camres.org:8080/api/v2/artifacts/2-1000622?state=10101")));
        links.add(new ArtifactLink(
                new URI("http://limsdev.cri.camres.org:8080/api/v2/artifacts/2-1000622?state=10121")));

        ClientHttpRequestFactory mockFactory = EasyMock.createMock(ClientHttpRequestFactory.class);
        restTemplate.setRequestFactory(mockFactory);

        EasyMock.replay(mockFactory);

        try {
            api.loadAll(links);
            fail("Fetching many artifacts with duplicate links succeeded.");
        } catch (IllegalArgumentException e) {
            if (!e.getMessage().endsWith("appears in the collection more than once.")) {
                throw e;
            }
            // Otherwise what we expect.
        }

        EasyMock.verify(mockFactory);
    }

    @Test
    public void testArtifactBatchFetch() throws Exception {
        List<LimsLink<Artifact>> links = new ArrayList<LimsLink<Artifact>>();

        links.add(new ArtifactLink(new URI("http://limsdev.cri.camres.org:8080/api/v2/artifacts/2-1000624")));
        links.add(new ArtifactLink(new URI("http://limsdev.cri.camres.org:8080/api/v2/artifacts/2-1000622")));
        links.add(new ArtifactLink(new URI("http://limsdev.cri.camres.org:8080/api/v2/artifacts/2-1000605")));
        links.add(new ArtifactLink(new URI("http://limsdev.cri.camres.org:8080/api/v2/artifacts/2-1000623")));
        links.add(new ArtifactLink(new URI("http://limsdev.cri.camres.org:8080/api/v2/artifacts/2-1000625")));

        File expectedResultFile = new File("src/test/xml/batchtestreordering-artifacts.xml");
        String expectedReply = FileUtils.readFileToString(expectedResultFile);

        URI uri = new URI("http://limsdev.cri.camres.org:8080/api/v2/artifacts/batch/retrieve");

        // Note: need PushbackInputStream to prevent the call to getBody() being made more than once.
        // See MessageBodyClientHttpResponseWrapper.

        InputStream responseStream = new PushbackInputStream(new ByteArrayInputStream(expectedReply.getBytes()));

        HttpHeaders headers = new HttpHeaders();

        ClientHttpResponse httpResponse = EasyMock.createMock(ClientHttpResponse.class);
        EasyMock.expect(httpResponse.getStatusCode()).andReturn(HttpStatus.OK).anyTimes();
        EasyMock.expect(httpResponse.getRawStatusCode()).andReturn(HttpStatus.OK.value()).anyTimes();
        EasyMock.expect(httpResponse.getHeaders()).andReturn(headers).anyTimes();
        EasyMock.expect(httpResponse.getBody()).andReturn(responseStream).once();
        httpResponse.close();
        EasyMock.expectLastCall().once();

        ClientHttpRequest httpRequest = EasyMock.createMock(ClientHttpRequest.class);
        EasyMock.expect(httpRequest.getHeaders()).andReturn(headers).anyTimes();
        EasyMock.expect(httpRequest.getBody()).andReturn(new NullOutputStream()).times(0, 2);
        EasyMock.expect(httpRequest.execute()).andReturn(httpResponse).once();

        ClientHttpRequestFactory mockFactory = EasyMock.createStrictMock(ClientHttpRequestFactory.class);
        EasyMock.expect(mockFactory.createRequest(uri, HttpMethod.POST)).andReturn(httpRequest).once();

        restTemplate.setRequestFactory(mockFactory);

        EasyMock.replay(httpResponse, httpRequest, mockFactory);

        List<Artifact> artifacts = api.loadAll(links);

        assertEquals("Wrong number of artifacts", links.size(), artifacts.size());

        for (int i = 0; i < links.size(); i++) {
            assertTrue("Artifact " + i + " wrong: " + artifacts.get(i).getUri(),
                    artifacts.get(i).getUri().toString().startsWith(links.get(i).getUri().toString()));
        }

        EasyMock.verify(httpResponse, httpRequest, mockFactory);
    }

    @Test
    public void testArtifactBatchUpdate() throws Exception {
        File expectedResultFile = new File("src/test/xml/batchtestreordering-artifacts.xml");
        String expectedReply = FileUtils.readFileToString(expectedResultFile);

        ArtifactBatchFetchResult updateArtifactsFetch = (ArtifactBatchFetchResult) marshaller
                .unmarshal(new StreamSource(expectedResultFile));

        List<Artifact> artifacts = updateArtifactsFetch.getArtifacts();

        // Rearrange these to a different order to that in the file.
        // This means the original XML file loaded above will return in an order
        // not matching either the Links object (below) or the original order
        // of the artifacts.
        Collections.shuffle(artifacts, new Random(997));

        // Copy the URI order as it is now to make sure it doesn't differ
        // after updating the artifacts.
        List<URI> uriOrder = new ArrayList<URI>();

        Links confirmLinks = new Links();
        for (Artifact a : artifacts) {
            uriOrder.add(a.getUri());
            confirmLinks.getLinks().add(new Link(a));
        }

        // The Links object that (would) come back should be in a different order.
        Collections.shuffle(confirmLinks.getLinks(), new Random(1024));

        StringWriter linksXML = new StringWriter();
        marshaller.marshal(confirmLinks, new StreamResult(linksXML));

        // Two calls to make here.

        URI updateUri = new URI("http://limsdev.cri.camres.org:8080/api/v2/artifacts/batch/update");
        URI retrieveUri = new URI("http://limsdev.cri.camres.org:8080/api/v2/artifacts/batch/retrieve");

        // Note: need PushbackInputStream to prevent the call to getBody() being made more than once.
        // See MessageBodyClientHttpResponseWrapper.

        InputStream response1Stream = new PushbackInputStream(
                new ByteArrayInputStream(linksXML.toString().getBytes()));
        InputStream response2Stream = new PushbackInputStream(new ByteArrayInputStream(expectedReply.getBytes()));

        HttpHeaders headers = new HttpHeaders();

        ClientHttpResponse httpResponse1 = EasyMock.createMock(ClientHttpResponse.class);
        EasyMock.expect(httpResponse1.getStatusCode()).andReturn(HttpStatus.OK).anyTimes();
        EasyMock.expect(httpResponse1.getRawStatusCode()).andReturn(HttpStatus.OK.value()).anyTimes();
        EasyMock.expect(httpResponse1.getHeaders()).andReturn(headers).anyTimes();
        EasyMock.expect(httpResponse1.getBody()).andReturn(response1Stream).once();
        httpResponse1.close();
        EasyMock.expectLastCall().once();

        ClientHttpRequest httpRequest1 = EasyMock.createMock(ClientHttpRequest.class);
        EasyMock.expect(httpRequest1.getHeaders()).andReturn(headers).anyTimes();
        EasyMock.expect(httpRequest1.getBody()).andReturn(new NullOutputStream()).times(0, 2);
        EasyMock.expect(httpRequest1.execute()).andReturn(httpResponse1).once();

        ClientHttpResponse httpResponse2 = EasyMock.createMock(ClientHttpResponse.class);
        EasyMock.expect(httpResponse2.getStatusCode()).andReturn(HttpStatus.OK).anyTimes();
        EasyMock.expect(httpResponse2.getRawStatusCode()).andReturn(HttpStatus.OK.value()).anyTimes();
        EasyMock.expect(httpResponse2.getHeaders()).andReturn(headers).anyTimes();
        EasyMock.expect(httpResponse2.getBody()).andReturn(response2Stream).once();
        httpResponse2.close();
        EasyMock.expectLastCall().once();

        ClientHttpRequest httpRequest2 = EasyMock.createMock(ClientHttpRequest.class);
        EasyMock.expect(httpRequest2.getHeaders()).andReturn(headers).anyTimes();
        EasyMock.expect(httpRequest2.getBody()).andReturn(new NullOutputStream()).times(0, 2);
        EasyMock.expect(httpRequest2.execute()).andReturn(httpResponse2).once();

        ClientHttpRequestFactory mockFactory = EasyMock.createStrictMock(ClientHttpRequestFactory.class);
        EasyMock.expect(mockFactory.createRequest(updateUri, HttpMethod.POST)).andReturn(httpRequest1).once();
        EasyMock.expect(mockFactory.createRequest(retrieveUri, HttpMethod.POST)).andReturn(httpRequest2).once();

        restTemplate.setRequestFactory(mockFactory);

        EasyMock.replay(httpResponse1, httpRequest1, httpResponse2, httpRequest2, mockFactory);

        api.updateAll(artifacts);

        assertEquals("Wrong number of artifacts", uriOrder.size(), artifacts.size());

        for (int i = 0; i < uriOrder.size(); i++) {
            assertEquals("Artifact " + i + " wrong:", uriOrder.get(i), artifacts.get(i).getUri());
        }

        EasyMock.verify(httpResponse2, httpRequest2, mockFactory);
    }
}