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

dcapwell pushed a commit to branch cassandra-4.0
in repository https://gitbox.apache.org/repos/asf/cassandra.git


The following commit(s) were added to refs/heads/cassandra-4.0 by this push:
     new 1bcfa08  DebuggableThreadPoolExecutor does not propagate client 
warnings
1bcfa08 is described below

commit 1bcfa087f4521135ef101c694f5e6ada8347827c
Author: Jacek Lewandowski <[email protected]>
AuthorDate: Thu Nov 18 13:03:42 2021 -0800

    DebuggableThreadPoolExecutor does not propagate client warnings
    
    patch by Jacek Lewandowski; reviewed by Andres de la Peña, Berenguer Blasi, 
David Capwell for CASSANDRA-17072
---
 CHANGES.txt                                        |   1 +
 .../AbstractLocalAwareExecutorService.java         |  11 +-
 .../concurrent/DebuggableThreadPoolExecutor.java   |  36 +++++--
 .../statements/schema/AlterKeyspaceStatement.java  |   8 --
 .../statements/schema/CreateKeyspaceStatement.java |  13 +--
 .../cassandra/db/compaction/CompactionManager.java |   2 +-
 .../org/apache/cassandra/service/ClientWarn.java   |   5 -
 .../DebuggableThreadPoolExecutorTest.java          |  76 +++++++++++++
 .../cassandra/concurrent/SEPExecutorTest.java      |  25 +++++
 .../schema/SchemaStatementWarningsTest.java        | 117 +++++++++++++++++++++
 10 files changed, 254 insertions(+), 40 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index cb8a8a9..1d72c0f 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 4.0.2
+ * DebuggableThreadPoolExecutor does not propagate client warnings 
(CASSANDRA-17072)
  * internode_send_buff_size_in_bytes and internode_recv_buff_size_in_bytes 
have new names. Backward compatibility with the old names added 
(CASSANDRA-17141)
  * Remove unused configuration parameters from cassandra.yaml (CASSANDRA-17132)
  * Queries performed with NODE_LOCAL consistency level do not update request 
metrics (CASSANDRA-17052)
diff --git 
a/src/java/org/apache/cassandra/concurrent/AbstractLocalAwareExecutorService.java
 
b/src/java/org/apache/cassandra/concurrent/AbstractLocalAwareExecutorService.java
index d666a36..e7bec19 100644
--- 
a/src/java/org/apache/cassandra/concurrent/AbstractLocalAwareExecutorService.java
+++ 
b/src/java/org/apache/cassandra/concurrent/AbstractLocalAwareExecutorService.java
@@ -32,8 +32,6 @@ import org.slf4j.LoggerFactory;
 import org.apache.cassandra.utils.concurrent.SimpleCondition;
 import org.apache.cassandra.utils.JVMStabilityInspector;
 
-import static org.apache.cassandra.tracing.Tracing.isTracing;
-
 public abstract class AbstractLocalAwareExecutorService implements 
