Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import lombok.Setter;
import org.gridsuite.modification.dto.FilterInfos;
import org.gridsuite.modification.dto.byfilter.assignment.*;
import org.gridsuite.modification.modifications.data.assignment.DataType;
import org.gridsuite.modification.server.entities.equipment.modification.VariationFilterEntity;
import org.gridsuite.modification.server.entities.equipment.modification.byfilter.AbstractAssignmentEntity;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
import lombok.NoArgsConstructor;
import org.gridsuite.modification.dto.FilterInfos;
import org.gridsuite.modification.dto.byfilter.formula.FormulaInfos;
import org.gridsuite.modification.dto.byfilter.formula.Operator;
import org.gridsuite.modification.dto.byfilter.formula.ReferenceFieldOrValue;
import org.gridsuite.modification.modifications.data.assignment.Operator;
import org.gridsuite.modification.modifications.data.assignment.ReferenceFieldOrValue;
import org.gridsuite.modification.server.entities.equipment.modification.VariationFilterEntity;
import org.gridsuite.modification.server.entities.equipment.modification.byfilter.AbstractAssignmentEntity;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Locale;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

Expand Down Expand Up @@ -200,6 +201,7 @@ private ApplicationStatus apply(ModificationApplicationGroup modificationGroupIn
UUID reporterId = modificationGroupInfos.reportInfos().getNodeUuid();
reportNode = ReportNode.newRootReportNode()
.withAllResourceBundlesFromClasspath()
.withLocale(Locale.ENGLISH)
.withMessageTemplate("network.modification.server.nodeUuid")
.withUntypedValue("nodeUuid", reporterId.toString())
.build();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright (c) 2026, 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/.
*/

package org.gridsuite.modification.server.modifications.byfilter;

import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.matching.MultiValuePattern;
import com.powsybl.iidm.network.IdentifiableType;
import lombok.SneakyThrows;
import org.gridsuite.filter.utils.EquipmentType;
import org.gridsuite.filter.wip.Filter;
import org.gridsuite.filter.wip.IdentifierListFilter;
import org.gridsuite.modification.server.modifications.AbstractNetworkModificationTest;
import org.gridsuite.modification.server.utils.FilterStub;
import org.gridsuite.modification.server.utils.StubbedFilterRequest;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;

import java.util.*;
import java.util.stream.Collectors;

/**
* @author Joris Mancini <joris.mancini_externe at rte-france.com>
*/
public abstract class AbstractByFilterTest extends AbstractNetworkModificationTest {

protected static final String PATH = "/v1/standalone-filters";

protected abstract Map<UUID, Set<String>> getFilterMapping();

protected abstract IdentifiableType getIdentifiableType();

protected abstract EquipmentType getEquipmentType();

protected FilterStub createFilterStub(UUID filterID, Collection<String> equipmentIds) {
return new FilterStub(filterID, equipmentFilter(Set.copyOf(equipmentIds)));
}

protected Filter equipmentFilter(Set<String> equipmentIds) {
return IdentifierListFilter.builder()
.equipmentType(getEquipmentType())
.equipmentIds(equipmentIds)
.build();
}

protected List<StubbedFilterRequest> stubStandaloneFilterRequests(List<List<UUID>> filterIdsList) {
Map<Set<UUID>, Integer> requestCounts = new LinkedHashMap<>();
filterIdsList.forEach(filterIds -> requestCounts.merge(filterIds.stream().collect(Collectors.toSet()), 1, Integer::sum));

Map<UUID, Filter> filtersById = getFilterMapping().entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, entry -> equipmentFilter(entry.getValue())));

List<StubbedFilterRequest> stubbedFilterRequests = new ArrayList<>();
for (Map.Entry<Set<UUID>, Integer> requestCount : requestCounts.entrySet()) {
List<FilterStub> filterStubs = requestCount.getKey().stream()
.map(filterId -> new FilterStub(filterId, Objects.requireNonNull(filtersById.get(filterId))))
.toList();
stubbedFilterRequests.add(new StubbedFilterRequest(stubStandaloneFilters(filterStubs), requestCount.getKey(), requestCount.getValue()));
}
return stubbedFilterRequests;
}

