Skip to content

Commit 96dfa86

Browse files
committed
test(http): pin the URL-query-only contract of ListExchangesServlet
ListExchangesServlet.doPost reads visible and int64_as_string from the URL query, not from the JSON body -- a counter-intuitive shape shared only by GetChainParametersServlet. Without a test, a future refactor that "normalizes" this POST path to read from the body would silently break clients that pass the flag via the URL.
1 parent 7ba22ba commit 96dfa86

1 file changed

Lines changed: 111 additions & 0 deletions

File tree

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package org.tron.core.services.http;
2+
3+
import static org.junit.Assert.assertFalse;
4+
import static org.junit.Assert.assertNotNull;
5+
import static org.junit.Assert.assertTrue;
6+
import static org.junit.Assert.fail;
7+
8+
import com.alibaba.fastjson.JSON;
9+
import com.alibaba.fastjson.JSONObject;
10+
import java.io.UnsupportedEncodingException;
11+
import javax.annotation.Resource;
12+
import org.junit.Test;
13+
import org.springframework.mock.web.MockHttpServletRequest;
14+
import org.springframework.mock.web.MockHttpServletResponse;
15+
import org.tron.common.BaseTest;
16+
import org.tron.common.TestConstants;
17+
import org.tron.core.config.args.Args;
18+
19+
/**
20+
* Integration tests for ListExchangesServlet. This servlet is the canonical example of the
21+
* "doGet-delegates-to-doPost, doPost reads URL query (not body)" shape: its doPost calls
22+
* Util.getVisible(request) and Util.getInt64AsString(request) instead of PostParams. The
23+
* tests below pin that contract so a future refactor that "normalizes" the POST path to
24+
* read from the body (as most other servlets do) will fail visibly rather than silently
25+
* breaking clients that pass the flag via URL query.
26+
*
27+
* <p>ExchangeList may be empty on the test DB, so item-level assertions are defensive:
28+
* they verify int64 quoting shape only when exchange_id is present in the response.
29+
*/
30+
public class ListExchangesServletTest extends BaseTest {
31+
32+
@Resource(name = "listExchangesServlet")
33+
private ListExchangesServlet servlet;
34+
35+
static {
36+
Args.setParam(
37+
new String[]{
38+
"--output-directory", dbPath(),
39+
}, TestConstants.TEST_CONF
40+
);
41+
}
42+
43+
private MockHttpServletRequest createPostJsonRequest(String body) {
44+
MockHttpServletRequest request = new MockHttpServletRequest();
45+
request.setMethod("POST");
46+
request.setContentType("application/json");
47+
request.setCharacterEncoding("UTF-8");
48+
if (body != null) {
49+
request.setContent(body.getBytes());
50+
}
51+
return request;
52+
}
53+
54+
@Test
55+
public void testPostWithQueryInt64AsStringTrue() {
56+
MockHttpServletRequest request = createPostJsonRequest(null);
57+
request.addParameter("int64_as_string", "true");
58+
MockHttpServletResponse response = new MockHttpServletResponse();
59+
servlet.doPost(request, response);
60+
try {
61+
String content = response.getContentAsString();
62+
assertNotNull("expected valid JSON, got: " + content, JSON.parseObject(content));
63+
if (content.contains("\"exchange_id\"")) {
64+
assertTrue("exchange_id should be quoted when URL query carries int64_as_string=true, "
65+
+ "got: " + content,
66+
content.matches("(?s).*\"exchange_id\"\\s*:\\s*\"\\d+\".*"));
67+
}
68+
} catch (UnsupportedEncodingException e) {
69+
fail(e.getMessage());
70+
}
71+
}
72+
73+
@Test
74+
public void testPostBodyFlagIsIgnored() {
75+
// Contract: ListExchangesServlet.doPost reads only URL query, mirroring how the same
76+
// servlet reads `visible`. A body-only flag must NOT take effect. Breaking this
77+
// behavior would be a silent regression for clients that pass the flag via URL.
78+
String body = "{\"int64_as_string\": true}";
79+
MockHttpServletRequest request = createPostJsonRequest(body);
80+
MockHttpServletResponse response = new MockHttpServletResponse();
81+
servlet.doPost(request, response);
82+
try {
83+
String content = response.getContentAsString();
84+
assertNotNull("expected valid JSON, got: " + content, JSON.parseObject(content));
85+
if (content.contains("\"exchange_id\"")) {
86+
assertFalse("body-only int64_as_string must be ignored on this servlet, got: " + content,
87+
content.matches("(?s).*\"exchange_id\"\\s*:\\s*\"\\d+\".*"));
88+
}
89+
} catch (UnsupportedEncodingException e) {
90+
fail(e.getMessage());
91+
}
92+
}
93+
94+
@Test
95+
public void testPostDefaultKeepsNumbers() {
96+
MockHttpServletRequest request = createPostJsonRequest(null);
97+
MockHttpServletResponse response = new MockHttpServletResponse();
98+
servlet.doPost(request, response);
99+
try {
100+
String content = response.getContentAsString();
101+
JSONObject result = JSON.parseObject(content);
102+
assertNotNull("expected valid JSON, got: " + content, result);
103+
if (content.contains("\"exchange_id\"")) {
104+
assertFalse("default behavior must not quote exchange_id, got: " + content,
105+
content.matches("(?s).*\"exchange_id\"\\s*:\\s*\"\\d+\".*"));
106+
}
107+
} catch (UnsupportedEncodingException e) {
108+
fail(e.getMessage());
109+
}
110+
}
111+
}

0 commit comments

Comments
 (0)