提交 36d8bce3 编写于 作者: T terrymanu

add test case for Executor module

上级 8b2598b2
......@@ -70,11 +70,12 @@ public abstract class AbstractShardingBothDataBasesAndTablesSpringDBUnitTest ext
private void selectData() throws SQLException {
String sql = "SELECT i.order_id, i.order_item_id FROM `t_order` o JOIN `t_order_item` i ON o.user_id = i.user_id AND o.order_id = i.order_id"
+ " WHERE o.`user_id` = ? AND o.`order_id` = ? ORDER BY i.order_item_id DESC";
+ " WHERE o.`user_id` = ? AND o.`order_id` = ? AND i.`order_id` = ? ORDER BY i.order_item_id DESC";
try (Connection connection = getShardingDataSource().getConnection()) {
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1, 1);
preparedStatement.setInt(2, 1);
preparedStatement.setInt(3, 1);
ResultSet resultSet = preparedStatement.executeQuery();
int count = 0;
while (resultSet.next()) {
......
......@@ -20,8 +20,6 @@ package com.dangdang.ddframe.rdb.sharding.spring.cases.namespace;
import com.dangdang.ddframe.rdb.sharding.spring.AbstractShardingBothDataBasesAndTablesSpringDBUnitTest;
import org.springframework.test.context.ContextConfiguration;
// TODO 解析可能有问题, 不能解析出关联表, 所以导致动态表时查找关联表分片value失败, 测试用例先用非Dynamic的, 防止install失败
//@ContextConfiguration(locations = "classpath:META-INF/rdb/namespace/withNamespaceAlgorithmExpressionForDynamic.xml")
@ContextConfiguration(locations = "classpath:META-INF/rdb/namespace/withNamespaceAlgorithmExpression.xml")
@ContextConfiguration(locations = "classpath:META-INF/rdb/namespace/withNamespaceAlgorithmExpressionForDynamic.xml")
public final class WithNamespaceAlgorithmExpressionForDynamicTest extends AbstractShardingBothDataBasesAndTablesSpringDBUnitTest {
}
......@@ -17,6 +17,15 @@
package com.dangdang.ddframe.rdb.sharding.executor;
import com.dangdang.ddframe.rdb.sharding.api.props.ShardingProperties;
import com.dangdang.ddframe.rdb.sharding.api.props.ShardingPropertiesConstant;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import lombok.extern.slf4j.Slf4j;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
......@@ -27,16 +36,6 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import com.dangdang.ddframe.rdb.sharding.api.props.ShardingProperties;
import com.dangdang.ddframe.rdb.sharding.api.props.ShardingPropertiesConstant;
import com.dangdang.ddframe.rdb.sharding.exception.ShardingJdbcException;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import lombok.extern.slf4j.Slf4j;
/**
* 多线程执行框架.
*
......@@ -117,7 +116,8 @@ public final class ExecutorEngine {
try {
return futures.get();
} catch (final InterruptedException | ExecutionException ex) {
throw new ShardingJdbcException(ex);
ExecutorExceptionHandler.handleException(ex);
return null;
}
}
}
......@@ -17,12 +17,11 @@
package com.dangdang.ddframe.rdb.sharding.executor;
import com.dangdang.ddframe.rdb.sharding.exception.ShardingJdbcException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.sql.SQLException;
/**
* 执行器执行时异常处理类.
*
......@@ -35,17 +34,31 @@ public final class ExecutorExceptionHandler {
private static ThreadLocal<Boolean> isExceptionThrown = new ThreadLocal<>();
/**
* 设置是否将SQL异常抛出.
*
* @param isExceptionThrown 是否将SQL异常抛出
* 设置是否将异常抛出.
*
* @param isExceptionThrown 是否将异常抛出
*/
public static void setExceptionThrown(final boolean isExceptionThrown) {
ExecutorExceptionHandler.isExceptionThrown.set(isExceptionThrown);
}
static void handleException(final SQLException ex) throws SQLException {
if (null == isExceptionThrown.get() || isExceptionThrown.get()) {
throw ex;
/**
* 获取是否将异常抛出.
*
* @return 是否将异常抛出
*/
public static boolean isExceptionThrown() {
return null == isExceptionThrown.get() ? true : isExceptionThrown.get();
}
/**
* 处理异常.
*
* @param ex 待处理的异常
*/
public static void handleException(final Exception ex) {
if (isExceptionThrown()) {
throw new ShardingJdbcException(ex);
}
log.error("exception occur: ", ex);
}
......
......@@ -23,6 +23,7 @@ import com.dangdang.ddframe.rdb.sharding.executor.event.DMLExecutionEventBus;
import com.dangdang.ddframe.rdb.sharding.executor.event.EventExecutionType;
import com.dangdang.ddframe.rdb.sharding.executor.wrapper.PreparedStatementExecutorWrapper;
import com.dangdang.ddframe.rdb.sharding.metrics.MetricsContext;
import com.google.common.base.Optional;
import lombok.RequiredArgsConstructor;
import java.sql.ResultSet;
......@@ -34,7 +35,8 @@ import java.util.List;
/**
* 多线程执行预编译语句对象请求的执行器.
*
* @author zhangliang, caohao
* @author zhangliang
* @author caohao
*/
@RequiredArgsConstructor
public final class PreparedStatementExecutor {
......@@ -58,7 +60,7 @@ public final class PreparedStatementExecutor {
return result;
}
result = executorEngine.execute(preparedStatementExecutorWrappers, new ExecuteUnit<PreparedStatementExecutorWrapper, ResultSet>() {
@Override
public ResultSet execute(final PreparedStatementExecutorWrapper input) throws Exception {
return input.getPreparedStatement().executeQuery();
......@@ -76,40 +78,24 @@ public final class PreparedStatementExecutor {
*/
public int executeUpdate() throws SQLException {
Context context = MetricsContext.start("ShardingPreparedStatement-executeUpdate");
int result = 0;
postDMLExecutionEvents();
final boolean isExceptionThrown = ExecutorExceptionHandler.isExceptionThrown();
if (1 == preparedStatementExecutorWrappers.size()) {
PreparedStatementExecutorWrapper preparedStatementExecutorWrapper = preparedStatementExecutorWrappers.iterator().next();
try {
result = preparedStatementExecutorWrapper.getPreparedStatement().executeUpdate();
} catch (final SQLException ex) {
postDMLExecutionEventsAfterExecution(preparedStatementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE);
ExecutorExceptionHandler.handleException(ex);
return result;
} finally {
MetricsContext.stop(context);
}
postDMLExecutionEventsAfterExecution(preparedStatementExecutorWrapper, EventExecutionType.EXECUTE_SUCCESS);
return result;
return executeUpdateInternal(preparedStatementExecutorWrappers.iterator().next(), isExceptionThrown, Optional.fromNullable(context));
}
result = executorEngine.execute(preparedStatementExecutorWrappers, new ExecuteUnit<PreparedStatementExecutorWrapper, Integer>() {
int result = executorEngine.execute(preparedStatementExecutorWrappers, new ExecuteUnit<PreparedStatementExecutorWrapper, Integer>() {
@Override
public Integer execute(final PreparedStatementExecutorWrapper input) throws Exception {
int result = 0;
try {
result = input.getPreparedStatement().executeUpdate();
} catch (final SQLException ex) {
postDMLExecutionEventsAfterExecution(input, EventExecutionType.EXECUTE_FAILURE);
ExecutorExceptionHandler.handleException(ex);
return result;
}
postDMLExecutionEventsAfterExecution(input, EventExecutionType.EXECUTE_SUCCESS);
return result;
return executeUpdateInternal(input, isExceptionThrown, Optional.<Context>absent());
}
}, new MergeUnit<Integer, Integer>() {
@Override
public Integer merge(final List<Integer> results) {
if (null == results) {
return 0;
}
int result = 0;
for (Integer each : results) {
result += each;
......@@ -121,6 +107,24 @@ public final class PreparedStatementExecutor {
return result;
}
private int executeUpdateInternal(final PreparedStatementExecutorWrapper preparedStatementExecutorWrapper, final boolean isExceptionThrown, final Optional<Context> context) throws SQLException {
int result;
ExecutorExceptionHandler.setExceptionThrown(isExceptionThrown);
try {
result = preparedStatementExecutorWrapper.getPreparedStatement().executeUpdate();
} catch (final SQLException ex) {
postDMLExecutionEventsAfterExecution(preparedStatementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE);
ExecutorExceptionHandler.handleException(ex);
return 0;
} finally {
if (context.isPresent()) {
MetricsContext.stop(context.get());
}
}
postDMLExecutionEventsAfterExecution(preparedStatementExecutorWrapper, EventExecutionType.EXECUTE_SUCCESS);
return result;
}
/**
* 执行SQL请求.
*
......@@ -130,41 +134,40 @@ public final class PreparedStatementExecutor {
public boolean execute() throws SQLException {
Context context = MetricsContext.start("ShardingPreparedStatement-execute");
postDMLExecutionEvents();
final boolean isExceptionThrown = ExecutorExceptionHandler.isExceptionThrown();
if (1 == preparedStatementExecutorWrappers.size()) {
boolean result = false;
PreparedStatementExecutorWrapper preparedStatementExecutorWrapper = preparedStatementExecutorWrappers.iterator().next();
try {
result = preparedStatementExecutorWrapper.getPreparedStatement().execute();
} catch (final SQLException ex) {
postDMLExecutionEventsAfterExecution(preparedStatementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE);
ExecutorExceptionHandler.handleException(ex);
return result;
} finally {
MetricsContext.stop(context);
}
postDMLExecutionEventsAfterExecution(preparedStatementExecutorWrapper, EventExecutionType.EXECUTE_SUCCESS);
return result;
return executeInternal(preparedStatementExecutorWrapper, isExceptionThrown, Optional.fromNullable(context));
}
List<Boolean> result = executorEngine.execute(preparedStatementExecutorWrappers, new ExecuteUnit<PreparedStatementExecutorWrapper, Boolean>() {
@Override
public Boolean execute(final PreparedStatementExecutorWrapper input) throws Exception {
boolean result = false;
try {
result = input.getPreparedStatement().execute();
} catch (final SQLException ex) {
postDMLExecutionEventsAfterExecution(input, EventExecutionType.EXECUTE_FAILURE);
ExecutorExceptionHandler.handleException(ex);
return result;
}
postDMLExecutionEventsAfterExecution(input, EventExecutionType.EXECUTE_SUCCESS);
return result;
return executeInternal(input, isExceptionThrown, Optional.<Context>absent());
}
});
MetricsContext.stop(context);
return result.get(0);
}
private boolean executeInternal(final PreparedStatementExecutorWrapper preparedStatementExecutorWrapper, final boolean isExceptionThrown, final Optional<Context> context) throws SQLException {
boolean result;
ExecutorExceptionHandler.setExceptionThrown(isExceptionThrown);
try {
result = preparedStatementExecutorWrapper.getPreparedStatement().execute();
} catch (final SQLException ex) {
postDMLExecutionEventsAfterExecution(preparedStatementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE);
ExecutorExceptionHandler.handleException(ex);
return false;
} finally {
if (context.isPresent()) {
MetricsContext.stop(context.get());
}
}
postDMLExecutionEventsAfterExecution(preparedStatementExecutorWrapper, EventExecutionType.EXECUTE_SUCCESS);
return result;
}
private void postDMLExecutionEvents() {
for (PreparedStatementExecutorWrapper each : preparedStatementExecutorWrappers) {
if (each.getDMLExecutionEvent().isPresent()) {
......
......@@ -23,6 +23,7 @@ import com.dangdang.ddframe.rdb.sharding.executor.event.DMLExecutionEventBus;
import com.dangdang.ddframe.rdb.sharding.executor.event.EventExecutionType;
import com.dangdang.ddframe.rdb.sharding.executor.wrapper.StatementExecutorWrapper;
import com.dangdang.ddframe.rdb.sharding.metrics.MetricsContext;
import com.google.common.base.Optional;
import lombok.RequiredArgsConstructor;
import java.sql.ResultSet;
......@@ -36,7 +37,8 @@ import java.util.List;
/**
* 多线程执行静态语句对象请求的执行器.
*
* @author gaohongtao, caohao
* @author gaohongtao
* @author caohao
*/
@RequiredArgsConstructor
public final class StatementExecutor {
......@@ -129,40 +131,24 @@ public final class StatementExecutor {
private int executeUpdate(final Updater updater) throws SQLException {
Context context = MetricsContext.start("ShardingStatement-executeUpdate");
postDMLExecutionEvents();
int result = 0;
final boolean isExceptionThrown = ExecutorExceptionHandler.isExceptionThrown();
int result;
if (1 == statementExecutorWrappers.size()) {
StatementExecutorWrapper statementExecutorWrapper = statementExecutorWrappers.iterator().next();
try {
result = updater.executeUpdate(statementExecutorWrapper.getStatement(), statementExecutorWrapper.getSqlExecutionUnit().getSql());
} catch (final SQLException ex) {
postDMLExecutionEventsAfterExecution(statementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE);
ExecutorExceptionHandler.handleException(ex);
return result;
} finally {
MetricsContext.stop(context);
}
postDMLExecutionEventsAfterExecution(statementExecutorWrapper, EventExecutionType.EXECUTE_SUCCESS);
return result;
return executeUpdateInternal(updater, statementExecutorWrappers.iterator().next(), isExceptionThrown, Optional.fromNullable(context));
}
result = executorEngine.execute(statementExecutorWrappers, new ExecuteUnit<StatementExecutorWrapper, Integer>() {
@Override
public Integer execute(final StatementExecutorWrapper input) throws Exception {
int result = 0;
try {
result = updater.executeUpdate(input.getStatement(), input.getSqlExecutionUnit().getSql());
} catch (final SQLException ex) {
postDMLExecutionEventsAfterExecution(input, EventExecutionType.EXECUTE_FAILURE);
ExecutorExceptionHandler.handleException(ex);
return result;
}
postDMLExecutionEventsAfterExecution(input, EventExecutionType.EXECUTE_SUCCESS);
return result;
return executeUpdateInternal(updater, input, isExceptionThrown, Optional.<Context>absent());
}
}, new MergeUnit<Integer, Integer>() {
@Override
public Integer merge(final List<Integer> results) {
if (null == results) {
return 0;
}
int result = 0;
for (int each : results) {
result += each;
......@@ -174,6 +160,24 @@ public final class StatementExecutor {
return result;
}
private int executeUpdateInternal(final Updater updater, final StatementExecutorWrapper statementExecutorWrapper, final boolean isExceptionThrown, final Optional<Context> context) {
int result;
ExecutorExceptionHandler.setExceptionThrown(isExceptionThrown);
try {
result = updater.executeUpdate(statementExecutorWrapper.getStatement(), statementExecutorWrapper.getSqlExecutionUnit().getSql());
} catch (final SQLException ex) {
postDMLExecutionEventsAfterExecution(statementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE);
ExecutorExceptionHandler.handleException(ex);
return 0;
} finally {
if (context.isPresent()) {
MetricsContext.stop(context.get());
}
}
postDMLExecutionEventsAfterExecution(statementExecutorWrapper, EventExecutionType.EXECUTE_SUCCESS);
return result;
}
/**
* 执行SQL请求.
*
......@@ -223,39 +227,37 @@ public final class StatementExecutor {
private boolean execute(final Executor executor) throws SQLException {
Context context = MetricsContext.start("ShardingStatement-execute");
postDMLExecutionEvents();
final boolean isExceptionThrown = ExecutorExceptionHandler.isExceptionThrown();
if (1 == statementExecutorWrappers.size()) {
StatementExecutorWrapper statementExecutorWrapper = statementExecutorWrappers.iterator().next();
boolean result;
try {
result = executor.execute(statementExecutorWrapper.getStatement(), statementExecutorWrapper.getSqlExecutionUnit().getSql());
} catch (final SQLException ex) {
postDMLExecutionEventsAfterExecution(statementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE);
ExecutorExceptionHandler.handleException(ex);
return false;
} finally {
MetricsContext.stop(context);
}
postDMLExecutionEventsAfterExecution(statementExecutorWrapper, EventExecutionType.EXECUTE_SUCCESS);
return result;
return executeInternal(executor, statementExecutorWrappers.iterator().next(), isExceptionThrown, Optional.fromNullable(context));
}
List<Boolean> result = executorEngine.execute(statementExecutorWrappers, new ExecuteUnit<StatementExecutorWrapper, Boolean>() {
@Override
public Boolean execute(final StatementExecutorWrapper input) throws Exception {
boolean result;
try {
result = executor.execute(input.getStatement(), input.getSqlExecutionUnit().getSql());
} catch (final SQLException ex) {
postDMLExecutionEventsAfterExecution(input, EventExecutionType.EXECUTE_FAILURE);
ExecutorExceptionHandler.handleException(ex);
return false;
}
postDMLExecutionEventsAfterExecution(input, EventExecutionType.EXECUTE_SUCCESS);
return result;
return executeInternal(executor, input, isExceptionThrown, Optional.<Context>absent());
}
});
MetricsContext.stop(context);
return result.get(0);
return null == result ? false : result.get(0);
}
private boolean executeInternal(final Executor executor, final StatementExecutorWrapper statementExecutorWrapper, final boolean isExceptionThrown, final Optional<Context> context) {
boolean result;
ExecutorExceptionHandler.setExceptionThrown(isExceptionThrown);
try {
result = executor.execute(statementExecutorWrapper.getStatement(), statementExecutorWrapper.getSqlExecutionUnit().getSql());
} catch (final SQLException ex) {
postDMLExecutionEventsAfterExecution(statementExecutorWrapper, EventExecutionType.EXECUTE_FAILURE);
ExecutorExceptionHandler.handleException(ex);
return false;
} finally {
if (context.isPresent()) {
MetricsContext.stop(context.get());
}
}
postDMLExecutionEventsAfterExecution(statementExecutorWrapper, EventExecutionType.EXECUTE_SUCCESS);
return result;
}
private void postDMLExecutionEvents() {
......@@ -283,12 +285,4 @@ public final class StatementExecutor {
boolean execute(Statement statement, String sql) throws SQLException;
}
@RequiredArgsConstructor
private class StatementEntity {
private final String sql;
private final Statement statement;
}
}
......@@ -17,6 +17,7 @@
package com.dangdang.ddframe.rdb.sharding.executor.event;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
......
......@@ -18,30 +18,32 @@
package com.dangdang.ddframe.rdb;
import com.dangdang.ddframe.rdb.integrate.AllIntegrateTests;
import com.dangdang.ddframe.rdb.sharding.api.AllApiTest;
import com.dangdang.ddframe.rdb.sharding.constants.AllConstantsTest;
import com.dangdang.ddframe.rdb.sharding.hint.AllHintTest;
import com.dangdang.ddframe.rdb.sharding.jdbc.AllJDBCTest;
import com.dangdang.ddframe.rdb.sharding.merger.AllMergerTest;
import com.dangdang.ddframe.rdb.sharding.metrics.AllMetricsTest;
import com.dangdang.ddframe.rdb.sharding.parser.AllParserTest;
import com.dangdang.ddframe.rdb.sharding.router.AllRouterTest;
import com.dangdang.ddframe.rdb.sharding.util.AllUtilTest;
import com.dangdang.ddframe.rdb.sharding.api.AllApiTests;
import com.dangdang.ddframe.rdb.sharding.constants.AllConstantsTests;
import com.dangdang.ddframe.rdb.sharding.executor.AllExecutorTests;
import com.dangdang.ddframe.rdb.sharding.hint.AllHintTests;
import com.dangdang.ddframe.rdb.sharding.jdbc.AllJDBCTests;
import com.dangdang.ddframe.rdb.sharding.merger.AllMergerTests;
import com.dangdang.ddframe.rdb.sharding.metrics.AllMetricsTests;
import com.dangdang.ddframe.rdb.sharding.parser.AllParserTests;
import com.dangdang.ddframe.rdb.sharding.router.AllRouterTests;
import com.dangdang.ddframe.rdb.sharding.util.AllUtilTests;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({
AllConstantsTest.class,
AllApiTest.class,
AllParserTest.class,
AllRouterTest.class,
AllMergerTest.class,
AllJDBCTest.class,
AllHintTest.class,
AllUtilTest.class,
AllMetricsTest.class,
AllConstantsTests.class,
AllApiTests.class,
AllParserTests.class,
AllRouterTests.class,
AllMergerTests.class,
AllExecutorTests.class,
AllJDBCTests.class,
AllHintTests.class,
AllUtilTests.class,
AllMetricsTests.class,
AllIntegrateTests.class
})
public class AllTests {
......
......@@ -52,5 +52,5 @@ import org.junit.runners.Suite;
NoneTableShardingAlgorithmTest.class,
HintManagerTest.class
})
public class AllApiTest {
public class AllApiTests {
}
......@@ -104,12 +104,19 @@ public final class TableRuleTest {
}
@Test
public void assertGetActualDataNodes() {
public void assertGetActualDataNodesForStatic() {
TableRule actual = new TableRule("logicTable", Arrays.asList("ds0.table_0", "ds0.table_1", "ds0.table_2", "ds1.table_0", "ds1.table_1", "ds1.table_2"), createDataSourceRule());
assertThat(actual.getActualDataNodes(Collections.singletonList("ds1"), Arrays.asList("table_0", "table_1")), is(
(Collection<DataNode>) Sets.newLinkedHashSet(Arrays.asList(new DataNode("ds1", "table_0"), new DataNode("ds1", "table_1")))));
}
@Test
public void assertGetActualDataNodesForDynamic() {
TableRule actual = new TableRule("logicTable", createDataSourceRule());
assertThat(actual.getActualDataNodes(Collections.singletonList("ds1"), Arrays.asList("table_0", "table_1")), is(
(Collection<DataNode>) Sets.newLinkedHashSet(Arrays.asList(new DataNode("ds1", "table_0"), new DataNode("ds1", "table_1")))));
}
@Test
public void assertGetActualDatasourceNames() {
TableRule actual = new TableRule("logicTable", Arrays.asList("ds0.table_0", "ds0.table_1", "ds0.table_2", "ds1.table_0", "ds1.table_1", "ds1.table_2"), createDataSourceRule());
......
......@@ -22,5 +22,5 @@ import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses(DatabaseTypeTest.class)
public class AllConstantsTest {
public class AllConstantsTests {
}
/**
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed 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.
* </p>
*/
package com.dangdang.ddframe.rdb.sharding.executor;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
ExecutorExceptionHandlerTest.class,
StatementExecutorTest.class,
PreparedStatementExecutorTest.class
})
public class AllExecutorTests {
}
/**
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed 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.
* </p>
*/
package com.dangdang.ddframe.rdb.sharding.executor;
import com.dangdang.ddframe.rdb.sharding.exception.ShardingJdbcException;
import com.dangdang.ddframe.rdb.sharding.executor.fixture.ExecutorTestUtil;
import org.junit.After;
import org.junit.Test;
import java.sql.SQLException;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class ExecutorExceptionHandlerTest {
@After
public void tearDown() throws NoSuchFieldException, IllegalAccessException {
ExecutorTestUtil.clear();
}
@Test(expected = ShardingJdbcException.class)
public void assertHandleExceptionWithoutSet() {
assertTrue(ExecutorExceptionHandler.isExceptionThrown());
ExecutorExceptionHandler.handleException(new SQLException(""));
}
@Test(expected = ShardingJdbcException.class)
public void assertHandleExceptionWhenExceptionThrownIsTrue() {
ExecutorExceptionHandler.setExceptionThrown(true);
assertTrue(ExecutorExceptionHandler.isExceptionThrown());
ExecutorExceptionHandler.handleException(new SQLException(""));
}
@Test
public void assertHandleExceptionWhenExceptionThrownIsFalse() {
ExecutorExceptionHandler.setExceptionThrown(false);
assertFalse(ExecutorExceptionHandler.isExceptionThrown());
ExecutorExceptionHandler.handleException(new SQLException(""));
}
}
/**
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed 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.
* </p>
*/
package com.dangdang.ddframe.rdb.sharding.executor;
import com.dangdang.ddframe.rdb.sharding.executor.event.DMLExecutionEventBus;
import com.dangdang.ddframe.rdb.sharding.executor.event.EventExecutionType;
import com.dangdang.ddframe.rdb.sharding.executor.fixture.EventCaller;
import com.dangdang.ddframe.rdb.sharding.executor.fixture.ExecutorTestUtil;
import com.dangdang.ddframe.rdb.sharding.executor.fixture.TestDMLExecutionEventListener;
import com.dangdang.ddframe.rdb.sharding.executor.wrapper.PreparedStatementExecutorWrapper;
import com.dangdang.ddframe.rdb.sharding.router.SQLExecutionUnit;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsCollectionContaining.hasItem;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public final class PreparedStatementExecutorTest {
private ExecutorEngine executorEngine;
@Mock
private EventCaller eventCaller;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ExecutorExceptionHandler.setExceptionThrown(false);
executorEngine = new ExecutorEngine(ExecutorTestUtil.createShardingProperties());
DMLExecutionEventBus.register(new TestDMLExecutionEventListener(eventCaller));
}
@After
public void tearDown() throws NoSuchFieldException, IllegalAccessException {
ExecutorTestUtil.clear();
}
@Test
public void assertExecuteQueryForSinglePreparedStatement() throws SQLException {
PreparedStatement preparedStatement = mock(PreparedStatement.class);
PreparedStatementExecutorWrapper wrapper = createPreparedStatementExecutorWrapperForDQL(preparedStatement, "ds_0");
ResultSet resultSet = mock(ResultSet.class);
when(preparedStatement.executeQuery()).thenReturn(resultSet);
PreparedStatementExecutor actual = new PreparedStatementExecutor(executorEngine, Collections.singleton(wrapper));
assertThat(actual.executeQuery(), is(Collections.singletonList(resultSet)));
verify(preparedStatement).executeQuery();
}
@Test
public void assertExecuteQueryForMultiplePreparedStatements() throws SQLException {
PreparedStatement preparedStatement1 = mock(PreparedStatement.class);
PreparedStatementExecutorWrapper wrapper1 = createPreparedStatementExecutorWrapperForDQL(preparedStatement1, "ds_0");
PreparedStatement preparedStatement2 = mock(PreparedStatement.class);
PreparedStatementExecutorWrapper wrapper2 = createPreparedStatementExecutorWrapperForDQL(preparedStatement2, "ds_1");
ResultSet resultSet1 = mock(ResultSet.class);
ResultSet resultSet2 = mock(ResultSet.class);
when(preparedStatement1.executeQuery()).thenReturn(resultSet1);
when(preparedStatement2.executeQuery()).thenReturn(resultSet2);
PreparedStatementExecutor actual = new PreparedStatementExecutor(executorEngine, Arrays.asList(wrapper1, wrapper2));
List<ResultSet> actualResultSets = actual.executeQuery();
assertThat(actualResultSets, hasItem(resultSet1));
assertThat(actualResultSets, hasItem(resultSet2));
verify(preparedStatement1).executeQuery();
verify(preparedStatement2).executeQuery();
}
@Test
public void assertExecuteUpdateForSinglePreparedStatementSuccess() throws SQLException {
PreparedStatement preparedStatement = mock(PreparedStatement.class);
PreparedStatementExecutorWrapper wrapper = createPreparedStatementExecutorWrapperForDML(preparedStatement, "ds_0");
when(preparedStatement.executeUpdate()).thenReturn(10);
PreparedStatementExecutor actual = new PreparedStatementExecutor(executorEngine, Collections.singleton(wrapper));
assertThat(actual.executeUpdate(), is(10));
verify(preparedStatement).executeUpdate();
verify(eventCaller, times(2)).verifyDataSource("ds_0");
verify(eventCaller, times(2)).verifySQL("DELETE FROM dual");
verify(eventCaller, times(2)).verifyParameters(Collections.emptyList());
verify(eventCaller).verifyEventExecutionType(EventExecutionType.BEFORE_EXECUTE);
verify(eventCaller).verifyEventExecutionType(EventExecutionType.EXECUTE_SUCCESS);
}
@Test
public void assertExecuteUpdateForMultiplePreparedStatementsSuccess() throws SQLException {
PreparedStatement preparedStatement1 = mock(PreparedStatement.class);
PreparedStatementExecutorWrapper wrapper1 = createPreparedStatementExecutorWrapperForDML(preparedStatement1, "ds_0");
PreparedStatement preparedStatement2 = mock(PreparedStatement.class);
PreparedStatementExecutorWrapper wrapper2 = createPreparedStatementExecutorWrapperForDML(preparedStatement2, "ds_1");
when(preparedStatement1.executeUpdate()).thenReturn(10);
when(preparedStatement2.executeUpdate()).thenReturn(20);
PreparedStatementExecutor actual = new PreparedStatementExecutor(executorEngine, Arrays.asList(wrapper1, wrapper2));
assertThat(actual.executeUpdate(), is(30));
verify(preparedStatement1).executeUpdate();
verify(preparedStatement2).executeUpdate();
verify(eventCaller, times(2)).verifyDataSource("ds_0");
verify(eventCaller, times(2)).verifyDataSource("ds_1");
verify(eventCaller, times(4)).verifySQL("DELETE FROM dual");
verify(eventCaller, times(4)).verifyParameters(Collections.emptyList());
verify(eventCaller, times(2)).verifyEventExecutionType(EventExecutionType.BEFORE_EXECUTE);
verify(eventCaller, times(2)).verifyEventExecutionType(EventExecutionType.EXECUTE_SUCCESS);
}
@Test
public void assertExecuteUpdateForSinglePreparedStatementFailure() throws SQLException {
PreparedStatement preparedStatement = mock(PreparedStatement.class);
PreparedStatementExecutorWrapper wrapper = createPreparedStatementExecutorWrapperForDML(preparedStatement, "ds_0");
when(preparedStatement.executeUpdate()).thenThrow(new SQLException());
PreparedStatementExecutor actual = new PreparedStatementExecutor(executorEngine, Collections.singleton(wrapper));
assertThat(actual.executeUpdate(), is(0));
verify(preparedStatement).executeUpdate();
verify(eventCaller, times(2)).verifyDataSource("ds_0");
verify(eventCaller, times(2)).verifySQL("DELETE FROM dual");
verify(eventCaller, times(2)).verifyParameters(Collections.emptyList());
verify(eventCaller).verifyEventExecutionType(EventExecutionType.BEFORE_EXECUTE);
verify(eventCaller).verifyEventExecutionType(EventExecutionType.EXECUTE_FAILURE);
}
@Test
public void assertExecuteUpdateForMultiplePreparedStatementsFailure() throws SQLException {
PreparedStatement preparedStatement1 = mock(PreparedStatement.class);
PreparedStatementExecutorWrapper wrapper1 = createPreparedStatementExecutorWrapperForDML(preparedStatement1, "ds_0");
PreparedStatement preparedStatement2 = mock(PreparedStatement.class);
PreparedStatementExecutorWrapper wrapper2 = createPreparedStatementExecutorWrapperForDML(preparedStatement2, "ds_1");
when(preparedStatement1.executeUpdate()).thenThrow(new SQLException());
when(preparedStatement2.executeUpdate()).thenThrow(new SQLException());
PreparedStatementExecutor actual = new PreparedStatementExecutor(executorEngine, Arrays.asList(wrapper1, wrapper2));
assertThat(actual.executeUpdate(), is(0));
verify(preparedStatement1).executeUpdate();
verify(preparedStatement2).executeUpdate();
verify(eventCaller, times(2)).verifyDataSource("ds_0");
verify(eventCaller, times(2)).verifyDataSource("ds_1");
verify(eventCaller, times(4)).verifySQL("DELETE FROM dual");
verify(eventCaller, times(4)).verifyParameters(Collections.emptyList());
verify(eventCaller, times(2)).verifyEventExecutionType(EventExecutionType.BEFORE_EXECUTE);
verify(eventCaller, times(2)).verifyEventExecutionType(EventExecutionType.EXECUTE_FAILURE);
}
@Test
public void assertExecuteForSinglePreparedStatementSuccessWithDML() throws SQLException {
PreparedStatement preparedStatement = mock(PreparedStatement.class);
PreparedStatementExecutorWrapper wrapper = createPreparedStatementExecutorWrapperForDML(preparedStatement, "ds_0");
when(preparedStatement.execute()).thenReturn(false);
PreparedStatementExecutor actual = new PreparedStatementExecutor(executorEngine, Collections.singleton(wrapper));
assertFalse(actual.execute());
verify(preparedStatement).execute();
verify(eventCaller, times(2)).verifyDataSource("ds_0");
verify(eventCaller, times(2)).verifySQL("DELETE FROM dual");
verify(eventCaller, times(2)).verifyParameters(Collections.emptyList());
verify(eventCaller).verifyEventExecutionType(EventExecutionType.BEFORE_EXECUTE);
verify(eventCaller).verifyEventExecutionType(EventExecutionType.EXECUTE_SUCCESS);
}
@Test
public void assertExecuteForMultiplePreparedStatementsSuccessWithDML() throws SQLException {
PreparedStatement preparedStatement1 = mock(PreparedStatement.class);
PreparedStatementExecutorWrapper wrapper1 = createPreparedStatementExecutorWrapperForDML(preparedStatement1, "ds_0");
PreparedStatement preparedStatement2 = mock(PreparedStatement.class);
PreparedStatementExecutorWrapper wrapper2 = createPreparedStatementExecutorWrapperForDML(preparedStatement2, "ds_1");
when(preparedStatement1.execute()).thenReturn(false);
when(preparedStatement2.execute()).thenReturn(false);
PreparedStatementExecutor actual = new PreparedStatementExecutor(executorEngine, Arrays.asList(wrapper1, wrapper2));
assertFalse(actual.execute());
verify(preparedStatement1).execute();
verify(preparedStatement2).execute();
verify(eventCaller, times(2)).verifyDataSource("ds_0");
verify(eventCaller, times(2)).verifyDataSource("ds_1");
verify(eventCaller, times(4)).verifySQL("DELETE FROM dual");
verify(eventCaller, times(4)).verifyParameters(Collections.emptyList());
verify(eventCaller, times(2)).verifyEventExecutionType(EventExecutionType.BEFORE_EXECUTE);
verify(eventCaller, times(2)).verifyEventExecutionType(EventExecutionType.EXECUTE_SUCCESS);
}
@Test
public void assertExecuteForSinglePreparedStatementFailureWithDML() throws SQLException {
PreparedStatement preparedStatement = mock(PreparedStatement.class);
PreparedStatementExecutorWrapper wrapper = createPreparedStatementExecutorWrapperForDML(preparedStatement, "ds_0");
when(preparedStatement.execute()).thenThrow(new SQLException());
PreparedStatementExecutor actual = new PreparedStatementExecutor(executorEngine, Collections.singleton(wrapper));
assertFalse(actual.execute());
verify(preparedStatement).execute();
verify(eventCaller, times(2)).verifyDataSource("ds_0");
verify(eventCaller, times(2)).verifySQL("DELETE FROM dual");
verify(eventCaller, times(2)).verifyParameters(Collections.emptyList());
verify(eventCaller).verifyEventExecutionType(EventExecutionType.BEFORE_EXECUTE);
verify(eventCaller).verifyEventExecutionType(EventExecutionType.EXECUTE_FAILURE);
}
@Test
public void assertExecuteForMultiplePreparedStatementsFailureWithDML() throws SQLException {
PreparedStatement preparedStatement1 = mock(PreparedStatement.class);
PreparedStatementExecutorWrapper wrapper1 = createPreparedStatementExecutorWrapperForDML(preparedStatement1, "ds_0");
PreparedStatement preparedStatement2 = mock(PreparedStatement.class);
PreparedStatementExecutorWrapper wrapper2 = createPreparedStatementExecutorWrapperForDML(preparedStatement2, "ds_1");
when(preparedStatement1.execute()).thenThrow(new SQLException());
when(preparedStatement2.execute()).thenThrow(new SQLException());
PreparedStatementExecutor actual = new PreparedStatementExecutor(executorEngine, Arrays.asList(wrapper1, wrapper2));
assertFalse(actual.execute());
verify(preparedStatement1).execute();
verify(preparedStatement2).execute();
verify(eventCaller, times(2)).verifyDataSource("ds_0");
verify(eventCaller, times(2)).verifyDataSource("ds_1");
verify(eventCaller, times(4)).verifySQL("DELETE FROM dual");
verify(eventCaller, times(4)).verifyParameters(Collections.emptyList());
verify(eventCaller, times(2)).verifyEventExecutionType(EventExecutionType.BEFORE_EXECUTE);
verify(eventCaller, times(2)).verifyEventExecutionType(EventExecutionType.EXECUTE_FAILURE);
}
@Test
public void assertExecuteForSinglePreparedStatementWithDQL() throws SQLException {
PreparedStatement preparedStatement = mock(PreparedStatement.class);
PreparedStatementExecutorWrapper wrapper = createPreparedStatementExecutorWrapperForDQL(preparedStatement, "ds_0");
when(preparedStatement.execute()).thenReturn(true);
PreparedStatementExecutor actual = new PreparedStatementExecutor(executorEngine, Collections.singleton(wrapper));
assertTrue(actual.execute());
verify(preparedStatement).execute();
}
@Test
public void assertExecuteForMultiplePreparedStatements() throws SQLException {
PreparedStatement preparedStatement1 = mock(PreparedStatement.class);
PreparedStatementExecutorWrapper wrapper1 = createPreparedStatementExecutorWrapperForDQL(preparedStatement1, "ds_0");
PreparedStatement preparedStatement2 = mock(PreparedStatement.class);
PreparedStatementExecutorWrapper wrapper2 = createPreparedStatementExecutorWrapperForDQL(preparedStatement2, "ds_0");
when(preparedStatement1.execute()).thenReturn(true);
when(preparedStatement2.execute()).thenReturn(true);
PreparedStatementExecutor actual = new PreparedStatementExecutor(executorEngine, Arrays.asList(wrapper1, wrapper2));
assertTrue(actual.execute());
verify(preparedStatement1).execute();
verify(preparedStatement2).execute();
}
private PreparedStatementExecutorWrapper createPreparedStatementExecutorWrapperForDQL(final PreparedStatement preparedStatement, final String dataSource) {
return createPreparedStatementExecutorWrapper(preparedStatement, dataSource, "SELECT * FROM dual");
}
private PreparedStatementExecutorWrapper createPreparedStatementExecutorWrapperForDML(final PreparedStatement preparedStatement, final String dataSource) {
return createPreparedStatementExecutorWrapper(preparedStatement, dataSource, "DELETE FROM dual");
}
private PreparedStatementExecutorWrapper createPreparedStatementExecutorWrapper(final PreparedStatement preparedStatement, final String dataSource, final String sql) {
return new PreparedStatementExecutorWrapper(preparedStatement, Collections.emptyList(), new SQLExecutionUnit(dataSource, sql));
}
}
/**
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed 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.
* </p>
*/
package com.dangdang.ddframe.rdb.sharding.executor.fixture;
import com.dangdang.ddframe.rdb.sharding.executor.event.EventExecutionType;
import java.util.List;
public interface EventCaller {
void verifyDataSource(String dataSource);
void verifySQL(String sql);
void verifyParameters(List<Object> parameters);
void verifyEventExecutionType(EventExecutionType eventExecutionType);
}
/**
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed 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.
* </p>
*/
package com.dangdang.ddframe.rdb.sharding.executor.fixture;
import com.dangdang.ddframe.rdb.sharding.api.props.ShardingProperties;
import com.dangdang.ddframe.rdb.sharding.api.props.ShardingPropertiesConstant;
import com.dangdang.ddframe.rdb.sharding.executor.ExecutorExceptionHandler;
import com.dangdang.ddframe.rdb.sharding.metrics.MetricsContext;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.lang.reflect.Field;
import java.util.Properties;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class ExecutorTestUtil {
public static ShardingProperties createShardingProperties() {
Properties prop = new Properties();
prop.setProperty(ShardingPropertiesConstant.METRICS_ENABLE.getKey(), Boolean.TRUE.toString());
ShardingProperties result = new ShardingProperties(prop);
MetricsContext.init(result);
return result;
}
public static void clear() throws NoSuchFieldException, IllegalAccessException {
Field field = ExecutorExceptionHandler.class.getDeclaredField("isExceptionThrown");
field.setAccessible(true);
((ThreadLocal) field.get(ExecutorExceptionHandler.class)).remove();
}
}
/**
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed 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.
* </p>
*/
package com.dangdang.ddframe.rdb.sharding.executor.fixture;
import com.dangdang.ddframe.rdb.sharding.executor.event.DMLExecutionEvent;
import com.dangdang.ddframe.rdb.sharding.executor.event.DMLExecutionEventListener;
import com.google.common.eventbus.AllowConcurrentEvents;
import com.google.common.eventbus.Subscribe;
import lombok.AllArgsConstructor;
@AllArgsConstructor
public final class TestDMLExecutionEventListener implements DMLExecutionEventListener {
private final EventCaller eventCaller;
@Override
public String getName() {
return "test_listener" + System.nanoTime();
}
@Subscribe
@AllowConcurrentEvents
public void listen(final DMLExecutionEvent event) {
eventCaller.verifyDataSource(event.getDataSource());
eventCaller.verifySQL(event.getSql());
eventCaller.verifyParameters(event.getParameters());
eventCaller.verifyEventExecutionType(event.getEventExecutionType());
}
}
......@@ -24,5 +24,5 @@ import org.junit.runners.Suite;
@Suite.SuiteClasses(
HintManagerHolderTest.class
)
public class AllHintTest {
public class AllHintTests {
}
......@@ -55,5 +55,5 @@ import org.junit.runners.Suite;
JdbcMethodInvocationTest.class,
AbstractRowSetResultSetAdapterTest.class
})
public class AllJDBCTest {
public class AllJDBCTests {
}
......@@ -44,5 +44,5 @@ import org.junit.runners.Suite;
MemoryOrderByResultSetTest.class,
GroupByRowTest.class
})
public class AllMergerTest {
public class AllMergerTests {
}
......@@ -62,7 +62,6 @@ public final class AggregationResultSetTest {
@Parameterized.Parameters(name = "{index}: testTarget:{0}, aggregation type:{1}, columns:{2}, r1:{3}, r2:{4}, rsName:{5}, rsClass:{6}, result:{7}")
public static Collection init() {
return Arrays.asList(new Object[][]{
{TestTarget.INDEX, AggregationType.SUM, Collections.singletonList("column"),
Collections.singletonList(6), Collections.singletonList(2), Optional.absent(), Integer.class, 8},
......
......@@ -24,5 +24,5 @@ import org.junit.runners.Suite;
@Suite.SuiteClasses(
MetricsContextTest.class
)
public class AllMetricsTest {
public class AllMetricsTests {
}
......@@ -34,5 +34,5 @@ import org.junit.runners.Suite;
OrParseTest.class,
UnsupportedParseTest.class
})
public class AllParserTest {
public class AllParserTests {
}
......@@ -35,5 +35,5 @@ import org.junit.runners.Suite;
CartesianResultTest.class,
SingleRouterUtilTest.class
})
public class AllRouterTest {
public class AllRouterTests {
}
......@@ -25,6 +25,6 @@ import org.junit.runners.Suite;
StringUtilTest.class,
SQLUtilTest.class
})
public class AllUtilTest {
public class AllUtilTests {
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册