@SneakyThrows
protected UUID stubStandaloneFilters(List<FilterStub> filterStubs) {
List<UUID> filterIds = filterStubs.stream().map(FilterStub::id).toList();
return wireMockServer.stubFor(WireMock.get(WireMock.urlPathEqualTo(PATH))
.withQueryParam("ids", havingExactlyIdsIgnoringOrder(filterIds))
.willReturn(WireMock.ok()
.withBody(mapper.writeValueAsString(filterStubs.stream().collect(Collectors.toMap(
FilterStub::id,
FilterStub::filter
))))
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))).getId();
}

protected void verifyStandaloneFiltersRequest(UUID stubId, Set<UUID> filterIds) {
verifyStandaloneFiltersRequest(stubId, filterIds, 1);
}

protected void verifyStandaloneFiltersRequest(UUID stubId, Set<UUID> filterIds, int nbRequests) {
wireMockUtils.verifyGetRequest(stubId, PATH, "ids", havingExactlyIdsIgnoringOrder(filterIds), false, nbRequests);
}

protected void verifyStandaloneFiltersRequests(List<StubbedFilterRequest> stubs) {
stubs.forEach(stub -> wireMockUtils.verifyGetRequest(
stub.stubId(), PATH, "ids", havingExactlyIdsIgnoringOrder(stub.filterIds()), false, stub.requestCount()));
}

