This is an automated email from the ASF dual-hosted git repository.

jjramos pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/develop by this push:
     new 6933232  GEODE-7487: Update Running CQ Context (#4369)
6933232 is described below

commit 693323257481dbf5b785421061369abb5497742e
Author: Juan José Ramos <[email protected]>
AuthorDate: Thu Nov 28 13:05:19 2019 +0000

    GEODE-7487: Update Running CQ Context (#4369)
    
    - Added unit and integration tests.
    - Implemented method to invalidate the cache used by CQs.
    - Updated the context implementation to change the internal
      MethodInvocationAuthorizer used whenever the CQ resets the
      ExecutionContext.
    - Added a warning message whenever the MethodInvocationAuthorizer
      returned by the QueryConfigurationService is null.
---
 .../DefaultQuerySecurityIntegrationTest.java       | 34 +++------
 .../DefaultQueryServiceIntegrationTest.java        | 80 ++++++++++++++++++++++
 .../internal/ExecutionContextIntegrationTest.java  | 41 ++++++++---
 .../cache/query/internal/DefaultQueryService.java  | 12 +++-
 .../cache/query/internal/ExecutionContext.java     | 27 ++++----
 .../geode/cache/query/internal/cq/ServerCQ.java    |  7 ++
 .../query/internal/AttributeDescriptorTest.java    |  7 +-
 .../internal/CompiledAggregateFunctionTest.java    |  6 +-
 .../cache/query/internal/ExecutionContextTest.java | 23 ++-----
 .../cache/query/internal/MethodDispatchTest.java   |  7 +-
 .../cache/query/internal/NWayMergeResultsTest.java |  6 +-
 .../geode/cache/query/internal/QCompilerTest.java  |  6 +-
 .../query/internal/QueryExecutionContextTest.java  |  6 +-
 .../internal/index/CompactRangeIndexTest.java      | 12 ++--
 .../cache/PartitionedRegionQueryEvaluatorTest.java |  9 +--
 .../cache/query/cq/internal/ServerCQImpl.java      | 16 ++++-
 .../cache/query/cq/internal/ServerCQImplTest.java  | 76 ++++++++++++++++++++
 17 files changed, 281 insertions(+), 94 deletions(-)

diff --git 
a/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/DefaultQuerySecurityIntegrationTest.java
 
b/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/DefaultQuerySecurityIntegrationTest.java
index 17237d4..08fb8a7 100644
--- 
a/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/DefaultQuerySecurityIntegrationTest.java
+++ 
b/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/DefaultQuerySecurityIntegrationTest.java
@@ -19,11 +19,11 @@ import static 
org.apache.geode.test.awaitility.GeodeAwaitility.await;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import java.lang.reflect.Method;
+import java.util.Collections;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.IntStream;
 
@@ -95,7 +95,7 @@ public class DefaultQuerySecurityIntegrationTest {
   }
 
   private void 
executeQueryAndAssertThatAuthorizerWasInstantiatedExpectedAmountOfTimes(
-      String queryString, RegionShortcut regionShortcut) {
+      String queryString) {
     IntStream.range(1, executions).forEach(counter -> {
       try {
         DefaultQuery query = spy(new DefaultQuery(queryString, spiedCache, 
false));
@@ -103,12 +103,7 @@ public class DefaultQuerySecurityIntegrationTest {
 
         SelectResults result = (SelectResults) query.execute();
         assertThat(result.size()).isEqualTo(entries);
-        if (!regionShortcut.equals(RegionShortcut.PARTITION)) {
-          assertThat(SpyAuthorizer.instantiations.get()).isEqualTo(counter);
-        } else {
-          // execute + getEmptyResultSet + executeOnLocalNode
-          assertThat(SpyAuthorizer.instantiations.get()).isEqualTo(3 * 
counter);
-        }
+        assertThat(SpyAuthorizer.instantiations.get()).isEqualTo(1);
       } catch (Exception exception) {
         throw new RuntimeException(exception);
       }
@@ -116,17 +111,14 @@ public class DefaultQuerySecurityIntegrationTest {
   }
 
   @Before
-  public void setUp() {
+  public void setUp() throws ClassNotFoundException {
     SpyAuthorizer.instantiations.set(0);
     SpyAuthorizer.authorizations.set(0);
 
     spiedCache = spy(server.getCache());
-    doAnswer(answer -> {
-      InternalQueryService spyQueryService = spy((InternalQueryService) 
answer.callRealMethod());
-      doReturn(new 
SpyAuthorizer()).when(spyQueryService).getMethodInvocationAuthorizer();
-
-      return spyQueryService;
-    }).when(spiedCache).getQueryService();
+    QueryConfigurationService queryConfig = 
spiedCache.getService(QueryConfigurationService.class);
+    queryConfig.updateMethodAuthorizer(spiedCache, 
SpyAuthorizer.class.getName(),
+        Collections.emptySet());
   }
 
   @Test
@@ -186,8 +178,7 @@ public class DefaultQuerySecurityIntegrationTest {
     createAndPopulateRegion(regionName, regionShortcut);
     String queryString = "SELECT object.name FROM /" + regionName + " object";
 
-    
executeQueryAndAssertThatAuthorizerWasInstantiatedExpectedAmountOfTimes(queryString,
-        regionShortcut);
+    
executeQueryAndAssertThatAuthorizerWasInstantiatedExpectedAmountOfTimes(queryString);
   }
 
   @Test
@@ -199,8 +190,7 @@ public class DefaultQuerySecurityIntegrationTest {
     createAndPopulateRegion(regionName, regionShortcut);
     String queryString = "SELECT object.privateID, object.name FROM /" + 
regionName + " object";
 
-    
executeQueryAndAssertThatAuthorizerWasInstantiatedExpectedAmountOfTimes(queryString,
-        regionShortcut);
+    
executeQueryAndAssertThatAuthorizerWasInstantiatedExpectedAmountOfTimes(queryString);
   }
 
   @Test
@@ -212,8 +202,7 @@ public class DefaultQuerySecurityIntegrationTest {
     createAndPopulateRegion(regionName, regionShortcut);
     String queryString = "SELECT object.getName() FROM /" + regionName + " 
object";
 
-    
executeQueryAndAssertThatAuthorizerWasInstantiatedExpectedAmountOfTimes(queryString,
-        regionShortcut);
+    
executeQueryAndAssertThatAuthorizerWasInstantiatedExpectedAmountOfTimes(queryString);
   }
 
   @Test
@@ -225,8 +214,7 @@ public class DefaultQuerySecurityIntegrationTest {
     createAndPopulateRegion(regionName, regionShortcut);
     String queryString = "SELECT object.getId(), object.getName() FROM /" + 
regionName + " object";
 
-    
executeQueryAndAssertThatAuthorizerWasInstantiatedExpectedAmountOfTimes(queryString,
-        regionShortcut);
+    
executeQueryAndAssertThatAuthorizerWasInstantiatedExpectedAmountOfTimes(queryString);
   }
 
   private static class SpyQueryExecutor implements Answer {
diff --git 
a/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/DefaultQueryServiceIntegrationTest.java
 
b/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/DefaultQueryServiceIntegrationTest.java
new file mode 100644
index 0000000..7f410df
--- /dev/null
+++ 
b/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/DefaultQueryServiceIntegrationTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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.geode.cache.query.internal;
+
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TemporaryFolder;
+import org.junit.rules.TestName;
+
+import org.apache.geode.cache.RegionShortcut;
+import org.apache.geode.internal.cache.InternalCache;
+import org.apache.geode.test.assertj.LogFileAssert;
+import org.apache.geode.test.junit.categories.OQLQueryTest;
+import org.apache.geode.test.junit.rules.ServerStarterRule;
+
+@Category(OQLQueryTest.class)
+public class DefaultQueryServiceIntegrationTest {
+  private File logFile;
+  private InternalCache spiedCache;
+
+  @Rule
+  public TestName testName = new TestName();
+
+  @Rule
+  public ServerStarterRule server = new ServerStarterRule();
+
+  @Rule
+  public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+  @Before
+  public void setUp() throws IOException {
+    logFile = temporaryFolder.newFile(testName.getMethodName() + ".log");
+    server.withProperty("log-file", logFile.getAbsolutePath())
+        .withRegion(RegionShortcut.LOCAL, testName.getMethodName())
+        .startServer();
+
+    spiedCache = spy(server.getCache());
+  }
+
+  @Test
+  public void constructorShouldThrowExceptionWhenCacheIsNull() {
+    assertThatThrownBy(() -> new DefaultQueryService(null))
+        .isInstanceOf(IllegalArgumentException.class)
+        .hasMessage("Cache must not be null");
+  }
+
+  @Test
+  public void constructorShouldLogWarningWhenMethodAuthorizerIsNull() {
+    QueryConfigurationService mockService = 
mock(QueryConfigurationService.class);
+    when(mockService.getMethodAuthorizer()).thenReturn(null);
+    
when(spiedCache.getService(QueryConfigurationService.class)).thenReturn(mockService);
+
+    assertThatCode(() -> new 
DefaultQueryService(spiedCache)).doesNotThrowAnyException();
+    LogFileAssert.assertThat(logFile).contains(
+        "MethodInvocationAuthorizer returned by the QueryConfigurationService 
is null, problems might arise if there are queries using method invocations.");
+  }
+}
diff --git 
a/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/ExecutionContextIntegrationTest.java
 
b/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/ExecutionContextIntegrationTest.java
index 53a4c71..85ba93b 100644
--- 
a/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/ExecutionContextIntegrationTest.java
+++ 
b/geode-core/src/integrationTest/java/org/apache/geode/cache/query/internal/ExecutionContextIntegrationTest.java
@@ -23,6 +23,7 @@ import static 
org.apache.geode.distributed.ConfigurationProperties.SECURITY_MANA
 import static org.assertj.core.api.Assertions.assertThat;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -33,13 +34,14 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
-import org.apache.geode.SystemFailure;
 import org.apache.geode.cache.RegionShortcut;
 import org.apache.geode.cache.query.NameResolutionException;
 import org.apache.geode.cache.query.TypeMismatchException;
 import org.apache.geode.cache.query.security.MethodInvocationAuthorizer;
+import org.apache.geode.cache.query.security.RegExMethodAuthorizer;
 import org.apache.geode.cache.query.security.RestrictedMethodAuthorizer;
 import org.apache.geode.examples.SimpleSecurityManager;
+import org.apache.geode.internal.cache.InternalCache;
 import org.apache.geode.test.dunit.ThreadUtils;
 import org.apache.geode.test.junit.categories.OQLQueryTest;
 import org.apache.geode.test.junit.rules.ServerStarterRule;
@@ -131,6 +133,14 @@ public class ExecutionContextIntegrationTest {
     return i;
   }
 
+  private void restartServerWithSecurityEnabled() {
+    server.stopMember();
+    server.withProperty(SECURITY_MANAGER, 
SimpleSecurityManager.class.getName())
+        .withProperty("security-username", "cluster")
+        .withProperty("security-password", "cluster")
+        .startServer();
+  }
+
   @Test
   public void constructorShouldUseConfiguredMethodAuthorizer() {
     ExecutionContext unsecuredContext = new QueryExecutionContext(null, 
server.getCache());
@@ -140,17 +150,35 @@ public class ExecutionContextIntegrationTest {
     assertThat(noOpAuthorizer).isNotNull();
     
assertThat(noOpAuthorizer).isSameAs(QueryConfigurationServiceImpl.getNoOpAuthorizer());
 
+    // Security Enabled -> RestrictedMethodAuthorizer
+    restartServerWithSecurityEnabled();
+    ExecutionContext securedContext = new QueryExecutionContext(null, 
server.getCache());
+    MethodInvocationAuthorizer authorizer = 
securedContext.getMethodInvocationAuthorizer();
+    assertThat(authorizer).isNotNull();
+    assertThat(authorizer).isInstanceOf(RestrictedMethodAuthorizer.class);
+  }
+
+  @Test
+  public void resetShouldUpdateTheMethodInvocationAuthorizer() throws 
ClassNotFoundException {
     server.stopMember();
 
     // Security Enabled -> RestrictedMethodAuthorizer
-    server.withProperty(SECURITY_MANAGER, 
SimpleSecurityManager.class.getName())
-        .withProperty("security-username", "cluster")
-        .withProperty("security-password", "cluster")
-        .startServer();
+    restartServerWithSecurityEnabled();
     ExecutionContext securedContext = new QueryExecutionContext(null, 
server.getCache());
     MethodInvocationAuthorizer authorizer = 
securedContext.getMethodInvocationAuthorizer();
     assertThat(authorizer).isNotNull();
     assertThat(authorizer).isInstanceOf(RestrictedMethodAuthorizer.class);
+
+    // Change the authorizer
+    InternalCache internalCache = server.getCache();
+    
internalCache.getService(QueryConfigurationService.class).updateMethodAuthorizer(internalCache,
+        RegExMethodAuthorizer.class.getName(), Collections.emptySet());
+
+    // Reset the context - used by CQs when processing events
+    securedContext.reset();
+    MethodInvocationAuthorizer newAuthorizer = 
securedContext.getMethodInvocationAuthorizer();
+    assertThat(newAuthorizer).isNotNull();
+    assertThat(newAuthorizer).isInstanceOf(RegExMethodAuthorizer.class);
   }
 
   @Test
@@ -323,9 +351,6 @@ public class ExecutionContextIntegrationTest {
         while (runtimeIterator.hasNext()) {
           assertIteratorScopeMultiThreaded(runtimeIterator);
         }
-      } catch (VirtualMachineError e) {
-        SystemFailure.initiateFailure(e);
-        throw e;
       } catch (Throwable th) {
         throw new RuntimeException(th);
       }
diff --git 
a/geode-core/src/main/java/org/apache/geode/cache/query/internal/DefaultQueryService.java
 
b/geode-core/src/main/java/org/apache/geode/cache/query/internal/DefaultQueryService.java
index 2d914bb..cec72be 100644
--- 
a/geode-core/src/main/java/org/apache/geode/cache/query/internal/DefaultQueryService.java
+++ 
b/geode-core/src/main/java/org/apache/geode/cache/query/internal/DefaultQueryService.java
@@ -108,14 +108,20 @@ public class DefaultQueryService implements 
InternalQueryService {
   private Map<Region, HashSet<IndexCreationData>> indexDefinitions =
       Collections.synchronizedMap(new HashMap<>());
 
-
   public DefaultQueryService(InternalCache cache) {
     if (cache == null)
-      throw new IllegalArgumentException("cache must not be null");
-    this.cache = cache;
+      throw new IllegalArgumentException("Cache must not be null");
     QueryConfigurationService queryConfigurationService =
         cache.getService(QueryConfigurationService.class);
+
+    this.cache = cache;
     this.methodInvocationAuthorizer = 
queryConfigurationService.getMethodAuthorizer();
+
+    // Should never happen, adding the check as a safeguard.
+    if (this.methodInvocationAuthorizer == null) {
+      logger.warn(
+          "MethodInvocationAuthorizer returned by the 
QueryConfigurationService is null, problems might arise if there are queries 
using method invocations.");
+    }
   }
 
   /**
diff --git 
a/geode-core/src/main/java/org/apache/geode/cache/query/internal/ExecutionContext.java
 
b/geode-core/src/main/java/org/apache/geode/cache/query/internal/ExecutionContext.java
index afaba37..54a6e6e 100644
--- 
a/geode-core/src/main/java/org/apache/geode/cache/query/internal/ExecutionContext.java
+++ 
b/geode-core/src/main/java/org/apache/geode/cache/query/internal/ExecutionContext.java
@@ -102,13 +102,19 @@ public class ExecutionContext {
   static final ThreadLocal<AtomicBoolean> isCanceled =
       ThreadLocal.withInitial(AtomicBoolean::new);
 
-  // Authorizer to use during the query execution.
-  private final MethodInvocationAuthorizer methodInvocationAuthorizer;
+  /**
+   * Authorizer to use during query execution.
+   * It can not be changed for queries in flight, but it should be modifiable 
for running CQs,
+   * that's the only reason why this field is not marked as {@code final}.
+   *
+   * @see ExecutionContext#reset()
+   */
+  private MethodInvocationAuthorizer methodInvocationAuthorizer;
+  private final QueryConfigurationService queryConfigurationService;
 
   /**
    * Returns the {@link MethodInvocationAuthorizer} that will be used, if 
needed, during the
-   * execution
-   * of the query associated with this context.
+   * execution of the query associated with this context.
    *
    * @return the {@link MethodInvocationAuthorizer} that will be used, if 
needed, during the
    *         execution of the query associated with this context.
@@ -124,16 +130,11 @@ public class ExecutionContext {
    * @see org.apache.geode.cache.Region#query
    */
   public ExecutionContext(Object[] bindArguments, InternalCache cache) {
-    this.bindArguments = bindArguments;
     this.cache = cache;
+    this.bindArguments = bindArguments;
     this.cancelationTask = Optional.empty();
-
-    // Authorization & authentication logic happens on server side only.
-    if (cache.isClient()) {
-      this.methodInvocationAuthorizer = 
QueryConfigurationServiceImpl.getNoOpAuthorizer();
-    } else {
-      this.methodInvocationAuthorizer = 
cache.getQueryService().getMethodInvocationAuthorizer();
-    }
+    this.queryConfigurationService = 
cache.getService(QueryConfigurationService.class);
+    this.methodInvocationAuthorizer = 
queryConfigurationService.getMethodAuthorizer();
   }
 
   Optional<ScheduledFuture> getCancelationTask() {
@@ -585,6 +586,8 @@ public class ExecutionContext {
    */
   public void reset() {
     scopes.clear();
+    // Make sure we use the most up to date authorizer in CQs.
+    methodInvocationAuthorizer = 
queryConfigurationService.getMethodAuthorizer();
   }
 
   public BucketRegion getBucketRegion() {
diff --git 
a/geode-core/src/main/java/org/apache/geode/cache/query/internal/cq/ServerCQ.java
 
b/geode-core/src/main/java/org/apache/geode/cache/query/internal/cq/ServerCQ.java
index abc589c..c36cd4b 100644
--- 
a/geode-core/src/main/java/org/apache/geode/cache/query/internal/cq/ServerCQ.java
+++ 
b/geode-core/src/main/java/org/apache/geode/cache/query/internal/cq/ServerCQ.java
@@ -54,6 +54,13 @@ public interface ServerCQ extends InternalCqQuery {
   void removeFromCqResultKeys(Object key, boolean isTokenMode);
 
   /**
+   * Invalidates the internal cache containing the keys that are part of the 
CQ query results.
+   * Once this method finishes, the CQ engine will not apply the internal 
optimization for already
+   * seen keys anymore, not until the cache is manually rebuilt.
+   */
+  void invalidateCqResultKeys();
+
+  /**
    * Sets the CQ Results key cache state as initialized.
    */
   void setCqResultsCacheInitialized();
diff --git 
a/geode-core/src/test/java/org/apache/geode/cache/query/internal/AttributeDescriptorTest.java
 
b/geode-core/src/test/java/org/apache/geode/cache/query/internal/AttributeDescriptorTest.java
index 34f4062..f7c2a20 100644
--- 
a/geode-core/src/test/java/org/apache/geode/cache/query/internal/AttributeDescriptorTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/cache/query/internal/AttributeDescriptorTest.java
@@ -71,9 +71,10 @@ public class AttributeDescriptorTest {
     typeRegistry = new TypeRegistry(mockCache, true);
     methodInvocationAuthorizer = spy(MethodInvocationAuthorizer.class);
 
-    InternalQueryService mockQueryService = mock(InternalQueryService.class);
-    when(mockCache.getQueryService()).thenReturn(mockQueryService);
-    
when(mockQueryService.getMethodInvocationAuthorizer()).thenReturn(methodInvocationAuthorizer);
+    QueryConfigurationService mockService = 
mock(QueryConfigurationService.class);
+    
when(mockService.getMethodAuthorizer()).thenReturn(methodInvocationAuthorizer);
+
+    
when(mockCache.getService(QueryConfigurationService.class)).thenReturn(mockService);
     queryExecutionContext = new QueryExecutionContext(null, mockCache);
   }
 
diff --git 
a/geode-core/src/test/java/org/apache/geode/cache/query/internal/CompiledAggregateFunctionTest.java
 
b/geode-core/src/test/java/org/apache/geode/cache/query/internal/CompiledAggregateFunctionTest.java
index f86d424..c7b77d5 100644
--- 
a/geode-core/src/test/java/org/apache/geode/cache/query/internal/CompiledAggregateFunctionTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/cache/query/internal/CompiledAggregateFunctionTest.java
@@ -51,9 +51,9 @@ public class CompiledAggregateFunctionTest {
   @Before
   public void setUp() throws Exception {
     cache = mock(InternalCache.class);
-    when(cache.getQueryService()).thenReturn(mock(InternalQueryService.class));
-    when(cache.getQueryService().getMethodInvocationAuthorizer())
-        .thenReturn(mock(MethodInvocationAuthorizer.class));
+    QueryConfigurationService mockService = 
mock(QueryConfigurationService.class);
+    
when(mockService.getMethodAuthorizer()).thenReturn(mock(MethodInvocationAuthorizer.class));
+    
when(cache.getService(QueryConfigurationService.class)).thenReturn(mockService);
 
     bucketList = Collections.singletonList(1);
   }
diff --git 
a/geode-core/src/test/java/org/apache/geode/cache/query/internal/ExecutionContextTest.java
 
b/geode-core/src/test/java/org/apache/geode/cache/query/internal/ExecutionContextTest.java
index 8f00610..4d37c90 100644
--- 
a/geode-core/src/test/java/org/apache/geode/cache/query/internal/ExecutionContextTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/cache/query/internal/ExecutionContextTest.java
@@ -16,8 +16,6 @@ package org.apache.geode.cache.query.internal;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import org.junit.Test;
@@ -29,30 +27,19 @@ import org.apache.geode.internal.cache.InternalCache;
 public class ExecutionContextTest {
 
   @Test
-  public void constructorShouldUseNoOpMethodAuthorizerOnClientSide() {
+  public void constructorShouldUseConfiguredMethodAuthorizer() {
     InternalCache mockCache = mock(InternalCache.class);
-    when(mockCache.isClient()).thenReturn(true);
-
-    ExecutionContext executionContext = new ExecutionContext(null, mockCache);
-    assertThat(executionContext.getMethodInvocationAuthorizer())
-        .isSameAs(QueryConfigurationServiceImpl.getNoOpAuthorizer());
-    verify(mockCache, times(0)).getQueryService();
-  }
-
-  @Test
-  public void constructorShouldUseConfiguredMethodAuthorizerOnServerSide() {
-    InternalCache mockCache = mock(InternalCache.class);
-    InternalQueryService mockQueryService = mock(InternalQueryService.class);
-    when(mockCache.getQueryService()).thenReturn(mockQueryService);
+    QueryConfigurationService mockService = 
mock(QueryConfigurationService.class);
+    
when(mockCache.getService(QueryConfigurationService.class)).thenReturn(mockService);
 
     MethodInvocationAuthorizer noOpAuthorizer = 
QueryConfigurationServiceImpl.getNoOpAuthorizer();
-    
when(mockQueryService.getMethodInvocationAuthorizer()).thenReturn(noOpAuthorizer);
+    when(mockService.getMethodAuthorizer()).thenReturn(noOpAuthorizer);
     ExecutionContext executionContextNoOpAuthorizer = new 
ExecutionContext(null, mockCache);
     assertThat(executionContextNoOpAuthorizer.getMethodInvocationAuthorizer())
         .isSameAs(noOpAuthorizer);
 
     MethodInvocationAuthorizer restrictedAuthorizer = new 
RestrictedMethodAuthorizer(mockCache);
-    
when(mockQueryService.getMethodInvocationAuthorizer()).thenReturn(restrictedAuthorizer);
+    when(mockService.getMethodAuthorizer()).thenReturn(restrictedAuthorizer);
     ExecutionContext executionContextRestrictedAuthorizer = new 
ExecutionContext(null, mockCache);
     
assertThat(executionContextRestrictedAuthorizer.getMethodInvocationAuthorizer())
         .isSameAs(restrictedAuthorizer);
diff --git 
a/geode-core/src/test/java/org/apache/geode/cache/query/internal/MethodDispatchTest.java
 
b/geode-core/src/test/java/org/apache/geode/cache/query/internal/MethodDispatchTest.java
index 3ae72f3..eaae032 100644
--- 
a/geode-core/src/test/java/org/apache/geode/cache/query/internal/MethodDispatchTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/cache/query/internal/MethodDispatchTest.java
@@ -58,10 +58,11 @@ public class MethodDispatchTest {
     emptyList = Collections.emptyList();
     methodInvocationAuthorizer = spy(MethodInvocationAuthorizer.class);
 
+    QueryConfigurationService mockService = 
mock(QueryConfigurationService.class);
+    
when(mockService.getMethodAuthorizer()).thenReturn(methodInvocationAuthorizer);
     InternalCache mockCache = mock(InternalCache.class);
-    InternalQueryService mockQueryService = mock(InternalQueryService.class);
-    when(mockCache.getQueryService()).thenReturn(mockQueryService);
-    
when(mockQueryService.getMethodInvocationAuthorizer()).thenReturn(methodInvocationAuthorizer);
+    
when(mockCache.getService(QueryConfigurationService.class)).thenReturn(mockService);
+
     queryExecutionContext = new QueryExecutionContext(null, mockCache);
   }
 
diff --git 
a/geode-core/src/test/java/org/apache/geode/cache/query/internal/NWayMergeResultsTest.java
 
b/geode-core/src/test/java/org/apache/geode/cache/query/internal/NWayMergeResultsTest.java
index c341da5..baafff3 100644
--- 
a/geode-core/src/test/java/org/apache/geode/cache/query/internal/NWayMergeResultsTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/cache/query/internal/NWayMergeResultsTest.java
@@ -45,10 +45,10 @@ public class NWayMergeResultsTest {
 
   @Before
   public void setUp() {
+    QueryConfigurationService mockService = 
mock(QueryConfigurationService.class);
+    
when(mockService.getMethodAuthorizer()).thenReturn(mock(MethodInvocationAuthorizer.class));
     InternalCache mockCache = mock(InternalCache.class);
-    
when(mockCache.getQueryService()).thenReturn(mock(InternalQueryService.class));
-    when(mockCache.getQueryService().getMethodInvocationAuthorizer())
-        .thenReturn(mock(MethodInvocationAuthorizer.class));
+    
when(mockCache.getService(QueryConfigurationService.class)).thenReturn(mockService);
 
     context = new ExecutionContext(null, mockCache);
   }
diff --git 
a/geode-core/src/test/java/org/apache/geode/cache/query/internal/QCompilerTest.java
 
b/geode-core/src/test/java/org/apache/geode/cache/query/internal/QCompilerTest.java
index 74bc4f1..fcf4bbd 100644
--- 
a/geode-core/src/test/java/org/apache/geode/cache/query/internal/QCompilerTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/cache/query/internal/QCompilerTest.java
@@ -46,10 +46,10 @@ public class QCompilerTest {
 
   @Before
   public void setUp() {
+    QueryConfigurationService mockService = 
mock(QueryConfigurationService.class);
+    
when(mockService.getMethodAuthorizer()).thenReturn(mock(MethodInvocationAuthorizer.class));
     InternalCache mockCache = mock(InternalCache.class);
-    
when(mockCache.getQueryService()).thenReturn(mock(InternalQueryService.class));
-    when(mockCache.getQueryService().getMethodInvocationAuthorizer())
-        .thenReturn(mock(MethodInvocationAuthorizer.class));
+    
when(mockCache.getService(QueryConfigurationService.class)).thenReturn(mockService);
 
     context = new QueryExecutionContext(null, mockCache);
   }
diff --git 
a/geode-core/src/test/java/org/apache/geode/cache/query/internal/QueryExecutionContextTest.java
 
b/geode-core/src/test/java/org/apache/geode/cache/query/internal/QueryExecutionContextTest.java
index f7ec2fc..6edc038 100644
--- 
a/geode-core/src/test/java/org/apache/geode/cache/query/internal/QueryExecutionContextTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/cache/query/internal/QueryExecutionContextTest.java
@@ -30,10 +30,10 @@ public class QueryExecutionContextTest {
 
   @Before
   public void setUp() {
+    QueryConfigurationService mockService = 
mock(QueryConfigurationService.class);
+    
when(mockService.getMethodAuthorizer()).thenReturn(mock(MethodInvocationAuthorizer.class));
     InternalCache mockCache = mock(InternalCache.class);
-    
when(mockCache.getQueryService()).thenReturn(mock(InternalQueryService.class));
-    when(mockCache.getQueryService().getMethodInvocationAuthorizer())
-        .thenReturn(mock(MethodInvocationAuthorizer.class));
+    
when(mockCache.getService(QueryConfigurationService.class)).thenReturn(mockService);
 
     context = new QueryExecutionContext(null, mockCache);
   }
diff --git 
a/geode-core/src/test/java/org/apache/geode/cache/query/internal/index/CompactRangeIndexTest.java
 
b/geode-core/src/test/java/org/apache/geode/cache/query/internal/index/CompactRangeIndexTest.java
index abd7dcb..2d8a3e8 100644
--- 
a/geode-core/src/test/java/org/apache/geode/cache/query/internal/index/CompactRangeIndexTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/cache/query/internal/index/CompactRangeIndexTest.java
@@ -30,7 +30,7 @@ import org.mockito.junit.MockitoRule;
 import org.apache.geode.Statistics;
 import org.apache.geode.cache.RegionAttributes;
 import org.apache.geode.cache.query.internal.DefaultQueryService;
-import org.apache.geode.cache.query.internal.InternalQueryService;
+import org.apache.geode.cache.query.internal.QueryConfigurationService;
 import 
org.apache.geode.cache.query.internal.index.AbstractIndex.InternalIndexStatistics;
 import org.apache.geode.cache.query.security.MethodInvocationAuthorizer;
 import org.apache.geode.cache.query.types.ObjectType;
@@ -60,15 +60,16 @@ public class CompactRangeIndexTest {
 
   @Before
   public void setup() {
+    QueryConfigurationService mockService = 
mock(QueryConfigurationService.class);
+    
when(mockService.getMethodAuthorizer()).thenReturn(mock(MethodInvocationAuthorizer.class));
+
     when(region.getCache()).thenReturn(cache);
     when(region.getAttributes()).thenReturn(mock(RegionAttributes.class));
     when(cache.getDistributedSystem()).thenReturn(ids);
     when(ids.createAtomicStatistics(any(), eq("Index1"))).thenReturn(stats);
     when(cache.getRegion(any())).thenReturn(region);
     
when(img.putCanonicalizedIteratorNameIfAbsent(any())).thenReturn("index_iter");
-    when(cache.getQueryService()).thenReturn(mock(InternalQueryService.class));
-    when(cache.getQueryService().getMethodInvocationAuthorizer())
-        .thenReturn(mock(MethodInvocationAuthorizer.class));
+    
when(cache.getService(QueryConfigurationService.class)).thenReturn(mockService);
 
     IndexCreationHelper helper = new 
FunctionalIndexCreationHelper("/exampleRegion", "status",
         "*", null, cache, null, img);
@@ -85,7 +86,6 @@ public class CompactRangeIndexTest {
     when(region.getCache()).thenReturn(cache);
     when(cache.getCachePerfStats()).thenReturn(cacheperfstat);
     when(cache.getQueryService()).thenReturn(queryservice);
-    when(queryservice.getMethodInvocationAuthorizer()).thenReturn(null);
 
     index.addMapping(entry);
     verify(indstats).incNumUpdates();
@@ -97,7 +97,6 @@ public class CompactRangeIndexTest {
     when(region.getCache()).thenReturn(cache);
     when(cache.getCachePerfStats()).thenReturn(cacheperfstat);
     when(cache.getQueryService()).thenReturn(queryservice);
-    when(queryservice.getMethodInvocationAuthorizer()).thenReturn(null);
 
     index.removeMapping(entry, 3);
 
@@ -108,7 +107,6 @@ public class CompactRangeIndexTest {
     when(region.getCache()).thenReturn(cache);
     when(cache.getCachePerfStats()).thenReturn(cacheperfstat);
     when(cache.getQueryService()).thenReturn(queryservice);
-    when(queryservice.getMethodInvocationAuthorizer()).thenReturn(null);
 
     index.removeMapping(entry, 1);
     index.addMapping(entry);
diff --git 
a/geode-core/src/test/java/org/apache/geode/internal/cache/PartitionedRegionQueryEvaluatorTest.java
 
b/geode-core/src/test/java/org/apache/geode/internal/cache/PartitionedRegionQueryEvaluatorTest.java
index 8336733..cc49d56 100644
--- 
a/geode-core/src/test/java/org/apache/geode/internal/cache/PartitionedRegionQueryEvaluatorTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/internal/cache/PartitionedRegionQueryEvaluatorTest.java
@@ -40,8 +40,8 @@ import org.apache.geode.cache.query.internal.CompiledSelect;
 import org.apache.geode.cache.query.internal.CompiledValue;
 import org.apache.geode.cache.query.internal.DefaultQuery;
 import org.apache.geode.cache.query.internal.ExecutionContext;
-import org.apache.geode.cache.query.internal.InternalQueryService;
 import org.apache.geode.cache.query.internal.LinkedResultSet;
+import org.apache.geode.cache.query.internal.QueryConfigurationService;
 import org.apache.geode.cache.query.internal.types.ObjectTypeImpl;
 import org.apache.geode.cache.query.security.MethodInvocationAuthorizer;
 import org.apache.geode.distributed.internal.DistributionMessage;
@@ -66,14 +66,15 @@ public class PartitionedRegionQueryEvaluatorTest {
 
   @Before
   public void setup() throws Exception {
+    QueryConfigurationService mockService = 
mock(QueryConfigurationService.class);
+    
when(mockService.getMethodAuthorizer()).thenReturn(mock(MethodInvocationAuthorizer.class));
+
     localNode = new InternalDistributedMember("localhost", 8888);
     remoteNodeA = new InternalDistributedMember("localhost", 8889);
     remoteNodeB = new InternalDistributedMember("localhost", 8890);
     GemFireCacheImpl cache = Fakes.cache();
     system = (InternalDistributedSystem) cache.getDistributedSystem();
-    when(cache.getQueryService()).thenReturn(mock(InternalQueryService.class));
-    when(cache.getQueryService().getMethodInvocationAuthorizer())
-        .thenReturn(mock(MethodInvocationAuthorizer.class));
+    
when(cache.getService(QueryConfigurationService.class)).thenReturn(mockService);
 
     allNodes.add(localNode);
     allNodes.add(remoteNodeA);
diff --git 
a/geode-cq/src/main/java/org/apache/geode/cache/query/cq/internal/ServerCQImpl.java
 
b/geode-cq/src/main/java/org/apache/geode/cache/query/cq/internal/ServerCQImpl.java
index 2d5b67b..4be8817 100644
--- 
a/geode-cq/src/main/java/org/apache/geode/cache/query/cq/internal/ServerCQImpl.java
+++ 
b/geode-cq/src/main/java/org/apache/geode/cache/query/cq/internal/ServerCQImpl.java
@@ -280,7 +280,7 @@ public class ServerCQImpl extends CqQueryImpl implements 
DataSerializable, Serve
    *
    * @return String modified query.
    */
-  private Query constructServerSideQuery() throws QueryException {
+  Query constructServerSideQuery() throws QueryException {
     InternalCache cache = cqService.getInternalCache();
     DefaultQuery locQuery = (DefaultQuery) 
cache.getLocalQueryService().newQuery(this.queryString);
     CompiledSelect select = locQuery.getSimpleSelect();
@@ -363,6 +363,20 @@ public class ServerCQImpl extends CqQueryImpl implements 
DataSerializable, Serve
     }
   }
 
+  @Override
+  public void invalidateCqResultKeys() {
+    if (!CqServiceProvider.MAINTAIN_KEYS) {
+      return;
+    }
+
+    if (this.cqResultKeys != null) {
+      synchronized (this.cqResultKeys) {
+        this.cqResultKeys.clear();
+        this.cqResultKeysInitialized = false;
+      }
+    }
+  }
+
   /**
    * Marks the key as destroyed in the CQ Results key cache.
    */
diff --git 
a/geode-cq/src/test/java/org/apache/geode/cache/query/cq/internal/ServerCQImplTest.java
 
b/geode-cq/src/test/java/org/apache/geode/cache/query/cq/internal/ServerCQImplTest.java
new file mode 100644
index 0000000..3fdf818
--- /dev/null
+++ 
b/geode-cq/src/test/java/org/apache/geode/cache/query/cq/internal/ServerCQImplTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.geode.cache.query.cq.internal;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.geode.cache.Cache;
+import org.apache.geode.cache.DataPolicy;
+import org.apache.geode.cache.query.Query;
+import org.apache.geode.cache.query.QueryException;
+import org.apache.geode.cache.query.internal.CqStateImpl;
+import org.apache.geode.internal.cache.LocalRegion;
+import org.apache.geode.internal.cache.tier.sockets.ClientProxyMembershipID;
+import org.apache.geode.internal.logging.InternalLogWriter;
+
+public class ServerCQImplTest {
+  private ServerCQImpl serverCq;
+  private CqServiceImpl mockCqService;
+
+  @Before
+  @SuppressWarnings("deprecation")
+  public void setUp() {
+    mockCqService = mock(CqServiceImpl.class);
+    when(mockCqService.getCache()).thenReturn(mock(Cache.class));
+    when(mockCqService.getCache().getSecurityLoggerI18n())
+        .thenReturn(mock(InternalLogWriter.class));
+    serverCq = spy(
+        new ServerCQImpl(mockCqService, "cqName", "SELECT * FROM /region", 
false, "test"));
+  }
+
+  @Test
+  @SuppressWarnings("unchecked")
+  public void invalidateCqResultKeysShouldClearCacheAndDisableInitializedFlag()
+      throws QueryException {
+    ClientProxyMembershipID mockClientProxyMembershipID = 
mock(ClientProxyMembershipID.class);
+    doNothing().when(serverCq).validateCq();
+    doReturn(mock(Query.class)).when(serverCq).constructServerSideQuery();
+    LocalRegion mockLocalRegion = mock(LocalRegion.class);
+    when(mockLocalRegion.getDataPolicy()).thenReturn(DataPolicy.PARTITION);
+    
when(mockCqService.getCache().getRegion(any())).thenReturn(mockLocalRegion);
+    doNothing().when(serverCq).updateCqCreateStats();
+    serverCq.registerCq(mockClientProxyMembershipID, null, CqStateImpl.INIT);
+
+    // Initialize cache
+    serverCq.addToCqResultKeys("key1");
+    serverCq.setCqResultsCacheInitialized();
+    assertThat(serverCq.cqResultKeysInitialized).isTrue();
+    assertThat(serverCq.isPartOfCqResult("key1")).isTrue();
+
+    // Invalidate and assert results
+    serverCq.invalidateCqResultKeys();
+    assertThat(serverCq.cqResultKeysInitialized).isFalse();
+    assertThat(serverCq.isPartOfCqResult("key1")).isFalse();
+  }
+}

Reply via email to