Skip to content

Commit bd6ec10

Browse files
committed
Fixed tests and also added unit test for depth in good faith
1 parent 2c29b53 commit bd6ec10

5 files changed

Lines changed: 145 additions & 31 deletions

File tree

src/main/java/graphql/normalized/ExecutableNormalizedOperation.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public ExecutableNormalizedOperation(
4242
Map<ExecutableNormalizedField, MergedField> normalizedFieldToMergedField,
4343
Map<ExecutableNormalizedField, QueryDirectives> normalizedFieldToQueryDirectives,
4444
ImmutableListMultimap<FieldCoordinates, ExecutableNormalizedField> coordinatesToNormalizedFields,
45+
int operationFieldCount,
4546
int operationDepth) {
4647
this.operation = operation;
4748
this.operationName = operationName;
@@ -50,7 +51,7 @@ public ExecutableNormalizedOperation(
5051
this.normalizedFieldToMergedField = normalizedFieldToMergedField;
5152
this.normalizedFieldToQueryDirectives = normalizedFieldToQueryDirectives;
5253
this.coordinatesToNormalizedFields = coordinatesToNormalizedFields;
53-
this.operationFieldCount = fieldToNormalizedField.keySet().size();
54+
this.operationFieldCount = operationFieldCount;
5455
this.operationDepth = operationDepth;
5556
}
5657

src/main/java/graphql/normalized/ExecutableNormalizedOperationFactory.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ private static class ExecutableNormalizedOperationFactoryImpl {
431431
private final ImmutableMap.Builder<ExecutableNormalizedField, QueryDirectives> normalizedFieldToQueryDirectives = ImmutableMap.builder();
432432
private final ImmutableListMultimap.Builder<FieldCoordinates, ExecutableNormalizedField> coordinatesToNormalizedFields = ImmutableListMultimap.builder();
433433
private int fieldCount = 0;
434+
private int maxDepthSeen = 0;
434435

435436
private ExecutableNormalizedOperationFactoryImpl(
436437
GraphQLSchema graphQLSchema,
@@ -456,7 +457,6 @@ private ExecutableNormalizedOperation createNormalizedQueryImpl() {
456457

457458
CollectNFResult collectFromOperationResult = collectFromOperation(rootType);
458459

459-
int maxDepthSeen = 0;
460460
for (ExecutableNormalizedField topLevel : collectFromOperationResult.children) {
461461
ImmutableList<FieldAndAstParent> fieldAndAstParents = collectFromOperationResult.normalizedFieldToAstFields.get(topLevel);
462462
MergedField mergedField = newMergedField(fieldAndAstParents);
@@ -485,6 +485,7 @@ private ExecutableNormalizedOperation createNormalizedQueryImpl() {
485485
normalizedFieldToMergedField.build(),
486486
normalizedFieldToQueryDirectives.build(),
487487
coordinatesToNormalizedFields.build(),
488+
fieldCount,
488489
maxDepthSeen
489490
);
490491
}
@@ -629,6 +630,11 @@ private void createNFs(ImmutableList.Builder<ExecutableNormalizedField> nfListBu
629630
private ExecutableNormalizedField createNF(CollectedFieldGroup collectedFieldGroup,
630631
int level,
631632
ExecutableNormalizedField parent) {
633+
634+
this.fieldCount++;
635+
if (this.fieldCount > this.options.getMaxFieldsCount()) {
636+
throw new AbortExecutionException("Maximum field count exceeded. " + this.fieldCount + " > " + this.options.getMaxFieldsCount());
637+
}
632638
Field field;
633639
Set<GraphQLObjectType> objectTypes = collectedFieldGroup.objectTypes;
634640
field = collectedFieldGroup.fields.iterator().next().field;
@@ -641,10 +647,6 @@ private ExecutableNormalizedField createNF(CollectedFieldGroup collectedFieldGro
641647
normalizedArgumentValues = ValuesResolver.getNormalizedArgumentValues(fieldDefinition.getArguments(), field.getArguments(), this.normalizedVariableValues);
642648
}
643649
ImmutableList<String> objectTypeNames = map(objectTypes, GraphQLObjectType::getName);
644-
this.fieldCount++;
645-
if (this.fieldCount > this.options.getMaxFieldsCount()) {
646-
throw new AbortExecutionException("Maximum field count exceeded. " + this.fieldCount + " > " + this.options.getMaxFieldsCount());
647-
}
648650
return ExecutableNormalizedField.newNormalizedField()
649651
.alias(field.getAlias())
650652
.resolvedArguments(argumentValues)

src/test/groovy/graphql/InterfacesImplementingInterfacesTest.groovy

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -893,16 +893,31 @@ class InterfacesImplementingInterfacesTest extends Specification {
893893
given:
894894
def graphQLSchema = createComplexSchema()
895895

896+
GraphQL graphQL = GraphQL.newGraphQL(graphQLSchema).build()
897+
896898
when:
897-
def result = GraphQL.newGraphQL(graphQLSchema).build().execute("""
899+
String query = """
898900
{
899901
nodeType: __type(name: "Node") {
900902
possibleTypes {
901903
kind
902904
name
903905
}
904906
}
905-
resourceType: __type(name: "Resource") {
907+
}
908+
"""
909+
def result = graphQL.execute(query)
910+
911+
then:
912+
!result.errors
913+
result.data == [
914+
nodeType: [possibleTypes: [[kind: 'OBJECT', name: 'File'], [kind: 'OBJECT', name: 'Image']]],
915+
]
916+
917+
when:
918+
query = """
919+
{
920+
resourceType: __type(name: "Resource") {
906921
possibleTypes {
907922
kind
908923
name
@@ -911,22 +926,35 @@ class InterfacesImplementingInterfacesTest extends Specification {
911926
kind
912927
name
913928
}
914-
}
915-
imageType: __type(name: "Image") {
929+
}
930+
}
931+
"""
932+
result = graphQL.execute(query)
933+
934+
then:
935+
!result.errors
936+
result.data == [
937+
resourceType: [possibleTypes: [[kind: 'OBJECT', name: 'File'], [kind: 'OBJECT', name: 'Image']], interfaces: [[kind: 'INTERFACE', name: 'Node']]]
938+
]
939+
940+
when:
941+
942+
query = """
943+
{
944+
imageType: __type(name: "Image") {
916945
interfaces {
917946
kind
918947
name
919948
}
920949
}
921-
}
922-
""")
950+
}
951+
"""
952+
result = graphQL.execute(query)
923953

924954
then:
925955
!result.errors
926956
result.data == [
927-
nodeType : [possibleTypes: [[kind: 'OBJECT', name: 'File'], [kind: 'OBJECT', name: 'Image']]],
928957
imageType : [interfaces: [[kind: 'INTERFACE', name: 'Resource'], [kind: 'INTERFACE', name: 'Node']]],
929-
resourceType: [possibleTypes: [[kind: 'OBJECT', name: 'File'], [kind: 'OBJECT', name: 'Image']], interfaces: [[kind: 'INTERFACE', name: 'Node']]]
930958
]
931959
}
932960

src/test/groovy/graphql/UnionTest.groovy

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import spock.lang.Specification
44

55
class UnionTest extends Specification {
66

7-
def "can introspect on union and intersection types"() {
7+
def "can introspect on union types"() {
88
def query = """
99
{
1010
Named: __type(name: "Named") {
@@ -15,15 +15,6 @@ class UnionTest extends Specification {
1515
possibleTypes { name }
1616
enumValues { name }
1717
inputFields { name }
18-
}
19-
Pet: __type(name: "Pet") {
20-
kind
21-
name
22-
fields { name }
23-
interfaces { name }
24-
possibleTypes { name }
25-
enumValues { name }
26-
inputFields { name }
2718
}
2819
}
2920
"""
@@ -42,8 +33,32 @@ class UnionTest extends Specification {
4233
],
4334
enumValues : null,
4435
inputFields : null
45-
],
46-
Pet : [
36+
]]
37+
when:
38+
def executionResult = GraphQL.newGraphQL(GarfieldSchema.GarfieldSchema).build().execute(query)
39+
40+
then:
41+
executionResult.data == expectedResult
42+
43+
44+
}
45+
46+
def "can introspect on intersection types"() {
47+
def query = """
48+
{
49+
Pet: __type(name: "Pet") {
50+
kind
51+
name
52+
fields { name }
53+
interfaces { name }
54+
possibleTypes { name }
55+
enumValues { name }
56+
inputFields { name }
57+
}
58+
}
59+
"""
60+
61+
def expectedResult = [Pet : [
4762
kind : 'UNION',
4863
name : 'Pet',
4964
fields : null,

src/test/groovy/graphql/introspection/GoodFaithIntrospectionInstrumentationTest.groovy

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package graphql.introspection
33
import graphql.ExecutionInput
44
import graphql.ExecutionResult
55
import graphql.TestUtil
6+
import graphql.execution.AbortExecutionException
67
import graphql.execution.CoercedVariables
78
import graphql.language.Document
89
import graphql.normalized.ExecutableNormalizedOperationFactory
@@ -15,6 +16,7 @@ class GoodFaithIntrospectionInstrumentationTest extends Specification {
1516
def setup() {
1617
GoodFaithIntrospection.enabledJvmWide(true)
1718
}
19+
1820
def cleanup() {
1921
GoodFaithIntrospection.enabledJvmWide(true)
2022
}
@@ -23,11 +25,11 @@ class GoodFaithIntrospectionInstrumentationTest extends Specification {
2325

2426
when:
2527
Document document = TestUtil.toDocument(IntrospectionQuery.INTROSPECTION_QUERY)
26-
def eno = ExecutableNormalizedOperationFactory.createExecutableNormalizedOperation(graphql.getGraphQLSchema(),document,
27-
"IntrospectionQuery", CoercedVariables.emptyVariables())
28+
def eno = ExecutableNormalizedOperationFactory.createExecutableNormalizedOperation(graphql.getGraphQLSchema(), document,
29+
"IntrospectionQuery", CoercedVariables.emptyVariables())
2830

2931
then:
30-
eno.getOperationFieldCount() < GoodFaithIntrospection.GOOD_FAITH_MAX_FIELDS_COUNT // currently 62
32+
eno.getOperationFieldCount() < GoodFaithIntrospection.GOOD_FAITH_MAX_FIELDS_COUNT // currently 189
3133
eno.getOperationDepth() < GoodFaithIntrospection.GOOD_FAITH_MAX_DEPTH_COUNT // currently 13
3234
}
3335

@@ -89,7 +91,7 @@ class GoodFaithIntrospectionInstrumentationTest extends Specification {
8991
a1: __type(name : "t") { name }
9092
a2 : __type(name : "t1") { name }
9193
}
92-
""" | _
94+
""" | _
9395
// a case for schema repeated - dont ask twice
9496
""" query badActor {
9597
__schema { types { name} }
@@ -101,7 +103,7 @@ class GoodFaithIntrospectionInstrumentationTest extends Specification {
101103
a1: __schema { types { name} }
102104
a2 : __schema { types { name} }
103105
}
104-
""" | _
106+
""" | _
105107

106108
}
107109

@@ -161,4 +163,70 @@ class GoodFaithIntrospectionInstrumentationTest extends Specification {
161163
!er.errors.isEmpty()
162164
er.errors[0] instanceof GoodFaithIntrospection.BadFaithIntrospectionError
163165
}
166+
167+
def "can stop deep queries"() {
168+
169+
when:
170+
def query = createDeepQuery(depth)
171+
def then = System.currentTimeMillis()
172+
ExecutionResult er = graphql.execute(query)
173+
def ms = System.currentTimeMillis()-then
174+
175+
then:
176+
!er.errors.isEmpty()
177+
er.errors[0].class == targetError
178+
er.data == null // it stopped hard - it did not continue to normal business
179+
println "Took " + ms + "ms"
180+
181+
where:
182+
depth | targetError
183+
2 | GoodFaithIntrospection.BadFaithIntrospectionError.class
184+
10 | AbortExecutionException.class
185+
15 | AbortExecutionException.class
186+
20 | AbortExecutionException.class
187+
25 | AbortExecutionException.class
188+
50 | AbortExecutionException.class
189+
100 | AbortExecutionException.class
190+
}
191+
192+
String createDeepQuery(int depth = 25) {
193+
def result = """
194+
query test {
195+
__schema {
196+
types {
197+
...F1
198+
}
199+
}
200+
}
201+
"""
202+
for (int i = 1; i < depth; i++) {
203+
result += """
204+
fragment F$i on __Type {
205+
fields {
206+
type {
207+
...F${i + 1}
208+
}
209+
}
210+
211+
ofType {
212+
...F${i + 1}
213+
}
214+
}
215+
216+
217+
"""
218+
}
219+
result += """
220+
fragment F$depth on __Type {
221+
fields {
222+
type {
223+
name
224+
}
225+
}
226+
}
227+
228+
229+
"""
230+
return result
231+
}
164232
}

0 commit comments

Comments
 (0)