Skip to content

Commit deb35be

Browse files
andimarekclaude
andcommitted
Add tests for tooBigOperation good faith introspection path
The refactored GoodFaithIntrospection validation had uncovered code paths for queries that exceed complexity limits (field count or depth) without triggering the tooManyFields cycle check. These tests exercise: - Wide introspection query exceeding field count limit (>500 fields) - Deep introspection query exceeding depth limit (>20 levels via ofType) - Custom user limits combined with good faith limits Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 455c7c8 commit deb35be

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed

src/test/groovy/graphql/introspection/GoodFaithIntrospectionTest.groovy

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import graphql.TestUtil
66
import graphql.execution.CoercedVariables
77
import graphql.language.Document
88
import graphql.normalized.ExecutableNormalizedOperationFactory
9+
import graphql.validation.QueryComplexityLimits
910
import spock.lang.Specification
1011

1112
class GoodFaithIntrospectionTest extends Specification {
@@ -188,6 +189,77 @@ class GoodFaithIntrospectionTest extends Specification {
188189
100 | GoodFaithIntrospection.BadFaithIntrospectionError.class
189190
}
190191

192+
def "good faith limits are applied on top of custom user limits"() {
193+
given:
194+
def limits = QueryComplexityLimits.newLimits().maxFieldsCount(200).maxDepth(15).build()
195+
def executionInput = ExecutionInput.newExecutionInput(IntrospectionQuery.INTROSPECTION_QUERY)
196+
.graphQLContext([(QueryComplexityLimits.KEY): limits])
197+
.build()
198+
199+
when:
200+
ExecutionResult er = graphql.execute(executionInput)
201+
202+
then:
203+
er.errors.isEmpty()
204+
}
205+
206+
def "containsIntrospectionFields handles operation with no selection set"() {
207+
given:
208+
def op = graphql.language.OperationDefinition.newOperationDefinition()
209+
.name("empty")
210+
.operation(graphql.language.OperationDefinition.Operation.QUERY)
211+
.build()
212+
def doc = Document.newDocument().definition(op).build()
213+
214+
expect:
215+
!GoodFaithIntrospection.containsIntrospectionFields(doc)
216+
}
217+
218+
def "introspection query exceeding field count limit is detected as bad faith"() {
219+
given:
220+
// Build a wide introspection query that exceeds GOOD_FAITH_MAX_FIELDS_COUNT (500)
221+
// using non-cycle-forming fields (aliases of 'name') so the tooManyFields check
222+
// does not fire first, exercising the tooBigOperation code path instead
223+
def sb = new StringBuilder()
224+
sb.append("query { __schema { types { ")
225+
for (int i = 0; i < 510; i++) {
226+
sb.append("a${i}: name ")
227+
}
228+
sb.append("} } }")
229+
230+
when:
231+
ExecutionResult er = graphql.execute(sb.toString())
232+
233+
then:
234+
!er.errors.isEmpty()
235+
er.errors[0] instanceof GoodFaithIntrospection.BadFaithIntrospectionError
236+
er.errors[0].message.contains("too big")
237+
}
238+
239+
def "introspection query exceeding depth limit is detected as bad faith"() {
240+
given:
241+
// Build a deep introspection query using ofType (not a cycle-forming field)
242+
// that exceeds GOOD_FAITH_MAX_DEPTH_COUNT (20)
243+
def sb = new StringBuilder()
244+
sb.append("query { __schema { types { ")
245+
for (int i = 0; i < 20; i++) {
246+
sb.append("ofType { ")
247+
}
248+
sb.append("name ")
249+
for (int i = 0; i < 20; i++) {
250+
sb.append("} ")
251+
}
252+
sb.append("} } }")
253+
254+
when:
255+
ExecutionResult er = graphql.execute(sb.toString())
256+
257+
then:
258+
!er.errors.isEmpty()
259+
er.errors[0] instanceof GoodFaithIntrospection.BadFaithIntrospectionError
260+
er.errors[0].message.contains("too big")
261+
}
262+
191263
String createDeepQuery(int depth = 25) {
192264
def result = """
193265
query test {

0 commit comments

Comments
 (0)