|
|
@@ -1,13 +1,18 @@
|
|
|
package com.payment.platform.module.payment.unified.client;
|
|
|
|
|
|
+import ch.qos.logback.classic.Logger;
|
|
|
+import ch.qos.logback.classic.spi.ILoggingEvent;
|
|
|
+import ch.qos.logback.core.read.ListAppender;
|
|
|
import com.payment.platform.module.payment.unified.config.UnifiedPayProperties;
|
|
|
import com.sun.net.httpserver.HttpExchange;
|
|
|
import com.sun.net.httpserver.HttpServer;
|
|
|
import org.junit.jupiter.api.Test;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
import java.net.InetSocketAddress;
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
+import java.util.List;
|
|
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
|
|
@@ -49,6 +54,48 @@ class JdkUnifiedTransportTest {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ @Test
|
|
|
+ void timeout_logsCauseSoProductionCanDiagnoseIt() throws Exception {
|
|
|
+ Logger logger = (Logger) LoggerFactory.getLogger(JdkUnifiedTransport.class);
|
|
|
+ ListAppender<ILoggingEvent> appender = new ListAppender<>();
|
|
|
+ appender.start();
|
|
|
+ logger.addAppender(appender);
|
|
|
+
|
|
|
+ HttpServer server = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0);
|
|
|
+ server.createContext("/slow", exchange -> {
|
|
|
+ sleepQuietly(300);
|
|
|
+ try {
|
|
|
+ respond(exchange, 200, "{\"code\":0}");
|
|
|
+ } catch (IOException ignored) {
|
|
|
+ // 客户端已超时断开,写响应失败是预期
|
|
|
+ }
|
|
|
+ });
|
|
|
+ server.start();
|
|
|
+ try {
|
|
|
+ UnifiedPayProperties props = new UnifiedPayProperties();
|
|
|
+ props.setConnectTimeoutMs(1000);
|
|
|
+ props.setReadTimeoutMs(100);
|
|
|
+ JdkUnifiedTransport transport = new JdkUnifiedTransport(props);
|
|
|
+
|
|
|
+ assertThrows(UnifiedApiException.class,
|
|
|
+ () -> transport.post(base(server) + "/slow", "{}"));
|
|
|
+
|
|
|
+ List<String> logs = appender.list.stream()
|
|
|
+ .map(ILoggingEvent::getFormattedMessage)
|
|
|
+ .toList();
|
|
|
+ // 正控:没挂上 appender 时下面的断言会变成空列表上的假绿
|
|
|
+ assertFalse(logs.isEmpty(),
|
|
|
+ "上游网络异常必须留日志,否则线上只能看到 500 文案");
|
|
|
+ String text = String.join("\n", logs);
|
|
|
+ assertTrue(text.contains("上游网络异常"), "缺固定锚点: " + text);
|
|
|
+ assertTrue(text.toLowerCase().contains("timeout"),
|
|
|
+ "日志应带底层异常类型/信息,才能区分超时、DNS、TLS: " + text);
|
|
|
+ } finally {
|
|
|
+ logger.detachAppender(appender);
|
|
|
+ server.stop(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
@Test
|
|
|
void success_returnsResponseBodyVerbatim() throws Exception {
|
|
|
HttpServer server = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0);
|