diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ControlBlockService.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ControlBlockService.java index 87af47858..59f0b8b7e 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ControlBlockService.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ControlBlockService.java @@ -216,7 +216,7 @@ public SettingsOrError getNetworkSettings(ControlBlockAdapter controlBlockAdapte compasICDHeader.get().getIEDSystemVersioninstance(), bayIntOrExt); Settings settings = comSettingsByCriteria.get(criteria); - return new SettingsOrError(settings, settings != null ? null : "No controlBlock communication configuration found for this these criteria " + criteria); + return new SettingsOrError(settings, settings != null ? null : "No controlBlock communication configuration found with these " + criteria); } private String removeVFromSystemVersion(TCompasSystemVersion compasSystemVersion) { diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ControlBlockServiceTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ControlBlockServiceTest.java index c8dcda845..3309621ad 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ControlBlockServiceTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ControlBlockServiceTest.java @@ -12,7 +12,6 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.lfenergy.compas.scl2007b4.model.*; -import org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings; import org.lfenergy.compas.sct.commons.dto.ControlBlockTarget; import org.lfenergy.compas.sct.commons.dto.FcdaForDataSetsCreation; import org.lfenergy.compas.sct.commons.dto.SclReportItem; @@ -33,7 +32,6 @@ import org.mockito.InjectMocks; import org.mockito.junit.jupiter.MockitoExtension; -import java.math.BigDecimal; import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.HashSet; @@ -376,90 +374,91 @@ void updateAllSourceDataSetsAndControlBlocks_should_sort_FCDA_inside_DataSet_and } @Test - void configureNetworkForAllControlBlocks_should_create_GSE_and_SMV_elements() { + void configureNetworkForAllControlBlocks_should_create_GSE_elements() { // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_controlblock_network_configuration.xml"); - CBCom cbCom = new CBCom(); - cbCom.setMacRanges(new MacRanges()); - cbCom.setAppIdRanges(new AppIdRanges()); - cbCom.setVlans(new Vlans()); - // GSEControl - cbCom.getMacRanges().getMacRange().add(newRange(TCBType.GOOSE, "01-0C-CD-01-00-00", "01-0C-CD-01-01-FF")); - cbCom.getMacRanges().getMacRange().add(newRange(TCBType.SV, "01-0C-CD-04-00-00", "01-0C-CD-04-FF-FF")); - cbCom.getAppIdRanges().getAppIdRange().add(newRange(TCBType.GOOSE, "0000", "4000")); - cbCom.getAppIdRanges().getAppIdRange().add(newRange(TCBType.SV, "4000", "7FFF")); - cbCom.getVlans().getVlan().addAll(List.of( - newVlan(TCBType.GOOSE, TBayIntOrExt.BAY_INTERNAL, "301", "1"), - newVlan(TCBType.GOOSE, TBayIntOrExt.BAY_EXTERNAL, "302", "2"), - newVlan(TCBType.SV, TBayIntOrExt.BAY_INTERNAL, "303", "3"), - newVlan(TCBType.SV, TBayIntOrExt.BAY_EXTERNAL, "304", "4") - )); + CBCom cbCom = createCbCom(); // When List sclReportItems = controlBlockService.configureNetworkForAllControlBlocks(scd, cbCom); // Then assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isTrue(); - TConnectedAP connectedAP = new SclRootAdapter(scd).findConnectedApAdapter("IED_NAME2", "AP_NAME").get().getCurrentElem(); - TGSE gse = connectedAP.getGSE().stream() - .filter(tgse -> "CB_LD_INST21_GSI".equals(tgse.getCbName())) - .findFirst().get(); - assertThat(gse.getLdInst()).isEqualTo("LD_INST21"); - assertThat(gse.getMinTime()).extracting(TDurationInMilliSec::getUnit, TDurationInMilliSec::getMultiplier, TDurationInMilliSec::getValue) - .containsExactly("s", "m", new BigDecimal("10")); - assertThat(gse.getMaxTime()).extracting(TDurationInMilliSec::getUnit, TDurationInMilliSec::getMultiplier, TDurationInMilliSec::getValue) - .containsExactly("s", "m", new BigDecimal("2000")); - assertThat(gse.getAddress().getP()).extracting(TP::getType, TP::getValue) - .containsExactlyInAnyOrder( - Tuple.tuple("VLAN-PRIORITY", "1"), - Tuple.tuple("APPID", "0000"), - Tuple.tuple("MAC-Address", "01-0C-CD-01-00-00"), - Tuple.tuple("VLAN-ID", "12D") - ); - TSMV smv = connectedAP.getSMV().stream() - .filter(tsmv -> "CB_LD_INST21_SVI".equals(tsmv.getCbName())) - .findFirst().get(); - assertThat(smv.getLdInst()).isEqualTo("LD_INST21"); - assertThat(smv.getAddress().getP()).extracting(TP::getType, TP::getValue) - .containsExactlyInAnyOrder( - Tuple.tuple("VLAN-PRIORITY", "3"), - Tuple.tuple("APPID", "4000"), - Tuple.tuple("MAC-Address", "01-0C-CD-04-00-00"), - Tuple.tuple("VLAN-ID", "12F") - ); + TGSE gse1 = getCommunicationGSE(scd, "IED_NAME2", "CB_LD_INST21_GSI"); + assertThat(gse1.getLdInst()).isEqualTo("LD_INST21"); + assertThat(SclDuration.from(gse1.getMinTime())).isEqualTo(new SclDuration("10", "s", "m")); + assertThat(SclDuration.from(gse1.getMaxTime())).isEqualTo(new SclDuration("2000", "s", "m")); + assertThat(gse1.getAddress().getP()).extracting(TP::getType, TP::getValue).containsExactlyInAnyOrder( + Tuple.tuple("VLAN-PRIORITY", "1"), + Tuple.tuple("APPID", "0000"), + Tuple.tuple("MAC-Address", "01-0C-CD-01-00-00"), + Tuple.tuple("VLAN-ID", "12D") + ); + TGSE gse2 = getCommunicationGSE(scd, "IED_NAME2", "CB_LD_INST21_GMI"); + assertThat(gse2.getLdInst()).isEqualTo("LD_INST21"); + assertThat(SclDuration.from(gse2.getMinTime())).isEqualTo(new SclDuration("10", "s", "m")); + assertThat(SclDuration.from(gse2.getMaxTime())).isEqualTo(new SclDuration("2000", "s", "m")); + assertThat(gse2.getAddress().getP()).extracting(TP::getType, TP::getValue).containsExactlyInAnyOrder( + Tuple.tuple("VLAN-PRIORITY", "1"), + Tuple.tuple("APPID", "0001"), + Tuple.tuple("MAC-Address", "01-0C-CD-01-00-01"), + Tuple.tuple("VLAN-ID", "12D") + ); + TGSE gse3 = getCommunicationGSE(scd, "IED_NAME3", "CB_LD_INST31_GSE"); + assertThat(gse3.getLdInst()).isEqualTo("LD_INST31"); + assertThat(SclDuration.from(gse3.getMinTime())).isEqualTo(new SclDuration("10", "s", "m")); + assertThat(SclDuration.from(gse3.getMaxTime())).isEqualTo(new SclDuration("2000", "s", "m")); + assertThat(gse3.getAddress().getP()).extracting(TP::getType, TP::getValue).containsExactlyInAnyOrder( + Tuple.tuple("VLAN-PRIORITY", "2"), + Tuple.tuple("APPID", "0002"), + Tuple.tuple("MAC-Address", "01-0C-CD-01-00-02"), + Tuple.tuple("VLAN-ID", "12E") + ); MarshallerWrapper.assertValidateXmlSchema(scd); } - private static TVlan newVlan(TCBType tcbType, TBayIntOrExt tBayIntOrExt, String value, String vlanPriority) { - TVlan gseVlan = new TVlan(); - gseVlan.setCBType(tcbType); - gseVlan.setXY("01.00"); - gseVlan.setZW("009.001"); - gseVlan.setIEDType(TIEDType.BCU); - gseVlan.setIEDRedundancy(TIEDRedundancy.A); - gseVlan.setIEDSystemVersionInstance("1"); - gseVlan.setBayIntOrExt(tBayIntOrExt); - gseVlan.setVlanId(value); - gseVlan.setVlanPriority(vlanPriority); - gseVlan.setMinTime("10"); - gseVlan.setMaxTime("2000"); - return gseVlan; - } + @Test + void configureNetworkForAllControlBlocks_should_create_SMV_elements() { + // Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_controlblock_network_configuration.xml"); - private static TRange newRange(TCBType tcbType, String start, String end) { - TRange macRangeGSE = new TRange(); - macRangeGSE.setCBType(tcbType); - macRangeGSE.setStart(start); - macRangeGSE.setEnd(end); - return macRangeGSE; + CBCom cbCom = createCbCom(); + + // When + List sclReportItems = controlBlockService.configureNetworkForAllControlBlocks(scd, cbCom); + // Then + assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isTrue(); + TSMV smv1 = getCommunicationSMV(scd, "IED_NAME2", "CB_LD_INST21_SVI"); + assertThat(smv1.getLdInst()).isEqualTo("LD_INST21"); + assertThat(smv1.getAddress().getP()).extracting(TP::getType, TP::getValue).containsExactlyInAnyOrder( + Tuple.tuple("VLAN-PRIORITY", "3"), + Tuple.tuple("APPID", "4000"), + Tuple.tuple("MAC-Address", "01-0C-CD-04-00-00"), + Tuple.tuple("VLAN-ID", "12F") + ); + assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isTrue(); + TSMV smv2 = getCommunicationSMV(scd, "IED_NAME3", "CB_LD_INST31_SVE"); + assertThat(smv2.getLdInst()).isEqualTo("LD_INST31"); + assertThat(smv2.getAddress().getP()).extracting(TP::getType, TP::getValue).containsExactlyInAnyOrder( + Tuple.tuple("VLAN-PRIORITY", "4"), + Tuple.tuple("APPID", "4001"), + Tuple.tuple("MAC-Address", "01-0C-CD-04-00-01"), + Tuple.tuple("VLAN-ID", "130") + ); + MarshallerWrapper.assertValidateXmlSchema(scd); } @Test void configureNetworkForAllControlBlocks_should_create_GSE_with_incremental_appid_and_mac_addresses() { // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_controlblock_network_configuration.xml"); + CBCom cbCom = createCbCom(); + cbCom.getAppIdRanges().getAppIdRange().get(0).setStart("0009"); + cbCom.getAppIdRanges().getAppIdRange().get(0).setEnd("000B"); + cbCom.getMacRanges().getMacRange().get(0).setStart("01-02-03-04-00-FF"); + cbCom.getMacRanges().getMacRange().get(0).setEnd("01-02-03-04-01-01"); // When - List sclReportItems = controlBlockService.configureNetworkForAllControlBlocks(scd, new CBCom()); + List sclReportItems = controlBlockService.configureNetworkForAllControlBlocks(scd, cbCom); // Then assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isTrue(); assertThat(streamAllConnectedApGseP(scd, "APPID")) @@ -470,18 +469,15 @@ void configureNetworkForAllControlBlocks_should_create_GSE_with_incremental_appi @ParameterizedTest @MethodSource("provideConfigureNetworkForAllControlBlocksErrors") - void configureNetworkForAllControlBlocks_should_fail_when_no_settings_for_this_controlBlock(ControlBlockNetworkSettings controlBlockNetworkSettings, - RangesPerCbType rangesPerCbType, String expectedMessage) { + void configureNetworkForAllControlBlocks_should_fail_when_no_settings_for_this_controlBlock(CBCom cbCom, String expectedMessage, String expectedXPath) { // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_controlblock_network_configuration.xml"); // When - List sclReportItems = controlBlockService.configureNetworkForAllControlBlocks(scd, new CBCom()); + List sclReportItems = controlBlockService.configureNetworkForAllControlBlocks(scd, cbCom); // Then assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isFalse(); assertThat(sclReportItems) - .extracting(SclReportItem::message, SclReportItem::xpath) - .contains(Tuple.tuple(expectedMessage, - "/SCL/IED[@name=\"IED_NAME2\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST21\"]/LN0/GSEControl[@name=\"CB_LD_INST21_GMI\"]")); + .contains(SclReportItem.error(expectedXPath, expectedMessage)); } @Test @@ -523,31 +519,97 @@ void removeControlBlocksAndDatasetAndExtRefSrc_should_remove_controlBlocks_and_D .noneMatch(TAnyLN::isSetReportControl); assertIsMarshallable(scl); } -/* + + public static Stream provideConfigureNetworkForAllControlBlocksErrors() { - Settings settingsWithNullVlanId = new Settings(null, (byte) 1, newDurationInMilliSec(1), newDurationInMilliSec(2)); - Settings settings = new Settings(1, (byte) 1, newDurationInMilliSec(1), newDurationInMilliSec(2)); + CBCom cbComWithNoVlan = createCbCom(); + cbComWithNoVlan.getVlans().getVlan().clear(); + CBCom cbComWithMissingVlanId = createCbCom(); + cbComWithMissingVlanId.getVlans().getVlan().get(0).setVlanId(null); + CBCom cbComWithNotEnoughAppId = createCbCom(); + cbComWithNotEnoughAppId.getAppIdRanges().getAppIdRange().get(0).setStart("0000"); + cbComWithNotEnoughAppId.getAppIdRanges().getAppIdRange().get(0).setEnd("00001"); + CBCom cbComWithNotEnoughMacAddress = createCbCom(); + cbComWithNotEnoughMacAddress.getMacRanges().getMacRange().get(0).setStart("01-0C-CD-01-00-00"); + cbComWithNotEnoughMacAddress.getMacRanges().getMacRange().get(0).setEnd("01-0C-CD-01-00-01"); + return Stream.of( - Arguments.of((ControlBlockNetworkSettings) controlBlockAdapter -> new SettingsOrError(null, null), - RANGES_PER_CB_TYPE, - "Cannot configure network for this ControlBlock because no settings was provided"), - Arguments.of((ControlBlockNetworkSettings) controlBlockAdapter -> new SettingsOrError(null, "Custom error message"), - RANGES_PER_CB_TYPE, - "Cannot configure network for this ControlBlock because: Custom error message"), - Arguments.of((ControlBlockNetworkSettings) controlBlockAdapter -> new SettingsOrError(settingsWithNullVlanId, null), - RANGES_PER_CB_TYPE, - "Cannot configure network for this ControlBlock because no Vlan Id was provided in the settings"), - Arguments.of((ControlBlockNetworkSettings) controlBlockAdapter -> new SettingsOrError(settings, null), - new RangesPerCbType( - new NetworkRanges(GSE_APP_ID_MIN, GSE_APP_ID_MIN, GSE_MAC_ADDRESS_PREFIX + "00-FF", GSE_MAC_ADDRESS_PREFIX + "01-AA"), - SMV_NETWORK_RANGES), - "Cannot configure network for this ControlBlock because range of appId is exhausted"), - Arguments.of((ControlBlockNetworkSettings) controlBlockAdapter -> new SettingsOrError(settings, null), - new RangesPerCbType( - new NetworkRanges(GSE_APP_ID_MIN, GSE_APP_ID_MIN + 10, GSE_MAC_ADDRESS_PREFIX + "00-FF", GSE_MAC_ADDRESS_PREFIX + "00-FF"), - SMV_NETWORK_RANGES), - "Cannot configure network for this ControlBlock because range of MAC Address is exhausted") + Arguments.of(cbComWithNoVlan, "Cannot configure communication for this ControlBlock because: No controlBlock communication configuration found with these Criteria[cbType=GOOSE, systemVersionWithoutV=01.00.009.001, iedType=BCU, iedRedundancy=A, iedSystemVersionInstance=1, bayIntOrExt=BAY_INTERNAL]", + "/SCL/IED[@name=\"IED_NAME2\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST21\"]/LN0/GSEControl[@name=\"CB_LD_INST21_GMI\"]"), + Arguments.of(cbComWithMissingVlanId, "Cannot configure communication for this ControlBlock because no Vlan Id was provided in the settings", + "/SCL/IED[@name=\"IED_NAME2\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST21\"]/LN0/GSEControl[@name=\"CB_LD_INST21_GMI\"]"), + Arguments.of(cbComWithNotEnoughAppId, "Cannot configure communication for this ControlBlock because range of appId is exhausted", + "/SCL/IED[@name=\"IED_NAME3\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST31\"]/LN0/GSEControl[@name=\"CB_LD_INST31_GSE\"]"), + Arguments.of(cbComWithNotEnoughMacAddress, "Cannot configure communication for this ControlBlock because range of MAC Address is exhausted", + "/SCL/IED[@name=\"IED_NAME3\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST31\"]/LN0/GSEControl[@name=\"CB_LD_INST31_GSE\"]") ); - }*/ + } + + private static TGSE getCommunicationGSE(SCL scd, String iedName, String cbName) { + return new SclRootAdapter(scd).findConnectedApAdapter(iedName, "AP_NAME").orElseThrow() + .getCurrentElem() + .getGSE().stream() + .filter(tgse -> cbName.equals(tgse.getCbName())) + .findFirst().orElseThrow(); + } + + private static TSMV getCommunicationSMV(SCL scd, String iedName, String cbName) { + return new SclRootAdapter(scd).findConnectedApAdapter(iedName, "AP_NAME").orElseThrow() + .getCurrentElem() + .getSMV().stream() + .filter(tsmv -> cbName.equals(tsmv.getCbName())) + .findFirst().orElseThrow(); + } + + private static CBCom createCbCom() { + CBCom cbCom = new CBCom(); + cbCom.setMacRanges(new MacRanges()); + cbCom.setAppIdRanges(new AppIdRanges()); + cbCom.setVlans(new Vlans()); + cbCom.getMacRanges().getMacRange().add(newRange(TCBType.GOOSE, "01-0C-CD-01-00-00", "01-0C-CD-01-01-FF")); + cbCom.getMacRanges().getMacRange().add(newRange(TCBType.SV, "01-0C-CD-04-00-00", "01-0C-CD-04-FF-FF")); + cbCom.getAppIdRanges().getAppIdRange().add(newRange(TCBType.GOOSE, "0000", "4000")); + cbCom.getAppIdRanges().getAppIdRange().add(newRange(TCBType.SV, "4000", "7FFF")); + cbCom.getVlans().getVlan().addAll(List.of( + newVlan(TCBType.GOOSE, TBayIntOrExt.BAY_INTERNAL, "301", "1"), + newVlan(TCBType.GOOSE, TBayIntOrExt.BAY_EXTERNAL, "302", "2"), + newVlan(TCBType.SV, TBayIntOrExt.BAY_INTERNAL, "303", "3"), + newVlan(TCBType.SV, TBayIntOrExt.BAY_EXTERNAL, "304", "4") + )); + return cbCom; + } + + private static TRange newRange(TCBType tcbType, String start, String end) { + TRange macRangeGSE = new TRange(); + macRangeGSE.setCBType(tcbType); + macRangeGSE.setStart(start); + macRangeGSE.setEnd(end); + return macRangeGSE; + } + + private static TVlan newVlan(TCBType tcbType, TBayIntOrExt tBayIntOrExt, String value, String vlanPriority) { + TVlan gseVlan = new TVlan(); + gseVlan.setCBType(tcbType); + gseVlan.setXY("01.00"); + gseVlan.setZW("009.001"); + gseVlan.setIEDType(TIEDType.BCU); + gseVlan.setIEDRedundancy(TIEDRedundancy.A); + gseVlan.setIEDSystemVersionInstance("1"); + gseVlan.setBayIntOrExt(tBayIntOrExt); + gseVlan.setVlanId(value); + gseVlan.setVlanPriority(vlanPriority); + gseVlan.setMinTime("10"); + gseVlan.setMaxTime("2000"); + return gseVlan; + } + + /** + * Facilite la comparaison de TDurationInMilliSec + */ + record SclDuration(String value, String unit, String multiplier) { + static SclDuration from(TDurationInMilliSec tDurationInMilliSec) { + return new SclDuration(tDurationInMilliSec.getValue().toString(), tDurationInMilliSec.getUnit(), tDurationInMilliSec.getMultiplier()); + } + } }