blob: b49572dc4bfb0152d867c8ffadf3d00d12a2a30b [file] [log] [blame]
/*
* 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.distributed.test;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Test;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bind.annotation.SuperCall;
import org.apache.cassandra.cql3.QueryOptions;
import org.apache.cassandra.cql3.statements.ModificationStatement;
import org.apache.cassandra.cql3.statements.SelectStatement;
import org.apache.cassandra.distributed.Cluster;
import org.apache.cassandra.distributed.api.ConsistencyLevel;
import org.apache.cassandra.service.QueryState;
import org.apache.cassandra.transport.messages.ResultMessage;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
public class ByteBuddyExamples extends TestBaseImpl
{
@Test
public void writeFailureTest() throws Throwable
{
try(Cluster cluster = init(Cluster.build(1)
.withInstanceInitializer(BBFailHelper::install)
.start()))
{
cluster.schemaChange("create table " + KEYSPACE + ".tbl (id int primary key, t int)");
try
{
cluster.coordinator(1).execute("insert into " + KEYSPACE + ".tbl (id, t) values (1, 1)", ConsistencyLevel.ALL);
fail("Should fail");
}
catch (RuntimeException e)
{
// expected
}
}
}
public static class BBFailHelper
{
static void install(ClassLoader cl, int nodeNumber)
{
new ByteBuddy().redefine(ModificationStatement.class)
.method(named("execute"))
.intercept(MethodDelegation.to(BBFailHelper.class))
.make()
.load(cl, ClassLoadingStrategy.Default.INJECTION);
}
public static ResultMessage execute()
{
throw new RuntimeException();
}
}
@Test
public void countTest() throws IOException
{
try(Cluster cluster = init(Cluster.build(2)
.withInstanceInitializer(BBCountHelper::install)
.start()))
{
cluster.schemaChange("create table " + KEYSPACE + ".tbl (id int primary key, t int)");
cluster.coordinator(1).execute("select * from " + KEYSPACE + ".tbl;", ConsistencyLevel.ALL);
cluster.coordinator(2).execute("select * from " + KEYSPACE + ".tbl;", ConsistencyLevel.ALL);
cluster.get(1).runOnInstance(() -> {
assertEquals(1, BBCountHelper.count.get());
});
cluster.get(2).runOnInstance(() -> {
assertEquals(0, BBCountHelper.count.get());
});
}
}
public static class BBCountHelper
{
static AtomicInteger count = new AtomicInteger();
static void install(ClassLoader cl, int nodeNumber)
{
if (nodeNumber != 1)
return;
new ByteBuddy().rebase(SelectStatement.class)
.method(named("execute").and(takesArguments(3)))
.intercept(MethodDelegation.to(BBCountHelper.class))
.make()
.load(cl, ClassLoadingStrategy.Default.INJECTION);
}
public static ResultMessage.Rows execute(QueryState state, QueryOptions options, long queryStartNanoTime, @SuperCall Callable<ResultMessage.Rows> r) throws Exception
{
count.incrementAndGet();
return r.call();
}
}
}