package com.constellio.data.dao.services.bigVault.solr; import static com.constellio.data.dao.dto.records.RecordsFlushing.LATER; import static com.constellio.data.dao.dto.records.RecordsFlushing.NOW; import static com.constellio.data.dao.dto.records.RecordsFlushing.WITHIN_MILLISECONDS; import static com.constellio.data.dao.dto.records.RecordsFlushing.WITHIN_SECONDS; import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.IOException; import java.util.Arrays; import java.util.List; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.CloudSolrClient.RouteException; import org.apache.solr.client.solrj.impl.HttpSolrClient.RemoteSolrException; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.params.SolrParams; import org.junit.Before; import org.junit.Test; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.Mockito; import com.constellio.data.dao.services.bigVault.solr.BigVaultException.CouldNotExecuteQuery; import com.constellio.data.dao.services.bigVault.solr.BigVaultException.OptimisticLocking; import com.constellio.data.dao.services.bigVault.solr.BigVaultRuntimeException.BadRequest; import com.constellio.data.dao.services.solr.SolrServerFactory; import com.constellio.data.extensions.DataLayerSystemExtensions; import com.constellio.data.io.concurrent.filesystem.AtomicFileSystem; import com.constellio.sdk.tests.ConstellioTest; public class BigVaultServerUnitTest extends ConstellioTest { @Mock DataLayerSystemExtensions extensions; @Mock AtomicFileSystem solrFileSystem; @Mock SolrParams solrParams; @Mock SolrClient server; @Mock SolrServerFactory solrServerFactory; @Mock SolrInputDocument doc1, doc2, doc3, doc4, doc5, doc6, doc7, doc8, doc9, doc10, doc11; @Mock List<String> deletedDocs1, deletedDocs2, deletedDocs3, deleteQueriesStrings; @Mock List<SolrInputDocument> addedDocs, modifiedDocs; @Mock List<SolrParams> deleteQueries; BigVaultServer bigVaultServer; @Mock QueryResponse theQueryResponse; @Mock SolrDocumentList theQueryResults; @Mock SolrDocumentList emptyQueryResults; @Mock SolrDocumentList twoElementsQueryResults; @Mock SolrDocument theUniqueResult; @Before public void setUp() { String serverName = "Test"; when(solrServerFactory.getConfigFileSystem(serverName)).thenReturn(solrFileSystem); when(solrServerFactory.newSolrServer(serverName)).thenReturn(server); bigVaultServer = spy(new BigVaultServer(serverName, BigVaultLogger.disabled(), solrServerFactory, extensions)); when(emptyQueryResults.size()).thenReturn(0); when(twoElementsQueryResults.size()).thenReturn(2); } @Test public void whenAddThenCommitEveryDoc() throws Exception { doReturn(null).when(bigVaultServer).add(any(BigVaultServerTransaction.class)); List<SolrInputDocument> transaction1NewDocs = Arrays.asList(doc1); List<SolrInputDocument> transaction1UpdatedDocs = Arrays.asList(doc2); List<SolrInputDocument> transaction2NewDocs = Arrays.asList(doc3); List<SolrInputDocument> transaction3UpdatedDocs = Arrays.asList(doc4); BigVaultServerTransaction t1, t2, t3, t4; bigVaultServer.addAll(t1 = new BigVaultServerTransaction(LATER).setNewDocuments(transaction1NewDocs) .setUpdatedDocuments(transaction1UpdatedDocs)); bigVaultServer.addAll(t2 = new BigVaultServerTransaction(NOW).setNewDocuments(transaction2NewDocs) .setDeletedRecords(deletedDocs1)); bigVaultServer.addAll(t3 = new BigVaultServerTransaction(WITHIN_SECONDS(1)) .setUpdatedDocuments(transaction3UpdatedDocs).setDeletedRecords(deletedDocs2)); bigVaultServer.addAll(t4 = new BigVaultServerTransaction(WITHIN_MILLISECONDS(2)).setDeletedRecords(deletedDocs3)); InOrder inOrder = Mockito.inOrder(server, bigVaultServer); inOrder.verify(bigVaultServer).add(t1); inOrder.verify(bigVaultServer).add(t2); inOrder.verify(server).commit(true, true, true); inOrder.verify(bigVaultServer).add(t3); inOrder.verify(bigVaultServer).add(t4); } @Test(expected = BigVaultException.NonUniqueResult.class) public void givenNonUniqueResultsWhenQuerySingleResultThenThrowNonUniqueResultException() throws Exception { when(server.query(solrParams)).thenReturn(theQueryResponse); when(theQueryResponse.getResults()).thenReturn(twoElementsQueryResults); bigVaultServer.querySingleResult(solrParams); } @Test(expected = BigVaultException.NoResult.class) public void givenNoResultWhenQuerySingleResultThenThrowNoResultException() throws Exception { when(server.query(solrParams)).thenReturn(theQueryResponse); when(theQueryResponse.getResults()).thenReturn(emptyQueryResults); bigVaultServer.querySingleResult(solrParams); } @Test() public void givenUniqueResultWhenQuerySingleResultThenReturnUniqueResult() throws Exception { when(server.query(solrParams)).thenReturn(theQueryResponse); when(theQueryResponse.getResults()).thenReturn(theQueryResults); when(theQueryResults.size()).thenReturn(1); when(theQueryResults.get(0)).thenReturn(theUniqueResult); assertEquals(theUniqueResult, bigVaultServer.querySingleResult(solrParams)); } @Test public void whenQueryResultsThenReturnNestedSolrServerQueryResults() throws Exception { when(server.query(solrParams)).thenReturn(theQueryResponse); when(theQueryResponse.getResults()).thenReturn(theQueryResults); assertEquals(theQueryResults, bigVaultServer.queryResults(solrParams)); verify(server).query(solrParams); } @Test public void whenQueryThenQueryNestedSolrServer() throws Exception { when(server.query(solrParams)).thenReturn(theQueryResponse); assertEquals(theQueryResponse, bigVaultServer.query(solrParams)); verify(server).query(solrParams); } @Test(expected = BigVaultException.CouldNotExecuteQuery.class) public void givenQueryWhenNestedSolrExceptionThenThrowCouldNotExecuteQuery() throws Exception { SolrServerException e = mock(SolrServerException.class); when(e.getMessage()).thenReturn("Random injected fault"); when(server.query(solrParams)).thenThrow(e); bigVaultServer.query(solrParams); } @Test(expected = BigVaultException.CouldNotExecuteQuery.class) public void givenQueryWhenRemoteSolrExceptionWithCode500ThenThrowCouldNotExecuteQuery() throws Exception { RemoteSolrException e = mock(RemoteSolrException.class); when(e.getMessage()).thenReturn("Random injected fault"); when(e.code()).thenReturn(500); when(server.query(solrParams)).thenThrow(e); bigVaultServer.query(solrParams); } @Test(expected = BadRequest.BadRequest.class) public void givenQueryWhenRemoteSolrExceptionWithCode400ThenThrowBadRequest() throws Exception { RemoteSolrException e = mock(RemoteSolrException.class); when(e.getMessage()).thenReturn("Random injected fault"); when(e.code()).thenReturn(400); when(server.query(solrParams)).thenThrow(e); bigVaultServer.query(solrParams); } @Test(expected = BigVaultRuntimeException.SolrInternalError.class) public void whenRemoteSolrExceptionWithErrorCode500IsThrownThenThrowSolrInternalExceptionThrown() throws CouldNotExecuteQuery, OptimisticLocking, IOException, SolrServerException { RemoteSolrException e = mock(RemoteSolrException.class); when(e.getMessage()).thenReturn("Ze message"); when(e.code()).thenReturn(500); BigVaultServerTransaction transaction = new BigVaultServerTransaction(LATER(), addedDocs, modifiedDocs, deletedDocs1, deleteQueriesStrings); doThrow(e).when(bigVaultServer).addAndCommit(transaction); bigVaultServer.tryAddAll(transaction, 3); } @Test(expected = BigVaultRuntimeException.SolrInternalError.class) public void whenRouteExceptionWithErrorCode500IsThrownThenThrowSolrInternalExceptionThrown() throws CouldNotExecuteQuery, OptimisticLocking, IOException, SolrServerException { BigVaultServerTransaction transaction = new BigVaultServerTransaction(LATER(), addedDocs, modifiedDocs, deletedDocs1, deleteQueriesStrings); RouteException e = mock(RouteException.class); when(e.code()).thenReturn(500); when(e.getMessage()).thenReturn("Ze message"); doThrow(e).when(bigVaultServer) .addAndCommit(transaction); bigVaultServer.tryAddAll(transaction, 3); } @Test(expected = OptimisticLocking.class) public void whenRouteExceptionWithErrorCode500WithMessageConflictThenThrowOptimisticLocking() throws Exception { BigVaultServerTransaction transaction = new BigVaultServerTransaction(LATER(), addedDocs, modifiedDocs, deletedDocs1, deleteQueriesStrings); RouteException e = mock(RouteException.class); when(e.code()).thenReturn(500); when(e.getMessage()).thenReturn( "version conflict for e80fda8a-f842-48de-9ccf-c6ec847a18f7 expected=1487130319535472640 actual=1487130319704293376"); doThrow(e).when(bigVaultServer) .addAndCommit(transaction); bigVaultServer.tryAddAll(transaction, 3); } @Test(expected = OptimisticLocking.class) public void whenRouteExceptionWithErrorCode500WithDocumentNotFoundForUpdateThenThrowOptimisticLocking() throws Exception { BigVaultServerTransaction transaction = new BigVaultServerTransaction(LATER(), addedDocs, modifiedDocs, deletedDocs1, deleteQueriesStrings); RouteException e = mock(RouteException.class); when(e.code()).thenReturn(500); when(e.getMessage()).thenReturn("Document not found for update. id=idx_act_idOfAnotherNonExistentIndex"); doThrow(e).when(bigVaultServer) .addAndCommit(transaction); bigVaultServer.tryAddAll(transaction, 3); } }