提交 e7a7f751 编写于 作者: R Rossen Stoyanchev

Prefix REST client test support classes w/ "MockRest"

Add "MockRest-" prefix to RequestMatchers and ResponseCreators to
make it easy to find classes with static imports with
Ctrl+Shift+T "MockRest" - similar to the "MockMvc"
prefix on the server-side.
上级 d4fa5c03
......@@ -24,8 +24,8 @@ import java.util.List;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.test.web.mock.client.match.RequestMatchers;
import org.springframework.test.web.mock.client.response.ResponseCreators;
import org.springframework.test.web.mock.client.match.MockRestRequestMatchers;
import org.springframework.test.web.mock.client.response.MockRestResponseCreators;
import org.springframework.util.Assert;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.client.support.RestGatewaySupport;
......@@ -58,9 +58,9 @@ import org.springframework.web.client.support.RestGatewaySupport;
* {@link ResponseActions#andExpect(RequestMatcher) andExpect(RequestMatcher)} and
* {@link ResponseActions#andRespond(ResponseCreator) andRespond(ResponseCreator)}
* to set up request expectations and responses, most likely relying on the default
* {@code RequestMatcher} implementations provided in {@link RequestMatchers}
* {@code RequestMatcher} implementations provided in {@link MockRestRequestMatchers}
* and the {@code ResponseCreator} implementations provided in
* {@link ResponseCreators} both of which can be statically imported.
* {@link MockRestResponseCreators} both of which can be statically imported.
*
* <p>At the end of the test use {@link #verify()} to ensure all expected
* requests were actually performed.
......@@ -132,7 +132,7 @@ public class MockRestServiceServer {
* before using the {@code RestTemplate}, to set up expectations for multiple
* requests.
*
* @param requestMatcher a request expectation, see {@link RequestMatchers}
* @param requestMatcher a request expectation, see {@link MockRestRequestMatchers}
* @return used to set up further expectations or to define a response
*/
public ResponseActions expect(RequestMatcher requestMatcher) {
......
......@@ -19,11 +19,11 @@ import java.io.IOException;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.test.web.mock.client.response.ResponseCreators;
import org.springframework.test.web.mock.client.response.MockRestResponseCreators;
/**
* A contract for creating a {@link ClientHttpResponse}.
* Implementations can be obtained via {@link ResponseCreators}.
* Implementations can be obtained via {@link MockRestResponseCreators}.
*
* @author Craig Walls
* @since 3.2
......
......@@ -35,7 +35,7 @@ import org.w3c.dom.Node;
/**
* Factory for request content {@code RequestMatcher}'s. An instance of this
* class is typically accessed via {@link RequestMatchers#content()}.
* class is typically accessed via {@link MockRestRequestMatchers#content()}.
*
* @author Rossen Stoyanchev
* @since 3.2
......@@ -47,7 +47,7 @@ public class ContentRequestMatchers {
/**
* Class constructor, not for direct instantiation.
* Use {@link RequestMatchers#content()}.
* Use {@link MockRestRequestMatchers#content()}.
*/
protected ContentRequestMatchers() {
this.xmlHelper = new XmlExpectationsHelper();
......
......@@ -44,8 +44,8 @@ public class JsonPathRequestMatchers {
/**
* Class constructor, not for direct instantiation. Use
* {@link RequestMatchers#jsonPath(String, Matcher)} or
* {@link RequestMatchers#jsonPath(String, Object...)}.
* {@link MockRestRequestMatchers#jsonPath(String, Matcher)} or
* {@link MockRestRequestMatchers#jsonPath(String, Object...)}.
*
* @param expression the JSONPath expression
* @param args arguments to parameterize the JSONPath expression with using
......
......@@ -46,13 +46,13 @@ import org.springframework.util.Assert;
* @author Rossen Stoyanchev
* @since 3.2
*/
public abstract class RequestMatchers {
public abstract class MockRestRequestMatchers {
/**
* Private class constructor.
*/
private RequestMatchers() {
private MockRestRequestMatchers() {
}
/**
......
......@@ -43,8 +43,8 @@ public class XpathRequestMatchers {
/**
* Class constructor, not for direct instantiation. Use
* {@link RequestMatchers#xpath(String, Object...)} or
* {@link RequestMatchers#xpath(String, Map, Object...)}.
* {@link MockRestRequestMatchers#xpath(String, Object...)} or
* {@link MockRestRequestMatchers#xpath(String, Map, Object...)}.
*
* @param expression the XPath expression
* @param namespaces XML namespaces referenced in the XPath expression, or {@code null}
......
......@@ -17,7 +17,7 @@
/**
* Contains built-in {@link org.springframework.test.web.mock.client.RequestMatcher}
* implementations. Use
* {@link org.springframework.test.web.mock.client.match.RequestMatchers}
* {@link org.springframework.test.web.mock.client.match.MockRestRequestMatchers}
* to gain access to instances of those implementations.
*/
package org.springframework.test.web.mock.client.match;
......@@ -49,7 +49,7 @@ public class DefaultResponseCreator implements ResponseCreator {
/**
* Protected constructor.
* Use static factory methods in {@link ResponseCreators}.
* Use static factory methods in {@link MockRestResponseCreators}.
*/
protected DefaultResponseCreator(HttpStatus statusCode) {
Assert.notNull(statusCode);
......
......@@ -35,10 +35,10 @@ import org.springframework.test.web.mock.client.ResponseCreator;
* @author Rossen Stoyanchev
* @since 3.2
*/
public abstract class ResponseCreators {
public abstract class MockRestResponseCreators {
private ResponseCreators() {
private MockRestResponseCreators() {
}
/**
......
......@@ -17,7 +17,7 @@
/**
* Contains built-in {@link org.springframework.test.web.mock.client.ResponseCreator}
* implementations. Use
* {@link org.springframework.test.web.mock.client.response.ResponseCreators}
* {@link org.springframework.test.web.mock.client.response.MockRestResponseCreators}
* to gain access to instances of those implementations.
*/
package org.springframework.test.web.mock.client.response;
......@@ -18,7 +18,7 @@ package org.springframework.test.web.mock.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.springframework.test.web.mock.client.match.RequestMatchers.anything;
import static org.springframework.test.web.mock.client.match.MockRestRequestMatchers.anything;
import java.net.URI;
......
......@@ -22,7 +22,7 @@ import org.junit.Test;
import org.springframework.http.MediaType;
import org.springframework.mock.http.client.MockClientHttpRequest;
import org.springframework.test.web.mock.client.match.ContentRequestMatchers;
import org.springframework.test.web.mock.client.match.RequestMatchers;
import org.springframework.test.web.mock.client.match.MockRestRequestMatchers;
/**
* Tests for {@link ContentRequestMatchers}.
......@@ -42,36 +42,36 @@ public class ContentRequestMatchersTests {
public void testContentType() throws Exception {
this.request.getHeaders().setContentType(MediaType.APPLICATION_JSON);
RequestMatchers.content().mimeType("application/json").match(this.request);
RequestMatchers.content().mimeType(MediaType.APPLICATION_JSON).match(this.request);
MockRestRequestMatchers.content().mimeType("application/json").match(this.request);
MockRestRequestMatchers.content().mimeType(MediaType.APPLICATION_JSON).match(this.request);
}
@Test(expected=AssertionError.class)
public void testContentTypeNoMatch1() throws Exception {
this.request.getHeaders().setContentType(MediaType.APPLICATION_JSON);
RequestMatchers.content().mimeType("application/xml").match(this.request);
MockRestRequestMatchers.content().mimeType("application/xml").match(this.request);
}
@Test(expected=AssertionError.class)
public void testContentTypeNoMatch2() throws Exception {
this.request.getHeaders().setContentType(MediaType.APPLICATION_JSON);
RequestMatchers.content().mimeType(MediaType.APPLICATION_ATOM_XML).match(this.request);
MockRestRequestMatchers.content().mimeType(MediaType.APPLICATION_ATOM_XML).match(this.request);
}
@Test
public void testString() throws Exception {
this.request.getBody().write("test".getBytes());
RequestMatchers.content().string("test").match(this.request);
MockRestRequestMatchers.content().string("test").match(this.request);
}
@Test(expected=AssertionError.class)
public void testStringNoMatch() throws Exception {
this.request.getBody().write("test".getBytes());
RequestMatchers.content().string("Test").match(this.request);
MockRestRequestMatchers.content().string("Test").match(this.request);
}
@Test
......@@ -79,14 +79,14 @@ public class ContentRequestMatchersTests {
byte[] content = "test".getBytes();
this.request.getBody().write(content);
RequestMatchers.content().bytes(content).match(this.request);
MockRestRequestMatchers.content().bytes(content).match(this.request);
}
@Test(expected=AssertionError.class)
public void testBytesNoMatch() throws Exception {
this.request.getBody().write("test".getBytes());
RequestMatchers.content().bytes("Test".getBytes()).match(this.request);
MockRestRequestMatchers.content().bytes("Test".getBytes()).match(this.request);
}
@Test
......@@ -94,14 +94,14 @@ public class ContentRequestMatchersTests {
String content = "<foo><bar>baz</bar><bar>bazz</bar></foo>";
this.request.getBody().write(content.getBytes());
RequestMatchers.content().xml(content).match(this.request);
MockRestRequestMatchers.content().xml(content).match(this.request);
}
@Test(expected=AssertionError.class)
public void testXmlNoMatch() throws Exception {
this.request.getBody().write("<foo>11</foo>".getBytes());
RequestMatchers.content().xml("<foo>22</foo>").match(this.request);
MockRestRequestMatchers.content().xml("<foo>22</foo>").match(this.request);
}
@Test
......@@ -109,7 +109,7 @@ public class ContentRequestMatchersTests {
String content = "<foo><bar>baz</bar></foo>";
this.request.getBody().write(content.getBytes());
RequestMatchers.content().node(hasXPath("/foo/bar")).match(this.request);
MockRestRequestMatchers.content().node(hasXPath("/foo/bar")).match(this.request);
}
@Test(expected=AssertionError.class)
......@@ -117,7 +117,7 @@ public class ContentRequestMatchersTests {
String content = "<foo><bar>baz</bar></foo>";
this.request.getBody().write(content.getBytes());
RequestMatchers.content().node(hasXPath("/foo/bar/bar")).match(this.request);
MockRestRequestMatchers.content().node(hasXPath("/foo/bar/bar")).match(this.request);
}
}
......@@ -24,10 +24,10 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.http.HttpMethod;
import org.springframework.mock.http.client.MockClientHttpRequest;
import org.springframework.test.web.mock.client.match.RequestMatchers;
import org.springframework.test.web.mock.client.match.MockRestRequestMatchers;
/**
* Tests for {@link RequestMatchers}.
* Tests for {@link MockRestRequestMatchers}.
*
* @author Craig Walls
* @author Rossen Stoyanchev
......@@ -45,54 +45,54 @@ public class RequestMatchersTests {
public void requestTo() throws Exception {
this.request.setURI(new URI("http://foo.com/bar"));
RequestMatchers.requestTo("http://foo.com/bar").match(this.request);
MockRestRequestMatchers.requestTo("http://foo.com/bar").match(this.request);
}
@Test(expected=AssertionError.class)
public void requestToNoMatch() throws Exception {
this.request.setURI(new URI("http://foo.com/bar"));
RequestMatchers.requestTo("http://foo.com/wrong").match(this.request);
MockRestRequestMatchers.requestTo("http://foo.com/wrong").match(this.request);
}
@Test
public void requestToContains() throws Exception {
this.request.setURI(new URI("http://foo.com/bar"));
RequestMatchers.requestTo(containsString("bar")).match(this.request);
MockRestRequestMatchers.requestTo(containsString("bar")).match(this.request);
}
@Test
public void method() throws Exception {
this.request.setMethod(HttpMethod.GET);
RequestMatchers.method(HttpMethod.GET).match(this.request);
MockRestRequestMatchers.method(HttpMethod.GET).match(this.request);
}
@Test(expected=AssertionError.class)
public void methodNoMatch() throws Exception {
this.request.setMethod(HttpMethod.POST);
RequestMatchers.method(HttpMethod.GET).match(this.request);
MockRestRequestMatchers.method(HttpMethod.GET).match(this.request);
}
@Test
public void header() throws Exception {
this.request.getHeaders().put("foo", Arrays.asList("bar", "baz"));
RequestMatchers.header("foo", "bar", "baz").match(this.request);
MockRestRequestMatchers.header("foo", "bar", "baz").match(this.request);
}
@Test(expected=AssertionError.class)
public void headerMissing() throws Exception {
RequestMatchers.header("foo", "bar").match(this.request);
MockRestRequestMatchers.header("foo", "bar").match(this.request);
}
@Test(expected=AssertionError.class)
public void headerMissingValue() throws Exception {
this.request.getHeaders().put("foo", Arrays.asList("bar", "baz"));
RequestMatchers.header("foo", "bad").match(this.request);
MockRestRequestMatchers.header("foo", "bad").match(this.request);
}
@SuppressWarnings("unchecked")
......@@ -100,13 +100,13 @@ public class RequestMatchersTests {
public void headerContains() throws Exception {
this.request.getHeaders().put("foo", Arrays.asList("bar", "baz"));
RequestMatchers.header("foo", containsString("ba")).match(this.request);
MockRestRequestMatchers.header("foo", containsString("ba")).match(this.request);
}
@SuppressWarnings("unchecked")
@Test(expected=AssertionError.class)
public void headerContainsWithMissingHeader() throws Exception {
RequestMatchers.header("foo", containsString("baz")).match(this.request);
MockRestRequestMatchers.header("foo", containsString("baz")).match(this.request);
}
@SuppressWarnings("unchecked")
......@@ -114,26 +114,26 @@ public class RequestMatchersTests {
public void headerContainsWithMissingValue() throws Exception {
this.request.getHeaders().put("foo", Arrays.asList("bar", "baz"));
RequestMatchers.header("foo", containsString("bx")).match(this.request);
MockRestRequestMatchers.header("foo", containsString("bx")).match(this.request);
}
@Test
public void headers() throws Exception {
this.request.getHeaders().put("foo", Arrays.asList("bar", "baz"));
RequestMatchers.header("foo", "bar", "baz").match(this.request);
MockRestRequestMatchers.header("foo", "bar", "baz").match(this.request);
}
@Test(expected=AssertionError.class)
public void headersWithMissingHeader() throws Exception {
RequestMatchers.header("foo", "bar").match(this.request);
MockRestRequestMatchers.header("foo", "bar").match(this.request);
}
@Test(expected=AssertionError.class)
public void headersWithMissingValue() throws Exception {
this.request.getHeaders().put("foo", Arrays.asList("bar"));
RequestMatchers.header("foo", "bar", "baz").match(this.request);
MockRestRequestMatchers.header("foo", "bar", "baz").match(this.request);
}
}
\ No newline at end of file
......@@ -27,11 +27,11 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.mock.http.client.MockClientHttpResponse;
import org.springframework.test.web.mock.client.response.DefaultResponseCreator;
import org.springframework.test.web.mock.client.response.ResponseCreators;
import org.springframework.test.web.mock.client.response.MockRestResponseCreators;
import org.springframework.util.FileCopyUtils;
/**
* Tests for the {@link ResponseCreators} static factory methods.
* Tests for the {@link MockRestResponseCreators} static factory methods.
*
* @author Rossen Stoyanchev
*/
......@@ -39,7 +39,7 @@ public class ResponseCreatorsTests {
@Test
public void success() throws Exception {
MockClientHttpResponse response = (MockClientHttpResponse) ResponseCreators.withSuccess().createResponse(null);
MockClientHttpResponse response = (MockClientHttpResponse) MockRestResponseCreators.withSuccess().createResponse(null);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertTrue(response.getHeaders().isEmpty());
......@@ -48,7 +48,7 @@ public class ResponseCreatorsTests {
@Test
public void successWithContent() throws Exception {
DefaultResponseCreator responseCreator = ResponseCreators.withSuccess("foo", MediaType.TEXT_PLAIN);
DefaultResponseCreator responseCreator = MockRestResponseCreators.withSuccess("foo", MediaType.TEXT_PLAIN);
MockClientHttpResponse response = (MockClientHttpResponse) responseCreator.createResponse(null);
assertEquals(HttpStatus.OK, response.getStatusCode());
......@@ -58,7 +58,7 @@ public class ResponseCreatorsTests {
@Test
public void successWithContentWithoutContentType() throws Exception {
DefaultResponseCreator responseCreator = ResponseCreators.withSuccess("foo", null);
DefaultResponseCreator responseCreator = MockRestResponseCreators.withSuccess("foo", null);
MockClientHttpResponse response = (MockClientHttpResponse) responseCreator.createResponse(null);
assertEquals(HttpStatus.OK, response.getStatusCode());
......@@ -69,7 +69,7 @@ public class ResponseCreatorsTests {
@Test
public void created() throws Exception {
URI location = new URI("/foo");
DefaultResponseCreator responseCreator = ResponseCreators.withCreatedEntity(location);
DefaultResponseCreator responseCreator = MockRestResponseCreators.withCreatedEntity(location);
MockClientHttpResponse response = (MockClientHttpResponse) responseCreator.createResponse(null);
assertEquals(HttpStatus.CREATED, response.getStatusCode());
......@@ -79,7 +79,7 @@ public class ResponseCreatorsTests {
@Test
public void noContent() throws Exception {
DefaultResponseCreator responseCreator = ResponseCreators.withNoContent();
DefaultResponseCreator responseCreator = MockRestResponseCreators.withNoContent();
MockClientHttpResponse response = (MockClientHttpResponse) responseCreator.createResponse(null);
assertEquals(HttpStatus.NO_CONTENT, response.getStatusCode());
......@@ -89,7 +89,7 @@ public class ResponseCreatorsTests {
@Test
public void badRequest() throws Exception {
DefaultResponseCreator responseCreator = ResponseCreators.withBadRequest();
DefaultResponseCreator responseCreator = MockRestResponseCreators.withBadRequest();
MockClientHttpResponse response = (MockClientHttpResponse) responseCreator.createResponse(null);
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
......@@ -99,7 +99,7 @@ public class ResponseCreatorsTests {
@Test
public void unauthorized() throws Exception {
DefaultResponseCreator responseCreator = ResponseCreators.withUnauthorizedRequest();
DefaultResponseCreator responseCreator = MockRestResponseCreators.withUnauthorizedRequest();
MockClientHttpResponse response = (MockClientHttpResponse) responseCreator.createResponse(null);
assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode());
......@@ -109,7 +109,7 @@ public class ResponseCreatorsTests {
@Test
public void serverError() throws Exception {
DefaultResponseCreator responseCreator = ResponseCreators.withServerError();
DefaultResponseCreator responseCreator = MockRestResponseCreators.withServerError();
MockClientHttpResponse response = (MockClientHttpResponse) responseCreator.createResponse(null);
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
......@@ -119,7 +119,7 @@ public class ResponseCreatorsTests {
@Test
public void withStatus() throws Exception {
DefaultResponseCreator responseCreator = ResponseCreators.withStatus(HttpStatus.FORBIDDEN);
DefaultResponseCreator responseCreator = MockRestResponseCreators.withStatus(HttpStatus.FORBIDDEN);
MockClientHttpResponse response = (MockClientHttpResponse) responseCreator.createResponse(null);
assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode());
......
......@@ -16,9 +16,9 @@
package org.springframework.test.web.mock.client.samples;
import static org.junit.Assert.assertTrue;
import static org.springframework.test.web.mock.client.match.RequestMatchers.method;
import static org.springframework.test.web.mock.client.match.RequestMatchers.requestTo;
import static org.springframework.test.web.mock.client.response.ResponseCreators.withSuccess;
import static org.springframework.test.web.mock.client.match.MockRestRequestMatchers.method;
import static org.springframework.test.web.mock.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.mock.client.response.MockRestResponseCreators.withSuccess;
import org.junit.Before;
import org.junit.Test;
......
......@@ -17,8 +17,8 @@ package org.springframework.test.web.mock.client.samples.matchers;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertTrue;
import static org.springframework.test.web.mock.client.match.RequestMatchers.content;
import static org.springframework.test.web.mock.client.response.ResponseCreators.withSuccess;
import static org.springframework.test.web.mock.client.match.MockRestRequestMatchers.content;
import static org.springframework.test.web.mock.client.response.MockRestResponseCreators.withSuccess;
import java.net.URI;
import java.util.ArrayList;
......
......@@ -16,9 +16,9 @@
package org.springframework.test.web.mock.client.samples.matchers;
import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.mock.client.match.RequestMatchers.header;
import static org.springframework.test.web.mock.client.match.RequestMatchers.requestTo;
import static org.springframework.test.web.mock.client.response.ResponseCreators.withSuccess;
import static org.springframework.test.web.mock.client.match.MockRestRequestMatchers.header;
import static org.springframework.test.web.mock.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.mock.client.response.MockRestResponseCreators.withSuccess;
import java.net.URI;
import java.util.ArrayList;
......
......@@ -20,10 +20,10 @@ import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.isIn;
import static org.hamcrest.Matchers.startsWith;
import static org.springframework.test.web.mock.client.match.RequestMatchers.content;
import static org.springframework.test.web.mock.client.match.RequestMatchers.jsonPath;
import static org.springframework.test.web.mock.client.match.RequestMatchers.requestTo;
import static org.springframework.test.web.mock.client.response.ResponseCreators.withSuccess;
import static org.springframework.test.web.mock.client.match.MockRestRequestMatchers.content;
import static org.springframework.test.web.mock.client.match.MockRestRequestMatchers.jsonPath;
import static org.springframework.test.web.mock.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.mock.client.response.MockRestResponseCreators.withSuccess;
import java.net.URI;
import java.util.ArrayList;
......
......@@ -16,9 +16,9 @@
package org.springframework.test.web.mock.client.samples.matchers;
import static org.hamcrest.Matchers.hasXPath;
import static org.springframework.test.web.mock.client.match.RequestMatchers.content;
import static org.springframework.test.web.mock.client.match.RequestMatchers.requestTo;
import static org.springframework.test.web.mock.client.response.ResponseCreators.withSuccess;
import static org.springframework.test.web.mock.client.match.MockRestRequestMatchers.content;
import static org.springframework.test.web.mock.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.mock.client.response.MockRestResponseCreators.withSuccess;
import java.net.URI;
import java.util.ArrayList;
......
......@@ -21,10 +21,10 @@ import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.startsWith;
import static org.springframework.test.web.mock.client.match.RequestMatchers.content;
import static org.springframework.test.web.mock.client.match.RequestMatchers.requestTo;
import static org.springframework.test.web.mock.client.match.RequestMatchers.xpath;
import static org.springframework.test.web.mock.client.response.ResponseCreators.withSuccess;
import static org.springframework.test.web.mock.client.match.MockRestRequestMatchers.content;
import static org.springframework.test.web.mock.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.mock.client.match.MockRestRequestMatchers.xpath;
import static org.springframework.test.web.mock.client.response.MockRestResponseCreators.withSuccess;
import java.net.URI;
import java.util.ArrayList;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册