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 @@ -146,8 +146,8 @@ private <T, E extends Exception> T withRetry(String url,
@Deprecated
private static class ProxyErrorExceptionPropagator implements RestClientExceptionPropagator {
@Override
public void propagate(Exception exception, String failedUrl) {
throw ProxyRethrowException.buildProxyException(exception, failedUrl);
public void propagate(Throwable throwable, String failedUrl) {
throw ProxyRethrowException.buildProxyException(throwable, failedUrl);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public ProxyErrorException(ProxyErrorException cause) {
this.httpStatus = cause.httpStatus;
}

public ProxyErrorException(Exception cause, String url) {
public ProxyErrorException(Throwable cause, String url) {
super("Exception while communicating with " + url, cause);
ErrorsDescription errorsDescription;
this.httpStatus = HttpStatus.EXPECTATION_FAILED;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public ProxyRethrowException(ProxyErrorException cause) {
* @deprecated Change to throw RestClientException when {@link ProxyErrorException} will be removed
*/
@Deprecated
public static ProxyErrorException buildProxyException(Exception cause, String url) {
public static ProxyErrorException buildProxyException(Throwable cause, String url) {
ProxyErrorException e = new ProxyErrorException(cause, url);
final ResponseEntity<ErrorsDescription> responseEntity = e.getResponseEntity();
if (responseEntity == null || !responseEntity.hasBody()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package com.netcracker.cloud.restlegacy.restclient.error;

public interface RestClientExceptionPropagator {
void propagate(Exception exception, String failedUrl);
void propagate(Throwable throwable, String failedUrl);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@
class RestClientExceptionPropagatorV2 implements RestClientExceptionPropagator {

@Override
public void propagate(Exception exception, String failedUrl) {
propagateIfPossible(exception, RestClientException.class);
throw new RestClientException("Exception while communication with service " + failedUrl, exception);
public void propagate(Throwable throwable, String failedUrl) {
propagateIfPossible(throwable, RestClientException.class);
throw new RestClientException("Exception while communication with service " + failedUrl, throwable);
}

private <X extends Throwable> void propagateIfPossible (Throwable throwable, Class<X> clazz) throws X {
if (clazz.isInstance(throwable)) {
throw clazz.cast(throwable);
}
if (throwable instanceof RuntimeException) {
throw (RuntimeException) throwable;
if (throwable instanceof RuntimeException runtimeException) {
throw runtimeException;
}
if (throwable instanceof Error) {
throw (Error) throwable;
if (throwable instanceof Error error) {
throw error;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.netcracker.cloud.restlegacy.restclient.error.v2;

import org.junit.jupiter.api.Test;
import org.springframework.web.client.RestClientException;

import static org.junit.jupiter.api.Assertions.*;

class RestClientExceptionPropagatorV2Test {

private final RestClientExceptionPropagatorV2 propagator = new RestClientExceptionPropagatorV2();
private final String failedUrl = "http://test-service";

@Test
void propagate_shouldRethrowRestClientExceptionAsIs() {
RestClientException ex = new RestClientException("Already RestClientException");

RestClientException thrown = assertThrows(
RestClientException.class,
() -> propagator.propagate(ex, failedUrl)
);

assertSame(ex, thrown, "RestClientException should be propagated as-is");
}

@Test
void propagate_shouldRethrowRuntimeExceptionAsIs() {
RuntimeException ex = new RuntimeException("Runtime exception");

RuntimeException thrown = assertThrows(
RuntimeException.class,
() -> propagator.propagate(ex, failedUrl)
);

assertSame(ex, thrown, "RuntimeException should be propagated as-is");
}

@Test
void propagate_shouldRethrowErrorAsIs() {
Error error = new OutOfMemoryError("Critical error");

Error thrown = assertThrows(
OutOfMemoryError.class,
() -> propagator.propagate(error, failedUrl)
);

assertSame(error, thrown, "Error should be propagated as-is");
}

@Test
void propagate_shouldWrapCheckedException() {
Exception ex = new Exception("Checked exception");

RestClientException thrown = assertThrows(
RestClientException.class,
() -> propagator.propagate(ex, failedUrl)
);

assertEquals("Exception while communication with service " + failedUrl, thrown.getMessage());
assertSame(ex, thrown.getCause(), "Original exception should be wrapped as cause");
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.netcracker.cloud.restlegacy.restclient.retry;


import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertThrows;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,20 @@ public static GatewayNameKey fromGatewayName(String gateway) {
// default route type is INTERNAL
return INTERNAL;
}
if (PUBLIC_GATEWAY_SERVICE.equals(gateway)) {
return PUBLIC;
}
if (PRIVATE_GATEWAY_SERVICE.equals(gateway)) {
return PRIVATE;
}
if (INTERNAL_GATEWAY_SERVICE.equals(gateway)) {
return INTERNAL;
}
return FACADE;
return switch (gateway) {
case PUBLIC_GATEWAY_SERVICE -> PUBLIC;
case PRIVATE_GATEWAY_SERVICE -> PRIVATE;
case INTERNAL_GATEWAY_SERVICE -> INTERNAL;
default -> FACADE;
};
}

public String toGatewayName() {
switch (this) {
case PUBLIC:
return PUBLIC_GATEWAY_SERVICE;
case PRIVATE:
return PRIVATE_GATEWAY_SERVICE;
case INTERNAL:
return INTERNAL_GATEWAY_SERVICE;
default:
return null;
}
return switch (this) {
case PUBLIC -> PUBLIC_GATEWAY_SERVICE;
case PRIVATE -> PRIVATE_GATEWAY_SERVICE;
case INTERNAL -> INTERNAL_GATEWAY_SERVICE;
default -> null;
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
Expand Down Expand Up @@ -44,11 +46,12 @@ public boolean equals(Object o) {
return true;
}
return routes != null && that.routes != null && routes.size() == that.routes.size()
&& routes.containsAll(that.routes) && that.routes.containsAll(routes);
&& new HashSet<>(routes).containsAll(that.routes) && new HashSet<>(that.routes).containsAll(routes);
}

@Override
public int hashCode() {
return Objects.hash(version);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Data
@Builder
Expand All @@ -21,11 +25,12 @@ public RouteV3 merge(RouteV3 anotherRoute) {
}

private void mergeRules(List<Rule> rulesToMerge) {
rulesToMerge.forEach(ruleToMerge -> {
if (rules.stream().noneMatch(ruleToMerge::equals)) {
rules.add(ruleToMerge);
}
});
if (rulesToMerge == null || rulesToMerge.isEmpty()) {
return;
}

List<Rule> currentRules = (rules == null) ? List.of() : rules;
this.rules = Stream.concat(currentRules.stream(), rulesToMerge.stream()).distinct().toList();
}

@Override
Expand All @@ -37,11 +42,12 @@ public boolean equals(Object o) {
return false;
}
return rules != null && routeV3.rules != null && rules.size() == routeV3.rules.size()
&& rules.containsAll(routeV3.rules) && routeV3.rules.containsAll(rules);
&& new HashSet<>(rules).containsAll(routeV3.rules) && new HashSet<>(routeV3.rules).containsAll(rules);
}

@Override
public int hashCode() {
return Objects.hash(destination);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.netcracker.cloud.routesregistration.common.gateway.route;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class GatewayNameKeyTest {
@Test
void fromGatewayName() {
assertEquals(GatewayNameKey.PUBLIC, GatewayNameKey.fromGatewayName("public-gateway-service"));
assertEquals(GatewayNameKey.PRIVATE, GatewayNameKey.fromGatewayName("private-gateway-service"));
assertEquals(GatewayNameKey.INTERNAL, GatewayNameKey.fromGatewayName("internal-gateway-service"));
assertEquals(GatewayNameKey.FACADE, GatewayNameKey.fromGatewayName("some-facade-gateway-service"));
assertEquals(GatewayNameKey.INTERNAL, GatewayNameKey.fromGatewayName(null));
assertEquals(GatewayNameKey.INTERNAL, GatewayNameKey.fromGatewayName(""));
}

@Test
void toGatewayName() {
assertEquals("public-gateway-service", GatewayNameKey.PUBLIC.toGatewayName());
assertEquals("private-gateway-service", GatewayNameKey.PRIVATE.toGatewayName());
assertEquals("internal-gateway-service", GatewayNameKey.INTERNAL.toGatewayName());
assertNull(GatewayNameKey.FACADE.toGatewayName());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package com.netcracker.cloud.routesregistration.common.gateway.route.v3.domain;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

class RouteV3Test {

private RouteDestination destination;
private RouteV3 route1;
private RouteV3 route2;
private Rule ruleA;
private Rule ruleB;
private Rule ruleDuplicate;

@BeforeEach
void setUp() {
destination = RouteDestination.builder()
.cluster("cluster-1")
.endpoint("endpoint-1")
.build();

ruleA = Rule.builder()
.prefixRewrite("/api/v1")
.allowed(true)
.timeout(1000L)
.build();

ruleB = Rule.builder()
.prefixRewrite("/api/v2")
.allowed(false)
.timeout(2000L)
.build();

ruleDuplicate = Rule.builder()
.prefixRewrite("/api/v1")
.allowed(true)
.timeout(1000L)
.build(); // identical to ruleA

route1 = RouteV3.builder()
.destination(destination)
.rules(List.of(ruleA))
.build();

route2 = RouteV3.builder()
.destination(destination)
.rules(List.of(ruleB, ruleDuplicate))
.build();
}

@Test
void merge_shouldCombineUniqueRules() {
RouteV3 merged = route1.merge(route2);

assertEquals(2, route1.getRules().size());
assertTrue(route1.getRules().contains(ruleA));
assertTrue(route1.getRules().contains(ruleB));
assertTrue(route1.getRules().contains(ruleDuplicate));
assertSame(merged, route1);
}

@Test
void merge_shouldNotAddDuplicateRules() {
route1.merge(RouteV3.builder()
.destination(destination)
.rules(List.of(ruleDuplicate))
.build());

assertEquals(1, route1.getRules().size(), "Duplicate rule should not be added");
}

@Test
void merge_shouldThrowExceptionForDifferentDestinations() {
RouteDestination otherDestination = RouteDestination.builder()
.cluster("cluster-2")
.endpoint("endpoint-2")
.build();

RouteV3 routeWithDifferentDest = RouteV3.builder()
.destination(otherDestination)
.rules(List.of(ruleB))
.build();

IllegalArgumentException ex = assertThrows(
IllegalArgumentException.class,
() -> route1.merge(routeWithDifferentDest)
);

assertEquals("Cannot merge RouteV3 with different RouteDestination", ex.getMessage());
}

@Test
void merge_shouldHandleEmptyRules() {
RouteV3 emptyRulesRoute = RouteV3.builder()
.destination(destination)
.rules(List.of())
.build();

route1.merge(emptyRulesRoute);
assertEquals(1, route1.getRules().size());
}

@Test
void merge_shouldHandleNullRuleListsSafely() {
RouteV3 nullRulesRoute = RouteV3.builder()
.destination(destination)
.rules(null)
.build();

assertDoesNotThrow(() -> route1.merge(nullRulesRoute));
assertEquals(1, route1.getRules().size());
}
}
Loading
Loading