org.cbioportal.session_service.SessionServiceTest.java Source code

Java tutorial

Introduction

Here is the source code for org.cbioportal.session_service.SessionServiceTest.java

Source

/*
 * Copyright (c) 2016 Memorial Sloan-Kettering Cancer Center.
 *
 * This library 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. The software and documentation provided hereunder
 * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no
 * obligations to provide maintenance, support, updates, enhancements or
 * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be
 * liable to any party for direct, indirect, special, incidental or
 * consequential damages, including lost profits, arising out of the use of this
 * software and its documentation, even if Memorial Sloan-Kettering Cancer
 * Center has been advised of the possibility of such damage.
 */

/*
 * This file is part of cBioPortal Session Service.
 *
 * cBioPortal is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License.
 *
 * 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.cbioportal.session_service;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;

import java.net.URL;

import org.junit.*;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.TestRestTemplate;
import org.springframework.http.*;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.web.client.RestTemplate;

import java.util.regex.Pattern;
import java.util.List;
import java.util.ArrayList;
import java.util.regex.Matcher;

/**
 * @author Manda Wilson 
 */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SessionService.class)
@WebAppConfiguration
// pick random port for testing
@IntegrationTest({ "server.port=0" })
// use application-test.properties config file
@ActiveProfiles("test")
public class SessionServiceTest {

    // get randomly assigned port
    @Value("${local.server.port}")
    private int port;

    private URL base;
    private RestTemplate template;

    @Before
    public void setUp() throws Exception {
        this.base = new URL("http://localhost:" + port + "/api/sessions/");
        template = new TestRestTemplate();
    }

    @After
    public void tearDown() throws Exception {
        // get all and delete them
        ResponseEntity<String> response = template.getForEntity(base.toString() + "msk_portal/main_session/",
                String.class);
        List<String> ids = parseIds(response.getBody());
        for (String id : ids) {
            template.delete(base.toString() + "msk_portal/main_session/" + id);
        }
    }

    @Test
    public void getSessionsNoData() throws Exception {
        ResponseEntity<String> response = template.getForEntity(base.toString() + "msk_portal/main_session/",
                String.class);
        assertThat(response.getBody(), equalTo("[]"));
        assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
    }

    @Test
    public void getSessionsData() throws Exception {
        // first add data
        String data = "\"portal-session\":\"my session information\"";
        ResponseEntity<String> response = addData("msk_portal", "main_session", data);

        // now test data is returned by GET /api/sessions/source/type/
        response = template.getForEntity(base.toString() + "msk_portal/main_session/", String.class);
        assertThat(expectedResponse(response.getBody(), "msk_portal", "main_session", data, true), equalTo(true));
        assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
    }

