package org.molgenis.integrationtest.platform; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import org.mockito.Mockito; import org.molgenis.data.FileRepositoryCollectionFactory; import org.molgenis.data.MolgenisDataAccessException; import org.molgenis.data.importer.EntityImportReport; import org.molgenis.data.importer.ImportService; import org.molgenis.data.importer.ImportServiceFactory; import org.molgenis.data.importer.ImportServiceRegistrar; import org.molgenis.data.support.FileRepositoryCollection; import org.molgenis.util.ResourceUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; import org.springframework.test.context.transaction.TransactionConfiguration; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.io.File; import java.util.*; import java.util.stream.Collectors; import static java.util.Arrays.asList; import static java.util.Collections.emptyMap; import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.toSet; import static org.molgenis.data.DatabaseAction.ADD; import static org.molgenis.data.DatabaseAction.ADD_UPDATE_EXISTING; import static org.molgenis.data.meta.DefaultPackage.PACKAGE_DEFAULT; import static org.molgenis.data.meta.model.Package.PACKAGE_SEPARATOR; import static org.testng.Assert.assertEquals; /** * Test the Importer test cases */ @TransactionConfiguration(defaultRollback = false) @ContextConfiguration(classes = { PlatformITConfig.class }) @TestExecutionListeners(listeners = WithSecurityContextTestExecutionListener.class) public class ImportServiceIT extends AbstractTestNGSpringContextTests { private final static Logger LOG = LoggerFactory.getLogger(ImportServiceIT.class); @Autowired private ImportServiceFactory importServiceFactory; @Autowired private FileRepositoryCollectionFactory fileRepositoryCollectionFactory; @Autowired private ImportServiceRegistrar importServiceRegistrar; @BeforeClass public void beforeClass() { ContextRefreshedEvent contextRefreshedEvent = Mockito.mock(ContextRefreshedEvent.class); Mockito.when(contextRefreshedEvent.getApplicationContext()).thenReturn(applicationContext); importServiceRegistrar.register(contextRefreshedEvent); } @DataProvider(name = "doImportEmxAddProvider") public Iterator<Object[]> doImportEmxAddProvider() { List<Object[]> data = new ArrayList<>(); data.add(createAddData("it_emx_datatypes.xlsx", asList("it", "emx", "datatypes"), ImmutableMap.<String, Integer>builder().put("TypeTestRef", 5).put("TypeTest", 38).build(), ImmutableSet.of("Person", "TypeTestRef", "Location", "TypeTest"))); data.add(createAddData("it_emx_deep_nesting.xlsx", asList("it", "deep"), ImmutableMap.<String, Integer>builder().put("TestCategorical_1", 50).put("TestMref_1", 50) .put("TestXref_2", 50).put("TestXref_1", 50) .put("advanced" + PACKAGE_SEPARATOR + "p" + PACKAGE_SEPARATOR + "TestEntity_2", 50).build(), ImmutableSet.of("TestCategorical_1", "TestMref_1", "TestXref_2", "TestXref_1", "TestEntity_0", "advanced_TestEntity_1", "advanced_p_TestEntity_2"))); data.add(createAddData("it_emx_lookup_attribute.xlsx", asList("it", "emx", "lookupattribute"), ImmutableMap.<String, Integer>builder().put("Ref1", 2).put("Ref2", 2).put("Ref3", 2).put("Ref4", 2) .put("Ref5", 2).build(), ImmutableSet .of("AbstractTop", "AbstractMiddle", "Ref1", "Ref2", "Ref3", "Ref4", "Ref5", "TestLookupAttributes"))); data.add(createAddData("it_emx_autoid.xlsx", asList("it", "emx", "autoid"), ImmutableMap.of("testAutoId", 4), ImmutableSet.of("testAutoId"))); data.add(createAddData("it_emx_onetomany.xlsx", asList("it", "emx", "onetomany"), ImmutableMap.<String, Integer>builder().put("book", 4).put("author", 2).put("node", 4).build(), ImmutableSet.of("book", "author", "node"))); data.add(createAddData("it_emx_self_references.xlsx", asList("it", "emx", "selfreferences"), ImmutableMap.of("PersonTest", 11), ImmutableSet.of("PersonTest"))); data.add(createAddData("it_emx_tags.xlsx", asList("it", "emx", "tags"), emptyMap(), ImmutableSet.of("TagEntity"))); return data.iterator(); } @Test(dataProvider = "doImportEmxAddProvider") @WithMockUser(username = "SYSTEM", authorities = { "ROLE_SYSTEM" }) public void testDoImportAddEmx(File file, Map<String, Integer> entityCountMap, Set<String> addedEntityTypes) { FileRepositoryCollection repoCollection = fileRepositoryCollectionFactory.createFileRepositoryCollection(file); ImportService importService = importServiceFactory.getImportService(file, repoCollection); EntityImportReport importReport = importService.doImport(repoCollection, ADD, PACKAGE_DEFAULT); validateImportReport(importReport, entityCountMap, addedEntityTypes); } @DataProvider(name = "doImportEmxAddUpdateProvider") public Iterator<Object[]> doImportEmxAddUpdateProvider() { List<Object[]> data = new ArrayList<>(); data.add(createUpdateData("it_emx_addupdate.xlsx", "it_emx_addupdate-addupdate.xlsx", asList("it", "emx", "addupdate"), ImmutableMap.<String, Integer>builder().put("TestAddUpdate", 3).build(), Collections.emptySet())); return data.iterator(); } @Test(dataProvider = "doImportEmxAddUpdateProvider") @WithMockUser(username = "SYSTEM", authorities = { "ROLE_SYSTEM" }) public void testDoImportAddUpdateEmx(File file, File addUpdateFile, Map<String, Integer> entityCountMap, Set<String> addedEntityTypes) { executeAddUpdateOrUpdateTest(file, addUpdateFile, entityCountMap, addedEntityTypes); } private void executeAddUpdateOrUpdateTest(File file, File addUpdateFile, Map<String, Integer> entityCountMap, Set<String> addedEntityTypes) { FileRepositoryCollection addRepoCollection = fileRepositoryCollectionFactory .createFileRepositoryCollection(file); ImportService addImportService = importServiceFactory.getImportService(file, addRepoCollection); addImportService.doImport(addRepoCollection, ADD, PACKAGE_DEFAULT); FileRepositoryCollection addUpdateRepoCollection = fileRepositoryCollectionFactory .createFileRepositoryCollection(addUpdateFile); ImportService addUpdateImportService = importServiceFactory .getImportService(addUpdateFile, addUpdateRepoCollection); EntityImportReport importReport = addUpdateImportService .doImport(addUpdateRepoCollection, ADD_UPDATE_EXISTING, PACKAGE_DEFAULT); validateImportReport(importReport, entityCountMap, addedEntityTypes); } @DataProvider(name = "doImportEmxUpdateProvider") public Iterator<Object[]> doImportEmxUpdateProvider() { List<Object[]> data = new ArrayList<>(); data.add(createUpdateData("it_emx_update.xlsx", "it_emx_update-update.xlsx", asList("it", "emx", "update"), ImmutableMap.<String, Integer>builder().put("TestUpdate", 2).build(), Collections.emptySet())); return data.iterator(); } @Test(dataProvider = "doImportEmxUpdateProvider") @WithMockUser(username = "SYSTEM", authorities = { "ROLE_SYSTEM" }) public void testDoImportUpdateEmx(File file, File updateFile, Map<String, Integer> entityCountMap, Set<String> addedEntityTypes) { executeAddUpdateOrUpdateTest(file, updateFile, entityCountMap, addedEntityTypes); } @DataProvider(name = "doImportEmxUpdateAsNonSuperuserProvider") public Iterator<Object[]> doImportEmxUpdateAsNonSuperuserProvider() { List<Object[]> data = new ArrayList<>(); data.add(createUpdateData("it_emx_nonsu_update.xlsx", "it_emx_nonsu_update-update.xlsx", asList("it", "emx", "nonsu", "update"), ImmutableMap.<String, Integer>builder().put("TestUpdate", 2).build(), Collections.emptySet())); return data.iterator(); } @Test(dataProvider = "doImportEmxUpdateAsNonSuperuserProvider") @WithMockUser(username = "user", authorities = { "ROLE_SU" }) public void testDoImportUpdateAsNonSuperuserEmx(File file, File updateFile, Map<String, Integer> entityCountMap, Set<String> addedEntityTypes) { executeAddUpdateOrUpdateTest(file, updateFile, entityCountMap, addedEntityTypes); } private static Object[] createAddData(String fileName, List<String> packageTokens, Map<String, Integer> entityCountMap, Set<String> entityTypeNames) { File file = getFile("/xls/" + fileName); String packageName = String.join(PACKAGE_SEPARATOR, packageTokens); Map<String, Object> entityTypeCountMap = entityCountMap.entrySet().stream().collect( Collectors.toMap(entry -> packageName + PACKAGE_SEPARATOR + entry.getKey(), Map.Entry::getValue)); Set<String> entityTypeFullyQualifiedNames = entityTypeNames.stream() .map(entityName -> packageName + PACKAGE_SEPARATOR + entityName).collect(toSet()); return new Object[] { file, entityTypeCountMap, entityTypeFullyQualifiedNames }; } private static Object[] createUpdateData(String fileName, String updateFileName, List<String> packageTokens, Map<String, Integer> entityCountMap, Set<String> entityTypeNames) { File addFile = getFile("/xls/" + fileName); File updateFile = getFile("/xls/" + updateFileName); String packageName = String.join(PACKAGE_SEPARATOR, packageTokens); Map<String, Object> entityTypeCountMap = entityCountMap.entrySet().stream().collect( Collectors.toMap(entry -> packageName + PACKAGE_SEPARATOR + entry.getKey(), Map.Entry::getValue)); Set<String> entityTypeFullyQualifiedNames = entityTypeNames.stream() .map(entityName -> packageName + PACKAGE_SEPARATOR + entityName).collect(toSet()); return new Object[] { addFile, updateFile, entityTypeCountMap, entityTypeFullyQualifiedNames }; } private static void validateImportReport(EntityImportReport importReport, Map<String, Integer> entityTypeCountMap, Set<String> addedEntityTypeIds) { assertEquals(ImmutableSet.copyOf(importReport.getNewEntities()), addedEntityTypeIds); assertEquals(importReport.getNrImportedEntitiesMap(), entityTypeCountMap); } private static File getFile(String resourceName) { requireNonNull(resourceName); try { File file = ResourceUtils.getFile(ImportServiceIT.class, resourceName); LOG.trace("emx import integration test file: [{}]", file); return file; } catch (Exception e) { LOG.error("File name: [{}]", resourceName); throw new MolgenisDataAccessException(e); } } }