LocalAwareExecutorService
 {
     private static final Logger logger = 
LoggerFactory.getLogger(AbstractLocalAwareExecutorService.class);
@@ -98,7 +96,12 @@ public abstract class AbstractLocalAwareExecutorService 
implements LocalAwareExe
 
     protected <T> FutureTask<T> newTaskFor(Callable<T> callable)
     {
-        if (isTracing())
+        return newTaskFor(callable, ExecutorLocals.create());
+    }
+
+    protected <T> FutureTask<T> newTaskFor(Callable<T> callable, 
ExecutorLocals locals)
+    {
+        if (locals != null)
         {
             if (callable instanceof LocalSessionFutureTask)
                 return (LocalSessionFutureTask<T>) callable;
@@ -218,7 +221,7 @@ public abstract class AbstractLocalAwareExecutorService 
implements LocalAwareExe
 
     public void execute(Runnable command)
     {
-        addTask(newTaskFor(command, ExecutorLocals.create()));
+        addTask(newTaskFor(command, null, ExecutorLocals.create()));
     }
 
     public void execute(Runnable command, ExecutorLocals locals)
diff --git 
a/src/java/org/apache/cassandra/concurrent/DebuggableThreadPoolExecutor.java 
b/src/java/org/apache/cassandra/concurrent/DebuggableThreadPoolExecutor.java
index a2de775..7d9da4d 100644
--- a/src/java/org/apache/cassandra/concurrent/DebuggableThreadPoolExecutor.java
+++ b/src/java/org/apache/cassandra/concurrent/DebuggableThreadPoolExecutor.java
@@ -36,8 +36,6 @@ import java.util.concurrent.TimeUnit;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import static org.apache.cassandra.tracing.Tracing.isTracing;
-
 /**
  * This class encorporates some Executor best practices for Cassandra.  Most 
of the executors in the system
  * should use or extend this.  There are two main improvements over a vanilla 
TPE:
@@ -169,20 +167,27 @@ public class DebuggableThreadPoolExecutor extends 
ThreadPoolExecutor implements
         execute(command);
     }
 
+    private ExecutorLocals maybeCreateExecutorLocals(Object command)
+    {
+        return command instanceof LocalSessionWrapper ? null : 
ExecutorLocals.create();
+    }
+
     // execute does not call newTaskFor
     @Override
     public void execute(Runnable command)
     {
-        super.execute(isTracing() && !(command instanceof LocalSessionWrapper)
-                      ? LocalSessionWrapper.create(command)
+        ExecutorLocals locals = maybeCreateExecutorLocals(command);
+        super.execute(locals != null
+                      ? LocalSessionWrapper.create(command, locals)
                       : command);
     }
 
     @Override
     protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T result)
     {
-        if (isTracing() && !(runnable instanceof LocalSessionWrapper))
-            return LocalSessionWrapper.create(runnable, result);
+        ExecutorLocals locals = maybeCreateExecutorLocals(runnable);
+        if (locals != null)
+            return LocalSessionWrapper.create(runnable, result, locals);
         if (runnable instanceof RunnableFuture)
             return new ForwardingRunnableFuture<>((RunnableFuture) runnable, 
result);
         return super.newTaskFor(runnable, result);
@@ -191,8 +196,9 @@ public class DebuggableThreadPoolExecutor extends 
ThreadPoolExecutor implements
     @Override
     protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable)
     {
-        if (isTracing() && !(callable instanceof LocalSessionWrapper))
-            return LocalSessionWrapper.create(callable);
+        ExecutorLocals locals = maybeCreateExecutorLocals(callable);
+        if (locals != null)
+            return LocalSessionWrapper.create(callable, locals);
         return super.newTaskFor(callable);
     }
 
@@ -201,11 +207,11 @@ public class DebuggableThreadPoolExecutor extends 
ThreadPoolExecutor implements
     {
         super.afterExecute(r, t);
 
-        maybeResetTraceSessionWrapper(r);
+        maybeResetLocalSessionWrapper(r);
         logExceptionsAfterExecute(r, t);
     }
 
-    protected static void maybeResetTraceSessionWrapper(Runnable r)
+    protected static void maybeResetLocalSessionWrapper(Runnable r)
     {
         if (r instanceof LocalSessionWrapper)
         {
@@ -354,6 +360,11 @@ public class DebuggableThreadPoolExecutor extends 
ThreadPoolExecutor implements
             return create(command, null, ExecutorLocals.create());
         }
 
+        static LocalSessionWrapper<Object> create(Runnable command, 
ExecutorLocals locals)
+        {
+            return create(command, null, locals);
+        }
+
         static <T> LocalSessionWrapper<T> create(Runnable command, T result)
         {
             return create(command, result, ExecutorLocals.create());
@@ -371,6 +382,11 @@ public class DebuggableThreadPoolExecutor extends 
ThreadPoolExecutor implements
             return new LocalSessionWrapper<>(command, ExecutorLocals.create());
         }
 
+        static <T> LocalSessionWrapper<T> create(Callable<T> command, 
ExecutorLocals locals)
+        {
+            return new LocalSessionWrapper<>(command, locals);
+        }
+
         private void setupContext()
         {
             ExecutorLocals.set(locals);
diff --git 
a/src/java/org/apache/cassandra/cql3/statements/schema/AlterKeyspaceStatement.java
 
b/src/java/org/apache/cassandra/cql3/statements/schema/AlterKeyspaceStatement.java
index c1b9bc2..f208e4a 100644
--- 
a/src/java/org/apache/cassandra/cql3/statements/schema/AlterKeyspaceStatement.java
+++ 
b/src/java/org/apache/cassandra/cql3/statements/schema/AlterKeyspaceStatement.java
@@ -42,7 +42,6 @@ import 
org.apache.cassandra.schema.KeyspaceMetadata.KeyspaceDiff;
 import org.apache.cassandra.schema.Keyspaces;
 import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
 import org.apache.cassandra.service.ClientState;
-import org.apache.cassandra.service.ClientWarn;
 import org.apache.cassandra.transport.Event.SchemaChange;
 import org.apache.cassandra.transport.Event.SchemaChange.Change;
 import org.apache.cassandra.utils.FBUtilities;
@@ -63,9 +62,6 @@ public final class AlterKeyspaceStatement extends 
AlterSchemaStatement
 
     public Keyspaces apply(Keyspaces schema)
     {
-        if (ClientWarn.instance.get() == null)
-            ClientWarn.instance.captureWarnings();
-        int previousNumWarnings = ClientWarn.instance.numWarnings();
         attrs.validate();
 
         KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
@@ -84,10 +80,6 @@ public final class AlterKeyspaceStatement extends 
AlterSchemaStatement
 
         Keyspaces res = schema.withAddedOrUpdated(newKeyspace);
 
-        int newNumWarnings = ClientWarn.instance.numWarnings();
-        if (newNumWarnings > previousNumWarnings)
-            
clientWarnings.addAll(ClientWarn.instance.getWarnings().subList(previousNumWarnings,
 newNumWarnings));
-
         return res;
     }
 
diff --git 
a/src/java/org/apache/cassandra/cql3/statements/schema/CreateKeyspaceStatement.java
 
b/src/java/org/apache/cassandra/cql3/statements/schema/CreateKeyspaceStatement.java
index 806b50a..9aa27ce 100644
--- 
a/src/java/org/apache/cassandra/cql3/statements/schema/CreateKeyspaceStatement.java
+++ 
b/src/java/org/apache/cassandra/cql3/statements/schema/CreateKeyspaceStatement.java
@@ -41,7 +41,6 @@ import org.apache.cassandra.schema.Keyspaces;
 import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
 import org.apache.cassandra.schema.Schema;
 import org.apache.cassandra.service.ClientState;
-import org.apache.cassandra.service.ClientWarn;
 import org.apache.cassandra.transport.Event.SchemaChange;
 import org.apache.cassandra.transport.Event.SchemaChange.Change;
 
@@ -62,10 +61,6 @@ public final class CreateKeyspaceStatement extends 
AlterSchemaStatement
 
     public Keyspaces apply(Keyspaces schema)
     {
-        if (ClientWarn.instance.get() == null)
-            ClientWarn.instance.captureWarnings();
-        int previousNumWarnings = ClientWarn.instance.numWarnings();
-
         attrs.validate();
 
         if (!attrs.hasOption(Option.REPLICATION))
@@ -85,13 +80,7 @@ public final class CreateKeyspaceStatement extends 
AlterSchemaStatement
             throw ire("Unable to use given strategy class: LocalStrategy is 
reserved for internal use.");
 
         keyspace.params.validate(keyspaceName);
-        Keyspaces keyspaces = schema.withAddedOrUpdated(keyspace);
-
-        int newNumWarnings = ClientWarn.instance.numWarnings();
-        if (newNumWarnings > previousNumWarnings)
-            
clientWarnings.addAll(ClientWarn.instance.getWarnings().subList(previousNumWarnings,
 newNumWarnings));
-
-        return keyspaces;
+        return schema.withAddedOrUpdated(keyspace);
     }
 
     SchemaChange schemaChangeEvent(KeyspacesDiff diff)
diff --git a/src/java/org/apache/cassandra/db/compaction/CompactionManager.java 
b/src/java/org/apache/cassandra/db/compaction/CompactionManager.java
index 8d4f136..933418e 100644
--- a/src/java/org/apache/cassandra/db/compaction/CompactionManager.java
+++ b/src/java/org/apache/cassandra/db/compaction/CompactionManager.java
@@ -1826,7 +1826,7 @@ public class CompactionManager implements 
CompactionManagerMBean
         @Override
         public void afterExecute(Runnable r, Throwable t)
         {
-            DebuggableThreadPoolExecutor.maybeResetTraceSessionWrapper(r);
+            DebuggableThreadPoolExecutor.maybeResetLocalSessionWrapper(r);
 
             if (t == null)
                 t = DebuggableThreadPoolExecutor.extractThrowable(r);
diff --git a/src/java/org/apache/cassandra/service/ClientWarn.java 
b/src/java/org/apache/cassandra/service/ClientWarn.java
index ec79854..5a6a878 100644
--- a/src/java/org/apache/cassandra/service/ClientWarn.java
+++ b/src/java/org/apache/cassandra/service/ClientWarn.java
@@ -64,11 +64,6 @@ public class ClientWarn implements 
ExecutorLocal<ClientWarn.State>
         return state.warnings;
     }
 
-    public int numWarnings()
-    {
-        return getWarnings() == null ? 0 : getWarnings().size();
-    }
-
     public void resetWarnings()
     {
         warnLocal.remove();
diff --git 
a/test/unit/org/apache/cassandra/concurrent/DebuggableThreadPoolExecutorTest.java
 
b/test/unit/org/apache/cassandra/concurrent/DebuggableThreadPoolExecutorTest.java
index 58200c9..43c0fdf 100644
--- 
a/test/unit/org/apache/cassandra/concurrent/DebuggableThreadPoolExecutorTest.java
+++ 
b/test/unit/org/apache/cassandra/concurrent/DebuggableThreadPoolExecutorTest.java
@@ -22,6 +22,8 @@ package org.apache.cassandra.concurrent;
 
 
 import java.util.UUID;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.RunnableFuture;
@@ -31,16 +33,22 @@ import java.util.concurrent.atomic.AtomicReference;
 import com.google.common.base.Throwables;
 import com.google.common.net.InetAddresses;
 import com.google.common.util.concurrent.ListenableFutureTask;
+import com.google.common.util.concurrent.Uninterruptibles;
 import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
 import org.apache.cassandra.config.DatabaseDescriptor;
 import org.apache.cassandra.locator.InetAddressAndPort;
+import org.apache.cassandra.service.ClientWarn;
 import org.apache.cassandra.tracing.TraceState;
 import org.apache.cassandra.tracing.TraceStateImpl;
 import org.apache.cassandra.tracing.Tracing;
+import org.apache.cassandra.utils.FBUtilities;
 import org.apache.cassandra.utils.WrappedRunnable;
+import org.assertj.core.api.Assertions;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
 
 public class DebuggableThreadPoolExecutorTest
 {
@@ -79,6 +87,74 @@ public class DebuggableThreadPoolExecutorTest
     }
 
     @Test
+    public void testLocalStatePropagation()
+    {
+        DebuggableThreadPoolExecutor executor = 
DebuggableThreadPoolExecutor.createWithFixedPoolSize("TEST", 1);
+        try
+        {
+            checkLocalStateIsPropagated(executor);
+        }
+        finally
+        {
+            executor.shutdown();
+        }
+    }
+
+    public static void checkLocalStateIsPropagated(LocalAwareExecutorService 
executor)
+    {
+        checkClientWarningsArePropagated(executor, () -> executor.execute(() 
-> ClientWarn.instance.warn("msg")));
+        checkClientWarningsArePropagated(executor, () -> executor.submit(() -> 
ClientWarn.instance.warn("msg")));
+        checkClientWarningsArePropagated(executor, () -> executor.submit(() -> 
ClientWarn.instance.warn("msg"), null));
+        checkClientWarningsArePropagated(executor, () -> 
executor.submit((Callable<Void>) () -> {
+            ClientWarn.instance.warn("msg");
+            return null;
+        }));
+
+        checkTracingIsPropagated(executor, () -> executor.execute(() -> 
Tracing.trace("msg")));
+        checkTracingIsPropagated(executor, () -> executor.submit(() -> 
Tracing.trace("msg")));
+        checkTracingIsPropagated(executor, () -> executor.submit(() -> 
Tracing.trace("msg"), null));
+        checkTracingIsPropagated(executor, () -> 
executor.submit((Callable<Void>) () -> {
+            Tracing.trace("msg");
+            return null;
+        }));
+    }
+
+    public static void 
checkClientWarningsArePropagated(LocalAwareExecutorService executor, Runnable 
schedulingTask) {
+        ClientWarn.instance.captureWarnings();
+        
Assertions.assertThat(ClientWarn.instance.getWarnings()).isNullOrEmpty();
+
+        ClientWarn.instance.warn("msg0");
+        long initCompletedTasks = executor.getCompletedTaskCount();
+        schedulingTask.run();
+        while (executor.getCompletedTaskCount() == initCompletedTasks) 
Uninterruptibles.sleepUninterruptibly(10, MILLISECONDS);
+        ClientWarn.instance.warn("msg1");
+
+        
Assertions.assertThat(ClientWarn.instance.getWarnings()).containsExactlyInAnyOrder("msg0",
 "msg", "msg1");
+    }
+
+    public static void checkTracingIsPropagated(LocalAwareExecutorService 
executor, Runnable schedulingTask) {
+        ClientWarn.instance.captureWarnings();
+        
Assertions.assertThat(ClientWarn.instance.getWarnings()).isNullOrEmpty();
+
+        ConcurrentLinkedQueue<String> q = new ConcurrentLinkedQueue<>();
+        Tracing.instance.set(new 
TraceState(FBUtilities.getLocalAddressAndPort(), UUID.randomUUID(), 
Tracing.TraceType.NONE)
+        {
+            @Override
+            protected void traceImpl(String message)
+            {
+                q.add(message);
+            }
+        });
+        Tracing.trace("msg0");
+        long initCompletedTasks = executor.getCompletedTaskCount();
+        schedulingTask.run();
+        while (executor.getCompletedTaskCount() == initCompletedTasks) 
Uninterruptibles.sleepUninterruptibly(10, MILLISECONDS);
+        Tracing.trace("msg1");
+
+        Assertions.assertThat(q.toArray()).containsExactlyInAnyOrder("msg0", 
"msg", "msg1");
+    }
+
+    @Test
     public void testExecuteFutureTaskWhileTracing()
     {
         LinkedBlockingQueue<Runnable> q = new LinkedBlockingQueue<Runnable>(1);
diff --git a/test/unit/org/apache/cassandra/concurrent/SEPExecutorTest.java 
b/test/unit/org/apache/cassandra/concurrent/SEPExecutorTest.java
index b18c328..97e389c 100644
--- a/test/unit/org/apache/cassandra/concurrent/SEPExecutorTest.java
+++ b/test/unit/org/apache/cassandra/concurrent/SEPExecutorTest.java
@@ -30,15 +30,24 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.junit.Assert;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
+import org.apache.cassandra.config.DatabaseDescriptor;
 import org.apache.cassandra.utils.FBUtilities;
 
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.concurrent.TimeUnit.MINUTES;
+import static 
org.apache.cassandra.concurrent.DebuggableThreadPoolExecutorTest.checkLocalStateIsPropagated;
 
 public class SEPExecutorTest
 {
+    @BeforeClass
+    public static void beforeClass()
+    {
+        DatabaseDescriptor.daemonInitialization();
+    }
+
     @Test
     public void shutdownTest() throws Throwable
     {
@@ -261,4 +270,20 @@ public class SEPExecutorTest
         // Will return true if all of the LatchWaiters count down before the 
timeout
         Assert.assertTrue("Test tasks did not hit max concurrency goal", 
concurrencyGoal.await(3L, TimeUnit.SECONDS));
     }
+
+    @Test
+    public void testLocalStatePropagation() throws InterruptedException, 
TimeoutException
+    {
+        SharedExecutorPool sharedPool = new SharedExecutorPool("TestPool");
+        try
+        {
+            LocalAwareExecutorService executor = sharedPool.newExecutor(1, 
"TEST", "TEST");
+            checkLocalStateIsPropagated(executor);
+        }
+        finally
+        {
+            sharedPool.shutdownAndWait(1, TimeUnit.SECONDS);
+        }
+    }
+
 }
diff --git 
a/test/unit/org/apache/cassandra/schema/SchemaStatementWarningsTest.java 
b/test/unit/org/apache/cassandra/schema/SchemaStatementWarningsTest.java
new file mode 100644
index 0000000..1978548
--- /dev/null
+++ b/test/unit/org/apache/cassandra/schema/SchemaStatementWarningsTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.cassandra.schema;
+
+import java.util.HashSet;
+import java.util.Queue;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.apache.cassandra.cql3.CQLTester;
+import org.apache.cassandra.service.ClientWarn;
+import org.assertj.core.api.Assertions;
+import org.jboss.byteman.contrib.bmunit.BMRule;
+import org.jboss.byteman.contrib.bmunit.BMRules;
+import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
+
+@RunWith(BMUnitRunner.class)
+public class SchemaStatementWarningsTest extends CQLTester
+{
+    private static volatile String msg1, msg2;
+    private static final Queue<String> injectedWarnings = new 
ConcurrentLinkedQueue<>();
+
+    @Before
+    public void before()
+    {
+        msg1 = UUID.randomUUID().toString();
+        msg2 = UUID.randomUUID().toString();
+    }
+
+    @Test
+    @BMRules(rules = { @BMRule(name = "client warning 1",
+                               targetClass = "CreateKeyspaceStatement",
+                               targetMethod = "apply",
+                               targetLocation = "AT INVOKE 
KeyspaceParams.validate",
+                               action = 
"org.apache.cassandra.schema.SchemaStatementWarningsTest.addWarn()"),
+                       @BMRule(name = "client warning 2",
+                               targetClass = "CreateKeyspaceStatement",
+                               targetMethod = "clientWarnings",
+                               targetLocation = "AT EXIT",
+                               action = "return 
org.apache.cassandra.schema.SchemaStatementWarningsTest.addWarnToList($!)"),
+                       @BMRule(name = "client warning 3",
+                               targetClass = "AlterSchemaStatement",
+                               targetMethod = "clientWarnings",
+                               targetLocation = "AT EXIT",
+                               action = "return 
org.apache.cassandra.schema.SchemaStatementWarningsTest.addWarnToList($!)") })
+    public void testClientWarningsOnCreateKeyspace()
+    {
+        ClientWarn.instance.captureWarnings();
+        injectedWarnings.clear();
+        createKeyspace("CREATE KEYSPACE %s WITH replication = {'class': 
'SimpleStrategy', 'replication_factor': 1}");
+
+        Assertions.assertThat(injectedWarnings).contains(msg1, msg2); // 
failure here means the bm rules need to be updated
+        
Assertions.assertThat(ClientWarn.instance.getWarnings()).containsExactlyInAnyOrder(msg1,
 msg2);
+    }
+
+    @Test
+    @BMRules(rules = { @BMRule(name = "client warning 1",
+                               targetClass = "CreateTableStatement",
+                               targetMethod = "apply",
+                               targetLocation = "AT INVOKE 
TableMetadata.validate",
+                               action = 
"org.apache.cassandra.schema.SchemaStatementWarningsTest.addWarn()"),
+                       @BMRule(name = "client warning 2",
+                               targetClass = "CreateTableStatement",
+                               targetMethod = "clientWarnings",
+                               targetLocation = "AT EXIT",
+                               action = "return 
org.apache.cassandra.schema.SchemaStatementWarningsTest.addWarnToList($!)"),
+                       @BMRule(name = "client warning 3",
+                               targetClass = "AlterSchemaStatement",
+                               targetMethod = "clientWarnings",
+                               targetLocation = "AT EXIT",
+                               action = "return 
org.apache.cassandra.schema.SchemaStatementWarningsTest.addWarnToList($!)"),
+    })
+    public void testClientWarningsOnCreateTable()
+    {
+        ClientWarn.instance.captureWarnings();
+        injectedWarnings.clear();
+        createTable("CREATE TABLE %s (k int primary key, v int)");
+
+        Assertions.assertThat(injectedWarnings).contains(msg1, msg2); // 
failure here means the bm rules need to be updated
+        
Assertions.assertThat(ClientWarn.instance.getWarnings()).containsExactlyInAnyOrder(msg1,
 msg2);
+    }
+
+    public static void addWarn()
+    {
+        ClientWarn.instance.warn(msg1);
+        injectedWarnings.add(msg1);
+    }
+
+    public static Set<String> addWarnToList(Set<String> warns)
+    {
+        warns = new HashSet<>(warns);
+        warns.add(msg2);
+        injectedWarnings.add(msg2);
+        return warns;
+    }
+}

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to