protected MultiValuePattern havingExactlyIdsIgnoringOrder(Collection<UUID> filterIds) {
String[] expectedIds = filterIds.stream()
.map(UUID::toString)
.distinct()
.toArray(String[]::new);
return WireMock.havingExactly(expectedIds);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,31 @@
package org.gridsuite.modification.server.modifications.byfilter.assignment;

import com.fasterxml.jackson.core.type.TypeReference;
import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.matching.StringValuePattern;
import com.powsybl.iidm.network.IdentifiableType;
import com.powsybl.iidm.network.Network;
import org.gridsuite.filter.AbstractFilter;
import org.gridsuite.filter.identifierlistfilter.IdentifierListFilter;
import org.gridsuite.filter.identifierlistfilter.IdentifierListFilterEquipmentAttributes;
import org.gridsuite.filter.utils.EquipmentType;
import org.gridsuite.modification.dto.FilterInfos;
import org.gridsuite.modification.dto.ModificationByAssignmentInfos;
import org.gridsuite.modification.dto.byfilter.assignment.AssignmentInfos;
import org.gridsuite.modification.dto.byfilter.assignment.DataType;
import org.gridsuite.modification.dto.byfilter.assignment.DoubleAssignmentInfos;
import org.gridsuite.modification.dto.byfilter.assignment.PropertyAssignmentInfos;
import org.gridsuite.modification.dto.byfilter.equipmentfield.PropertyField;
import org.gridsuite.modification.modifications.data.assignment.DataType;
import org.gridsuite.modification.server.dto.NetworkModificationResult;
import org.gridsuite.modification.server.dto.NetworkModificationsResult;
import org.gridsuite.modification.server.impacts.AbstractBaseImpact;
import org.gridsuite.modification.server.modifications.AbstractNetworkModificationTest;
import org.gridsuite.modification.server.modifications.byfilter.AbstractByFilterTest;
import org.gridsuite.modification.server.service.FilterService;
import org.gridsuite.modification.server.utils.FilterStub;
import org.gridsuite.modification.server.utils.NetworkCreation;
import org.gridsuite.modification.server.utils.StubbedFilterRequest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultActions;
import java.util.*;
import java.util.stream.Collectors;

import static org.assertj.core.api.Assertions.assertThat;
import static org.gridsuite.modification.server.impacts.TestImpactUtils.createCollectionElementImpact;
import static org.junit.jupiter.api.Assertions.assertEquals;
Expand All @@ -52,24 +47,20 @@
* @author Thang PHAM <quyet-thang.pham at rte-france.com>
*/
@Tag("IntegrationTest")
abstract class AbstractModificationByAssignmentTest extends AbstractNetworkModificationTest {
abstract class AbstractModificationByAssignmentTest extends AbstractByFilterTest {
protected static final UUID FILTER_ID_1 = UUID.randomUUID();
protected static final UUID FILTER_ID_2 = UUID.randomUUID();
protected static final UUID FILTER_ID_3 = UUID.randomUUID();
protected static final UUID FILTER_ID_4 = UUID.randomUUID();
protected static final UUID FILTER_ID_5 = UUID.randomUUID();
protected static final UUID FILTER_ID_6 = UUID.randomUUID();
protected static final UUID FILTER_WITH_ALL_WRONG_IDS = UUID.randomUUID();
protected static final UUID FILTER_WITH_ONE_WRONG_ID = UUID.randomUUID();
protected final FilterInfos filter1 = new FilterInfos(FILTER_ID_1, "filter1");
protected final FilterInfos filter2 = new FilterInfos(FILTER_ID_2, "filter2");
protected final FilterInfos filter3 = new FilterInfos(FILTER_ID_3, "filter3");
protected final FilterInfos filter4 = new FilterInfos(FILTER_ID_4, "filter4");
protected final FilterInfos filter5 = new FilterInfos(FILTER_ID_5, "filter5");
protected final FilterInfos filter6 = new FilterInfos(FILTER_ID_6, "filter6");
protected final FilterInfos filterWithOneWrongId = new FilterInfos(FILTER_WITH_ONE_WRONG_ID, "filterWithOneWrongId");

protected static final String PATH = "/v1/filters/metadata";
Comment thread
KoloMenek marked this conversation as resolved.

@Override
protected void assertResultImpacts(List<AbstractBaseImpact> impacts) {
Expand Down Expand Up @@ -104,82 +95,52 @@ public void testByModificationError() throws Exception {
checkCreationApplicationStatus(List.of(assignmentWithNoEditedField), NetworkModificationResult.ApplicationStatus.WITH_ERRORS);
}

protected void checkCreateWithWarning(List<AssignmentInfos<?>> assignments, List<IdentifierListFilterEquipmentAttributes> existingEquipmentList) throws Exception {
AbstractFilter filter = getFilterEquipments(FILTER_WITH_ONE_WRONG_ID, existingEquipmentList);

UUID stubId = wireMockServer.stubFor(WireMock.get(WireMock.urlMatching("/v1/filters/metadata\\?ids=" + FILTER_WITH_ONE_WRONG_ID))
.willReturn(WireMock.ok()
.withBody(mapper.writeValueAsString(List.of(filter)))
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))).getId();

checkCreationApplicationStatus(assignments, NetworkModificationResult.ApplicationStatus.WITH_WARNINGS);

wireMockUtils.verifyGetRequest(stubId, PATH, handleQueryParams(List.of(FILTER_WITH_ONE_WRONG_ID)), false);
}

protected void checkCreateWithError(List<AssignmentInfos<?>> assignments, List<AbstractFilter> filterEquipments) throws Exception {
String filterIds = filterEquipments.stream()
.map(AbstractFilter::getId)
.map(UUID::toString)
.collect(Collectors.joining(","));

UUID stubId = wireMockServer.stubFor(WireMock.get(WireMock.urlMatching("/v1/filters/metadata\\?ids=" + filterIds))
.willReturn(WireMock.ok()
.withBody(mapper.writeValueAsString(filterEquipments))
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))).getId();
protected void checkCreateWithStatus(List<AssignmentInfos<?>> assignments, List<FilterStub> filterEquipments,
NetworkModificationResult.ApplicationStatus applicationStatus) throws Exception {
UUID stubId = stubStandaloneFilters(filterEquipments);

checkCreationApplicationStatus(assignments, NetworkModificationResult.ApplicationStatus.WITH_ERRORS);
checkCreationApplicationStatus(assignments, applicationStatus);

wireMockUtils.verifyGetRequest(stubId,
PATH,
handleQueryParams(filterEquipments.stream().map(AbstractFilter::getId).toList()),
false);
verifyStandaloneFiltersRequest(stubId, filterEquipments.stream().map(FilterStub::id).collect(Collectors.toSet()));
}

@Test
public void testModificationWithAllWrongEquipmentIds() throws Exception {
AbstractFilter filter = getFilterEquipments(FILTER_WITH_ALL_WRONG_IDS, List.of());
FilterStub filter = createFilterStub(FILTER_WITH_ALL_WRONG_IDS, Set.of());

List<AssignmentInfos<?>> assignmentsWithWrongFilter = getAssignmentInfos().stream()
.peek(assignmentInfos -> assignmentInfos.setFilters(List.of(new FilterInfos(FILTER_WITH_ALL_WRONG_IDS, "filterWithWrongId"))))
.toList();

UUID stubId = wireMockServer.stubFor(WireMock.get(WireMock.urlMatching("/v1/filters/metadata\\?ids=" + FILTER_WITH_ALL_WRONG_IDS))
.willReturn(WireMock.ok()
.withBody(mapper.writeValueAsString(List.of(filter)))
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))).getId();
UUID stubId = stubStandaloneFilters(List.of(filter));

checkCreationApplicationStatus(assignmentsWithWrongFilter, NetworkModificationResult.ApplicationStatus.WITH_ERRORS);

wireMockUtils.verifyGetRequest(stubId, PATH, handleQueryParams(List.of(FILTER_WITH_ALL_WRONG_IDS)), false);
verifyStandaloneFiltersRequest(stubId, Set.of(FILTER_WITH_ALL_WRONG_IDS), getAssignmentInfos().size());
}

@Test
@Override
public void testCreate() throws Exception {
List<AbstractFilter> filters = getTestFilters();
UUID stubId = wireMockServer.stubFor(WireMock.get(WireMock.urlMatching(getPath(true) + ".{2,}"))
.willReturn(WireMock.ok()
.withBody(mapper.writeValueAsString(filters))
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))).getId();
List<StubbedFilterRequest> stubs = stubStandaloneFilterRequests(getAssignmentInfos().stream()
.map(assignment -> assignment.getFilters().stream().map(FilterInfos::getId).toList())
.toList());

super.testCreate();

wireMockUtils.verifyGetRequest(stubId, PATH, handleQueryParams(filters.stream().map(AbstractFilter::getId).toList()), false);
verifyStandaloneFiltersRequests(stubs);
}

@Test
@Override
public void testCopy() throws Exception {
List<AbstractFilter> filters = getTestFilters();
UUID stubId = wireMockServer.stubFor(WireMock.get(WireMock.urlMatching(getPath(true) + ".{2,}"))
.willReturn(WireMock.ok()
.withBody(mapper.writeValueAsString(filters))
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))).getId();
List<StubbedFilterRequest> stubs = stubStandaloneFilterRequests(getAssignmentInfos().stream()
.map(assignment -> assignment.getFilters().stream().map(FilterInfos::getId).toList())
.toList());

super.testCopy();

wireMockUtils.verifyGetRequest(stubId, PATH, handleQueryParams(filters.stream().map(AbstractFilter::getId).toList()), false);
verifyStandaloneFiltersRequests(stubs);
}

