package org.molgenis.integrationtest.platform; import org.molgenis.data.*; import org.molgenis.data.elasticsearch.SearchService; import org.molgenis.data.elasticsearch.index.job.IndexService; import org.molgenis.data.i18n.LanguageService; import org.molgenis.data.i18n.model.I18nStringMetaData; import org.molgenis.data.i18n.model.LanguageFactory; import org.molgenis.data.i18n.model.LanguageMetadata; import org.molgenis.data.index.IndexActionRegisterServiceImpl; import org.molgenis.data.index.meta.IndexActionMetaData; import org.molgenis.data.listeners.EntityListener; import org.molgenis.data.listeners.EntityListenersService; import org.molgenis.data.meta.MetaDataServiceImpl; import org.molgenis.data.meta.model.*; import org.molgenis.data.support.DynamicEntity; import org.molgenis.data.support.QueryImpl; import org.molgenis.test.data.EntitySelfXrefTestHarness; import org.molgenis.test.data.EntityTestHarness; import org.molgenis.test.data.staticentity.TestEntityStatic; import org.molgenis.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; import org.springframework.transaction.annotation.Transactional; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.text.ParseException; import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Supplier; import java.util.stream.Stream; import java.util.stream.StreamSupport; import static com.google.common.collect.Lists.newArrayList; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; import static java.util.stream.Collectors.toList; import static java.util.stream.Stream.concat; import static java.util.stream.Stream.of; import static org.molgenis.data.RepositoryCapability.*; import static org.molgenis.data.i18n.model.I18nStringMetaData.I18N_STRING; import static org.molgenis.data.i18n.model.LanguageMetadata.LANGUAGE; import static org.molgenis.data.meta.model.AttributeMetadata.ATTRIBUTE_META_DATA; import static org.molgenis.data.meta.model.EntityTypeMetadata.ENTITY_TYPE_META_DATA; import static org.molgenis.data.meta.model.PackageMetadata.PACKAGE; import static org.molgenis.security.core.runas.RunAsSystemProxy.runAsSystem; import static org.molgenis.test.data.EntityTestHarness.*; import static org.molgenis.util.MolgenisDateFormat.getDateFormat; import static org.molgenis.util.MolgenisDateFormat.getDateTimeFormat; import static org.testng.Assert.*; @ContextConfiguration(classes = { PlatformITConfig.class }) public class PlatformIT extends AbstractTestNGSpringContextTests { private final Logger LOG = LoggerFactory.getLogger(PlatformIT.class); private static EntityType entityTypeStatic; private static EntityType refEntityTypeStatic; private static EntityType entityTypeDynamic; private static EntityType refEntityTypeDynamic; private static EntityType selfXrefEntityType; @Autowired private IndexService indexService; @Autowired private EntityTestHarness testHarness; @Autowired private EntitySelfXrefTestHarness entitySelfXrefTestHarness; @Autowired private DataService dataService; @Autowired private SearchService searchService; @Autowired private MetaDataServiceImpl metaDataService; @Autowired private EntityListenersService entityListenersService; @Autowired private LanguageService languageService; @Autowired private I18nStringMetaData i18nStringMetaData; @Autowired private LanguageMetadata languageMetadata; @Autowired private EntityTypeMetadata entityTypeMetadata; @Autowired private AttributeMetadata attributeMetadata; @Autowired private LanguageFactory languageFactory; @Autowired private AttributeFactory attributeFactory; @Autowired private IndexActionRegisterServiceImpl indexActionRegisterService; /** * Wait till the whole index is stable. Index job is done a-synchronized. */ public static void waitForWorkToBeFinished(IndexService indexService, Logger log) { try { indexService.waitForAllIndicesStable(); log.info("All work finished"); } catch (InterruptedException e) { log.warn("Interrupted while waiting for index to become stable!", e); fail("Interrupted while waiting for index to become stable!"); } } /** * Wait till the index is stable. Index job is executed asynchronously. This method waits for all index jobs * relevant for this entity to be finished. * * @param entityName name of the entitiy whose index needs to be stable */ public static void waitForIndexToBeStable(String entityName, IndexService indexService, Logger log) { try { indexService.waitForIndexToBeStableIncludingReferences(entityName); log.info("Index for entity [{}] incl. references is stable", entityName); } catch (InterruptedException e) { log.info("Interrupted waiting for [{}] incl. references to become stable", entityName, e); } } @BeforeClass public void setUp() { refEntityTypeStatic = testHarness.createStaticRefTestEntityType(); entityTypeStatic = testHarness.createStaticTestEntityType(); refEntityTypeDynamic = testHarness.createDynamicRefEntityType(); entityTypeDynamic = testHarness.createDynamicTestEntityType(); // Create a self refer entity selfXrefEntityType = entitySelfXrefTestHarness.createDynamicEntityType(); selfXrefEntityType.getAttribute(ATTR_XREF).setRefEntity(selfXrefEntityType); runAsSystem(() -> { addDefaultLanguages(); metaDataService.addEntityType(refEntityTypeDynamic); metaDataService.addEntityType(entityTypeDynamic); metaDataService.addEntityType(selfXrefEntityType); }); setAuthentication(); waitForWorkToBeFinished(indexService, LOG); } static List<GrantedAuthority> makeAuthorities(String entityName, boolean write, boolean read, boolean count) { List<GrantedAuthority> authorities = newArrayList(); if (write) authorities.add(new SimpleGrantedAuthority("ROLE_ENTITY_WRITE_" + entityName)); if (read) authorities.add(new SimpleGrantedAuthority("ROLE_ENTITY_READ_" + entityName)); if (count) authorities.add(new SimpleGrantedAuthority("ROLE_ENTITY_COUNT_" + entityName)); return authorities; } private void setAuthentication() { List<GrantedAuthority> authorities = newArrayList(); authorities.add(new SimpleGrantedAuthority("ROLE_ENTITY_READ_" + ENTITY_TYPE_META_DATA)); authorities.add(new SimpleGrantedAuthority("ROLE_ENTITY_READ_" + ATTRIBUTE_META_DATA)); authorities.add(new SimpleGrantedAuthority("ROLE_ENTITY_READ_" + PACKAGE)); authorities.addAll(makeAuthorities(refEntityTypeStatic.getName(), true, true, true)); authorities.addAll(makeAuthorities(entityTypeStatic.getName(), true, true, true)); authorities.addAll(makeAuthorities(entityTypeDynamic.getName(), true, true, true)); authorities.addAll(makeAuthorities(refEntityTypeDynamic.getName(), false, true, true)); authorities.addAll(makeAuthorities(selfXrefEntityType.getName(), true, true, true)); authorities.addAll(makeAuthorities(languageMetadata.getName(), true, true, true)); authorities.addAll(makeAuthorities(attributeMetadata.getName(), true, true, true)); authorities.addAll(makeAuthorities(i18nStringMetaData.getName(), true, false, false)); authorities.addAll(makeAuthorities(entityTypeMetadata.getName(), true, true, true)); SecurityContextHolder.getContext() .setAuthentication(new TestingAuthenticationToken("user", "user", authorities)); } @AfterMethod public void afterMethod() { runAsSystem(() -> { dataService.deleteAll(entityTypeStatic.getName()); dataService.deleteAll(refEntityTypeStatic.getName()); dataService.deleteAll(entityTypeDynamic.getName()); dataService.deleteAll(refEntityTypeDynamic.getName()); dataService.deleteAll(selfXrefEntityType.getName()); }); waitForIndexToBeStable(entityTypeStatic.getName(), indexService, LOG); waitForIndexToBeStable(refEntityTypeStatic.getName(), indexService, LOG); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); waitForIndexToBeStable(refEntityTypeDynamic.getName(), indexService, LOG); waitForIndexToBeStable(selfXrefEntityType.getName(), indexService, LOG); } private void addDefaultLanguages() { dataService.add(LANGUAGE, languageFactory .create(LanguageService.DEFAULT_LANGUAGE_CODE, LanguageService.DEFAULT_LANGUAGE_NAME, true)); dataService .add(LANGUAGE, languageFactory.create("nl", new Locale("nl").getDisplayName(new Locale("nl")), false)); dataService .add(LANGUAGE, languageFactory.create("pt", new Locale("pt").getDisplayName(new Locale("pt")), false)); dataService .add(LANGUAGE, languageFactory.create("es", new Locale("es").getDisplayName(new Locale("es")), false)); dataService .add(LANGUAGE, languageFactory.create("de", new Locale("de").getDisplayName(new Locale("de")), false)); dataService .add(LANGUAGE, languageFactory.create("it", new Locale("it").getDisplayName(new Locale("it")), false)); dataService .add(LANGUAGE, languageFactory.create("fr", new Locale("fr").getDisplayName(new Locale("fr")), false)); dataService.add(LANGUAGE, languageFactory.create("xx", "My language", false)); } @Test(singleThreaded = true) public void testLanguageService() { assertEquals(dataService.getMeta().getEntityType(ENTITY_TYPE_META_DATA).getAttribute("label-en").getName(), "label-en"); assertEquals(dataService.getMeta().getEntityType(ENTITY_TYPE_META_DATA).getLabelAttribute("en").getName(), "simpleName"); assertEquals(dataService.getMeta().getEntityType(ENTITY_TYPE_META_DATA).getLabelAttribute("pt").getName(), "simpleName"); assertEquals(dataService.getMeta().getEntityType(ENTITY_TYPE_META_DATA).getLabelAttribute("nl").getName(), "simpleName"); assertEquals(dataService.getMeta().getEntityType(ENTITY_TYPE_META_DATA).getLabelAttribute().getName(), "simpleName"); assertEquals(languageService.getCurrentUserLanguageCode(), "en"); assertEqualsNoOrder(languageService.getLanguageCodes().toArray(), new String[] { "en", "nl", "de", "es", "it", "pt", "fr", "xx" }); // NL assertNotNull(dataService.getEntityType(I18N_STRING).getAttribute("nl")); assertNotNull(dataService.getEntityType(ENTITY_TYPE_META_DATA).getAttribute("label-nl")); assertNotNull(dataService.getEntityType(ENTITY_TYPE_META_DATA).getAttribute("description-nl")); assertNotNull(dataService.getEntityType(ATTRIBUTE_META_DATA).getAttribute("label-nl")); assertNotNull(dataService.getEntityType(ATTRIBUTE_META_DATA).getAttribute("description-nl")); // EN assertNotNull(dataService.getEntityType(I18N_STRING).getAttribute("en")); assertNotNull(dataService.getEntityType(ENTITY_TYPE_META_DATA).getAttribute("label-en")); assertNotNull(dataService.getEntityType(ENTITY_TYPE_META_DATA).getAttribute("description-en")); assertNotNull(dataService.getEntityType(ATTRIBUTE_META_DATA).getAttribute("label-en")); assertNotNull(dataService.getEntityType(ATTRIBUTE_META_DATA).getAttribute("description-en")); Entity car = new DynamicEntity(i18nStringMetaData); car.set(I18nStringMetaData.MSGID, "car"); car.set("en", "car"); car.set("nl", "auto"); dataService.add(I18nStringMetaData.I18N_STRING, car); assertEquals(languageService.getBundle("en").getString("car"), "car"); assertEquals(languageService.getBundle("nl").getString("car"), "auto"); // Test default value assertEquals(languageService.getBundle().getString("car"), "car"); } @Test(singleThreaded = true) public void testEntityListener() { List<Entity> refEntities = testHarness.createTestRefEntities(refEntityTypeDynamic, 6); List<Entity> entities = testHarness.createTestEntities(entityTypeDynamic, 2, refEntities).collect(toList()); runAsSystem(() -> { dataService.add(refEntityTypeDynamic.getName(), refEntities.stream()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); }); AtomicInteger updateCalled = new AtomicInteger(0); EntityListener listener = new EntityListener() { @Override public Object getEntityId() { return entities.get(0).getIdValue(); } @Override public void postUpdate(Entity entity) { updateCalled.incrementAndGet(); assertEquals(entity.getIdValue(), entities.get(0).getIdValue()); } }; try { // Test that the listener is being called entityListenersService.addEntityListener(entityTypeDynamic.getName(), listener); dataService.update(entityTypeDynamic.getName(), entities.stream()); assertEquals(updateCalled.get(), 1); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); assertPresent(entityTypeDynamic, entities); } finally { // Test that the listener is actually removed and not called anymore entityListenersService.removeEntityListener(entityTypeDynamic.getName(), listener); updateCalled.set(0); dataService.update(entityTypeDynamic.getName(), entities.stream()); assertEquals(updateCalled.get(), 0); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); assertPresent(entityTypeDynamic, entities); } } @Test(singleThreaded = true) public void testAdd() { List<Entity> entities = createDynamic(2).collect(toList()); assertEquals(searchService.count(entityTypeDynamic), 0); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); assertEquals(dataService.count(entityTypeDynamic.getName(), new QueryImpl<>()), 2); assertEquals(searchService.count(entityTypeDynamic), 2); assertPresent(entityTypeDynamic, entities); } @Test(singleThreaded = true) public void testCount() { List<Entity> entities = createDynamic(2).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); assertEquals(dataService.count(entityTypeDynamic.getName(), new QueryImpl<>()), 2); assertEquals(searchService.count(entityTypeDynamic), 2); assertPresent(entityTypeDynamic, entities); } @Test(singleThreaded = true) public void testDelete() { Entity entity = createDynamic(1).findFirst().get(); dataService.add(entityTypeDynamic.getName(), entity); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); assertPresent(entityTypeDynamic, entity); dataService.delete(entityTypeDynamic.getName(), entity); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); assertNotPresent(entity); } @Test(singleThreaded = true) public void testDeleteById() { Entity entity = createDynamic(1).findFirst().get(); dataService.add(entityTypeDynamic.getName(), entity); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); assertPresent(entityTypeDynamic, entity); dataService.deleteById(entityTypeDynamic.getName(), entity.getIdValue()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); assertNotPresent(entity); } @Test(singleThreaded = true) public void testDeleteStream() { List<Entity> entities = createDynamic(2).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); assertEquals(dataService.count(entityTypeDynamic.getName(), new QueryImpl<>()), entities.size()); dataService.delete(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); assertEquals(dataService.count(entityTypeDynamic.getName(), new QueryImpl<>()), 0); } @Test(singleThreaded = true) public void testDeleteAll() { List<Entity> entities = createDynamic(5).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); assertEquals(dataService.count(entityTypeDynamic.getName(), new QueryImpl<>()), entities.size()); dataService.deleteAll(entityTypeDynamic.getName()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); assertEquals(dataService.count(entityTypeDynamic.getName(), new QueryImpl<>()), 0); } @Test(singleThreaded = true) public void testFindAllEmpty() { Stream<Entity> retrieved = dataService.findAll(entityTypeDynamic.getName()); assertEquals(retrieved.count(), 0); } @Test(singleThreaded = true) public void testFindAll() { List<Entity> entities = createDynamic(5).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Stream<Entity> retrieved = dataService.findAll(entityTypeDynamic.getName()); assertEquals(retrieved.count(), entities.size()); } @Test(singleThreaded = true) public void testFindAllTyped() { List<Entity> entities = createDynamic(1).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Supplier<Stream<Entity>> retrieved = () -> dataService.findAll(entityTypeDynamic.getName(), Entity.class); assertEquals(retrieved.get().count(), 1); assertEquals(retrieved.get().iterator().next().getIdValue(), entities.get(0).getIdValue()); } @Test(singleThreaded = true) public void testFindAllByIds() { List<Entity> entities = createDynamic(5).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Stream<Object> ids = Stream.concat(entities.stream().map(Entity::getIdValue), of("bogus")); Stream<Entity> retrieved = dataService.findAll(entityTypeDynamic.getName(), ids); assertEquals(retrieved.count(), entities.size()); } @Test(singleThreaded = true) public void testFindAllByIdsTyped() { List<Entity> entities = createStatic(5).collect(toList()); dataService.add(entityTypeStatic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeStatic.getName(), indexService, LOG); Supplier<Stream<TestEntityStatic>> retrieved = () -> dataService.findAll(entityTypeStatic.getName(), Stream.concat(entities.stream().map(Entity::getIdValue), of("bogus")), TestEntityStatic.class); assertEquals(retrieved.get().count(), entities.size()); assertEquals(retrieved.get().iterator().next().getId(), entities.get(0).getIdValue()); assertEquals(retrieved.get().iterator().next().getIdValue(), entities.get(0).getIdValue()); } @Test(singleThreaded = true) public void testFindAllStreamFetch() { List<Entity> entities = createDynamic(5).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Stream<Object> ids = concat(entities.stream().map(Entity::getIdValue), of("bogus")); Stream<Entity> retrieved = dataService.findAll(entityTypeDynamic.getName(), ids, new Fetch().field(ATTR_ID)); assertEquals(retrieved.count(), entities.size()); } @DataProvider(name = "findQueryOperatorEq") private static Object[][] findQueryOperatorEq() throws ParseException { return new Object[][] { { ATTR_ID, "1", singletonList(1) }, { ATTR_STRING, "string1", asList(0, 1, 2) }, { ATTR_BOOL, true, asList(0, 2) }, { ATTR_DATE, getDateFormat().parse("2012-12-21"), asList(0, 1, 2) }, { ATTR_DATETIME, getDateTimeFormat().parse("1985-08-12T11:12:13+0500"), asList(0, 1, 2) }, { ATTR_DECIMAL, 1.123, singletonList(1) }, { ATTR_HTML, "<html>where is my head and where is my body</html>", singletonList(1) }, { ATTR_HYPERLINK, "http://www.molgenis.org", asList(0, 1, 2) }, { ATTR_LONG, 1000000L, singletonList(1) }, { ATTR_INT, 11, singletonList(1) }, { ATTR_SCRIPT, "/bin/blaat/script.sh", asList(0, 1, 2) }, { ATTR_EMAIL, "this.is@mail.address", asList(0, 1, 2) }, // null checks { ATTR_ID, null, emptyList() }, { ATTR_STRING, null, emptyList() }, { ATTR_BOOL, null, emptyList() }, { ATTR_CATEGORICAL, null, emptyList() }, { ATTR_CATEGORICAL_MREF, null, emptyList() }, { ATTR_DATE, null, emptyList() }, { ATTR_DATETIME, null, emptyList() }, { ATTR_DECIMAL, null, emptyList() }, { ATTR_HTML, null, asList(0, 2) }, { ATTR_HYPERLINK, null, emptyList() }, { ATTR_LONG, null, emptyList() }, { ATTR_INT, 11, singletonList(1) }, { ATTR_SCRIPT, null, emptyList() }, { ATTR_EMAIL, null, emptyList() }, { ATTR_XREF, null, emptyList() }, { ATTR_MREF, null, emptyList() } }; } @Test(singleThreaded = true, dataProvider = "findQueryOperatorEq") public void testFindQueryOperatorEq(String attrName, Object value, List<Integer> expectedEntityIndices) { List<Entity> entities = createDynamic(3).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Supplier<Stream<Entity>> found = () -> dataService.query(entityTypeDynamic.getName()).eq(attrName, value) .findAll(); List<Entity> foundAsList = found.get().collect(toList()); assertEquals(foundAsList.size(), expectedEntityIndices.size()); for (int i = 0; i < expectedEntityIndices.size(); ++i) { assertTrue(EntityUtils.equals(foundAsList.get(i), entities.get(expectedEntityIndices.get(i)))); } } @DataProvider(name = "findQueryOperatorIn") private static Object[][] findQueryOperatorIn() { return new Object[][] { { singletonList("-1"), emptyList() }, { asList("-1", "0"), singletonList(0) }, { asList("0", "1"), asList(0, 1) }, { asList("1", "2"), singletonList(1) } }; } @Test(singleThreaded = true, dataProvider = "findQueryOperatorIn") public void testFindQueryOperatorIn(List<String> ids, List<Integer> expectedEntityIndices) { List<Entity> entities = createDynamic(2).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Supplier<Stream<Entity>> found = () -> dataService.query(entityTypeDynamic.getName()).in(ATTR_ID, ids) .findAll(); List<Entity> foundAsList = found.get().collect(toList()); assertEquals(foundAsList.size(), expectedEntityIndices.size()); for (int i = 0; i < expectedEntityIndices.size(); ++i) { assertTrue(EntityUtils.equals(foundAsList.get(i), entities.get(expectedEntityIndices.get(i)))); } } @DataProvider(name = "findQueryOperatorLess") private static Object[][] findQueryOperatorLess() { return new Object[][] { { 9, emptyList() }, { 10, emptyList() }, { 11, singletonList(0) }, { 12, asList(0, 1) }, { 13, asList(0, 1, 2) } }; } @Test(singleThreaded = true, dataProvider = "findQueryOperatorLess") public void testFindQueryOperatorLess(int value, List<Integer> expectedEntityIndices) { List<Entity> entities = createDynamic(5).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Supplier<Stream<Entity>> found = () -> dataService.query(entityTypeDynamic.getName()).lt(ATTR_INT, value) .findAll(); List<Entity> foundAsList = found.get().collect(toList()); assertEquals(foundAsList.size(), expectedEntityIndices.size()); for (int i = 0; i < expectedEntityIndices.size(); ++i) { assertTrue(EntityUtils.equals(foundAsList.get(i), entities.get(expectedEntityIndices.get(i)))); } } @DataProvider(name = "findQueryOperatorLessEqual") private static Object[][] findQueryOperatorLessEqual() { return new Object[][] { { 9, emptyList() }, { 10, singletonList(0) }, { 11, asList(0, 1) }, { 12, asList(0, 1, 2) }, { 13, asList(0, 1, 2, 3) } }; } @Test(singleThreaded = true, dataProvider = "findQueryOperatorLessEqual") public void testFindQueryOperatorLessEqual(int value, List<Integer> expectedEntityIndices) { List<Entity> entities = createDynamic(5).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Supplier<Stream<Entity>> found = () -> dataService.query(entityTypeDynamic.getName()).le(ATTR_INT, value) .findAll(); List<Entity> foundAsList = found.get().collect(toList()); assertEquals(foundAsList.size(), expectedEntityIndices.size()); for (int i = 0; i < expectedEntityIndices.size(); ++i) { assertTrue(EntityUtils.equals(foundAsList.get(i), entities.get(expectedEntityIndices.get(i)))); } } @DataProvider(name = "findQueryOperatorGreater") private static Object[][] findQueryOperatorGreater() { return new Object[][] { { 9, asList(0, 1, 2) }, { 10, asList(1, 2) }, { 11, singletonList(2) }, { 12, emptyList() } }; } @Test(singleThreaded = true, dataProvider = "findQueryOperatorGreater") public void testFindQueryOperatorGreater(int value, List<Integer> expectedEntityIndices) { List<Entity> entities = createDynamic(3).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Supplier<Stream<Entity>> found = () -> dataService.query(entityTypeDynamic.getName()).gt(ATTR_INT, value) .findAll(); List<Entity> foundAsList = found.get().collect(toList()); assertEquals(foundAsList.size(), expectedEntityIndices.size()); for (int i = 0; i < expectedEntityIndices.size(); ++i) { assertTrue(EntityUtils.equals(foundAsList.get(i), entities.get(expectedEntityIndices.get(i)))); } } @DataProvider(name = "findQueryOperatorGreaterEqual") private static Object[][] findQueryOperatorGreaterEqual() { return new Object[][] { { 9, asList(0, 1, 2) }, { 10, asList(0, 1, 2) }, { 11, asList(1, 2) }, { 12, singletonList(2) }, { 13, emptyList() } }; } @Test(singleThreaded = true, dataProvider = "findQueryOperatorGreaterEqual") public void testFindQueryOperatorGreaterEqual(int value, List<Integer> expectedEntityIndices) { List<Entity> entities = createDynamic(3).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Supplier<Stream<Entity>> found = () -> dataService.query(entityTypeDynamic.getName()).ge(ATTR_INT, value) .findAll(); List<Entity> foundAsList = found.get().collect(toList()); assertEquals(foundAsList.size(), expectedEntityIndices.size()); for (int i = 0; i < expectedEntityIndices.size(); ++i) { assertTrue(EntityUtils.equals(foundAsList.get(i), entities.get(expectedEntityIndices.get(i)))); } } @DataProvider(name = "findQueryOperatorRange") private static Object[][] findQueryOperatorRange() { return new Object[][] { { 0, 9, emptyList() }, { 0, 10, asList(0) }, { 10, 10, asList(0) }, { 10, 11, asList(0, 1) }, { 10, 12, asList(0, 1, 2) }, { 12, 20, asList(2) } }; } @Test(singleThreaded = true, dataProvider = "findQueryOperatorRange") public void testFindQueryOperatorRange(int low, int high, List<Integer> expectedEntityIndices) { List<Entity> entities = createDynamic(3).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Supplier<Stream<Entity>> found = () -> dataService.query(entityTypeDynamic.getName()).rng(ATTR_INT, low, high) .findAll(); List<Entity> foundAsList = found.get().collect(toList()); assertEquals(foundAsList.size(), expectedEntityIndices.size()); for (int i = 0; i < expectedEntityIndices.size(); ++i) { assertTrue(EntityUtils.equals(foundAsList.get(i), entities.get(expectedEntityIndices.get(i)))); } } @DataProvider(name = "findQueryOperatorLike") private static Object[][] findQueryOperatorLike() { return new Object[][] { { "ring", asList(0, 1) }, { "Ring", emptyList() }, { "nomatch", emptyList() } }; } @Test(singleThreaded = true, dataProvider = "findQueryOperatorLike") public void testFindQueryOperatorLike(String likeStr, List<Integer> expectedEntityIndices) { List<Entity> entities = createDynamic(2).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Supplier<Stream<Entity>> found = () -> dataService.query(entityTypeDynamic.getName()).like(ATTR_STRING, likeStr) .findAll(); List<Entity> foundAsList = found.get().collect(toList()); assertEquals(foundAsList.size(), expectedEntityIndices.size()); for (int i = 0; i < expectedEntityIndices.size(); ++i) { assertTrue(EntityUtils.equals(foundAsList.get(i), entities.get(expectedEntityIndices.get(i)))); } } @DataProvider(name = "findQueryOperatorNot") private static Object[][] findQueryOperatorNot() { return new Object[][] { { 9, asList(0, 1, 2) }, { 10, asList(1, 2) }, { 11, asList(0, 2) }, { 12, asList(0, 1) }, { 13, asList(0, 1, 2) } }; } @Test(singleThreaded = true, dataProvider = "findQueryOperatorNot") public void testFindQueryOperatorNot(int value, List<Integer> expectedEntityIndices) { List<Entity> entities = createDynamic(3).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Supplier<Stream<Entity>> found = () -> dataService.query(entityTypeDynamic.getName()).not().eq(ATTR_INT, value) .findAll(); List<Entity> foundAsList = found.get().collect(toList()); assertEquals(foundAsList.size(), expectedEntityIndices.size()); for (int i = 0; i < expectedEntityIndices.size(); ++i) { assertTrue(EntityUtils.equals(foundAsList.get(i), entities.get(expectedEntityIndices.get(i)))); } } /** * Test used as a caching benchmark */ @Test(singleThreaded = true, enabled = false) public void cachePerformanceTest() { List<Entity> entities = createDynamic(10000).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Query q1 = new QueryImpl<>().eq(EntityTestHarness.ATTR_STRING, "string1"); q1.pageSize(1000); Query q2 = new QueryImpl<>().eq(EntityTestHarness.ATTR_BOOL, true); q2.pageSize(500); Query q3 = new QueryImpl<>().eq(ATTR_DECIMAL, 1.123); runAsSystem(() -> { for (int i = 0; i < 100000; i++) { dataService.findAll(entityTypeDynamic.getName(), q1); dataService.findAll(entityTypeDynamic.getName(), q2); dataService.findOne(entityTypeDynamic.getName(), q3); } }); } @DataProvider(name = "findQueryOperatorAnd") private static Object[][] findQueryOperatorAnd() { return new Object[][] { { "string1", 10, asList(0) }, { "unknownString", 10, emptyList() }, { "string1", -1, emptyList() }, { "unknownString", -1, emptyList() } }; } @Test(singleThreaded = true, dataProvider = "findQueryOperatorAnd") public void testFindQueryOperatorAnd(String strValue, int value, List<Integer> expectedEntityIndices) { List<Entity> entities = createDynamic(3).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Supplier<Stream<Entity>> found = () -> dataService.query(entityTypeDynamic.getName()).eq(ATTR_STRING, strValue) .and().eq(ATTR_INT, value).findAll(); List<Entity> foundAsList = found.get().collect(toList()); assertEquals(foundAsList.size(), expectedEntityIndices.size()); for (int i = 0; i < expectedEntityIndices.size(); ++i) { assertTrue(EntityUtils.equals(foundAsList.get(i), entities.get(expectedEntityIndices.get(i)))); } } @DataProvider(name = "findQueryOperatorOr") private static Object[][] findQueryOperatorOr() { return new Object[][] { { "string1", 10, asList(0, 1, 2) }, { "unknownString", 10, asList(0) }, { "string1", -1, asList(0, 1, 2) }, { "unknownString", -1, emptyList() } }; } @Test(singleThreaded = true, dataProvider = "findQueryOperatorOr") public void testFindQueryOperatorOr(String strValue, int value, List<Integer> expectedEntityIndices) { List<Entity> entities = createDynamic(3).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Supplier<Stream<Entity>> found = () -> dataService.query(entityTypeDynamic.getName()).eq(ATTR_STRING, strValue) .or().eq(ATTR_INT, value).findAll(); List<Entity> foundAsList = found.get().collect(toList()); assertEquals(foundAsList.size(), expectedEntityIndices.size()); for (int i = 0; i < expectedEntityIndices.size(); ++i) { assertTrue(EntityUtils.equals(foundAsList.get(i), entities.get(expectedEntityIndices.get(i)))); } } @DataProvider(name = "findQueryOperatorNested") private static Object[][] findQueryOperatorNested() { return new Object[][] { { true, "string1", 10, asList(0, 2) }, { true, "unknownString", 10, asList(0) }, { true, "string1", -1, asList(0, 2) }, { true, "unknownString", -1, emptyList() }, { false, "string1", 10, singletonList(1) }, { false, "unknownString", 10, emptyList() }, { false, "string1", -1, asList(1) }, { false, "unknownString", -1, emptyList() } }; } @Test(singleThreaded = true, dataProvider = "findQueryOperatorNested") public void testFindQueryOperatorNested(boolean boolValue, String strValue, int value, List<Integer> expectedEntityIndices) { List<Entity> entities = createDynamic(3).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Supplier<Stream<Entity>> found = () -> dataService.query(entityTypeDynamic.getName()).eq(ATTR_BOOL, boolValue) .and().nest().eq(ATTR_STRING, strValue).or().eq(ATTR_INT, value).unnest().findAll(); List<Entity> foundAsList = found.get().collect(toList()); assertEquals(foundAsList.size(), expectedEntityIndices.size()); for (int i = 0; i < expectedEntityIndices.size(); ++i) { assertTrue(EntityUtils.equals(foundAsList.get(i), entities.get(expectedEntityIndices.get(i)))); } } @DataProvider(name = "findQueryOperatorSearch") private static Object[][] findQueryOperatorSearch() { return new Object[][] { { "body", asList(1) }, { "head", asList(1) }, { "unknownString", emptyList() } }; } @Test(singleThreaded = true, dataProvider = "findQueryOperatorSearch") public void testFindQueryOperatorSearch(String searchStr, List<Integer> expectedEntityIndices) { List<Entity> entities = createDynamic(2).collect(toList()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Supplier<Stream<Entity>> found = () -> dataService.query(entityTypeDynamic.getName()) .search(ATTR_HTML, searchStr).findAll(); List<Entity> foundAsList = found.get().collect(toList()); assertEquals(foundAsList.size(), expectedEntityIndices.size()); for (int i = 0; i < expectedEntityIndices.size(); ++i) { assertTrue(EntityUtils.equals(foundAsList.get(i), entities.get(expectedEntityIndices.get(i)))); } } @Test(singleThreaded = true) public void testFindQueryLimit2_Offset2_sortOnInt() { List<Entity> testRefEntities = testHarness.createTestRefEntities(refEntityTypeDynamic, 6); List<Entity> testEntities = testHarness.createTestEntities(entityTypeDynamic, 10, testRefEntities) .collect(toList()); runAsSystem(() -> { dataService.add(refEntityTypeDynamic.getName(), testRefEntities.stream()); dataService.add(entityTypeDynamic.getName(), testEntities.stream()); }); waitForIndexToBeStable(refEntityTypeDynamic.getName(), indexService, LOG); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Supplier<Stream<Entity>> found = () -> dataService.findAll(entityTypeDynamic.getName(), new QueryImpl<>().pageSize(2).offset(2).sort(new Sort(ATTR_ID, Sort.Direction.DESC))); List<Entity> foundAsList = found.get().collect(toList()); assertEquals(foundAsList.size(), 2); assertTrue(EntityUtils.equals(foundAsList.get(0), testEntities.get(7))); assertTrue(EntityUtils.equals(foundAsList.get(1), testEntities.get(6))); } @Test(singleThreaded = true) public void testFindQueryTypedStatic() { List<Entity> entities = createStatic(5).collect(toList()); dataService.add(entityTypeStatic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeStatic.getName(), indexService, LOG); Supplier<Stream<TestEntityStatic>> found = () -> dataService.findAll(entityTypeStatic.getName(), new QueryImpl<TestEntityStatic>().eq(ATTR_ID, entities.get(0).getIdValue()), TestEntityStatic.class); assertEquals(found.get().count(), 1); assertEquals(found.get().findFirst().get().getId(), entities.get(0).getIdValue()); } @Test(singleThreaded = true) public void testFindOne() { Entity entity = createDynamic(1).findFirst().get(); dataService.add(entityTypeDynamic.getName(), Stream.of(entity)); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); assertNotNull(dataService.findOneById(entityTypeDynamic.getName(), entity.getIdValue())); } @Test(singleThreaded = true) public void testFindOneTypedStatic() { Entity entity = createStatic(1).findFirst().get(); dataService.add(entityTypeStatic.getName(), Stream.of(entity)); waitForIndexToBeStable(entityTypeStatic.getName(), indexService, LOG); TestEntityStatic testEntityStatic = dataService .findOneById(entityTypeStatic.getName(), entity.getIdValue(), TestEntityStatic.class); assertNotNull(testEntityStatic); assertEquals(testEntityStatic.getId(), entity.getIdValue()); } @Test(singleThreaded = true) public void testFindOneFetch() { Entity entity = createDynamic(1).findFirst().get(); dataService.add(entityTypeDynamic.getName(), Stream.of(entity)); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); assertNotNull( dataService.findOneById(entityTypeDynamic.getName(), entity.getIdValue(), new Fetch().field(ATTR_ID))); } @Test(singleThreaded = true) public void testFindOneFetchTypedStatic() { TestEntityStatic entity = new TestEntityStatic(entityTypeStatic); entity.set(ATTR_ID, "1"); entity.set(ATTR_STRING, "string1"); entity.set(ATTR_BOOL, true); dataService.add(entityTypeStatic.getName(), Stream.of(entity)); waitForIndexToBeStable(entityTypeStatic.getName(), indexService, LOG); TestEntityStatic testEntityStatic = dataService .findOneById(entityTypeStatic.getName(), entity.getIdValue(), new Fetch().field(ATTR_ID), TestEntityStatic.class); assertNotNull(testEntityStatic); assertEquals(testEntityStatic.getIdValue(), entity.getIdValue()); } @Test(singleThreaded = true) public void testFindOneQuery() { Entity entity = createDynamic(1).findFirst().get(); dataService.add(entityTypeDynamic.getName(), entity); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); entity = dataService.findOne(entityTypeDynamic.getName(), new QueryImpl<>().eq(ATTR_ID, entity.getIdValue())); assertNotNull(entity); } @Test(singleThreaded = true) public void testFindOneQueryTypedStatic() { Entity entity = createStatic(1).findFirst().get(); dataService.add(entityTypeStatic.getName(), entity); waitForIndexToBeStable(entityTypeStatic.getName(), indexService, LOG); TestEntityStatic testEntityStatic = dataService .findOne(entityTypeStatic.getName(), new QueryImpl<TestEntityStatic>().eq(ATTR_ID, entity.getIdValue()), TestEntityStatic.class); assertNotNull(testEntityStatic); assertEquals(testEntityStatic.getId(), entity.getIdValue()); } @Test(singleThreaded = true) public void testGetCapabilities() { Set<RepositoryCapability> capabilities = dataService.getCapabilities(entityTypeDynamic.getName()); assertNotNull(capabilities); assertTrue(capabilities.containsAll(asList(MANAGABLE, QUERYABLE, WRITABLE, VALIDATE_REFERENCE_CONSTRAINT))); } @Test(singleThreaded = true) public void testGetEntityType() { EntityType entityType = dataService.getEntityType(entityTypeDynamic.getName()); assertNotNull(entityType); assertTrue(EntityUtils.equals(entityType, entityTypeDynamic)); } @Test(singleThreaded = true) public void testGetEntityNames() { Stream<String> names = dataService.getEntityNames(); assertNotNull(names); assertTrue(names.filter(entityTypeDynamic.getName()::equals).findFirst().isPresent()); } @Test(singleThreaded = true) public void testGetMeta() { assertNotNull(dataService.getMeta()); } @Test(singleThreaded = true) public void testGetKnownRepository() { Repository<Entity> repo = dataService.getRepository(entityTypeDynamic.getName()); assertNotNull(repo); assertEquals(repo.getName(), entityTypeDynamic.getName()); } @Test(singleThreaded = true, expectedExceptions = UnknownEntityException.class) public void testGetUnknownRepository() { dataService.getRepository("bogus"); } @Test(singleThreaded = true) public void testHasRepository() { assertTrue(dataService.hasRepository(entityTypeDynamic.getName())); assertFalse(dataService.hasRepository("bogus")); } @Test(singleThreaded = true) public void testIterator() { assertNotNull(dataService.iterator()); StreamSupport.stream(dataService.spliterator(), false).forEach(repo -> LOG.info(repo.getName())); Repository repo = dataService.getRepository(entityTypeDynamic.getName()); /* Repository equals is not implemented. The repository from dataService and from the dataService.getRepository are not the same instances. */ assertTrue(StreamSupport.stream(dataService.spliterator(), false) .anyMatch(e -> repo.getName().equals(e.getName()))); } @Test(singleThreaded = true) public void testQuery() { assertNotNull(dataService.query(entityTypeDynamic.getName())); try { dataService.query("bogus"); fail("Should have thrown UnknownEntityException"); } catch (UnknownEntityException e) { // Expected } } @Test(singleThreaded = true) public void testUpdate() { Entity entity = createDynamic(1).findFirst().get(); dataService.add(entityTypeDynamic.getName(), entity); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); entity = dataService.findOneById(entityTypeDynamic.getName(), entity.getIdValue()); assertNotNull(entity); assertEquals(entity.get(ATTR_STRING), "string1"); Query<Entity> q = new QueryImpl<>(); q.eq(ATTR_STRING, "qwerty"); entity.set(ATTR_STRING, "qwerty"); assertEquals(searchService.count(q, entityTypeDynamic), 0); dataService.update(entityTypeDynamic.getName(), entity); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); assertEquals(searchService.count(q, entityTypeDynamic), 1); assertPresent(entityTypeDynamic, entity); entity = dataService.findOneById(entityTypeDynamic.getName(), entity.getIdValue()); assertNotNull(entity.get(ATTR_STRING)); assertEquals(entity.get(ATTR_STRING), "qwerty"); } @Test(singleThreaded = true) public void testUpdateSingleRefEntityIndexesReferencingEntities() { dataService.add(entityTypeDynamic.getName(), createDynamic(30)); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Entity refEntity4 = dataService.findOneById(refEntityTypeDynamic.getName(), "4"); Query<Entity> q = new QueryImpl<>().search("refstring4"); assertEquals(searchService.count(q, entityTypeDynamic), 5); refEntity4.set(ATTR_REF_STRING, "qwerty"); runAsSystem(() -> dataService.update(refEntityTypeDynamic.getName(), refEntity4)); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); assertEquals(searchService.count(q, entityTypeDynamic), 0); assertEquals(searchService.count(new QueryImpl<>().search("qwerty"), entityTypeDynamic), 5); } @Test(singleThreaded = true, enabled = false) //FIXME: sys_md_attributes spam public void testUpdateSingleRefEntityIndexesLargeAmountOfReferencingEntities() { dataService.add(entityTypeDynamic.getName(), createDynamic(10000)); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Query<Entity> q = new QueryImpl<>().search("refstring4").or().search("refstring5"); assertEquals(searchService.count(q, entityTypeDynamic), 3333); Entity refEntity4 = dataService.findOneById(refEntityTypeDynamic.getName(), "4"); refEntity4.set(ATTR_REF_STRING, "qwerty"); runAsSystem(() -> dataService.update(refEntityTypeDynamic.getName(), refEntity4)); Entity refEntity5 = dataService.findOneById(refEntityTypeDynamic.getName(), "5"); refEntity5.set(ATTR_REF_STRING, "qwerty"); runAsSystem(() -> dataService.update(refEntityTypeDynamic.getName(), refEntity5)); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); assertEquals(searchService.count(q, entityTypeDynamic), 0); assertEquals(searchService.count(new QueryImpl<>().search("qwerty"), entityTypeDynamic), 3333); } @Test(singleThreaded = true) public void testUpdateStream() { Entity entity = createDynamic(1).findFirst().get(); dataService.add(entityTypeDynamic.getName(), entity); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); assertPresent(entityTypeDynamic, entity); entity = dataService.findOneById(entityTypeDynamic.getName(), entity.getIdValue()); assertNotNull(entity); assertEquals(entity.get(ATTR_STRING), "string1"); entity.set(ATTR_STRING, "qwerty"); Query<Entity> q = new QueryImpl<>(); q.eq(ATTR_STRING, "qwerty"); assertEquals(searchService.count(q, entityTypeDynamic), 0); dataService.update(entityTypeDynamic.getName(), of(entity)); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); assertEquals(searchService.count(q, entityTypeDynamic), 1); assertPresent(entityTypeDynamic, entity); entity = dataService.findOneById(entityTypeDynamic.getName(), entity.getIdValue()); assertNotNull(entity.get(ATTR_STRING)); assertEquals(entity.get(ATTR_STRING), "qwerty"); } private Stream<Entity> createDynamic(int count) { List<Entity> refEntities = testHarness.createTestRefEntities(refEntityTypeDynamic, 6); runAsSystem(() -> dataService.add(refEntityTypeDynamic.getName(), refEntities.stream())); return testHarness.createTestEntities(entityTypeDynamic, count, refEntities); } private Stream<Entity> createStatic(int count) { List<Entity> refEntities = testHarness.createTestRefEntities(refEntityTypeStatic, 6); runAsSystem(() -> dataService.add(refEntityTypeStatic.getName(), refEntities.stream())); return testHarness.createTestEntities(entityTypeStatic, count, refEntities); } private void assertPresent(EntityType emd, List<Entity> entities) { entities.forEach(e -> assertPresent(emd, e)); } private void assertPresent(EntityType emd, Entity entity) { // Found in PostgreSQL assertNotNull(dataService.findOneById(emd.getName(), entity.getIdValue())); // Found in index Elasticsearch Query<Entity> q = new QueryImpl<>(); q.eq(emd.getIdAttribute().getName(), entity.getIdValue()); assertEquals(searchService.count(q, emd), 1); } private void assertNotPresent(Entity entity) { // Found in PostgreSQL assertNull(dataService.findOneById(entityTypeDynamic.getName(), entity.getIdValue())); // Not found in index Elasticsearch Query<Entity> q = new QueryImpl<>(); q.eq(entityTypeDynamic.getIdAttribute().getName(), entity.getIdValue()); assertEquals(searchService.count(q, entityTypeDynamic), 0); } @Test(singleThreaded = true) public void testCreateSelfXref() { Entity entitySelfXref = entitySelfXrefTestHarness.createTestEntities(selfXrefEntityType, 1).collect(toList()) .get(0); //Create dataService.add(selfXrefEntityType.getName(), entitySelfXref); waitForIndexToBeStable(selfXrefEntityType.getName(), indexService, LOG); Entity entity = dataService.findOneById(selfXrefEntityType.getName(), entitySelfXref.getIdValue()); assertPresent(selfXrefEntityType, entity); Query<Entity> q1 = new QueryImpl<>(); q1.eq(ATTR_STRING, "attr_string_old"); Query<Entity> q2 = new QueryImpl<>(); q2.eq(ATTR_STRING, "attr_string_new"); entity.set(ATTR_STRING, "attr_string_new"); // Verify value in elasticsearch before update assertEquals(searchService.count(q1, selfXrefEntityType), 1); assertEquals(searchService.count(q2, selfXrefEntityType), 0); // Update dataService.update(selfXrefEntityType.getName(), entity); waitForIndexToBeStable(selfXrefEntityType.getName(), indexService, LOG); assertPresent(selfXrefEntityType, entity); // Verify value in elasticsearch after update assertEquals(searchService.count(q2, selfXrefEntityType), 1); assertEquals(searchService.count(q1, selfXrefEntityType), 0); // Verify value in PostgreSQL after update entity = dataService.findOneById(selfXrefEntityType.getName(), entity.getIdValue()); assertNotNull(entity.get(ATTR_STRING)); assertEquals(entity.get(ATTR_STRING), "attr_string_new"); // Check id are equals assertEquals(entity.getEntity(ATTR_XREF).getIdValue(), entity.getIdValue()); } @Test(singleThreaded = true) public void testIndexCreateMetaData() { IndexMetadataCUDOperationsPlatformIT .testIndexCreateMetaData(searchService, entityTypeStatic, entityTypeDynamic, metaDataService); } @Test(singleThreaded = true) public void testIndexDeleteMetaData() { IndexMetadataCUDOperationsPlatformIT .testIndexDeleteMetaData(searchService, dataService, entityTypeDynamic, metaDataService, indexService); } @Test(singleThreaded = true) public void testIndexUpdateMetaDataUpdateAttribute() { IndexMetadataCUDOperationsPlatformIT .testIndexUpdateMetaDataUpdateAttribute(searchService, entityTypeDynamic, metaDataService, indexService); } @Test(singleThreaded = true) public void testIndexUpdateMetaDataRemoveAttribute() { IndexMetadataCUDOperationsPlatformIT .testIndexUpdateMetaDataRemoveAttribute(entityTypeDynamic, EntityTestHarness.ATTR_CATEGORICAL, searchService, metaDataService, indexService); IndexMetadataCUDOperationsPlatformIT .testIndexUpdateMetaDataRemoveAttribute(entityTypeDynamic, EntityTestHarness.ATTR_BOOL, searchService, metaDataService, indexService); IndexMetadataCUDOperationsPlatformIT .testIndexUpdateMetaDataRemoveAttribute(entityTypeDynamic, EntityTestHarness.ATTR_DATE, searchService, metaDataService, indexService); IndexMetadataCUDOperationsPlatformIT .testIndexUpdateMetaDataRemoveAttribute(entityTypeDynamic, EntityTestHarness.ATTR_XREF, searchService, metaDataService, indexService); IndexMetadataCUDOperationsPlatformIT .testIndexUpdateMetaDataRemoveAttribute(entityTypeDynamic, EntityTestHarness.ATTR_DATETIME, searchService, metaDataService, indexService); IndexMetadataCUDOperationsPlatformIT .testIndexUpdateMetaDataRemoveAttribute(entityTypeDynamic, EntityTestHarness.ATTR_DECIMAL, searchService, metaDataService, indexService); IndexMetadataCUDOperationsPlatformIT .testIndexUpdateMetaDataRemoveAttribute(entityTypeDynamic, EntityTestHarness.ATTR_EMAIL, searchService, metaDataService, indexService); IndexMetadataCUDOperationsPlatformIT .testIndexUpdateMetaDataRemoveAttribute(entityTypeDynamic, EntityTestHarness.ATTR_HTML, searchService, metaDataService, indexService); IndexMetadataCUDOperationsPlatformIT .testIndexUpdateMetaDataRemoveAttribute(entityTypeDynamic, EntityTestHarness.ATTR_INT, searchService, metaDataService, indexService); IndexMetadataCUDOperationsPlatformIT .testIndexUpdateMetaDataRemoveAttribute(entityTypeDynamic, EntityTestHarness.ATTR_HYPERLINK, searchService, metaDataService, indexService); IndexMetadataCUDOperationsPlatformIT .testIndexUpdateMetaDataRemoveAttribute(entityTypeDynamic, EntityTestHarness.ATTR_COMPOUND, searchService, metaDataService, indexService); } // Derived from fix: https://github.com/molgenis/molgenis/issues/5227 @Test(singleThreaded = true) public void testIndexBatchUpdate() { List<Entity> refEntities = testHarness.createTestRefEntities(refEntityTypeDynamic, 2); List<Entity> entities = testHarness.createTestEntities(entityTypeDynamic, 2, refEntities).collect(toList()); runAsSystem(() -> { dataService.add(refEntityTypeDynamic.getName(), refEntities.stream()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); }); // test string1 from entity Query<Entity> q0 = new QueryImpl<>(); q0.search("string1"); Stream<Entity> result0 = searchService.searchAsStream(q0, entityTypeDynamic); assertEquals(result0.count(), 2); // test refstring1 from ref entity Query<Entity> q1 = new QueryImpl<>(); q1.search("refstring0"); Stream<Entity> result1 = searchService.searchAsStream(q1, entityTypeDynamic); assertEquals(result1.count(), 1); // test refstring1 from ref entity Query<Entity> q2 = new QueryImpl<>(); q2.search("refstring1"); Stream<Entity> result2 = searchService.searchAsStream(q2, entityTypeDynamic); assertEquals(result2.count(), 1); refEntities.get(0).set(ATTR_REF_STRING, "searchTestBatchUpdate"); runAsSystem(() -> { dataService.update(refEntityTypeDynamic.getName(), refEntities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); }); // test string1 from entity Stream<Entity> result3 = searchService.searchAsStream(q0, entityTypeDynamic); assertEquals(result3.count(), 2); // test refstring1 from ref entity Query<Entity> q4 = new QueryImpl<>(); q4.search("refstring0"); Stream<Entity> result4 = searchService.searchAsStream(q4, entityTypeDynamic); assertEquals(result4.count(), 0); // test refstring1 from ref entity Query<Entity> q5 = new QueryImpl<>(); q5.search("refstring1"); Stream<Entity> result5 = searchService.searchAsStream(q5, entityTypeDynamic); assertEquals(result5.count(), 1); // test refstring1 from ref entity Query<Entity> q6 = new QueryImpl<>(); q6.search("searchTestBatchUpdate"); Stream<Entity> result6 = searchService.searchAsStream(q6, entityTypeDynamic); assertEquals(result6.count(), 1); } /** * Test add and remove of a single attribute of a dynamic entity */ @Test(singleThreaded = true) public void addAndDeleteSingleAttribute() { final String NEW_ATTRIBUTE = "new_attribute"; Attribute newAttr = attributeFactory.create().setName(NEW_ATTRIBUTE); EntityType entityType = dataService.getEntityType(entityTypeDynamic.getName()); newAttr.setEntity(entityType); runAsSystem(() -> { dataService.getMeta().addAttribute(newAttr); List<Entity> refEntities = testHarness.createTestRefEntities(refEntityTypeDynamic, 2); List<Entity> entities = testHarness.createTestEntities(entityTypeDynamic, 2, refEntities).collect(toList()); dataService.add(refEntityTypeDynamic.getName(), refEntities.stream()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); dataService.update(entityType.getName(), StreamSupport.stream(dataService.findAll(entityType.getName()).spliterator(), false) .peek(e -> e.set(NEW_ATTRIBUTE, "NEW_ATTRIBUTE_" + e.getIdValue()))); }); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); // Tunnel via L3 flow Query<Entity> q0 = new QueryImpl<>().eq(NEW_ATTRIBUTE, "NEW_ATTRIBUTE_0").or() .eq(NEW_ATTRIBUTE, "NEW_ATTRIBUTE_1"); q0.pageSize(10); // L3 only caches queries with a page size q0.sort(new Sort().on(NEW_ATTRIBUTE)); runAsSystem(() -> { List expected = dataService.findAll(entityTypeDynamic.getName(), q0).map(Entity::getIdValue) .collect(toList()); assertEquals(expected, Arrays.asList("0", "1")); // Remove added attribute dataService.getMeta().deleteAttributeById(newAttr.getIdValue()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); }); // verify attribute is deleted by adding and removing it again runAsSystem(() -> { // Add attribute dataService.getMeta().addAttribute(newAttr); // Delete attribute dataService.getMeta().deleteAttributeById(newAttr.getIdValue()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); }); } /** * Test add stream attribute of a dynamic entity */ @Test(singleThreaded = true) public void addStreamAttribute() { final String NEW_ATTRIBUTE = "new_attribute"; Attribute newAttr = attributeFactory.create().setName(NEW_ATTRIBUTE); EntityType entityType = dataService.getEntityType(entityTypeDynamic.getName()); newAttr.setEntity(entityType); runAsSystem(() -> { dataService.getMeta().addAttributes(entityType.getName(), Stream.of(newAttr)); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); Attribute attribute = dataService.findOneById(ATTRIBUTE_META_DATA, newAttr.getIdValue(), Attribute.class); assertNotNull(attribute); // Tunnel via L3 flow Query<Entity> q0 = new QueryImpl<>().eq(NEW_ATTRIBUTE, "NEW_ATTRIBUTE_0").or() .eq(NEW_ATTRIBUTE, "NEW_ATTRIBUTE_1"); q0.pageSize(10); // L3 only caches queries with a page size q0.sort(new Sort().on(NEW_ATTRIBUTE)); List expected = dataService.findAll(entityTypeDynamic.getName(), q0).map(Entity::getIdValue) .collect(toList()); assertEquals(expected, Arrays.asList()); // Remove added attribute dataService.getMeta().deleteAttributeById(newAttr.getIdValue()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); }); } /** * Test update of a single attribute of a dynamic entity */ @Test(singleThreaded = true) public void updateAttribute() { final String NEW_ATTRIBUTE = "new_attribute"; Attribute newAttr = attributeFactory.create().setName(NEW_ATTRIBUTE); EntityType entityType = dataService.getEntityType(entityTypeDynamic.getName()); newAttr.setEntity(entityType); // Add attribute runAsSystem(() -> { dataService.getMeta().addAttribute(newAttr); List<Entity> refEntities = testHarness.createTestRefEntities(refEntityTypeDynamic, 2); List<Entity> entities = testHarness.createTestEntities(entityTypeDynamic, 2, refEntities).collect(toList()); dataService.add(refEntityTypeDynamic.getName(), refEntities.stream()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); dataService.update(entityType.getName(), StreamSupport.stream(dataService.findAll(entityType.getName()).spliterator(), false) .peek(e -> e.set(NEW_ATTRIBUTE, "NEW_ATTRIBUTE_" + e.getIdValue()))); }); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); // Verify old values assertNotEquals(newAttr.getSequenceNumber(), 0); assertFalse(newAttr.isReadOnly()); assertFalse(newAttr.isUnique()); assertNotEquals(newAttr.getLabel(), "test"); assertNotEquals(newAttr.getDescription(), "test"); assertTrue(newAttr.isNillable()); // New values newAttr.setSequenceNumber(0); newAttr.setReadOnly(true); newAttr.setUnique(true); newAttr.setLabel("test"); newAttr.setNillable(false); newAttr.setDescription("test"); // Update attribute runAsSystem(() -> { // Update added attribute dataService.update(ATTRIBUTE_META_DATA, newAttr); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); }); Attribute attr = dataService.findOneById(ATTRIBUTE_META_DATA, newAttr.getIdValue(), Attribute.class); assertEquals(attr.getSequenceNumber(), Integer.valueOf(0)); assertTrue(attr.isReadOnly()); assertTrue(attr.isUnique()); assertEquals(attr.getLabel(), "test"); assertEquals(attr.getDescription(), "test"); // Delete attribute runAsSystem(() -> { // Remove added attribute dataService.getMeta().deleteAttributeById(newAttr.getIdValue()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); }); } /* * Test add and remove of a single attribute of a dynamic entity */ @Test(singleThreaded = true) public void addAndDeleteSingleAttributeStream() { final String NEW_ATTRIBUTE = "new_attribute"; Attribute newAttr = attributeFactory.create().setName(NEW_ATTRIBUTE); EntityType entityType = dataService.getEntityType(entityTypeDynamic.getName()); newAttr.setEntity(entityType); newAttr.setSequenceNumber(2); entityType.addAttribute(newAttr); assertEquals(newAttr.getSequenceNumber(), Integer.valueOf(2)); // Test if sequence number is 2 runAsSystem(() -> { dataService.update(ENTITY_TYPE_META_DATA, Stream.of(entityType)); // Adds the column to the table dataService.add(ATTRIBUTE_META_DATA, Stream.of(newAttr)); List<Entity> refEntities = testHarness.createTestRefEntities(refEntityTypeDynamic, 2); List<Entity> entities = testHarness.createTestEntities(entityTypeDynamic, 2, refEntities).collect(toList()); dataService.add(refEntityTypeDynamic.getName(), refEntities.stream()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); dataService.update(entityType.getName(), StreamSupport.stream(dataService.findAll(entityType.getName()).spliterator(), false) .peek(e -> e.set(NEW_ATTRIBUTE, "NEW_ATTRIBUTE_" + e.getIdValue()))); }); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); // Tunnel via L3 flow Query<Entity> q0 = new QueryImpl<>().eq(NEW_ATTRIBUTE, "NEW_ATTRIBUTE_0").or() .eq(NEW_ATTRIBUTE, "NEW_ATTRIBUTE_1"); q0.pageSize(10); // L3 only caches queries with a page size q0.sort(new Sort().on(NEW_ATTRIBUTE)); runAsSystem(() -> { List expected = dataService.findAll(entityTypeDynamic.getName(), q0).map(Entity::getIdValue) .collect(toList()); assertEquals(expected, Arrays.asList("0", "1")); // Remove added attribute entityType.removeAttribute(newAttr); dataService.update(ENTITY_TYPE_META_DATA, Stream.of(entityType)); dataService.delete(ATTRIBUTE_META_DATA, Stream.of(newAttr)); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); }); // verify attribute is deleted by adding and removing it again runAsSystem(() -> { entityType.addAttribute(newAttr); dataService.update(ENTITY_TYPE_META_DATA, Stream.of(entityType)); dataService.add(ATTRIBUTE_META_DATA, Stream.of(newAttr)); // Remove added attribute entityType.removeAttribute(newAttr); dataService.update(ENTITY_TYPE_META_DATA, Stream.of(entityType)); dataService.delete(ATTRIBUTE_META_DATA, Stream.of(newAttr)); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); }); } @Test(singleThreaded = true) @Transactional public void storeIndexActions() { List<Entity> refEntities = testHarness.createTestRefEntities(refEntityTypeDynamic, 2); List<Entity> entities = testHarness.createTestEntities(entityTypeDynamic, 2, refEntities).collect(toList()); runAsSystem(() -> { dataService.add(refEntityTypeDynamic.getName(), refEntities.stream()); dataService.add(entityTypeDynamic.getName(), entities.stream()); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); indexActionRegisterService.register(entityTypeDynamic.getName(), "1"); indexActionRegisterService.register(entityTypeDynamic.getName(), null); Query q = new QueryImpl(); q.eq(IndexActionMetaData.ENTITY_FULL_NAME, "sys_test_TypeTestDynamic"); Stream<org.molgenis.data.index.meta.IndexAction> all = dataService .findAll(IndexActionMetaData.INDEX_ACTION, q); all.forEach(e -> { LOG.info(e.getEntityFullName() + "." + e.getEntityId()); }); waitForIndexToBeStable(entityTypeDynamic.getName(), indexService, LOG); }); } }