/** * Copyright (c) 2009-2011 VMware, Inc. All Rights Reserved. * * 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. */ package com.springsource.insight.plugin.jdbc.helpers.jdk16; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.List; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import com.springsource.insight.intercept.operation.Operation; import com.springsource.insight.intercept.operation.OperationList; import com.springsource.insight.intercept.operation.OperationMap; import com.springsource.insight.plugin.jdbc.JdbcOperationFinalizer; import com.springsource.insight.plugin.jdbc.JdbcPreparedStatementOperationCollectionAspect; import com.springsource.insight.plugin.jdbc.JdbcStatementOperationCollectionTestSupport; import com.springsource.insight.plugin.jdbc.helpers.AbstractConnection; import com.springsource.insight.plugin.jdbc.helpers.AbstractStatement; import com.springsource.insight.util.ObjectUtil; /** * */ public class Jdk16PreparedStatementCollectionAspectTest extends JdbcStatementOperationCollectionTestSupport { private final AtomicInteger callsCount = new AtomicInteger(0); private final AbstractStatement metaDataStmt = new Jdk16Statement(); private final DatabaseMetaData metaData = new Jdk16DatabaseMetaData() { @SuppressWarnings("synthetic-access") @Override public String getURL() throws SQLException { callsCount.incrementAndGet(); Connection c = metaDataStmt.getConnection(); try { CallableStatement cs = c.prepareCall("SHOW META DATA"); try { cs.executeQuery(); } finally { cs.close(); } } finally { c.close(); } return "jdbc:test:call=" + callsCount; } }; private final AbstractConnection metaDataConn = new Jdk16Connection() { @SuppressWarnings("synthetic-access") @Override public DatabaseMetaData getMetaData() throws SQLException { return metaData; } }; private final AbstractStatement testStmt = new Jdk16Statement(); public Jdk16PreparedStatementCollectionAspectTest() { metaDataStmt.setConnection(metaDataConn); metaDataConn.setStatement(testStmt); testStmt.setConnection(metaDataConn); } @Before @Override public void setUp() { super.setUp(); callsCount.set(0); } @Test public void testPreparedGetMetadataRunsSqlQuery() throws SQLException { final String sql = "select * from appointment where owner = 'Agim' and dateTime = '2009-06-01'"; PreparedStatement ps = metaDataConn.prepareStatement(sql); try { assertTrue("Failed to execute", ps.execute()); } finally { ps.close(); } assertEquals("Mismatched meta data calls count", 1, callsCount.intValue()); assertJdbcOperation(sql); } @Test public void testCallableGetMetadataRunsSqlQuery() throws SQLException { final String sql = "callMe()"; CallableStatement ps = metaDataConn.prepareCall(sql); try { ps.executeQuery(); } finally { ps.close(); } assertEquals("Mismatched meta data calls count", 1, callsCount.intValue()); assertJdbcOperation(sql); } @Test public void testReusePreparedIndexedParameterStatement() throws SQLException { final String sql = "select * from tests where test = 'testReusePreparedIndexedParameterStatement' and index < ?"; PreparedStatement ps = metaDataConn.prepareStatement(sql); final int NUM_ITERATIONS = Byte.SIZE; for (int index = 0; index < NUM_ITERATIONS; index++) { ps.setInt(1, index); assertTrue("Failed to execute for index=" + index, ps.execute()); } ArgumentCaptor<Operation> opCaptor = ArgumentCaptor.forClass(Operation.class); verify(spiedOperationCollector, times(NUM_ITERATIONS)).enter(opCaptor.capture()); List<Operation> ops = opCaptor.getAllValues(); assertEquals("Mismatched number of operations", NUM_ITERATIONS, ops.size()); Set<Operation> opsList = new TreeSet<Operation>(ObjectUtil.OBJECT_INSTANCE_COMPARATOR); for (int index = 0; index < ops.size(); index++) { Operation op = assertJdbcOperation(ops.get(index), sql); assertFalse("Non-unique operation for index=" + index, opsList.contains(op)); OperationList params = op.get(JdbcOperationFinalizer.PARAMS_VALUES, OperationList.class); assertNotNull("No parameters for index=" + index, params); assertEquals("Mismatched #params for index=" + index, 1, params.size()); assertEquals("Mismatched value for index=" + index, String.valueOf(index), params.get(0)); } } @Test public void testReusePreparedMappedParameterStatement() throws SQLException { final String sql = "select * from tests where test = 'testReusePreparedMappedParameterStatement' and index < ?"; CallableStatement ps = metaDataConn.prepareCall(sql); final int NUM_ITERATIONS = Byte.SIZE; final String TEST_PARAM = "testIndex"; for (int index = 0; index < NUM_ITERATIONS; index++) { ps.setInt(TEST_PARAM, index); assertTrue("Failed to execute for index=" + index, ps.execute()); } ArgumentCaptor<Operation> opCaptor = ArgumentCaptor.forClass(Operation.class); verify(spiedOperationCollector, times(NUM_ITERATIONS)).enter(opCaptor.capture()); List<Operation> ops = opCaptor.getAllValues(); assertEquals("Mismatched number of operations", NUM_ITERATIONS, ops.size()); Set<Operation> opsList = new TreeSet<Operation>(ObjectUtil.OBJECT_INSTANCE_COMPARATOR); for (int index = 0; index < ops.size(); index++) { Operation op = assertJdbcOperation(ops.get(index), sql); assertFalse("Non-unique operation for index=" + index, opsList.contains(op)); OperationMap params = op.get(JdbcOperationFinalizer.PARAMS_VALUES, OperationMap.class); assertNotNull("No parameters for index=" + index, params); assertEquals("Mismatched #params for index=" + index, 1, params.size()); assertEquals("Mismatched value for index=" + index, String.valueOf(index), params.get(TEST_PARAM)); } } @Override public JdbcPreparedStatementOperationCollectionAspect getAspect() { return JdbcPreparedStatementOperationCollectionAspect.aspectOf(); } }