protected void checkCreationApplicationStatus(List<? extends AssignmentInfos<?>> assignmentInfos,
Expand Down Expand Up @@ -226,31 +187,8 @@ protected ModificationByAssignmentInfos buildModificationUpdate() {
.build();
}

protected IdentifierListFilterEquipmentAttributes getIdentifiableAttributes(String id, Double distributionKey) {
return new IdentifierListFilterEquipmentAttributes(id, distributionKey);
}

protected AbstractFilter getFilterEquipments(UUID filterID, List<IdentifierListFilterEquipmentAttributes> identifiableAttributes) {
return IdentifierListFilter.builder().id(filterID).modificationDate(new Date()).equipmentType(getEquipmentType())
.filterEquipmentsAttributes(identifiableAttributes)
.build();
}

protected Map<String, StringValuePattern> handleQueryParams(List<UUID> filterIds) {
return Map.of("ids", WireMock.matching(filterIds.stream().map(uuid -> ".+").collect(Collectors.joining(","))));
}

protected String getPath(boolean isRegexPath) {
if (isRegexPath) {
return "/v1/filters/metadata\\?ids=";
}
return "/v1/filters/metadata?ids=";
}

protected abstract void createEquipments();

protected abstract List<AbstractFilter> getTestFilters();

protected List<AssignmentInfos<?>> getAssignmentInfos() {
PropertyAssignmentInfos spyAssignmentInfos = spy(PropertyAssignmentInfos.builder()
.editedField(PropertyField.FREE_PROPERTIES.name())
Expand All @@ -263,8 +201,4 @@ protected List<AssignmentInfos<?>> getAssignmentInfos() {
}

protected abstract List<AssignmentInfos<?>> getUpdatedAssignmentInfos();

protected abstract IdentifiableType getIdentifiableType();

protected abstract EquipmentType getEquipmentType();
}
Loading
Loading