This commit is contained in:
2026-09-29 18:06:18 +08:00
parent 54ad26c607
commit 2c60a29e0f
30 changed files with 384 additions and 139 deletions
@@ -0,0 +1,55 @@
package com.baiyue.common.web;
import com.baiyue.common.core.api.ApiResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import feign.FeignException;
import feign.Request;
import feign.Response;
import org.junit.jupiter.api.Test;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.Map;
import static org.assertj.core.api.Assertions.*;
class EventDeliveryFailureTest {
@Test void onlyExplicitProtocolOrAuthRejectionIsPermanent() {
for (String code : new String[]{"EVT_PROTOCOL", "A0401", "A0403"}) {
Throwable error = catchThrowable(() -> EventDeliveryFailure.requireSuccessful(response(code)));
assertThat(EventDeliveryFailure.isPermanent(error)).as(code).isTrue();
}
for (String code : new String[]{"EVT_DEPENDENCY", "A0400", "A0409", "A0429", "S0503", "unknown", null}) {
Throwable error = catchThrowable(() -> EventDeliveryFailure.requireSuccessful(response(code)));
assertThat(error).isInstanceOf(EventDeliveryFailure.class);
assertThat(EventDeliveryFailure.isPermanent(error)).as(code).isFalse();
}
assertThat(EventDeliveryFailure.isPermanent(new IllegalArgumentException("ACK mismatch"))).isFalse();
}
@Test void httpAuthenticationFailureIsPermanentBut429And503Retry() {
for (int status : new int[]{401, 403, 429, 503}) {
var http = http(status);
assertThat(EventDeliveryFailure.isPermanent(new RuntimeException("wrapper", http)))
.isEqualTo(status == 401 || status == 403);
assertThat(EventDeliveryFailure.diagnostic(http, "secret")).contains("HTTP " + status)
.doesNotContain("remote-body", "secret");
}
}
@Test void diagnosticsRemoveTokenHeadersSecretsAndLineBreaks() {
var failure = new IllegalStateException("secret-value\nAuthorization=Bearer abc.def.ghi; X-Internal-Service-Token=another-secret, access_token=third-secret");
String value = EventDeliveryFailure.diagnostic(failure, "secret-value");
assertThat(value).doesNotContain("secret-value", "abc.def.ghi", "another-secret", "third-secret", "\n");
assertThat(EventDeliveryFailure.diagnostic(new RuntimeException("x".repeat(1000)), "")).hasSize(500);
}
@Test void malformedJsonDiagnosticNeverCopiesPersistedPayload() {
Throwable failure = catchThrowable(() -> new ObjectMapper().readTree("private-payload-value"));
assertThat(EventDeliveryFailure.diagnostic(failure, ""))
.contains("Invalid event JSON").doesNotContain("private-payload-value");
}
private ApiResponse<Object> response(String code) {
return new ApiResponse<>(code, "consumer-message", null, "request-id", "trace-id", Instant.now());
}
private FeignException http(int status) {
var request = Request.create(Request.HttpMethod.POST, "http://consumer/events?token=secret", Map.of(), new byte[0], StandardCharsets.UTF_8, null);
return FeignException.errorStatus("receive", Response.builder().request(request).status(status).reason("failure")
.headers(Map.of()).body("remote-body-secret", StandardCharsets.UTF_8).build());
}
}