This is an automated email from the ASF dual-hosted git repository.
tuohai666 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new d17b29d42d Stabilize Sentinel CI assertion for PR 6375 (#6377)
d17b29d42d is described below
commit d17b29d42da729e1e5a8691c3fa19739b30811fb
Author: aias00 <[email protected]>
AuthorDate: Wed Jun 10 21:31:38 2026 +0800
Stabilize Sentinel CI assertion for PR 6375 (#6377)
The failed Actions job showed both concurrent Sentinel requests returning
pass, which made the test depend on a two-request race landing inside an
initialized rate-limit window. The test now sends a small bounded burst and
retries briefly until it observes both the allowed response and the expected
Sentinel rejection or fallback response.
Constraint: GitHub Actions job 80239368085 failed in
shenyu-integrated-test-http at SentinelPluginTest.test:76
Rejected: Increase the assertion timeout with two requests | still depends
on the same first-window race
Rejected: Change Sentinel production configuration | failure is a test
timing assumption, not a production behavior regression
Confidence: high
Scope-risk: narrow
Directive: Keep this test asserting both pass and limited responses, but
avoid exact request-count assumptions around Sentinel windows
Tested: ./mvnw -f ./shenyu-integrated-test/pom.xml -pl
shenyu-integrated-test-http -am -Pit -DskipTests test-compile
Tested: ./mvnw -pl shenyu-plugin/shenyu-plugin-request
-Dtest=org.apache.shenyu.plugin.request.RequestPluginTest test
Tested: git diff --check
Not-tested: Full Docker Compose shenyu-integrated-test-http run; local
machine lacks most required CI service images
---
.../test/http/combination/SentinelPluginTest.java | 64 +++++++++++++++++-----
1 file changed, 50 insertions(+), 14 deletions(-)
diff --git
a/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/SentinelPluginTest.java
b/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/SentinelPluginTest.java
index 521e3adfd5..bdf78a6441 100644
---
a/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/SentinelPluginTest.java
+++
b/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/SentinelPluginTest.java
@@ -35,6 +35,8 @@ import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -49,10 +51,18 @@ import static
org.junit.jupiter.api.Assertions.assertNotNull;
public final class SentinelPluginTest extends AbstractPluginDataInit {
+ private static final int SENTINEL_REQUEST_BURST_SIZE = 6;
+
+ private static final int SENTINEL_REQUEST_ATTEMPTS = 5;
+
+ private static final long SENTINEL_REQUEST_ATTEMPT_INTERVAL_MILLIS = 200L;
+
private static final String TEST_SENTINEL_PATH =
"/http/test/sentinel/pass";
private static final String TEST_SENTINEL_FALLBACK_PATH =
"fallback:/fallback/sentinel";
+ private static final String TEST_SENTINEL_RESTRICTED_MESSAGE = "You have
been restricted, please try again later!";
+
@BeforeEach
public void setup() throws IOException {
String pluginResult = initPlugin(PluginEnum.SENTINEL.getName(),
"{\"model\":\"black\"}");
@@ -67,13 +77,9 @@ public final class SentinelPluginTest extends
AbstractPluginDataInit {
Type returnType = new TypeToken<Map<String, Object>>() {
}.getType();
- Future<Map<String, Object>> first = this.getService().submit(() ->
HttpHelper.INSTANCE.postGateway(TEST_SENTINEL_PATH, returnType));
- Future<Map<String, Object>> second = this.getService().submit(() ->
HttpHelper.INSTANCE.postGateway(TEST_SENTINEL_PATH, returnType));
- Map<String, Object> firstResult = first.get();
- Map<String, Object> secondResult = second.get();
- Set<String> messages = toMessages(firstResult, secondResult);
+ Set<String> messages = collectMessagesUntil(returnType, "pass",
TEST_SENTINEL_RESTRICTED_MESSAGE);
assertThat(messages.contains("pass"), is(true));
- assertThat(messages.contains("You have been restricted, please try
again later!"), is(true));
+ assertThat(messages.contains(TEST_SENTINEL_RESTRICTED_MESSAGE),
is(true));
}
@Test
@@ -84,18 +90,48 @@ public final class SentinelPluginTest extends
AbstractPluginDataInit {
Type returnType = new TypeToken<Map<String, Object>>() {
}.getType();
- Future<Map<String, Object>> first = this.getService().submit(() ->
HttpHelper.INSTANCE.postGateway(TEST_SENTINEL_PATH, returnType));
- Future<Map<String, Object>> second = this.getService().submit(() ->
HttpHelper.INSTANCE.postGateway(TEST_SENTINEL_PATH, returnType));
- Map<String, Object> firstResult = first.get();
- Map<String, Object> secondResult = second.get();
- Set<String> messages = toMessages(firstResult, secondResult);
- Set<Integer> codes = toCodes(firstResult, secondResult);
+ List<Map<String, Object>> results = collectResultsUntil(returnType,
"pass", ShenyuResultEnum.SENTINEL_PLUGIN_FALLBACK.getMsg());
+ Set<String> messages = toMessages(results);
+ Set<Integer> codes = toCodes(results);
assertThat(messages.contains("pass"), is(true));
assertThat(codes.contains(ShenyuResultEnum.SENTINEL_PLUGIN_FALLBACK.getCode()),
is(true));
assertThat(messages.contains(ShenyuResultEnum.SENTINEL_PLUGIN_FALLBACK.getMsg()),
is(true));
}
- private static Set<String> toMessages(final Map<String, Object>...
results) {
+ private List<Map<String, Object>> collectResultsUntil(final Type
returnType,
+ final String...
expectedMessages)
+ throws ExecutionException, InterruptedException {
+ List<Map<String, Object>> results = new ArrayList<>();
+ Set<String> expected = new HashSet<>(Arrays.asList(expectedMessages));
+ for (int attempt = 0; attempt < SENTINEL_REQUEST_ATTEMPTS; attempt++) {
+ results.addAll(postSentinelRequestBurst(returnType));
+ if (toMessages(results).containsAll(expected)) {
+ return results;
+ }
+ Thread.sleep(SENTINEL_REQUEST_ATTEMPT_INTERVAL_MILLIS);
+ }
+ return results;
+ }
+
+ private Set<String> collectMessagesUntil(final Type returnType, final
String... expectedMessages)
+ throws ExecutionException, InterruptedException {
+ return toMessages(collectResultsUntil(returnType, expectedMessages));
+ }
+
+ private List<Map<String, Object>> postSentinelRequestBurst(final Type
returnType)
+ throws ExecutionException, InterruptedException {
+ List<Future<Map<String, Object>>> futures = new ArrayList<>();
+ for (int i = 0; i < SENTINEL_REQUEST_BURST_SIZE; i++) {
+ futures.add(this.getService().submit(() ->
HttpHelper.INSTANCE.postGateway(TEST_SENTINEL_PATH, returnType)));
+ }
+ List<Map<String, Object>> results = new ArrayList<>();
+ for (Future<Map<String, Object>> future : futures) {
+ results.add(future.get());
+ }
+ return results;
+ }
+
+ private static Set<String> toMessages(final List<Map<String, Object>>
results) {
Set<String> messages = new HashSet<>();
for (Map<String, Object> result : results) {
assertNotNull(result);
@@ -107,7 +143,7 @@ public final class SentinelPluginTest extends
AbstractPluginDataInit {
return messages;
}
- private static Set<Integer> toCodes(final Map<String, Object>... results) {
+ private static Set<Integer> toCodes(final List<Map<String, Object>>
results) {
Set<Integer> codes = new HashSet<>();
for (Map<String, Object> result : results) {
assertNotNull(result);