org.phenotips.data.indexing.internal.SolrPatientIndexerTest.java Source code

Java tutorial

Introduction

Here is the source code for org.phenotips.data.indexing.internal.SolrPatientIndexerTest.java

Source

/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program 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, 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 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.phenotips.data.indexing.internal;

import org.phenotips.data.Feature;
import org.phenotips.data.IndexedPatientData;
import org.phenotips.data.Patient;
import org.phenotips.data.PatientData;
import org.phenotips.data.PatientRepository;
import org.phenotips.data.indexing.PatientIndexer;
import org.phenotips.data.permissions.PatientAccess;
import org.phenotips.data.permissions.PermissionsManager;
import org.phenotips.data.permissions.Visibility;
import org.phenotips.data.permissions.internal.DefaultPatientAccess;
import org.phenotips.data.permissions.internal.visibility.PublicVisibility;
import org.phenotips.vocabulary.SolrCoreContainerHandler;
import org.phenotips.vocabulary.Vocabulary;
import org.phenotips.vocabulary.VocabularyTerm;

import org.xwiki.component.manager.ComponentLookupException;
import org.xwiki.component.util.ReflectionUtils;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.query.Query;
import org.xwiki.query.QueryException;
import org.xwiki.query.QueryManager;
import org.xwiki.test.mockito.MockitoComponentMockingRule;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.apache.solr.client.solrj.util.ClientUtils;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.core.CoreContainer;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.internal.matchers.CapturingMatcher;
import org.slf4j.Logger;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class SolrPatientIndexerTest {

    @Rule
    public MockitoComponentMockingRule<PatientIndexer> mocker = new MockitoComponentMockingRule<PatientIndexer>(
            SolrPatientIndexer.class);

    @Mock
    private Patient patient;

    @Mock
    private SolrClient server;

    private PatientIndexer patientIndexer;

    private Logger logger;

    private QueryManager qm;

    private PatientRepository patientRepository;

    private PermissionsManager permissions;

    private DocumentReference patientDocReference;

    @Before
    public void setUp() throws ComponentLookupException {

        MockitoAnnotations.initMocks(this);

        SolrCoreContainerHandler cores = this.mocker.getInstance(SolrCoreContainerHandler.class);
        doReturn(mock(CoreContainer.class)).when(cores).getContainer();

        this.permissions = this.mocker.getInstance(PermissionsManager.class);
        this.qm = this.mocker.getInstance(QueryManager.class);
        this.patientRepository = this.mocker.getInstance(PatientRepository.class);
        this.patientDocReference = new DocumentReference("wiki", "patient", "P0000001");
        this.patientIndexer = this.mocker.getComponentUnderTest();
        this.logger = this.mocker.getMockedLogger();

        ReflectionUtils.setFieldValue(this.patientIndexer, "server", this.server);
    }

    @Before
    public void setupVocabulary() throws ComponentLookupException {
        // Setup the vocabulary
        Vocabulary hpo = this.mocker.getInstance(Vocabulary.class, "hpo");

        // Setup mock term
        String[] ancestorIds = { "HP:0011842", "HP:0000924", "HP:0000118", "HP:0000001" };
        Set<VocabularyTerm> ancestors = new HashSet<VocabularyTerm>();
        for (String id : ancestorIds) {
            VocabularyTerm ancestor = mock(VocabularyTerm.class);
            when(ancestor.getId()).thenReturn(id);
            ancestors.add(ancestor);
        }
        VocabularyTerm term = mock(VocabularyTerm.class);
        when(term.getId()).thenReturn("HP:0001367");
        ancestors.add(term);

        when(term.getAncestorsAndSelf()).thenReturn(ancestors);
        when(hpo.getTerm(term.getId())).thenReturn(term);
    }

    @Test
    public void indexDefaultPhenotypeBehaviourTest() throws IOException, SolrServerException {
        Set<Feature> patientFeatures = new HashSet<>();
        Feature testFeature = mock(Feature.class);
        doReturn(true).when(testFeature).isPresent();
        doReturn("phenotype").when(testFeature).getType();
        doReturn("HP:0001367").when(testFeature).getId();
        patientFeatures.add(testFeature);
        Feature negativeTestFeature = mock(Feature.class);
        doReturn(false).when(negativeTestFeature).isPresent();
        doReturn("phenotype").when(negativeTestFeature).getType();
        doReturn("id2").when(negativeTestFeature).getId();
        patientFeatures.add(negativeTestFeature);
        doReturn(patientFeatures).when(this.patient).getFeatures();

        DocumentReference reporterReference = new DocumentReference("xwiki", "XWiki", "user");
        PatientAccess patientAccess = mock(DefaultPatientAccess.class);
        Visibility patientVisibility = new PublicVisibility();

        CapturingMatcher<SolrInputDocument> capturedArgument = new CapturingMatcher<>();
        when(this.server.add(argThat(capturedArgument))).thenReturn(mock(UpdateResponse.class));

        doReturn(this.patientDocReference).when(this.patient).getDocument();
        doReturn(reporterReference).when(this.patient).getReporter();
        doReturn(patientAccess).when(this.permissions).getPatientAccess(this.patient);
        doReturn(patientVisibility).when(patientAccess).getVisibility();

        this.patientIndexer.index(this.patient);

        SolrInputDocument inputDoc = capturedArgument.getLastValue();
        verify(this.server).add(inputDoc);
        Assert.assertEquals("public", inputDoc.getFieldValue("visibility"));
        Assert.assertEquals("HP:0001367", inputDoc.getFieldValue("phenotype"));
        Assert.assertEquals("id2", inputDoc.getFieldValue("negative_phenotype"));
        Assert.assertEquals(5, inputDoc.getFieldValues("extended_phenotype").size());
    }

    @Test
    public void indexDefaultGeneBehaviourTest() throws IOException, SolrServerException {
        Set<Feature> patientFeatures = new HashSet<>();
        Feature testFeature = mock(Feature.class);
        patientFeatures.add(testFeature);
        DocumentReference reporterReference = new DocumentReference("xwiki", "XWiki", "user");
        PatientAccess patientAccess = mock(DefaultPatientAccess.class);
        Visibility patientVisibility = new PublicVisibility();

        CapturingMatcher<SolrInputDocument> capturedArgument = new CapturingMatcher<>();
        when(this.server.add(argThat(capturedArgument))).thenReturn(mock(UpdateResponse.class));

        doReturn(patientDocReference).when(this.patient).getDocument();
        doReturn(reporterReference).when(this.patient).getReporter();

        doReturn(Collections.EMPTY_SET).when(this.patient).getFeatures();

        List<Map<String, String>> fakeGenes = new ArrayList<Map<String, String>>();
        Map<String, String> fakeGene = new HashMap<String, String>();
        fakeGene.put("gene", "CANDIDATE1");
        fakeGenes.add(fakeGene);
        fakeGene = new HashMap<String, String>();
        fakeGene.put("gene", "CANDIDATE2");
        fakeGene.put("status", "candidate");
        fakeGenes.add(fakeGene);
        fakeGene = new HashMap<String, String>();
        fakeGene.put("gene", "REJECTED1");
        fakeGene.put("status", "rejected");
        fakeGenes.add(fakeGene);
        fakeGene = new HashMap<String, String>();
        fakeGene.put("gene", "SOLVED1");
        fakeGene.put("status", "solved");
        fakeGenes.add(fakeGene);
        fakeGene = new HashMap<String, String>();
        fakeGene.put("gene", "");
        fakeGene.put("status", "candidate");
        fakeGenes.add(fakeGene);

        PatientData<Map<String, String>> fakeGeneData = new IndexedPatientData<Map<String, String>>("genes",
                fakeGenes);
        doReturn(fakeGeneData).when(this.patient).getData("genes");

        doReturn(patientAccess).when(this.permissions).getPatientAccess(this.patient);
        doReturn(patientVisibility).when(patientAccess).getVisibility();

        this.patientIndexer.index(this.patient);
        SolrInputDocument inputDoc = capturedArgument.getLastValue();
        verify(this.server).add(inputDoc);

        Collection<Object> indexedGenes;
        indexedGenes = inputDoc.getFieldValues("candidate_genes");
        Assert.assertEquals(2, indexedGenes.size());
        for (Object s : indexedGenes) {
            Assert.assertTrue(((String) s).startsWith("CANDIDATE"));
        }

        indexedGenes = inputDoc.getFieldValues("solved_genes");
        Assert.assertEquals(1, indexedGenes.size());
        Assert.assertEquals("SOLVED1", indexedGenes.iterator().next());

        indexedGenes = inputDoc.getFieldValues("rejected_genes");
        Assert.assertEquals(1, indexedGenes.size());
        Assert.assertEquals("REJECTED1", indexedGenes.iterator().next());
    }

    @Test
    public void indexThrowsSolrException() throws IOException, SolrServerException {
        Set<Feature> patientFeatures = new HashSet<>();
        Feature testFeature = mock(Feature.class);
        patientFeatures.add(testFeature);
        DocumentReference reporterReference = new DocumentReference("xwiki", "XWiki", "user");
        PatientAccess patientAccess = mock(DefaultPatientAccess.class);
        Visibility patientVisibility = new PublicVisibility();

        doReturn(this.patientDocReference).when(this.patient).getDocument();
        doReturn(reporterReference).when(this.patient).getReporter();

        doReturn(patientFeatures).when(this.patient).getFeatures();
        doReturn(true).when(testFeature).isPresent();
        doReturn("phenotype").when(testFeature).getType();
        doReturn("id").when(testFeature).getId();

        doReturn(patientAccess).when(this.permissions).getPatientAccess(this.patient);
        doReturn(patientVisibility).when(patientAccess).getVisibility();
        doThrow(new SolrServerException("Error while adding SolrInputDocument")).when(this.server)
                .add(any(SolrInputDocument.class));

        this.patientIndexer.index(this.patient);

        verify(this.logger).warn("Failed to perform Solr search: {}", "Error while adding SolrInputDocument");
    }

    @Test
    public void indexThrowsIOException() throws IOException, SolrServerException {
        Set<Feature> patientFeatures = new HashSet<>();
        Feature testFeature = mock(Feature.class);
        patientFeatures.add(testFeature);
        DocumentReference reporterReference = new DocumentReference("xwiki", "XWiki", "user");
        PatientAccess patientAccess = mock(DefaultPatientAccess.class);
        Visibility patientVisibility = new PublicVisibility();

        doReturn(this.patientDocReference).when(this.patient).getDocument();
        doReturn(reporterReference).when(this.patient).getReporter();

        doReturn(patientFeatures).when(this.patient).getFeatures();
        doReturn(true).when(testFeature).isPresent();
        doReturn("phenotype").when(testFeature).getType();
        doReturn("id").when(testFeature).getId();

        doReturn(patientAccess).when(this.permissions).getPatientAccess(this.patient);
        doReturn(patientVisibility).when(patientAccess).getVisibility();
        doThrow(new IOException("Error while adding SolrInputDocument")).when(this.server)
                .add(any(SolrInputDocument.class));

        this.patientIndexer.index(this.patient);

        verify(this.logger).warn("Error occurred while performing Solr search: {}",
                "Error while adding SolrInputDocument");
    }

    @Test
    public void indexGetReporterIsNull() throws IOException, SolrServerException {
        Set<Feature> patientFeatures = new HashSet<>();
        Feature testFeature = mock(Feature.class);
        patientFeatures.add(testFeature);
        PatientAccess patientAccess = mock(DefaultPatientAccess.class);
        Visibility patientVisibility = new PublicVisibility();

        CapturingMatcher<SolrInputDocument> capturedArgument = new CapturingMatcher<>();
        when(this.server.add(argThat(capturedArgument))).thenReturn(mock(UpdateResponse.class));

        doReturn(this.patientDocReference).when(this.patient).getDocument();
        doReturn(null).when(this.patient).getReporter();

        doReturn(patientFeatures).when(this.patient).getFeatures();
        doReturn(true).when(testFeature).isPresent();
        doReturn("phenotype").when(testFeature).getType();
        doReturn("id").when(testFeature).getId();

        doReturn(patientAccess).when(this.permissions).getPatientAccess(this.patient);
        doReturn(patientVisibility).when(patientAccess).getVisibility();

        this.patientIndexer.index(this.patient);
        SolrInputDocument inputDoc = capturedArgument.getLastValue();
        verify(this.server).add(inputDoc);
        Assert.assertEquals(inputDoc.getFieldValue("reporter"), "");
    }

    @Test
    public void deleteDefaultBehaviourTest() throws IOException, SolrServerException {
        doReturn(this.patientDocReference).when(this.patient).getDocument();
        this.patientIndexer.delete(this.patient);
        verify(this.server)
                .deleteByQuery("document:" + ClientUtils.escapeQueryChars(this.patientDocReference.toString()));
        verify(this.server).commit();
    }

    @Test
    public void deleteThrowsSolrException() throws IOException, SolrServerException {
        doReturn(this.patientDocReference).when(this.patient).getDocument();
        doThrow(new SolrServerException("commit failed")).when(this.server).commit();
        this.patientIndexer.delete(this.patient);
        verify(this.logger).warn("Failed to delete from Solr: {}", "commit failed");
    }

    @Test
    public void deleteThrowsIOException() throws IOException, SolrServerException {
        doReturn(this.patientDocReference).when(this.patient).getDocument();
        doThrow(new IOException("commit failed")).when(this.server).commit();
        this.patientIndexer.delete(this.patient);
        verify(this.logger).warn("Error occurred while deleting Solr documents: {}", "commit failed");
    }

    @Test
    public void reindexDefaultBehaviour() throws QueryException, IOException, SolrServerException {
        List<String> patientDocs = new ArrayList<>();
        patientDocs.add("P0000001");

        Query testQuery = mock(Query.class);
        doReturn(testQuery).when(this.qm).createQuery("from doc.object(PhenoTips.PatientClass) as patient",
                Query.XWQL);
        doReturn(patientDocs).when(testQuery).execute();
        doReturn(this.patient).when(this.patientRepository).getPatientById("P0000001");

        Set<Feature> patientFeatures = new HashSet<>();
        Feature testFeature = mock(Feature.class);
        patientFeatures.add(testFeature);
        DocumentReference reporterReference = new DocumentReference("xwiki", "XWiki", "user");
        PatientAccess patientAccess = mock(DefaultPatientAccess.class);
        Visibility patientVisibility = new PublicVisibility();

        doReturn(this.patientDocReference).when(this.patient).getDocument();
        doReturn(reporterReference).when(this.patient).getReporter();

        doReturn(patientFeatures).when(this.patient).getFeatures();
        doReturn(true).when(testFeature).isPresent();
        doReturn("phenotype").when(testFeature).getType();
        doReturn("id").when(testFeature).getId();

        doReturn(patientAccess).when(this.permissions).getPatientAccess(this.patient);
        doReturn(patientVisibility).when(patientAccess).getVisibility();

        this.patientIndexer.reindex();

        verify(this.server).deleteByQuery("*:*");
        verify(this.server).commit();

    }

    @Test
    public void reindexSolrServerException() throws QueryException, IOException, SolrServerException {
        List<String> patientDocs = new ArrayList<>();
        patientDocs.add("P0000001");

        Query testQuery = mock(Query.class);
        doReturn(testQuery).when(this.qm).createQuery("from doc.object(PhenoTips.PatientClass) as patient",
                Query.XWQL);
        doReturn(patientDocs).when(testQuery).execute();

        doThrow(new SolrServerException("deleteByQuery failed")).when(this.server).deleteByQuery("*:*");

        this.patientIndexer.reindex();

        verify(this.logger).warn("Failed to reindex patients: {}", "deleteByQuery failed");
    }

    @Test
    public void reindexIOException() throws QueryException, IOException, SolrServerException {
        List<String> patientDocs = new ArrayList<>();
        patientDocs.add("P0000001");

        Query testQuery = mock(Query.class);
        doReturn(testQuery).when(this.qm).createQuery("from doc.object(PhenoTips.PatientClass) as patient",
                Query.XWQL);
        doReturn(patientDocs).when(testQuery).execute();

        doThrow(new IOException("deleteByQuery failed")).when(this.server).deleteByQuery("*:*");

        this.patientIndexer.reindex();

        verify(this.logger).warn("Error occurred while reindexing patients: {}", "deleteByQuery failed");
    }

    @Test
    public void reindexQueryException() throws QueryException, IOException, SolrServerException {
        doThrow(new QueryException("createQuery failed", null, null)).when(this.qm)
                .createQuery("from doc.object(PhenoTips.PatientClass) as patient", Query.XWQL);

        this.patientIndexer.reindex();

        verify(this.logger).warn("Failed to search patients for reindexing: {}", "createQuery failed");

    }
}