ImportersTest.java
/**
* Copyright (c) 2017, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.iidm.network;
import com.powsybl.commons.PowsyblException;
import com.powsybl.commons.datasource.DataSource;
import com.powsybl.commons.datasource.DirectoryDataSource;
import com.powsybl.commons.datasource.ReadOnlyDataSource;
import com.powsybl.commons.report.PowsyblCoreReportResourceBundle;
import com.powsybl.commons.test.PowsyblCoreTestReportResourceBundle;
import com.powsybl.commons.report.ReportNode;
import com.powsybl.commons.test.TestUtil;
import com.powsybl.computation.ComputationManager;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.ExecutionException;
import static org.junit.jupiter.api.Assertions.*;
/**
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
*/
class ImportersTest extends AbstractConvertersTest {
private static final String WORK_DIR = "/work/";
private static final String FOO_TST = "foo.tst";
private final Importer testImporter = new TestImporter();
private final ImportPostProcessor testImportPostProcessor = new TestImportPostProcessor();
private final ImportersLoader loader = new ImportersLoaderList(Collections.singletonList(testImporter),
Collections.singletonList(testImportPostProcessor));
private final ComputationManager computationManager = Mockito.mock(ComputationManager.class);
private final ImportConfig importConfigMock = Mockito.mock(ImportConfig.class);
private final ImportConfig importConfigWithPostProcessor = new ImportConfig("test");
private final NetworkFactory networkFactory = new NetworkFactoryMock();
@BeforeEach
@Override
void setUp() throws IOException {
super.setUp();
Files.createFile(fileSystem.getPath(WORK_DIR + FOO_TST));
Files.createFile(fileSystem.getPath(WORK_DIR + "bar.tst"));
Files.createFile(fileSystem.getPath(WORK_DIR + "baz.txt"));
}
@Test
void getFormat() {
Collection<String> formats = Importer.getFormats(loader);
assertNotNull(formats);
assertEquals(1, formats.size());
assertTrue(formats.contains(TEST_FORMAT));
}
@Test
void list() {
Collection<Importer> importers = Importer.list(loader, computationManager, importConfigMock);
assertNotNull(importers);
assertEquals(1, importers.size());
assertTrue(importers.contains(testImporter));
}
@Test
void getImporter() {
Importer importer = Importer.find(loader, TEST_FORMAT, computationManager, importConfigMock);
assertNotNull(importer);
assertSame(testImporter, importer);
}
@Test
void getImporterWithImportConfig() {
Importer importer = Importer.find(loader, TEST_FORMAT, computationManager, importConfigWithPostProcessor);
assertNotNull(importer);
Network network = importer.importData(null, networkFactory, null);
assertNotNull(network);
assertEquals(LoadType.FICTITIOUS, network.getLoad("LOAD").getLoadType());
}
@Test
void getImporterWithImportConfigAndReportNode() throws IOException {
Importer importer = Importer.find(loader, TEST_FORMAT, computationManager, importConfigWithPostProcessor);
ReportNode reportNode = ReportNode.newRootReportNode()
.withResourceBundles(PowsyblCoreTestReportResourceBundle.TEST_BASE_NAME, PowsyblCoreReportResourceBundle.BASE_NAME)
.withMessageTemplate("testFunctionalLog")
.build();
assertNotNull(importer);
Network network = importer.importData(null, networkFactory, null, reportNode);
assertNotNull(network);
assertEquals(LoadType.FICTITIOUS, network.getLoad("LOAD").getLoadType());
// Check that the wrapped importer has received the functional logs reportNode and produced report items
assertEquals(1, reportNode.getChildren().size());
StringWriter sw = new StringWriter();
reportNode.print(sw);
String actual = TestUtil.normalizeLineSeparator(sw.toString());
String expected = TestUtil.normalizeLineSeparator(
"+ testFunctionalLogs\n" +
" Import model eurostagTutorialExample1\n");
assertEquals(expected, actual);
}
@Test
void getNullImporter() {
Importer importer = Importer.find(loader, UNSUPPORTED_FORMAT, computationManager, importConfigMock);
assertNull(importer);
}
@Test
void getPostProcessorNames() {
Collection<String> names = Importer.getPostProcessorNames(loader);
assertNotNull(names);
assertEquals(1, names.size());
assertTrue(names.contains("test"));
}
@Test
void addAndRemovePostProcessor() {
Importer importer1 = Importer.addPostProcessors(loader, testImporter, computationManager, "test");
Network network1 = importer1.importData(null, networkFactory, null);
assertNotNull(network1);
assertEquals(LoadType.FICTITIOUS, network1.getLoad("LOAD").getLoadType());
Importer importer2 = Importer.removePostProcessors(importer1);
Network network2 = importer2.importData(null, networkFactory, null);
assertNotNull(network2);
assertEquals(LoadType.UNDEFINED, network2.getLoad("LOAD").getLoadType());
}
@Test
void setPostProcessor() {
Importer importer = Importer.setPostProcessors(loader, testImporter, computationManager, "test");
Network network = importer.importData(null, networkFactory, null);
assertNotNull(network);
assertEquals(LoadType.FICTITIOUS, network.getLoad("LOAD").getLoadType());
}
@Test
void importBadData() {
PowsyblException e = assertThrows(PowsyblException.class, () -> Importers.importData(loader, UNSUPPORTED_FORMAT, null, null, computationManager, importConfigMock));
assertEquals("Import format " + UNSUPPORTED_FORMAT + " not supported", e.getMessage());
}
@Test
void importAll() throws InterruptedException, ExecutionException, IOException {
List<Boolean> isLoadPresent = new ArrayList<>();
Importers.importAll(fileSystem.getPath(WORK_DIR), testImporter, false, null, n -> isLoadPresent.add(n.getLoad("LOAD") != null), null, networkFactory, ReportNode.NO_OP);
assertEquals(2, isLoadPresent.size());
isLoadPresent.forEach(Assertions::assertTrue);
}
@Test
void importAllParallel() throws InterruptedException, ExecutionException, IOException {
List<Boolean> isLoadPresent = Collections.synchronizedList(new ArrayList<>());
Importers.importAll(fileSystem.getPath(WORK_DIR), testImporter, true, null, n -> isLoadPresent.add(n.getLoad("LOAD") != null), null, networkFactory, ReportNode.NO_OP);
assertEquals(2, isLoadPresent.size());
isLoadPresent.forEach(Assertions::assertTrue);
}
@Test
void createDataSource1() throws IOException {
DataSource dataSource = new DirectoryDataSource(fileSystem.getPath(WORK_DIR), "foo");
assertTrue(dataSource.exists(FOO_TST));
}
@Test
void createDataSource2() throws IOException {
DataSource dataSource = DataSource.fromPath(path);
assertTrue(dataSource.exists(FOO_TST));
}
@Test
void findImporter() {
Importer importer = Importer.find(DataSource.fromPath(path), loader, computationManager, importConfigMock);
assertNotNull(importer);
assertEquals(testImporter, importer);
}
@Test
void findNullImporter() {
Importer importer = Importer.find(DataSource.fromPath(badPath), loader, computationManager, importConfigMock);
assertNull(importer);
}
@Test
void loadNetwork1() {
Network network = Network.read(path, computationManager, importConfigMock, null, networkFactory, loader, ReportNode.NO_OP);
assertNotNull(network);
assertNotNull(network.getLoad("LOAD"));
}
@Test
void loadNullNetwork1() {
PowsyblException e = assertThrows(PowsyblException.class, () -> Network.read(badPath, computationManager, importConfigMock, null, networkFactory, loader, ReportNode.NO_OP));
assertEquals("Unsupported file format or invalid file.", e.getMessage());
}
@Test
void loadNetwork2() throws IOException {
try (var is = DataSource.fromPath(path).newInputStream(null, EXTENSION)) {
Network network = Network.read(FOO_TST, is, computationManager, importConfigMock, null, networkFactory, loader, ReportNode.NO_OP);
assertNotNull(network);
assertNotNull(network.getLoad("LOAD"));
}
}
@Test
void loadNullNetwork2() throws IOException {
InputStream is = DataSource.fromPath(badPath).newInputStream(null, "txt");
PowsyblException e = assertThrows(PowsyblException.class, () -> Network.read("baz.txt", is, computationManager, importConfigMock, null, networkFactory, loader, ReportNode.NO_OP));
assertEquals("Unsupported file format or invalid file.", e.getMessage());
}
@Test
void loadNetworks() throws InterruptedException, ExecutionException, IOException {
List<Boolean> isLoadPresent = new ArrayList<>();
Network.readAll(fileSystem.getPath(WORK_DIR), false, loader, computationManager, importConfigMock, null, n -> isLoadPresent.add(n.getLoad("LOAD") != null), null, networkFactory, ReportNode.NO_OP);
assertEquals(2, isLoadPresent.size());
isLoadPresent.forEach(Assertions::assertTrue);
}
@Test
void updateNetwork() {
Network network = Network.read(path, computationManager, importConfigMock, null, networkFactory, loader, ReportNode.NO_OP);
assertNotNull(network);
Load load = network.getLoad("LOAD");
assertNotNull(load);
// The mocked network simulates P0 is not set in first import, but is read when we call update
assertTrue(Double.isNaN(load.getP0()));
network.update(DataSource.fromPath(path), computationManager, importConfigMock, null, loader, ReportNode.NO_OP);
assertEquals(123.0, load.getP0());
}
@Test
void updateNetworkWithDefaultServiceLoader() {
Network network = Network.read(path, computationManager, importConfigMock, null, networkFactory, loader, ReportNode.NO_OP);
assertNotNull(network);
Load load = network.getLoad("LOAD");
assertNotNull(load);
ReadOnlyDataSource ds = DataSource.fromPath(path);
// The mocked network simulates P0 is not set in first import, but is read when we call update
assertTrue(Double.isNaN(load.getP0()));
// The test importer should be loadable with the default importer service loader,
// by passing only the data source we will cover the update method overloads
network.update(ds);
assertEquals(123.0, load.getP0());
// Another way of invoking the update, calling directly the importer to cover more overloads
load.setP0(0.0);
assertEquals(0.0, load.getP0());
new TestImporter().update(network, ds, new Properties());
assertEquals(123.0, load.getP0());
}
@Test
void updateNetworkWithBadData() throws IOException {
Network network = Network.read(path, computationManager, importConfigMock, null, networkFactory, loader, ReportNode.NO_OP);
assertNotNull(network);
Load load = network.getLoad("LOAD");
assertNotNull(load);
Path fileBadData = fileSystem.getPath(WORK_DIR + "bad-data.not-valid-extension-for-test-importer");
Files.createFile(fileBadData);
ReadOnlyDataSource ds = DataSource.fromPath(fileBadData);
PowsyblException e = assertThrows(
PowsyblException.class,
() -> network.update(ds, computationManager, importConfigMock, null, loader, ReportNode.NO_OP));
assertEquals("Unsupported file format or invalid file.", e.getMessage());
Files.delete(fileBadData);
}
@Test
void tryUpdateNetworkUsingImporterWithoutUpdateImplementation() throws IOException {
Path fileQux = fileSystem.getPath(WORK_DIR + "qux.tst-extension-no-updates");
Files.createFile(fileQux);
ImportersLoader loader1 = new ImportersLoaderList(Collections.singletonList(new TestImporterWithoutUpdate()));
Network network = Network.read(fileQux, computationManager, importConfigMock, null, networkFactory, loader1, ReportNode.NO_OP);
assertNotNull(network);
ReadOnlyDataSource ds = DataSource.fromPath(fileQux);
UnsupportedOperationException e = assertThrows(
UnsupportedOperationException.class,
() -> network.update(ds, computationManager, importConfigMock, null, loader1, ReportNode.NO_OP));
assertEquals("Importer do not implement updates", e.getMessage());
Files.delete(fileQux);
}
}