blob: 5ad929b5c136e33cc15a39f8211f426f6c0c63e8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jmeter.protocol.http.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.params.provider.Arguments.arguments;
import java.nio.charset.StandardCharsets;
import java.util.stream.Stream;
import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.http.config.GraphQLRequestParams;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
class TestGraphQLRequestParamUtils {
private static final String OPERATION_NAME = "";
private static final String QUERY =
"query($id: ID!) {\n"
+ " droid(id: $id) {\n"
+ " id\n"
+ " name\n"
+ " friends {\n"
+ " id\n"
+ " name\n"
+ " appearsIn\n"
+ " }\n"
+ " }\n"
+ "}\n";
private static final String VARIABLES =
"{\n"
+ " \"id\": \"2001\"\n"
+ "}\n";
private static final String EXPECTED_QUERY_GET_PARAM_VALUE =
"query($id: ID!) { droid(id: $id) { id name friends { id name appearsIn } } }";
private static final String EXPECTED_VARIABLES_GET_PARAM_VALUE = "{\"id\":\"2001\"}";
private static final String EXPECTED_POST_BODY =
"{"
+ "\"operationName\":null,"
+ "\"variables\":" + EXPECTED_VARIABLES_GET_PARAM_VALUE + ","
+ "\"query\":\"" + StringUtils.replace(QUERY.trim(), "\n", "\\n") + "\""
+ "}";
private static final ObjectMapper OBJECT_MAPPER = JsonMapper.builder()
// See https://github.com/FasterXML/jackson-core/issues/991
.enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION)
.build();;
private GraphQLRequestParams params;
@BeforeEach
void setUp() {
params = new GraphQLRequestParams(OPERATION_NAME, QUERY, VARIABLES);
}
@ParameterizedTest
@ValueSource(strings = { "application/json", "application/json;charset=utf-8", "application/json; charset=utf-8" })
void testIsGraphQLContentType(String contentType) {
assertTrue(GraphQLRequestParamUtils.isGraphQLContentType(contentType));
}
// null can't be used in a ValueSource directly, so we need to use a MethodSource
static Stream<String> invalidContentTypes() {
return Stream.of("application/vnd.api+json", "application/json-patch+json", "",
null);
}
@ParameterizedTest
@MethodSource("invalidContentTypes")
void testInvalidGraphQLContentType(String contentType) {
assertFalse(GraphQLRequestParamUtils.isGraphQLContentType(contentType));
}
static Stream<org.junit.jupiter.params.provider.Arguments> postBodyFieldNameAndJsonNodes() throws Exception {
final JsonNode expectedPostBodyJson = OBJECT_MAPPER.readTree(EXPECTED_POST_BODY);
final JsonNode actualPostBodyJson = OBJECT_MAPPER.readTree(
GraphQLRequestParamUtils.toPostBodyString(new GraphQLRequestParams(OPERATION_NAME, QUERY, VARIABLES)));
return Stream.of(
arguments(GraphQLRequestParamUtils.OPERATION_NAME_FIELD, expectedPostBodyJson, actualPostBodyJson),
arguments(GraphQLRequestParamUtils.VARIABLES_FIELD, expectedPostBodyJson, actualPostBodyJson),
arguments(GraphQLRequestParamUtils.QUERY_FIELD, expectedPostBodyJson, actualPostBodyJson));
}
@ParameterizedTest
@MethodSource("postBodyFieldNameAndJsonNodes")
void testFieldInJsonFromToPostBodyString(String fieldName, JsonNode expectedNode, JsonNode actualNode) {
assertEquals(expectedNode.get(fieldName), actualNode.get(fieldName),
"The value of the '" + fieldName + "' field doesn't match in " + actualNode);
}
@Test
void testQueryToGetParamValue() {
assertEquals(EXPECTED_QUERY_GET_PARAM_VALUE, GraphQLRequestParamUtils.queryToGetParamValue(params.getQuery()));
}
@Test
void testVariablesToGetParamValue() throws Exception {
assertEquals(OBJECT_MAPPER.readTree(EXPECTED_VARIABLES_GET_PARAM_VALUE),
OBJECT_MAPPER.readTree(GraphQLRequestParamUtils.variablesToGetParamValue(params.getVariables())));
}
@Test
void testToGraphQLRequestParamsWithPostData() throws Exception {
GraphQLRequestParams params = GraphQLRequestParamUtils
.toGraphQLRequestParams(EXPECTED_POST_BODY.getBytes(StandardCharsets.UTF_8), null);
assertNull(params.getOperationName());
assertEquals(QUERY.trim(), params.getQuery());
assertEquals(EXPECTED_VARIABLES_GET_PARAM_VALUE, params.getVariables());
params = GraphQLRequestParamUtils.toGraphQLRequestParams(
"{\"operationName\":\"op1\",\"variables\":{\"id\":123},\"query\":\"query { droid { id }}\"}"
.getBytes(StandardCharsets.UTF_8),
null);
assertEquals("op1", params.getOperationName());
assertEquals("query { droid { id }}", params.getQuery());
assertEquals("{\"id\":123}", params.getVariables());
}
@ParameterizedTest
@ValueSource(strings = { "", "{}"})
void testInvalidJsonData(String postDataAsString) {
byte[] postData = postDataAsString.getBytes(StandardCharsets.UTF_8);
assertThrows(IllegalArgumentException.class,
() -> GraphQLRequestParamUtils.toGraphQLRequestParams(postData, null));
}
@ParameterizedTest
@ValueSource(strings = { "{\"query\":\"select * from emp\"}",
"{\"operationName\":{\"id\":123},\"query\":\"query { droid { id }}\"}",
"{\"variables\":\"r2d2\",\"query\":\"query { droid { id }}\"}" })
void testInvalidGraphQueryParam(String postDataAsString) {
byte[] postData = postDataAsString.getBytes(StandardCharsets.UTF_8);
assertThrows(IllegalArgumentException.class,
() -> GraphQLRequestParamUtils.toGraphQLRequestParams(postData, null));
}
@Test
void testToGraphQLRequestParamsWithHttpArguments() throws Exception {
Arguments args = new Arguments();
args.addArgument(new HTTPArgument("query", "query { droid { id }}", "=", false));
GraphQLRequestParams params = GraphQLRequestParamUtils.toGraphQLRequestParams(args, null);
assertNull(params.getOperationName());
assertEquals("query { droid { id }}", params.getQuery());
assertNull(params.getVariables());
args = new Arguments();
args.addArgument(new HTTPArgument("operationName", "op1", "=", false));
args.addArgument(new HTTPArgument("query", "query { droid { id }}", "=", false));
args.addArgument(new HTTPArgument("variables", "{\"id\":123}", "=", false));
params = GraphQLRequestParamUtils.toGraphQLRequestParams(args, null);
assertEquals("op1", params.getOperationName());
assertEquals("query { droid { id }}", params.getQuery());
assertEquals("{\"id\":123}", params.getVariables());
args = new Arguments();
args.addArgument(new HTTPArgument("query", "query+%7B+droid+%7B+id+%7D%7D", "=", true));
params = GraphQLRequestParamUtils.toGraphQLRequestParams(args, null);
assertNull(params.getOperationName());
assertEquals("query { droid { id }}", params.getQuery());
assertNull(params.getVariables());
args = new Arguments();
args.addArgument(new HTTPArgument("query", "query%20%7B%20droid%20%7B%20id%20%7D%7D", "=", true));
params = GraphQLRequestParamUtils.toGraphQLRequestParams(args, null);
assertNull(params.getOperationName());
assertEquals("query { droid { id }}", params.getQuery());
assertNull(params.getVariables());
}
@Test
void testMissingParams() {
Arguments args = new Arguments();
assertThrows(IllegalArgumentException.class,
() -> GraphQLRequestParamUtils.toGraphQLRequestParams(args, null));
}
@Test
void testInvalidQueryParam() {
Arguments args = new Arguments();
args.addArgument(new HTTPArgument("query", "select * from emp", "=", false));
assertThrows(IllegalArgumentException.class,
() -> GraphQLRequestParamUtils.toGraphQLRequestParams(args, null));
}
@Test
void testInvalidQueryParamVariables() {
Arguments args = new Arguments();
args.addArgument(new HTTPArgument("query", "query { droid { id }}", "=", false));
args.addArgument(new HTTPArgument("variables", "r2d2", "=", false));
assertThrows(IllegalArgumentException.class,
() -> GraphQLRequestParamUtils.toGraphQLRequestParams(args, null));
}
}