This is an automated email from the ASF dual-hosted git repository.
radu pushed a commit to branch master
in repository
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-graphql-core.git
The following commit(s) were added to refs/heads/master by this push:
new 7028ec2 SLING-12893 - NPE in DefaultQueryExecutor
7028ec2 is described below
commit 7028ec2cca60940caab798e12badeef0135fbc46
Author: Martin Schulze <[email protected]>
AuthorDate: Wed Aug 20 14:31:30 2025 +0200
SLING-12893 - NPE in DefaultQueryExecutor
* fix NPE
* add unit test for Executor Cache
---------
Co-authored-by: Martin Schulze <[email protected]>
---
.../graphql/core/engine/DefaultQueryExecutor.java | 4 +-
.../core/engine/DefaultQueryExecutorCacheTest.java | 124 +++++++++++++++++++++
2 files changed, 126 insertions(+), 2 deletions(-)
diff --git
a/src/main/java/org/apache/sling/graphql/core/engine/DefaultQueryExecutor.java
b/src/main/java/org/apache/sling/graphql/core/engine/DefaultQueryExecutor.java
index 88d87cd..4fb73a5 100644
---
a/src/main/java/org/apache/sling/graphql/core/engine/DefaultQueryExecutor.java
+++
b/src/main/java/org/apache/sling/graphql/core/engine/DefaultQueryExecutor.java
@@ -405,12 +405,12 @@ public class DefaultQueryExecutor implements
QueryExecutor {
*/
String resourceToHashMapKey = getCacheKey(currentResource, selectors);
String oldHash = resourceToHashMap.get(resourceToHashMapKey);
- if (!newHash.equals(oldHash)) {
+ if (!newHash.equals(oldHash) || hashToSchemaMap.get(newHash) == null) {
readLock.unlock();
writeLock.lock();
try {
oldHash = resourceToHashMap.get(resourceToHashMapKey);
- if (!newHash.equals(oldHash)) {
+ if (!newHash.equals(oldHash) || hashToSchemaMap.get(newHash)
== null) {
typeRegistry = new SchemaParser().parse(sdl);
typeRegistry.add(Directives.CONNECTION);
typeRegistry.add(Directives.FETCHER);
diff --git
a/src/test/java/org/apache/sling/graphql/core/engine/DefaultQueryExecutorCacheTest.java
b/src/test/java/org/apache/sling/graphql/core/engine/DefaultQueryExecutorCacheTest.java
new file mode 100644
index 0000000..7ba4597
--- /dev/null
+++
b/src/test/java/org/apache/sling/graphql/core/engine/DefaultQueryExecutorCacheTest.java
@@ -0,0 +1,124 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.sling.graphql.core.engine;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.graphql.core.scalars.SlingScalarsProvider;
+import org.apache.sling.graphql.core.schema.RankedSchemaProviders;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import graphql.schema.idl.TypeDefinitionRegistry;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class DefaultQueryExecutorCacheTest {
+
+ @Mock
+ private RankedSchemaProviders schemaProvider;
+
+ @Mock
+ private SlingDataFetcherSelector dataFetcherSelector;
+
+ @Mock
+ private SlingTypeResolverSelector typeResolverSelector;
+
+ @Mock
+ private SlingScalarsProvider scalarsProvider;
+
+ @Mock
+ private Resource resource;
+
+ @InjectMocks
+ private DefaultQueryExecutor executor;
+
+ @Before
+ public void setUp() {
+ // Activate the component with default config
+ DefaultQueryExecutor.Config config =
mock(DefaultQueryExecutor.Config.class);
+ when(config.schemaCacheSize()).thenReturn(10);
+ when(config.maxQueryTokens()).thenReturn(15000);
+ when(config.maxWhitespaceTokens()).thenReturn(200000);
+ when(config.maxFieldCount()).thenReturn(100000);
+
+ executor.activate(config);
+
+ when(resource.getPath()).thenReturn("/content/test");
+ }
+
+ @Test
+ public void testGetTypeDefinitionRegistry_ValidSDL() {
+ String validSDL = "type Query { hello: String }";
+ String[] selectors = { "test" };
+
+ TypeDefinitionRegistry result =
executor.getTypeDefinitionRegistry(validSDL, resource, selectors);
+
+ assertNotNull(result);
+ assertTrue(result.getType("Query").isPresent());
+ }
+
+ @Test
+ public void testGetTypeDefinitionRegistry_InvalidSDL() {
+ String invalidSDL = "invalid graphql syntax {";
+ String[] selectors = { "test" };
+
+ TypeDefinitionRegistry result =
executor.getTypeDefinitionRegistry(invalidSDL, resource, selectors);
+
+ assertNull(result);
+ }
+
+ @Test
+ public void testGetTypeDefinitionRegistry_CacheDisabled() {
+ DefaultQueryExecutor.Config config =
mock(DefaultQueryExecutor.Config.class);
+ when(config.schemaCacheSize()).thenReturn(0);
+ executor.activate(config);
+
+ String sdl = "type Query { hello: String }";
+ String[] selectors = { "test" };
+
+ TypeDefinitionRegistry result =
executor.getTypeDefinitionRegistry(sdl, resource, selectors);
+
+ assertNotNull(result);
+ }
+
+ @Test
+ public void testGetTypeDefinitionRegistry_Extended() {
+ Resource resource2 = mock(Resource.class);
+ when(resource2.getPath()).thenReturn("/content/test2");
+
+ DefaultQueryExecutor.Config config =
mock(DefaultQueryExecutor.Config.class);
+ when(config.schemaCacheSize()).thenReturn(2);
+ executor.activate(config);
+
+ String sdl = "type Query { hello: String }";
+ String[] selectors = { "test" };
+
+ executor.getTypeDefinitionRegistry(sdl, resource2, selectors);
+ executor.getTypeDefinitionRegistry(sdl + " ", resource, selectors);
+ executor.getTypeDefinitionRegistry(sdl + " ", resource, selectors);
+ TypeDefinitionRegistry result =
executor.getTypeDefinitionRegistry(sdl, resource2, selectors);
+ assertNotNull(result);
+ }
+}