package com.constellio.app.modules.es.services.crawler;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.joda.time.LocalDateTime;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.constellio.app.modules.es.connectors.spi.Connector;
import com.constellio.app.modules.es.connectors.spi.ConnectorJob;
import com.constellio.app.modules.es.model.connectors.ConnectorInstance;
import com.constellio.app.modules.es.model.connectors.ConnectorType;
import com.constellio.app.modules.es.services.ConnectorManager;
import com.constellio.app.modules.es.services.ESSchemasRecordsServices;
import com.constellio.model.entities.records.Record;
import com.constellio.model.entities.schemas.MetadataSchema;
import com.constellio.model.entities.schemas.MetadataSchemaTypes;
import com.constellio.model.entities.schemas.Schemas;
import com.constellio.model.services.records.RecordServices;
import com.constellio.model.services.schemas.MetadataSchemasManager;
import com.constellio.model.services.schemas.builders.MetadataSchemaTypesBuilder;
import com.constellio.sdk.tests.ConstellioTest;
public class ConnectorCrawlerAcceptTest extends ConstellioTest {
private static boolean areConnectorsDoingJobs = true;
private static List<String> connectorEvents;
ConnectorInstance connector1, connector2;
String testConnectorTypeId = "testConnectorTypeId";
ConnectorManager connectorManager;
RecordServices recordServices;
ESSchemasRecordsServices es;
ConnectorCrawler connectorCrawler;
@Test
public void whenCrawlingACollectionWithoutConnectorsThenNothingHappens()
throws Exception {
crawl();
assertThat(connectorEvents).isEmpty();
}
@Test
public void givenConnectorThatReturnsEmptyJobsThanItsTraversalDateSetCorrectly()
throws Exception{
LocalDateTime now = LocalDateTime.now();
givenTimeIs(now);
areConnectorsDoingJobs = false;
ConnectorInstance<ConnectorInstance<?>> connectorInstance;
connectorManager.createConnector(connectorInstance = newEnabledTestConnectorWithCode("connector1"));
crawl();
connectorInstance = es.getConnectorInstance(connectorInstance.getId());
assertThat(connectorInstance.getLastTraversalOn()).isEqualTo(now);
}
@Test
public void givenConnectorThatDoesNotReturnsEmptyJobsThanItsTraversalDateIsNull()
throws Exception{
LocalDateTime now = LocalDateTime.now();
givenTimeIs(now);
areConnectorsDoingJobs = true;
ConnectorInstance<ConnectorInstance<?>> connectorInstance;
connectorManager.createConnector(connectorInstance = newEnabledTestConnectorWithCode("connector1"));
crawl();
connectorInstance = es.getConnectorInstance(connectorInstance.getId());
assertThat(connectorInstance.getLastTraversalOn()).isNull();
}
@Test
public void whenAConnectorDoingNoJobsIsCreatedThenItIsStartedOnNextCrawl()
throws Exception {
areConnectorsDoingJobs = false;
crawl();
assertThat(connectorEvents).isEmpty();
connectorManager.createConnector(newEnabledTestConnectorWithCode("connector1"));
assertThat(connectorEvents).isEmpty();
crawl();
assertThat(connectorEvents).isEqualTo(asList(
"connector1-initialize",
"connector1-start"));
crawl();
assertThat(connectorEvents).isEmpty();
connectorManager.createConnector(newEnabledTestConnectorWithCode("connector2"));
crawl();
assertThat(connectorEvents).isEqualTo(asList(
"connector2-initialize",
"connector2-start"));
}
@Test
public void givenTwoDisabledConnectorsThenNothingHappensUntilItIsStarted()
throws Exception {
connector1 = connectorManager.createConnector(newDisabledTestConnectorWithCode("connector1"));
connector2 = connectorManager.createConnector(newDisabledTestConnectorWithCode("connector2"));
crawl();
assertThat(connectorEvents).isEmpty();
connectorManager.save(connector2.setEnabled(true));
crawl();
assertThat(connectorEvents).containsOnly(
"connector2-initialize",
"connector2-start",
"connector2-getJobs",
"connector2-execute-job1",
"connector2-execute-job2",
"connector2-afterJobs");
connectorManager.save(connector1.setEnabled(true));
crawl();
assertThat(connectorEvents).containsOnly(
"connector1-initialize",
"connector1-start",
"connector1-getJobs",
"connector1-execute-job1",
"connector1-execute-job2",
"connector1-afterJobs",
"connector2-getJobs",
"connector2-execute-job3",
"connector2-execute-job4",
"connector2-afterJobs");
}
@Test
public void givenTwoConnectorsWhenDisabledThenStopCrawling()
throws Exception {
areConnectorsDoingJobs = true;
connector1 = connectorManager.createConnector(newEnabledTestConnectorWithCode("connector1"));
connector2 = connectorManager.createConnector(newEnabledTestConnectorWithCode("connector2"));
crawl();
assertThat(connectorEvents).containsOnly(
"connector1-initialize",
"connector1-start",
"connector2-initialize",
"connector2-start",
"connector1-getJobs",
"connector1-execute-job1",
"connector1-execute-job2",
"connector1-afterJobs",
"connector2-getJobs",
"connector2-execute-job1",
"connector2-execute-job2",
"connector2-afterJobs");
connectorManager.save(connector2.setEnabled(false));
crawl();
assertThat(connectorEvents).containsOnly(
"connector2-stop",
"connector1-getJobs",
"connector1-execute-job3",
"connector1-execute-job4",
"connector1-afterJobs");
connectorManager.save(connector1.setEnabled(false));
crawl();
assertThat(connectorEvents).isEqualTo(asList(
"connector1-stop"));
}
@Test
public void givenAConnectorAlreadyExistAndHasNoStartedTraversalWhenCrawlingForTheFirstTimeThenInitializeAndStartIt()
throws Exception {
areConnectorsDoingJobs = false;
connector1 = connectorManager.createConnector(newEnabledTestConnectorWithCode("connector1"));
crawl();
assertThat(connectorEvents).isEqualTo(asList(
"connector1-initialize",
"connector1-start"));
assertThat(es.getConnectorInstance(connector1.getId()).getTraversalCode()).isNotNull();
}
@Test
public void givenOneConnectorWhenCrawlingThenReturnJobsAndExecuteThem()
throws Exception {
areConnectorsDoingJobs = true;
connector1 = connectorManager.createConnector(newEnabledTestConnectorWithCode("connector1"));
crawl();
assertThat(connectorEvents).isEqualTo(asList(
"connector1-initialize",
"connector1-start",
"connector1-getJobs",
"connector1-execute-job1",
"connector1-execute-job2",
"connector1-afterJobs"));
crawl();
assertThat(connectorEvents).isEqualTo(asList(
"connector1-getJobs",
"connector1-execute-job3",
"connector1-execute-job4",
"connector1-afterJobs"));
}
@Test
public void givenTwoConnectorsWhenCrawlingThenReturnJobsOfBothAndExecuteThem()
throws Exception {
areConnectorsDoingJobs = true;
connector1 = connectorManager.createConnector(newEnabledTestConnectorWithCode("connector1"));
connector2 = connectorManager.createConnector(newEnabledTestConnectorWithCode("connector2"));
crawl();
assertThat(connectorEvents).containsOnly(
"connector1-initialize",
"connector1-start",
"connector2-initialize",
"connector2-start",
"connector1-getJobs",
"connector1-execute-job1",
"connector1-execute-job2",
"connector1-afterJobs",
"connector2-getJobs",
"connector2-execute-job1",
"connector2-execute-job2",
"connector2-afterJobs");
crawl();
assertThat(connectorEvents).containsOnly(
"connector1-getJobs",
"connector1-execute-job3",
"connector1-execute-job4",
"connector1-afterJobs",
"connector2-getJobs",
"connector2-execute-job3",
"connector2-execute-job4",
"connector2-afterJobs");
}
@Test
public void givenTwoConnectorsWhenRestartingCollectionOfOneThemRestartTraversalAndTheOtherContinue()
throws Exception {
areConnectorsDoingJobs = true;
connector1 = connectorManager.createConnector(newEnabledTestConnectorWithCode("connector1"));
connector2 = connectorManager.createConnector(newEnabledTestConnectorWithCode("connector2"));
crawl();
assertThat(connectorEvents).containsOnly(
"connector1-initialize",
"connector1-start",
"connector2-initialize",
"connector2-start",
"connector1-getJobs",
"connector1-execute-job1",
"connector1-execute-job2",
"connector1-afterJobs",
"connector2-getJobs",
"connector2-execute-job1",
"connector2-execute-job2",
"connector2-afterJobs");
connectorManager.restartConnectorTraversal(connector2.getId());
crawl();
assertThat(connectorEvents).containsOnly(
"connector2-stop",
"connector2-initialize",
"connector2-start",
"connector1-getJobs",
"connector1-execute-job3",
"connector1-execute-job4",
"connector1-afterJobs",
"connector2-getJobs",
"connector2-execute-job1",
"connector2-execute-job2",
"connector2-afterJobs");
}
@Test
public void givenAConnectorAlreadyExistAndHasAStartedTraversalWhenCrawlingForTheFirstTimeThenInitializeAndResumeIt()
throws Exception {
areConnectorsDoingJobs = false;
connector1 = connectorManager
.createConnector(newEnabledTestConnectorWithCode("connector1").setTraversalCode("zeTraversal"));
crawl();
assertThat(connectorEvents).isEqualTo(asList(
"connector1-initialize",
"connector1-resume"));
assertThat(es.getConnectorInstance(connector1.getId()).getTraversalCode()).isEqualTo("zeTraversal");
}
// ----------------------------------------------------------------------------------------------------------------
private void crawl() {
connectorEvents.clear();
connectorCrawler.crawlAllConnectors();
}
private ConnectorInstance<ConnectorInstance<?>> newEnabledTestConnectorWithCode(String code) {
MetadataSchemaTypes types = es.getModelLayerFactory().getMetadataSchemasManager().getSchemaTypes(zeCollection);
MetadataSchema schema = es.connectorInstance.schemaType().getSchema("test");
ConnectorInstance connectorInstance = new ConnectorInstance(recordServices.newRecordWithSchema(schema), types);
connectorInstance.setCode(code).setTitle(code);
connectorInstance.setEnabled(true);
connectorInstance.setConnectorType(testConnectorTypeId);
return connectorInstance;
}
private ConnectorInstance<ConnectorInstance<?>> newDisabledTestConnectorWithCode(String code) {
MetadataSchemaTypes types = es.getModelLayerFactory().getMetadataSchemasManager().getSchemaTypes(zeCollection);
MetadataSchema schema = es.connectorInstance.schemaType().getSchema("test");
ConnectorInstance connectorInstance = new ConnectorInstance(recordServices.newRecordWithSchema(schema), types);
connectorInstance.setCode(code).setTitle(code);
connectorInstance.setEnabled(false);
connectorInstance.setConnectorType(testConnectorTypeId);
return connectorInstance;
}
@Before
public void setUp()
throws Exception {
prepareSystem(withZeCollection().withConstellioESModule());
connectorEvents = new ArrayList<>();
es = new ESSchemasRecordsServices(zeCollection, getAppLayerFactory());
recordServices = es.getModelLayerFactory().newRecordServices();
connectorManager = es.getConnectorManager();
connectorManager.setCrawlerInParallel(false);
connectorCrawler = es.getConnectorManager().getCrawler();
connectorCrawler.timeWaitedWhenNoJobs = 0;
givenDummyConnectorType();
connectorEvents.clear();
}
private void givenDummyConnectorType()
throws Exception {
MetadataSchemasManager schemasManager = getModelLayerFactory().getMetadataSchemasManager();
MetadataSchemaTypesBuilder typesBuilder = schemasManager.modify(zeCollection);
typesBuilder.getSchemaType(ConnectorInstance.SCHEMA_TYPE).createCustomSchema("test");
schemasManager.saveUpdateSchemaTypes(typesBuilder);
ConnectorType type = es.newConnectorTypeWithId(testConnectorTypeId).setCode("test").setTitle("test")
.setConnectorClassName(ConnectorTest.class.getName()).setLinkedSchema(ConnectorInstance.SCHEMA_TYPE + "_test");
recordServices.add(type);
}
@After
public void tearDown()
throws Exception {
connectorEvents = null;
}
public static class ConnectorTest extends Connector {
String code;
AtomicInteger atomicInteger = new AtomicInteger();
@Override
public List<ConnectorJob> getJobs() {
if (!areConnectorsDoingJobs) {
return new ArrayList<>();
}
ConnectorJob job1 = new ConnectorJob(this, "job" + atomicInteger.incrementAndGet()) {
@Override
public void execute(Connector connector) {
connectorEvents.add(code + "-execute-" + jobName);
}
};
ConnectorJob job2 = new ConnectorJob(this, "job" + atomicInteger.incrementAndGet()) {
@Override
public void execute(Connector connector) {
connectorEvents.add(code + "-execute-" + jobName);
}
};
connectorEvents.add(code + "-getJobs");
return asList(job1, job2);
}
@Override
protected void initialize(Record instance) {
code = instance.get(Schemas.CODE);
connectorEvents.add(code + "-initialize");
}
@Override
public List<String> fetchTokens(String username) {
return new ArrayList<>();
}
@Override
public List<String> getConnectorDocumentTypes() {
return new ArrayList<>();
}
@Override
public void start() {
connectorEvents.add(code + "-start");
}
@Override
public void stop() {
connectorEvents.add(code + "-stop");
}
@Override
public void afterJobs(List<ConnectorJob> jobs) {
connectorEvents.add(code + "-afterJobs");
}
@Override
public void resume() {
connectorEvents.add(code + "-resume");
}
@Override
public List<String> getReportMetadatas(String reportMode) {
return null;
}
@Override
public String getMainConnectorDocumentType() {
return null;
}
@Override
public void onAllDocumentsDeleted() {
}
}
}