    @Test
    public void addSession() throws Exception {
        // add data
        String data = "\"portal-session\":\"my session information\"";
        ResponseEntity<String> response = addData("msk_portal", "main_session", data);

        // test that the status was 200 
        assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));

        // get id
        List<String> ids = parseIds(response.getBody());
        assertThat(ids.size(), equalTo(1));
        String id = ids.get(0);

        // get record
        response = template.getForEntity(base.toString() + "msk_portal/main_session/" + id, String.class);
        assertThat(expectedResponse(response.getBody(), "msk_portal", "main_session", data), equalTo(true));
    }

    @Test
    public void addSessionNoData() throws Exception {
        // add {} actually works TODO decide if it should
        String data = "";
        ResponseEntity<String> response = addData("msk_portal", "main_session", data);

        // test that we get an id back and that the status was 200 
        assertThat(response.getBody(), containsString("id"));
        assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));

        response = addData("msk_portal", "main_session", null);
        assertThat(response.getBody(), containsString("Required request body is missing"));
        assertThat(response.getStatusCode(), equalTo(HttpStatus.BAD_REQUEST));
    }

    @Test
    public void addSessionInvalidData() throws Exception {
        ResponseEntity<String> response = addData("msk_portal", "main_session",
                "\"portal-session\":blah blah blah");
        assertThat(response.getBody(),
                containsString("org.cbioportal.session_service.service.exception.SessionInvalidException"));
        assertThat(response.getStatusCode(), equalTo(HttpStatus.BAD_REQUEST));
    }

    @Test
    public void addSessionInvalidType() throws Exception {
        ResponseEntity<String> response = addData("msk_portal", "invalid_type",
                "\"portal-session\":\"blah blah blah\"");
        assertThat(response.getBody(), containsString("valid types are: 'main_session' and 'virtual_cohort'"));
        assertThat(response.getStatusCode(), equalTo(HttpStatus.BAD_REQUEST));
    }

    @Test
    public void addSessionUniqueness() throws Exception {
        // add data
        String data = "\"portal-session\":\"my session information\"";
        ResponseEntity<String> response = addData("msk_portal", "main_session", data);

        // test that the status was 200 
        assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));

        // get id
        List<String> ids = parseIds(response.getBody());
        assertThat(ids.size(), equalTo(1));
        String id = ids.get(0);

        // get record
        response = template.getForEntity(base.toString() + "msk_portal/main_session/" + id, String.class);
        assertThat(expectedResponse(response.getBody(), "msk_portal", "main_session", data), equalTo(true));

        // add same data to same source and type and confirm we get same id
        response = addData("msk_portal", "main_session", data);

        // get new id
        ids = parseIds(response.getBody());
        assertThat(ids.size(), equalTo(1));
        String newId = ids.get(0);

        // make sure we got the same id
        assertThat(newId, equalTo(id));

        // now test with a different source, and make sure we get a different id 
        response = addData("other_portal", "main_session", data);

        // get new id
        ids = parseIds(response.getBody());
        assertThat(ids.size(), equalTo(1));
        String differentId = ids.get(0);

        // make sure we got the same id
        assertThat(differentId, is(not(equalTo(id))));

        // confirm this is case sensitive
        response = addData("MSK_portal", "main_session", data);

        // get new id
        ids = parseIds(response.getBody());
        assertThat(ids.size(), equalTo(1));
        differentId = ids.get(0);

        // make sure we got a new id
        assertThat(differentId, is(not(equalTo(id))));

    }

    @Test
    public void getSession() throws Exception {
        // first add data
        String data = "\"portal-session\":{\"arg1\":\"first argument\"}";
        ResponseEntity<String> response = addData("msk_portal", "main_session", data);

        // get id
        List<String> ids = parseIds(response.getBody());
        assertThat(ids.size(), equalTo(1));
        String id = ids.get(0);

        // now test data is returned by GET /api/sessions/[ID]
        response = template.getForEntity(base.toString() + "msk_portal/main_session/" + id, String.class);
        assertThat(expectedResponse(response.getBody(), "msk_portal", "main_session", data), equalTo(true));
        assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
    }

    @Test
    public void getSessionInvalidId() throws Exception {
        ResponseEntity<String> response = template.getForEntity(base.toString() + "msk_portal/main_session/" + "id",
                String.class);
        assertThat(response.getBody(),
                containsString("org.cbioportal.session_service.service.exception.SessionNotFoundException"));
        assertThat(response.getStatusCode(), equalTo(HttpStatus.NOT_FOUND));
    }

    @Test
    public void getSessionWithQuery() throws Exception {
        // first add data
        String data = "\"portal-session\":{\"title\":\"my portal session\"}";
        ResponseEntity<String> response = addData("msk_portal", "main_session", data);

        // now query
        response = template.getForEntity(base.toString() + "msk_portal/main_session/"
                + "query?field=data.portal-session.title&value=my portal session", String.class);
        assertThat(expectedResponse(response.getBody(), "msk_portal", "main_session", data, true), equalTo(true));
        assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
    }

    @Test
    public void getSessionWithQueryNullCharacterInField() throws Exception {
        // first add data
        String data = "\"portal-session\":{\"title\":\"my portal session\"}";
        ResponseEntity<String> response = addData("msk_portal", "main_session", data);

        // now query
        response = template.getForEntity(base.toString() + "msk_portal/main_session/"
                + "query?field=data.p\0ortal-session.title&value=my portal session", String.class);
        assertThat(response.getBody(), containsString("Document field names can't have a NULL character"));
        assertThat(response.getStatusCode(), equalTo(HttpStatus.BAD_REQUEST));
    }

    @Test
    public void getSessionWithQueryFieldStartsWithDollarSign() throws Exception {
        // first add data
        String data = "\"portal-session\":{\"title\":\"my portal session\"}";
        ResponseEntity<String> response = addData("msk_portal", "main_session", data);

        // now query
        response = template.getForEntity(base.toString() + "msk_portal/main_session/"
                + "query?field=$data.portal-session.title&value=my portal session", String.class);
        assertThat(response.getBody(), containsString("Can't canonicalize query"));
        assertThat(response.getStatusCode(), equalTo(HttpStatus.BAD_REQUEST));
    }

    @Test
    public void updateSession() throws Exception {
        String data = "\"portal-session\":\"my session information\"";
        ResponseEntity<String> response = addData("msk_portal", "main_session", data);

        // get id
        List<String> ids = parseIds(response.getBody());
        assertThat(ids.size(), equalTo(1));
        String id = ids.get(0);

        // get record
        response = template.getForEntity(base.toString() + "msk_portal/main_session/" + id, String.class);
        assertThat(expectedResponse(response.getBody(), "msk_portal", "main_session", data), equalTo(true));

        // update record
        data = "\"portal-session\":\"my session UPDATED information\"";
        HttpEntity<String> entity = prepareData(data);
        response = template.exchange(base.toString() + "msk_portal/main_session/" + id, HttpMethod.PUT, entity,
                String.class);
        assertThat(response.getBody(), equalTo(null));

        // get updated record
        response = template.getForEntity(base.toString() + "msk_portal/main_session/" + id, String.class);
        assertThat(expectedResponse(response.getBody(), "msk_portal", "main_session", data), equalTo(true));
        assertThat(response.getBody(), containsString("UPDATED"));
        assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
    }

    @Test
    public void updateSessionInvalidData() throws Exception {
        String data = "\"portal-session\":{\"arg1\":\"first argument\"}";
        ResponseEntity<String> response = addData("msk_portal", "main_session", data);

        // get id
        List<String> ids = parseIds(response.getBody());
        assertThat(ids.size(), equalTo(1));
        String id = ids.get(0);

        HttpEntity<String> entity = prepareData("\"portal-session\":blah blah blah");
        response = template.exchange(base.toString() + "msk_portal/main_session/" + id, HttpMethod.PUT, entity,
                String.class);
        assertThat(response.getBody(),
                containsString("org.cbioportal.session_service.service.exception.SessionInvalidException"));
        assertThat(response.getStatusCode(), equalTo(HttpStatus.BAD_REQUEST));
    }

    @Test
    public void updateSessionInvalidId() throws Exception {
        HttpEntity<String> entity = prepareData("\"portal-session\":\"my session information\"");
        ResponseEntity<String> response = template.exchange(base.toString() + "msk_portal/main_session/id",
                HttpMethod.PUT, entity, String.class);
        assertThat(response.getBody(),
                containsString("org.cbioportal.session_service.service.exception.SessionNotFoundException"));
        assertThat(response.getStatusCode(), equalTo(HttpStatus.NOT_FOUND));
    }

    @Test
    public void updateSessionNoData() throws Exception {
        String data = "\"portal-session\":\"my session information\"";
        ResponseEntity<String> response = addData("msk_portal", "main_session", data);

        // get id
        List<String> ids = parseIds(response.getBody());
        assertThat(ids.size(), equalTo(1));
        String id = ids.get(0);

        HttpEntity<String> entity = prepareData(null);
        response = template.exchange(base.toString() + "msk_portal/main_session/" + id, HttpMethod.PUT, entity,
                String.class);

        assertThat(response.getBody(), containsString("Required request body is missing"));
        assertThat(response.getStatusCode(), equalTo(HttpStatus.BAD_REQUEST));
    }

    @Test
    public void deleteSession() throws Exception {
        // first add data
        String data = "\"portal-session\":{\"arg1\":\"first argument\"}";
        ResponseEntity<String> response = addData("msk_portal", "main_session", data);

        // get id
        List<String> ids = parseIds(response.getBody());
        assertThat(ids.size(), equalTo(1));
        String id = ids.get(0);

        // get record from database
        response = template.getForEntity(base.toString() + "msk_portal/main_session/" + id, String.class);
        assertThat(expectedResponse(response.getBody(), "msk_portal", "main_session", data), equalTo(true));

        // delete
        response = template.exchange(base.toString() + "msk_portal/main_session/" + id, HttpMethod.DELETE, null,
                String.class);
        assertThat(response.getBody(), equalTo(null));
        assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));

        // confirm record is gone
        response = template.getForEntity(base.toString() + "msk_portal/main_session/" + id, String.class);
        assertThat(response.getBody(),
                containsString("org.cbioportal.session_service.service.exception.SessionNotFoundException"));
        assertThat(response.getStatusCode(), equalTo(HttpStatus.NOT_FOUND));
    }

    @Test
    public void deleteSessionInvalidId() throws Exception {
        ResponseEntity<String> response = template.exchange(base.toString() + "msk_portal/main_session/id",
                HttpMethod.DELETE, null, String.class);
        assertThat(response.getBody(),
                containsString("org.cbioportal.session_service.service.exception.SessionNotFoundException"));
        assertThat(response.getStatusCode(), equalTo(HttpStatus.NOT_FOUND));
    }

    @Test
    public void deleteSessionValidIdWrongSource() throws Exception {
        // first add data
        String data = "\"portal-session\":{\"arg1\":\"first argument\"}";
        ResponseEntity<String> response = addData("msk_portal", "virtual_cohort", data);

        // get id
        List<String> ids = parseIds(response.getBody());
        assertThat(ids.size(), equalTo(1));
        String id = ids.get(0);

        // get record from database
        response = template.getForEntity(base.toString() + "msk_portal/virtual_cohort/" + id, String.class);
        assertThat(expectedResponse(response.getBody(), "msk_portal", "virtual_cohort", data), equalTo(true));

        // delete with different source
        response = template.exchange(base.toString() + "msk_portal/main_session/" + id, HttpMethod.DELETE, null,
                String.class);
        assertThat(response.getBody(), containsString("SessionNotFoundException"));
        assertThat(response.getStatusCode(), equalTo(HttpStatus.NOT_FOUND));

        // delete with correct source
        response = template.exchange(base.toString() + "msk_portal/virtual_cohort/" + id, HttpMethod.DELETE, null,
                String.class);
        assertThat(response.getBody(), equalTo(null));
        assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
    }

    private HttpEntity<String> prepareData(String data) throws Exception {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        if (data != null) {
            data = "{" + data + "}";
        }
        return new HttpEntity<String>(data, headers);
    }

    private ResponseEntity<String> addData(String source, String type, String data) throws Exception {
        HttpEntity<String> entity = prepareData(data);
        return template.exchange(base.toString() + source + "/" + type + "/", HttpMethod.POST, entity,
                String.class);
    }

    /*
     * plural is false.
     */
    private boolean expectedResponse(String responseBody, String source, String type, String data)
            throws Exception {
        return expectedResponse(responseBody, source, type, data, false);
    }

    private boolean expectedResponse(String responseBody, String source, String type, String data, boolean plural)
            throws Exception {
        // { and } are special characters in regexes, but also used in JSON so we need to escape them
        data = data.replaceAll("\\{", "\\\\{");
        data = data.replaceAll("\\}", "\\\\}");
        String pattern = "\\{\"id\":\"([^\"]+)\",\"data\":\\{" + data + "\\},\"source\":\"" + source
                + "\",\"type\":\"" + type + "\"\\}";
        if (plural) {
            pattern = "\\[" + pattern + "\\]";
        }
        pattern = "^" + pattern + "$";
        Pattern expectedResponsePattern = Pattern.compile(pattern);
        Matcher responseMatcher = expectedResponsePattern.matcher(responseBody);
        return responseMatcher.matches();
    }

    private List<String> parseIds(String json) throws Exception {
        Pattern idPattern = Pattern.compile("\"id\":\"([^\"]+)\"");
        Matcher idMatcher = idPattern.matcher(json);
        List<String> ids = new ArrayList<String>();
        while (idMatcher.find()) {
            ids.add(idMatcher.group(1));
        }
        return ids;
    }
};