From 20193495b425df986aa06edf09a36e28694a26ba Mon Sep 17 00:00:00 2001 From: ascrutae Date: Wed, 1 Mar 2017 15:41:12 +0800 Subject: [PATCH] add test case and fix some issue --- .../plugin/jdbc/CallableStatementTracing.java | 1 + .../plugin/jdbc/ConnectionTracing.java | 1 + .../plugin/jdbc/PreparedStatementTracing.java | 1 + .../skywalking/plugin/jdbc/SWConnection.java | 1 + .../plugin/jdbc/StatementTracing.java | 1 + .../plugin/jdbc/AbstractStatementTest.java | 43 + .../plugin/jdbc/SWCallableStatementTest.java | 752 ++++++++++++++++++ .../plugin/jdbc/SWConnectionTest.java | 361 +++++++++ .../plugin/jdbc/SWStatementTest.java | 309 +++++++ .../plugin/jdbc/SwPreparedStatementTest.java | 583 ++++++++++++++ 10 files changed, 2053 insertions(+) create mode 100644 skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/AbstractStatementTest.java create mode 100644 skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/SWCallableStatementTest.java create mode 100644 skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/SWConnectionTest.java create mode 100644 skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/SWStatementTest.java create mode 100644 skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/SwPreparedStatementTest.java diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/CallableStatementTracing.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/CallableStatementTracing.java index c295c3676c..a0633b1215 100644 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/CallableStatementTracing.java +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/CallableStatementTracing.java @@ -26,6 +26,7 @@ public class CallableStatementTracing { Tags.DB_TYPE.set(span, "sql"); Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); Tags.DB_STATEMENT.set(span, sql); + Tags.SPAN_LAYER.asDB(span); Tags.COMPONENT.set(span, connectInfo.getDBType()); if (!StringUtil.isEmpty(connectInfo.getHosts())) { Tags.PEERS.set(span, connectInfo.getHosts()); diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/ConnectionTracing.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/ConnectionTracing.java index 35d7417e41..62fb7f9c14 100755 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/ConnectionTracing.java +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/ConnectionTracing.java @@ -27,6 +27,7 @@ public class ConnectionTracing { Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); Tags.DB_STATEMENT.set(span, sql); Tags.COMPONENT.set(span, connectInfo.getDBType()); + Tags.SPAN_LAYER.asDB(span); if (!StringUtil.isEmpty(connectInfo.getHosts())) { Tags.PEERS.set(span, connectInfo.getHosts()); } else { diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/PreparedStatementTracing.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/PreparedStatementTracing.java index ed181b94a1..8823721be6 100644 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/PreparedStatementTracing.java +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/PreparedStatementTracing.java @@ -32,6 +32,7 @@ public class PreparedStatementTracing { Tags.PEER_PORT.set(span, connectInfo.getPort()); Tags.PEER_HOST.set(span, connectInfo.getHost()); } + Tags.SPAN_LAYER.asDB(span); return exec.exe(realStatement, sql); } catch (SQLException e) { Span span = ContextManager.INSTANCE.activeSpan(); diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWConnection.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWConnection.java index 919927cd7b..64a7e427ab 100755 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWConnection.java +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWConnection.java @@ -315,4 +315,5 @@ public class SWConnection implements Connection { return realConnection.getNetworkTimeout(); } + } diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/StatementTracing.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/StatementTracing.java index 4e4e4f3163..3644223405 100644 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/StatementTracing.java +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/StatementTracing.java @@ -26,6 +26,7 @@ public class StatementTracing { Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); Tags.DB_STATEMENT.set(span, sql); Tags.COMPONENT.set(span, connectInfo.getDBType()); + Tags.SPAN_LAYER.asDB(span); if (!StringUtil.isEmpty(connectInfo.getHosts())) { Tags.PEERS.set(span, connectInfo.getHosts()); } else { diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/AbstractStatementTest.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/AbstractStatementTest.java new file mode 100644 index 0000000000..e2fa288730 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/AbstractStatementTest.java @@ -0,0 +1,43 @@ +package com.a.eye.skywalking.plugin.jdbc; + +import com.a.eye.skywalking.sniffer.mock.context.MockTracerContextListener; +import com.a.eye.skywalking.trace.LogData; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.tag.Tags; + +import org.hamcrest.CoreMatchers; + +import java.sql.SQLException; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public abstract class AbstractStatementTest { + + protected MockTracerContextListener mockTracerContextListener; + + + protected void assertDBSpanLog(LogData logData) { + assertThat(logData.getFields().size(), is(4)); + assertThat(logData.getFields().get("event"), CoreMatchers.is("error")); + assertEquals(logData.getFields().get("error.kind"), SQLException.class.getName()); + assertNull(logData.getFields().get("message")); + } + + + protected void assertDBSpan(Span span, String exceptOperationName, String exceptDBStatement) { + assertDBSpan(span, exceptOperationName); + assertThat(Tags.DB_STATEMENT.get(span), is(exceptDBStatement)); + } + + + protected void assertDBSpan(Span span, String exceptOperationName) { + assertThat(span.getOperationName(), is(exceptOperationName)); + assertThat(Tags.COMPONENT.get(span), is("Mysql")); + assertThat(Tags.DB_INSTANCE.get(span), is("test")); + assertTrue(Tags.SPAN_LAYER.isDB(span)); + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/SWCallableStatementTest.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/SWCallableStatementTest.java new file mode 100644 index 0000000000..1861eceba4 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/SWCallableStatementTest.java @@ -0,0 +1,752 @@ +package com.a.eye.skywalking.plugin.jdbc; + +import com.a.eye.skywalking.api.context.TracerContext; +import com.a.eye.skywalking.sniffer.mock.context.MockTracerContextListener; +import com.a.eye.skywalking.sniffer.mock.context.SegmentAssert; +import com.a.eye.skywalking.trace.LogData; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.TraceSegment; +import com.a.eye.skywalking.trace.tag.Tags; +import com.mysql.cj.api.jdbc.JdbcConnection; + +import org.hamcrest.CoreMatchers; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Matchers; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.MalformedURLException; +import java.net.URL; +import java.sql.Array; +import java.sql.Blob; +import java.sql.CallableStatement; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.Date; +import java.sql.NClob; +import java.sql.Ref; +import java.sql.ResultSet; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Calendar; +import java.util.HashMap; +import java.util.Properties; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyByte; +import static org.mockito.Matchers.anyDouble; +import static org.mockito.Matchers.anyFloat; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyShort; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class SWCallableStatementTest extends AbstractStatementTest { + @Mock + private Array array; + @Mock + private SQLXML sqlxml; + @Mock + private RowId rowId; + @Mock + private Ref ref; + @Mock + private Clob clob; + @Mock + private NClob nClob; + @Mock + private Reader reader; + @Mock + private InputStream inputStream; + @Mock + private Blob blob; + @Mock + private com.mysql.cj.jdbc.CallableStatement mysqlCallableStatement; + @Mock + private JdbcConnection jdbcConnection; + private SWConnection swConnection; + private SWConnection multiHostConnection; + private byte[] bytesParam = new byte[]{1, 2}; + + @Before + public void setUp() throws Exception { + mockTracerContextListener = new MockTracerContextListener(); + swConnection = new SWConnection("jdbc:mysql://127.0.0.1:3306/test", new Properties(), jdbcConnection); + multiHostConnection = new SWConnection("jdbc:mysql://127.0.0.1:3306,127.0.0.1:3309/test", new Properties(), jdbcConnection); + + TracerContext.ListenerManager.add(mockTracerContextListener); + + when(jdbcConnection.prepareCall(anyString())).thenReturn(mysqlCallableStatement); + when(jdbcConnection.prepareCall(anyString(), anyInt(), anyInt(), anyInt())).thenReturn(mysqlCallableStatement); + when(jdbcConnection.prepareCall(anyString(), anyInt(), anyInt())).thenReturn(mysqlCallableStatement); + } + + @Test + public void testSetParam() throws SQLException, MalformedURLException { + CallableStatement callableStatement = multiHostConnection.prepareCall("SELECT * FROM test WHERE a = ? or b = ? or c=? or d = ? or e = ?" + + " or e = ? or f = ? or g = ? or h = ? or i = ? or j = ? or k = ? or l = ? or m = ? or n = ? or o = ? or p = ? " + + " or r = ? or s = ? or t = ? or u = ? or v = ? or w = ? or x = ? or y = ? or z = ? or a1 = ? or a2 = ? or a3 = ?" + + " or a4 = ? or a5 = ? or a6 = ? or a7 = ? or a8 = ? or a9 = ? or b1 = ? or b2 = ? or b3 = ? or b4 = ? or b5 = ?" + + " or b6 = ? or b7 = ? or b8 = ? or b9 = ? or c1 = ? or c2 = ? or c3 = ?"); + callableStatement.clearParameters(); + callableStatement.setAsciiStream(1, inputStream); + callableStatement.setAsciiStream(2, inputStream, 10); + callableStatement.setAsciiStream(3, inputStream, 1000000L); + callableStatement.setCharacterStream(4, reader); + callableStatement.setCharacterStream(4, reader, 10); + callableStatement.setCharacterStream(5, reader, 10L); + callableStatement.setShort(6, (short) 12); + callableStatement.setInt(7, 1); + callableStatement.setString(8, "test"); + callableStatement.setBoolean(9, true); + callableStatement.setLong(10, 100L); + callableStatement.setDouble(11, 12.0); + callableStatement.setFloat(12, 12.0f); + callableStatement.setByte(13, (byte) 1); + callableStatement.setBytes(14, bytesParam); + callableStatement.setDate(15, new Date(System.currentTimeMillis())); + callableStatement.setNull(16, 1); + callableStatement.setNull(17, 1, "test"); + callableStatement.setBigDecimal(18, new BigDecimal(10000)); + callableStatement.setBlob(19, inputStream); + callableStatement.setBlob(20, inputStream, 1000000L); + callableStatement.setClob(21, clob); + callableStatement.setClob(22, reader); + callableStatement.setClob(23, reader, 100L); + callableStatement.setNString(24, "test"); + callableStatement.setNCharacterStream(25, reader); + callableStatement.setNCharacterStream(26, reader, 1); + callableStatement.setNClob(27, nClob); + callableStatement.setNClob(28, reader, 1); + callableStatement.setObject(29, new Object()); + callableStatement.setObject(30, new Object(), 1); + callableStatement.setObject(31, new Object(), 1, 1); + callableStatement.setRef(32, ref); + callableStatement.setRowId(33, rowId); + callableStatement.setSQLXML(34, sqlxml); + callableStatement.setTime(35, new Time(System.currentTimeMillis())); + callableStatement.setTimestamp(36, new Timestamp(System.currentTimeMillis())); + callableStatement.setTimestamp(37, new Timestamp(System.currentTimeMillis()), Calendar.getInstance()); + callableStatement.setURL(38, new URL("http", "127.0.0.1", "test")); + callableStatement.setBinaryStream(39, inputStream); + callableStatement.setBinaryStream(40, inputStream, 1); + callableStatement.setBinaryStream(41, inputStream, 1L); + callableStatement.setNClob(42, reader); + callableStatement.setTime(43, new Time(System.currentTimeMillis()), Calendar.getInstance()); + callableStatement.setArray(45, array); + callableStatement.setBlob(46, blob); + callableStatement.setDate(47, new Date(System.currentTimeMillis()), Calendar.getInstance()); + + + callableStatement.getCharacterStream(4); + callableStatement.getCharacterStream("d"); + callableStatement.getShort(6); + callableStatement.getShort("g"); + callableStatement.getInt(7); + callableStatement.getInt("h"); + callableStatement.getString(8); + callableStatement.getString("i"); + callableStatement.getBoolean(9); + callableStatement.getBoolean("j"); + callableStatement.getLong(10); + callableStatement.getLong("k"); + callableStatement.getDouble(11); + callableStatement.getDouble("l"); + callableStatement.getFloat(12); + callableStatement.getFloat("m"); + callableStatement.getByte(13); + callableStatement.getByte("n"); + callableStatement.getBytes(14); + callableStatement.getBytes("o"); + callableStatement.getDate(15); + callableStatement.getDate("p"); + callableStatement.getBigDecimal(18); + callableStatement.getBigDecimal("s"); + callableStatement.getBlob(19); + callableStatement.getBlob("t"); + callableStatement.getClob(21); + callableStatement.getClob(21); + callableStatement.getClob("u"); + callableStatement.getNString(24); + callableStatement.getNString("y"); + callableStatement.getNCharacterStream(25); + callableStatement.getNCharacterStream("z"); + callableStatement.getNClob(27); + callableStatement.getNClob("a1"); + callableStatement.getRef(32); + callableStatement.getRef("a2"); + callableStatement.getRowId(33); + callableStatement.getRowId("a7"); + callableStatement.getSQLXML(34); + callableStatement.getSQLXML("a8"); + callableStatement.getTime(35); + callableStatement.getTime("a9"); + callableStatement.getTimestamp(36); + callableStatement.getTimestamp("b1"); + callableStatement.getURL(38); + callableStatement.getURL("b3"); + callableStatement.getArray(45); + callableStatement.getArray("c4"); + callableStatement.getDate(15); + callableStatement.getDate("p"); + callableStatement.getDate(15, Calendar.getInstance()); + callableStatement.getDate("p", Calendar.getInstance()); + callableStatement.getTime("a9"); + callableStatement.getTime("a9", Calendar.getInstance()); + callableStatement.getTime(43); + callableStatement.getTime(43, Calendar.getInstance()); + callableStatement.getTimestamp("p", Calendar.getInstance()); + callableStatement.getTimestamp(36, Calendar.getInstance()); + callableStatement.getObject(29); + callableStatement.getObject(29, new HashMap>()); + callableStatement.getObject("a4"); + callableStatement.getObject("a4", new HashMap>()); + callableStatement.getBigDecimal(18, 1); + callableStatement.wasNull(); + + callableStatement.setAsciiStream("a", inputStream); + callableStatement.setAsciiStream("b", inputStream, 10); + callableStatement.setAsciiStream("c", inputStream, 1000000L); + callableStatement.setCharacterStream("d", reader); + callableStatement.setCharacterStream("e", reader, 10); + callableStatement.setCharacterStream("f", reader, 10L); + callableStatement.setShort("g", (short) 12); + callableStatement.setInt("h", 1); + callableStatement.setString("i", "test"); + callableStatement.setBoolean("j", true); + callableStatement.setLong("k", 100L); + callableStatement.setDouble("l", 12.0); + callableStatement.setFloat("m", 12.0f); + callableStatement.setByte("n", (byte) 1); + callableStatement.setBytes("o", bytesParam); + callableStatement.setDate("p", new Date(System.currentTimeMillis())); + callableStatement.setNull("q", 1); + callableStatement.setNull("r", 1, "test"); + callableStatement.setBigDecimal("s", new BigDecimal(10000)); + callableStatement.setBlob("t", inputStream); + callableStatement.setBlob("u", inputStream, 1000000L); + callableStatement.setClob("v", clob); + callableStatement.setClob("w", reader); + callableStatement.setClob("x", reader, 100L); + callableStatement.setNString("y", "test"); + callableStatement.setNCharacterStream("z", reader); + callableStatement.setNCharacterStream("a1", reader, 1); + callableStatement.setNClob("a2", nClob); + callableStatement.setNClob("a3", reader, 1); + callableStatement.setObject("a4", new Object()); + callableStatement.setObject("a5", new Object(), 1); + callableStatement.setObject("a6", new Object(), 1, 1); + callableStatement.setRowId("a7", rowId); + callableStatement.setSQLXML("a8", sqlxml); + callableStatement.setTime("a9", new Time(System.currentTimeMillis())); + callableStatement.setTimestamp("b1", new Timestamp(System.currentTimeMillis())); + callableStatement.setTimestamp("b2", new Timestamp(System.currentTimeMillis()), Calendar.getInstance()); + callableStatement.setURL("b3", new URL("http", "127.0.0.1", "test")); + callableStatement.setBinaryStream("b4", inputStream); + callableStatement.setBinaryStream("b5", inputStream, 1); + callableStatement.setBinaryStream("b6", inputStream, 1L); + callableStatement.setNClob("b7", reader); + callableStatement.setTime("b8", new Time(System.currentTimeMillis()), Calendar.getInstance()); + callableStatement.setBlob("c1", blob); + callableStatement.setDate("c2", new Date(System.currentTimeMillis()), Calendar.getInstance()); + + callableStatement.registerOutParameter("c4", 1); + callableStatement.registerOutParameter("c5", 1, 1); + callableStatement.registerOutParameter("c6", 1, "test"); + callableStatement.registerOutParameter(48, 1); + callableStatement.registerOutParameter(49, 1, 1); + callableStatement.registerOutParameter(50, 1, "test"); + + ResultSet resultSet = callableStatement.executeQuery(); + callableStatement.close(); + + verify(mysqlCallableStatement, times(1)).clearParameters(); + verify(mysqlCallableStatement, times(1)).executeQuery(); + verify(mysqlCallableStatement, times(1)).close(); + verify(mysqlCallableStatement, times(1)).setAsciiStream(anyInt(), any(InputStream.class)); + verify(mysqlCallableStatement, times(1)).setAsciiStream(anyInt(), any(InputStream.class), anyInt()); + verify(mysqlCallableStatement, times(1)).setAsciiStream(anyInt(), any(InputStream.class), anyLong()); + verify(mysqlCallableStatement, times(1)).setCharacterStream(anyInt(), any(Reader.class)); + verify(mysqlCallableStatement, times(1)).setCharacterStream(anyInt(), any(Reader.class), anyInt()); + verify(mysqlCallableStatement, times(1)).setCharacterStream(anyInt(), any(Reader.class), anyLong()); + verify(mysqlCallableStatement, times(1)).setShort(anyInt(), anyShort()); + verify(mysqlCallableStatement, times(1)).setInt(anyInt(), anyInt()); + verify(mysqlCallableStatement, times(1)).setString(anyInt(), anyString()); + verify(mysqlCallableStatement, times(1)).setBoolean(anyInt(), anyBoolean()); + verify(mysqlCallableStatement, times(1)).setLong(anyInt(), anyLong()); + verify(mysqlCallableStatement, times(1)).setDouble(anyInt(), anyDouble()); + verify(mysqlCallableStatement, times(1)).setFloat(anyInt(), anyFloat()); + verify(mysqlCallableStatement, times(1)).setByte(anyInt(), anyByte()); + verify(mysqlCallableStatement, times(1)).setBytes(14, bytesParam); + verify(mysqlCallableStatement, times(1)).setDate(anyInt(), any(Date.class)); + verify(mysqlCallableStatement, times(1)).setNull(anyInt(), anyInt()); + verify(mysqlCallableStatement, times(1)).setNull(anyInt(), anyInt(), anyString()); + verify(mysqlCallableStatement, times(1)).setBigDecimal(anyInt(), any(BigDecimal.class)); + verify(mysqlCallableStatement, times(1)).setBlob(anyInt(), any(InputStream.class)); + verify(mysqlCallableStatement, times(1)).setBlob(anyInt(), any(InputStream.class), anyLong()); + verify(mysqlCallableStatement, times(1)).setClob(anyInt(), any(Clob.class)); + verify(mysqlCallableStatement, times(1)).setClob(anyInt(), any(Reader.class)); + verify(mysqlCallableStatement, times(1)).setClob(anyInt(), any(Reader.class), anyInt()); + verify(mysqlCallableStatement, times(1)).setNString(anyInt(), anyString()); + verify(mysqlCallableStatement, times(1)).setNCharacterStream(anyInt(), any(Reader.class)); + verify(mysqlCallableStatement, times(1)).setNCharacterStream(anyInt(), any(Reader.class), anyInt()); + verify(mysqlCallableStatement, times(1)).setNClob(27, nClob); + verify(mysqlCallableStatement, times(1)).setNClob(28, reader, 1); + verify(mysqlCallableStatement, times(1)).setObject(anyInt(), Matchers.anyObject()); + verify(mysqlCallableStatement, times(1)).setObject(anyInt(), Matchers.anyObject(), anyInt()); + verify(mysqlCallableStatement, times(1)).setObject(anyInt(), Matchers.anyObject(), anyInt(), anyInt()); + verify(mysqlCallableStatement, times(1)).setRef(anyInt(), any(Ref.class)); + verify(mysqlCallableStatement, times(1)).setRowId(anyInt(), any(RowId.class)); + verify(mysqlCallableStatement, times(1)).setSQLXML(anyInt(), any(SQLXML.class)); + verify(mysqlCallableStatement, times(1)).setTime(anyInt(), any(Time.class)); + verify(mysqlCallableStatement, times(1)).setTimestamp(anyInt(), any(Timestamp.class)); + verify(mysqlCallableStatement, times(1)).setTimestamp(anyInt(), any(Timestamp.class), any(Calendar.class)); + verify(mysqlCallableStatement, times(1)).setURL(anyInt(), any(URL.class)); + verify(mysqlCallableStatement, times(1)).setBinaryStream(anyInt(), any(InputStream.class)); + verify(mysqlCallableStatement, times(1)).setBinaryStream(anyInt(), any(InputStream.class), anyInt()); + verify(mysqlCallableStatement, times(1)).setBinaryStream(anyInt(), any(InputStream.class), anyLong()); + verify(mysqlCallableStatement, times(1)).setNClob(42, reader); + verify(mysqlCallableStatement, times(1)).setTime(anyInt(), any(Time.class), any(Calendar.class)); + verify(mysqlCallableStatement, times(1)).setTimestamp(anyInt(), any(Timestamp.class), any(Calendar.class)); + verify(mysqlCallableStatement, times(1)).setArray(anyInt(), any(Array.class)); + verify(mysqlCallableStatement, times(1)).setBlob(anyInt(), any(Blob.class)); + verify(mysqlCallableStatement, times(1)).setDate(anyInt(), any(Date.class), any(Calendar.class)); + + + verify(mysqlCallableStatement, times(1)).clearParameters(); + verify(mysqlCallableStatement, times(1)).executeQuery(); + verify(mysqlCallableStatement, times(1)).close(); + verify(mysqlCallableStatement, times(1)).setAsciiStream(anyString(), any(InputStream.class)); + verify(mysqlCallableStatement, times(1)).setAsciiStream(anyString(), any(InputStream.class), anyInt()); + verify(mysqlCallableStatement, times(1)).setAsciiStream(anyString(), any(InputStream.class), anyLong()); + verify(mysqlCallableStatement, times(1)).setCharacterStream(anyString(), any(Reader.class)); + verify(mysqlCallableStatement, times(1)).setCharacterStream(anyString(), any(Reader.class), anyInt()); + verify(mysqlCallableStatement, times(1)).setCharacterStream(anyString(), any(Reader.class), anyLong()); + verify(mysqlCallableStatement, times(1)).setShort(anyString(), anyShort()); + verify(mysqlCallableStatement, times(1)).setInt(anyString(), anyInt()); + verify(mysqlCallableStatement, times(1)).setString(anyString(), anyString()); + verify(mysqlCallableStatement, times(1)).setBoolean(anyString(), anyBoolean()); + verify(mysqlCallableStatement, times(1)).setLong(anyString(), anyLong()); + verify(mysqlCallableStatement, times(1)).setDouble(anyString(), anyDouble()); + verify(mysqlCallableStatement, times(1)).setFloat(anyString(), anyFloat()); + verify(mysqlCallableStatement, times(1)).setByte(anyString(), anyByte()); + verify(mysqlCallableStatement, times(1)).setBytes(14, bytesParam); + verify(mysqlCallableStatement, times(1)).setDate(anyString(), any(Date.class)); + verify(mysqlCallableStatement, times(1)).setNull(anyString(), anyInt()); + verify(mysqlCallableStatement, times(1)).setNull(anyString(), anyInt(), anyString()); + verify(mysqlCallableStatement, times(1)).setBigDecimal(anyString(), any(BigDecimal.class)); + verify(mysqlCallableStatement, times(1)).setBlob(anyString(), any(InputStream.class)); + verify(mysqlCallableStatement, times(1)).setBlob(anyString(), any(InputStream.class), anyLong()); + verify(mysqlCallableStatement, times(1)).setClob(anyString(), any(Clob.class)); + verify(mysqlCallableStatement, times(1)).setClob(anyString(), any(Reader.class)); + verify(mysqlCallableStatement, times(1)).setClob(anyString(), any(Reader.class), anyInt()); + verify(mysqlCallableStatement, times(1)).setNString(anyString(), anyString()); + verify(mysqlCallableStatement, times(1)).setNCharacterStream(anyString(), any(Reader.class)); + verify(mysqlCallableStatement, times(1)).setNCharacterStream(anyString(), any(Reader.class), anyInt()); + verify(mysqlCallableStatement, times(1)).setNClob(27, nClob); + verify(mysqlCallableStatement, times(1)).setNClob(28, reader, 1); + verify(mysqlCallableStatement, times(1)).setObject(anyString(), Matchers.anyObject()); + verify(mysqlCallableStatement, times(1)).setObject(anyString(), Matchers.anyObject(), anyInt()); + verify(mysqlCallableStatement, times(1)).setObject(anyString(), Matchers.anyObject(), anyInt(), anyInt()); + verify(mysqlCallableStatement, times(1)).setRowId(anyString(), any(RowId.class)); + verify(mysqlCallableStatement, times(1)).setSQLXML(anyString(), any(SQLXML.class)); + verify(mysqlCallableStatement, times(1)).setTime(anyString(), any(Time.class)); + verify(mysqlCallableStatement, times(1)).setTimestamp(anyString(), any(Timestamp.class)); + verify(mysqlCallableStatement, times(1)).setTimestamp(anyString(), any(Timestamp.class), any(Calendar.class)); + verify(mysqlCallableStatement, times(1)).setURL(anyString(), any(URL.class)); + verify(mysqlCallableStatement, times(1)).setBinaryStream(anyString(), any(InputStream.class)); + verify(mysqlCallableStatement, times(1)).setBinaryStream(anyString(), any(InputStream.class), anyInt()); + verify(mysqlCallableStatement, times(1)).setBinaryStream(anyString(), any(InputStream.class), anyLong()); + verify(mysqlCallableStatement, times(1)).setNClob(42, reader); + verify(mysqlCallableStatement, times(1)).setTime(anyString(), any(Time.class), any(Calendar.class)); + verify(mysqlCallableStatement, times(1)).setTimestamp(anyString(), any(Timestamp.class), any(Calendar.class)); + verify(mysqlCallableStatement, times(1)).setBlob(anyString(), any(Blob.class)); + verify(mysqlCallableStatement, times(1)).setDate(anyString(), any(Date.class), any(Calendar.class)); + } + + @Test + public void testCallableStatementConfig() throws SQLException { + CallableStatement callableStatement = swConnection.prepareCall("INSERT INTO test VALUES( ? , ?)", 1, 1); + callableStatement.setInt(1, 1); + callableStatement.setString(2, "a"); + callableStatement.getUpdateCount(); + callableStatement.setFetchDirection(1); + callableStatement.getFetchDirection(); + callableStatement.getResultSetConcurrency(); + callableStatement.getResultSetType(); + callableStatement.isClosed(); + callableStatement.setPoolable(false); + callableStatement.isPoolable(); + callableStatement.getWarnings(); + callableStatement.clearWarnings(); + callableStatement.setCursorName("test"); + callableStatement.setMaxFieldSize(11); + callableStatement.getMaxFieldSize(); + callableStatement.setMaxRows(10); + callableStatement.getMaxRows(); + callableStatement.getParameterMetaData(); + callableStatement.setEscapeProcessing(true); + callableStatement.setFetchSize(1); + callableStatement.getFetchSize(); + callableStatement.setQueryTimeout(1); + callableStatement.getQueryTimeout(); + Connection connection = callableStatement.getConnection(); + + callableStatement.execute(); + + callableStatement.getMoreResults(); + callableStatement.getMoreResults(1); + callableStatement.getResultSetHoldability(); + callableStatement.getMetaData(); + callableStatement.getResultSet(); + + callableStatement.close(); + verify(mysqlCallableStatement, times(1)).getUpdateCount(); + verify(mysqlCallableStatement, times(1)).getMoreResults(); + verify(mysqlCallableStatement, times(1)).setFetchDirection(anyInt()); + verify(mysqlCallableStatement, times(1)).getFetchDirection(); + verify(mysqlCallableStatement, times(1)).getResultSetType(); + verify(mysqlCallableStatement, times(1)).isClosed(); + verify(mysqlCallableStatement, times(1)).setPoolable(anyBoolean()); + verify(mysqlCallableStatement, times(1)).getWarnings(); + verify(mysqlCallableStatement, times(1)).clearWarnings(); + verify(mysqlCallableStatement, times(1)).setCursorName(anyString()); + verify(mysqlCallableStatement, times(1)).setMaxFieldSize(anyInt()); + verify(mysqlCallableStatement, times(1)).getMaxFieldSize(); + verify(mysqlCallableStatement, times(1)).setMaxRows(anyInt()); + verify(mysqlCallableStatement, times(1)).getMaxRows(); + verify(mysqlCallableStatement, times(1)).setEscapeProcessing(anyBoolean()); + verify(mysqlCallableStatement, times(1)).getResultSetConcurrency(); + verify(mysqlCallableStatement, times(1)).getResultSetConcurrency(); + verify(mysqlCallableStatement, times(1)).getResultSetType(); + verify(mysqlCallableStatement, times(1)).getMetaData(); + verify(mysqlCallableStatement, times(1)).getParameterMetaData(); + verify(mysqlCallableStatement, times(1)).getMoreResults(anyInt()); + verify(mysqlCallableStatement, times(1)).setFetchSize(anyInt()); + verify(mysqlCallableStatement, times(1)).getFetchSize(); + verify(mysqlCallableStatement, times(1)).getQueryTimeout(); + verify(mysqlCallableStatement, times(1)).setQueryTimeout(anyInt()); + verify(mysqlCallableStatement, times(1)).getResultSet(); + assertThat(connection, CoreMatchers.is(swConnection)); + } + + @Test + public void testExecuteQuery() throws SQLException { + CallableStatement callableStatement = swConnection.prepareCall("SELECT * FROM test", 1, 1, 1); + ResultSet resultSet = callableStatement.executeQuery(); + + callableStatement.close(); + + verify(mysqlCallableStatement, times(1)).executeQuery(); + verify(mysqlCallableStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/CallableStatement/executeQuery", "SELECT * FROM test"); + } + }); + } + + @Test + public void testQuerySqlWithSql() throws SQLException { + CallableStatement preparedStatement = swConnection.prepareCall("SELECT * FROM test", 1, 1); + ResultSet resultSet = preparedStatement.executeQuery("SELECT * FROM test"); + + preparedStatement.getGeneratedKeys(); + preparedStatement.close(); + + verify(mysqlCallableStatement, times(1)).executeQuery(anyString()); + verify(mysqlCallableStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/CallableStatement/executeQuery", "SELECT * FROM test"); + } + }); + } + + @Test + public void testInsertWithAutoGeneratedKey() throws SQLException { + CallableStatement preparedStatement = swConnection.prepareCall("INSERT INTO test VALUES(?)"); + boolean insertCount = preparedStatement.execute("INSERT INTO test VALUES(1)", 1); + preparedStatement.close(); + + verify(mysqlCallableStatement, times(1)).execute(anyString(), anyInt()); + verify(mysqlCallableStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/CallableStatement/execute", "INSERT INTO test VALUES(1)"); + } + }); + } + + @Test + public void testInsertWithIntColumnIndexes() throws SQLException { + CallableStatement preparedStatement = swConnection.prepareCall("INSERT INTO test VALUES(?)"); + boolean insertCount = preparedStatement.execute("INSERT INTO test VALUES(1)", new int[]{1, 2}); + preparedStatement.close(); + + verify(mysqlCallableStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/CallableStatement/execute", "INSERT INTO test VALUES(1)"); + } + }); + } + + @Test + public void testInsertWithStringColumnIndexes() throws SQLException { + CallableStatement preparedStatement = swConnection.prepareCall("INSERT INTO test VALUES(?)"); + boolean insertCount = preparedStatement.execute("INSERT INTO test VALUES(1)", new String[]{"1", "2"}); + preparedStatement.close(); + + verify(mysqlCallableStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/CallableStatement/execute", "INSERT INTO test VALUES(1)"); + } + }); + } + + @Test + public void testExecute() throws SQLException { + CallableStatement preparedStatement = swConnection.prepareCall("UPDATE test SET a = ?"); + preparedStatement.setString(1, "a"); + boolean updateCount = preparedStatement.execute("UPDATE test SET a = 1"); + preparedStatement.cancel(); + preparedStatement.close(); + + verify(mysqlCallableStatement, times(1)).execute(anyString()); + verify(mysqlCallableStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/CallableStatement/execute", "UPDATE test SET a = 1"); + } + }); + } + + @Test + public void testExecuteUpdate() throws SQLException { + CallableStatement preparedStatement = swConnection.prepareCall("UPDATE test SET a = ?"); + preparedStatement.setString(1, "a"); + int updateCount = preparedStatement.executeUpdate(); + preparedStatement.cancel(); + preparedStatement.close(); + + verify(mysqlCallableStatement, times(1)).executeUpdate(); + verify(mysqlCallableStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/CallableStatement/executeUpdate", "UPDATE test SET a = ?"); + } + }); + } + + @Test + public void testUpdateSql() throws SQLException { + CallableStatement preparedStatement = swConnection.prepareCall("UPDATE test SET a = ?"); + + int updateCount = preparedStatement.executeUpdate("UPDATE test SET a = 1"); + preparedStatement.cancel(); + preparedStatement.close(); + + verify(mysqlCallableStatement, times(1)).executeUpdate(anyString()); + verify(mysqlCallableStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/CallableStatement/executeUpdate", "UPDATE test SET a = 1"); + } + }); + } + + @Test + public void testUpdateWithAutoGeneratedKey() throws SQLException { + CallableStatement preparedStatement = swConnection.prepareCall("UPDATE test SET a = ?"); + + int updateCount = preparedStatement.executeUpdate("UPDATE test SET a = 1", 1); + preparedStatement.cancel(); + preparedStatement.close(); + + verify(mysqlCallableStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/CallableStatement/executeUpdate", "UPDATE test SET a = 1"); + } + }); + } + + @Test + public void testUpdateWithIntColumnIndexes() throws SQLException { + CallableStatement preparedStatement = swConnection.prepareCall("UPDATE test SET a = ?"); + + int updateCount = preparedStatement.executeUpdate("UPDATE test SET a = 1", new int[]{1}); + preparedStatement.cancel(); + preparedStatement.close(); + + verify(mysqlCallableStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/CallableStatement/executeUpdate", "UPDATE test SET a = 1"); + } + }); + } + + @Test + public void testUpdateWithStringColumnIndexes() throws SQLException { + CallableStatement preparedStatement = swConnection.prepareCall("UPDATE test SET a = ?"); + + int updateCount = preparedStatement.executeUpdate("UPDATE test SET a = 1", new String[]{"1"}); + preparedStatement.cancel(); + preparedStatement.close(); + + verify(mysqlCallableStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/CallableStatement/executeUpdate", "UPDATE test SET a = 1"); + } + }); + } + + + @Test + public void testBatch() throws SQLException, MalformedURLException { + CallableStatement preparedStatement = multiHostConnection.prepareCall("UPDATE test SET a = ? WHERE b = ?"); + preparedStatement.setShort(1, (short) 12); + preparedStatement.setTime(2, new Time(System.currentTimeMillis())); + preparedStatement.addBatch(); + int[] resultSet = preparedStatement.executeBatch(); + preparedStatement.clearBatch(); + + verify(mysqlCallableStatement, times(1)).executeBatch(); + verify(mysqlCallableStatement, times(1)).addBatch(); + verify(mysqlCallableStatement, times(1)).clearBatch(); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/CallableStatement/executeBatch", ""); + } + }); + } + + @Test + public void testQueryWithMultiHost() throws SQLException { + CallableStatement preparedStatement = multiHostConnection.prepareCall("SELECT * FROM test WHERE a = ? or b = ? or c=? or d = ?", 1, 1); + preparedStatement.setAsciiStream(1, inputStream); + preparedStatement.setAsciiStream(2, inputStream, 10); + preparedStatement.setAsciiStream(3, inputStream, 1000000L); + preparedStatement.setCharacterStream(4, reader); + ResultSet resultSet = preparedStatement.executeQuery(); + + preparedStatement.close(); + + verify(mysqlCallableStatement, times(1)).executeQuery(); + verify(mysqlCallableStatement, times(1)).close(); + } + + + @Test(expected = SQLException.class) + public void testMultiHostWithException() throws SQLException { + when(mysqlCallableStatement.executeQuery()).thenThrow(new SQLException()); + try { + CallableStatement preparedStatement = multiHostConnection.prepareCall("SELECT * FROM test WHERE a = ? or b = ? or c=? or d = ? or e=?"); + preparedStatement.setBigDecimal(1, new BigDecimal(10000)); + preparedStatement.setBlob(2, inputStream); + preparedStatement.setBlob(3, inputStream, 1000000L); + preparedStatement.setByte(3, (byte) 1); + preparedStatement.setBytes(4, bytesParam); + preparedStatement.setLong(5, 100L); + + ResultSet resultSet = preparedStatement.executeQuery(); + + preparedStatement.close(); + } finally { + verify(mysqlCallableStatement, times(1)).executeQuery(); + verify(mysqlCallableStatement, times(0)).close(); + verify(mysqlCallableStatement, times(1)).setBigDecimal(anyInt(), any(BigDecimal.class)); + verify(mysqlCallableStatement, times(1)).setBlob(anyInt(), any(InputStream.class)); + verify(mysqlCallableStatement, times(1)).setBlob(anyInt(), any(InputStream.class), anyLong()); + verify(mysqlCallableStatement, times(1)).setByte(anyInt(), anyByte()); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/CallableStatement/executeQuery", "SELECT * FROM test WHERE a = ? or b = ? or c=? or d = ? or e=?"); + assertThat(span.getLogs().size(), is(1)); + assertDBSpanLog(span.getLogs().get(0)); + } + }); + } + } + + @After + public void tearDown() throws Exception { + TracerContext.ListenerManager.remove(mockTracerContextListener); + } + +} \ No newline at end of file diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/SWConnectionTest.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/SWConnectionTest.java new file mode 100644 index 0000000000..59e47a9664 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/SWConnectionTest.java @@ -0,0 +1,361 @@ +package com.a.eye.skywalking.plugin.jdbc; + +import com.a.eye.skywalking.api.context.TracerContext; +import com.a.eye.skywalking.sniffer.mock.context.MockTracerContextListener; +import com.a.eye.skywalking.sniffer.mock.context.SegmentAssert; +import com.a.eye.skywalking.trace.TraceSegment; +import com.mysql.cj.api.jdbc.JdbcConnection; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Savepoint; +import java.util.HashMap; +import java.util.Properties; +import java.util.concurrent.Executor; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class SWConnectionTest extends AbstractStatementTest { + @Mock + private com.mysql.cj.jdbc.PreparedStatement mysqlPreparedStatement; + @Mock + private JdbcConnection jdbcConnection; + @Mock + private Executor executor; + @Mock + private Savepoint savepoint; + private SWConnection swConnection; + private SWConnection multiHostConnection; + + @Before + public void setUp() throws Exception { + mockTracerContextListener = new MockTracerContextListener(); + swConnection = new SWConnection("jdbc:mysql://127.0.0.1:3306/test", new Properties(), jdbcConnection); + multiHostConnection = new SWConnection("jdbc:mysql://127.0.0.1:3306,127.0.0.1:3309/test", new Properties(), jdbcConnection); + + TracerContext.ListenerManager.add(mockTracerContextListener); + + when(jdbcConnection.prepareStatement(anyString())).thenReturn(mysqlPreparedStatement); + } + + @Test + public void testCommit() throws SQLException { + PreparedStatement preparedStatement = swConnection.prepareStatement("SELECT * FROM test"); + + swConnection.commit(); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/commit"); + } + }); + } + + @Test + public void testMultiHostCommit() throws SQLException { + PreparedStatement preparedStatement = swConnection.prepareStatement("SELECT * FROM test", new String[]{"1"}); + multiHostConnection.commit(); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/commit"); + } + }); + } + + @Test(expected = SQLException.class) + public void testCommitWithException() throws SQLException { + PreparedStatement preparedStatement = swConnection.prepareStatement("SELECT * FROM test", new int[]{1}); + doThrow(new SQLException()).when(jdbcConnection).commit(); + try { + swConnection.commit(); + } finally { + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/commit"); + assertDBSpanLog(traceSegment.getSpans().get(0).getLogs().get(0)); + } + }); + } + } + + @Test + public void testRollBack() throws SQLException { + PreparedStatement preparedStatement = swConnection.prepareStatement("SELECT * FROM test", 1, 1); + swConnection.rollback(); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/rollback"); + + } + }); + } + + @Test + public void testMultiHostRollBack() throws SQLException { + PreparedStatement preparedStatement = swConnection.prepareStatement("SELECT * FROM test", 1, 1, 1); + multiHostConnection.rollback(); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/rollback"); + } + }); + } + + @Test(expected = SQLException.class) + public void testRollBackWithException() throws SQLException { + doThrow(new SQLException()).when(jdbcConnection).rollback(); + + swConnection.rollback(); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/rollback"); + } + }); + } + + + @Test + public void testRollBackWithSavePoint() throws SQLException { + swConnection.rollback(savepoint); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/rollback to savepoint"); + } + }); + } + + @Test + public void testMultiHostRollBackWithSavePoint() throws SQLException { + multiHostConnection.rollback(savepoint); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/rollback to savepoint"); + } + }); + } + + @Test(expected = SQLException.class) + public void testRollBackWithSavePointWithException() throws SQLException { + doThrow(new SQLException()).when(jdbcConnection).rollback(any(Savepoint.class)); + + swConnection.rollback(savepoint); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/rollback to savepoint"); + assertDBSpanLog(traceSegment.getSpans().get(0).getLogs().get(0)); + } + }); + } + + @Test + public void testClose() throws SQLException { + swConnection.close(); + swConnection.clearWarnings(); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/close"); + } + }); + } + + @Test + public void testMultiHostClose() throws SQLException { + multiHostConnection.close(); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/close"); + } + }); + } + + @Test(expected = SQLException.class) + public void testCloseWithException() throws SQLException { + doThrow(new SQLException()).when(jdbcConnection).close(); + + swConnection.close(); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/close"); + assertDBSpanLog(traceSegment.getSpans().get(0).getLogs().get(0)); + } + }); + } + + + @Test + public void testReleaseSavePoint() throws SQLException { + swConnection.releaseSavepoint(savepoint); + swConnection.clearWarnings(); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/releaseSavepoint savepoint"); + } + }); + } + + @Test + public void testMultiHostReleaseSavePoint() throws SQLException { + multiHostConnection.releaseSavepoint(savepoint); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/releaseSavepoint savepoint"); + } + }); + } + + @Test(expected = SQLException.class) + public void testReleaseSavePointWithException() throws SQLException { + doThrow(new SQLException()).when(jdbcConnection).releaseSavepoint(any(Savepoint.class)); + + swConnection.releaseSavepoint(savepoint); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + assertDBSpan(traceSegment.getSpans().get(0), "JDBC/Connection/releaseSavepoint savepoint"); + assertDBSpanLog(traceSegment.getSpans().get(0).getLogs().get(0)); + } + }); + } + + @Test + public void testSetConfig() throws SQLException { + swConnection.createArrayOf("1", new Object[0]); + swConnection.createBlob(); + swConnection.createClob(); + swConnection.createNClob(); + swConnection.createSQLXML(); + swConnection.nativeSQL("SELECT IT"); + swConnection.setAutoCommit(true); + swConnection.getAutoCommit(); + swConnection.setCatalog("test"); + swConnection.getCatalog(); + swConnection.setClientInfo(new Properties()); + swConnection.getClientInfo(); + swConnection.setHoldability(1); + swConnection.getHoldability(); + swConnection.setReadOnly(false); + swConnection.setClientInfo("test-client", "test-client"); + swConnection.getClientInfo("test"); + swConnection.setSavepoint(); + swConnection.getMetaData(); + swConnection.getTransactionIsolation(); + swConnection.getTypeMap(); + swConnection.getWarnings(); + swConnection.isClosed(); + swConnection.isReadOnly(); + swConnection.isValid(10); + swConnection.setSavepoint("test"); + swConnection.setTransactionIsolation(1); + swConnection.setTypeMap(new HashMap>()); + + verify(jdbcConnection, times(1)).createBlob(); + verify(jdbcConnection, times(1)).createClob(); + verify(jdbcConnection, times(1)).createNClob(); + verify(jdbcConnection, times(1)).createSQLXML(); + verify(jdbcConnection, times(1)).nativeSQL(anyString()); + verify(jdbcConnection, times(1)).setAutoCommit(anyBoolean()); + verify(jdbcConnection, times(1)).getAutoCommit(); + verify(jdbcConnection, times(1)).setCatalog(anyString()); + verify(jdbcConnection, times(1)).getCatalog(); + verify(jdbcConnection, times(1)).setClientInfo(anyString(), anyString()); + verify(jdbcConnection, times(1)).setHoldability(anyInt()); + verify(jdbcConnection, times(1)).getHoldability(); + verify(jdbcConnection, times(1)).setReadOnly(anyBoolean()); + verify(jdbcConnection, times(1)).getClientInfo(); + verify(jdbcConnection, times(1)).getClientInfo(anyString()); + verify(jdbcConnection, times(1)).setSavepoint(anyString()); + verify(jdbcConnection, times(1)).setSavepoint(); + verify(jdbcConnection, times(1)).getMetaData(); + verify(jdbcConnection, times(1)).getTransactionIsolation(); + verify(jdbcConnection, times(1)).getTypeMap(); + verify(jdbcConnection, times(1)).getWarnings(); + verify(jdbcConnection, times(1)).setTransactionIsolation(anyInt()); + verify(jdbcConnection, times(1)).getTransactionIsolation(); + verify(jdbcConnection, times(1)).isClosed(); + verify(jdbcConnection, times(1)).isReadOnly(); + verify(jdbcConnection, times(1)).isValid(anyInt()); + verify(jdbcConnection, times(1)).setTypeMap(any(HashMap.class)); + + + } + + @After + public void tearDown() throws Exception { + TracerContext.ListenerManager.remove(mockTracerContextListener); + } + +} \ No newline at end of file diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/SWStatementTest.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/SWStatementTest.java new file mode 100644 index 0000000000..fe8738c9e5 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/SWStatementTest.java @@ -0,0 +1,309 @@ +package com.a.eye.skywalking.plugin.jdbc; + +import com.a.eye.skywalking.api.context.TracerContext; +import com.a.eye.skywalking.sniffer.mock.context.MockTracerContextListener; +import com.a.eye.skywalking.sniffer.mock.context.SegmentAssert; +import com.a.eye.skywalking.trace.LogData; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.TraceSegment; +import com.a.eye.skywalking.trace.tag.Tags; +import com.mysql.cj.api.jdbc.JdbcConnection; + +import org.hamcrest.CoreMatchers; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import java.net.MalformedURLException; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Properties; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class SWStatementTest extends AbstractStatementTest { + @Mock + private com.mysql.cj.jdbc.StatementImpl mysqlStatement; + @Mock + private JdbcConnection jdbcConnection; + private SWConnection swConnection; + private SWConnection multiHostConnection; + + + @Before + public void setUp() throws Exception { + mockTracerContextListener = new MockTracerContextListener(); + swConnection = new SWConnection("jdbc:mysql://127.0.0.1:3306/test", new Properties(), jdbcConnection); + multiHostConnection = new SWConnection("jdbc:mysql://127.0.0.1:3306,127.0.0.1:3309/test", new Properties(), jdbcConnection); + + TracerContext.ListenerManager.add(mockTracerContextListener); + + when(jdbcConnection.createStatement()).thenReturn(mysqlStatement); + when(jdbcConnection.createStatement(anyInt(), anyInt())).thenReturn(mysqlStatement); + when(jdbcConnection.createStatement(anyInt(), anyInt(), anyInt())).thenReturn(mysqlStatement); + } + + @Test + public void testPreparedStatementConfig() throws SQLException { + Statement statement = swConnection.createStatement(); + statement.cancel(); + statement.getUpdateCount(); + statement.setFetchDirection(1); + statement.getFetchDirection(); + statement.getResultSetConcurrency(); + statement.getResultSetType(); + statement.isClosed(); + statement.setPoolable(false); + statement.isPoolable(); + statement.getWarnings(); + statement.clearWarnings(); + statement.setCursorName("test"); + statement.setMaxFieldSize(11); + statement.getMaxFieldSize(); + statement.setMaxRows(10); + statement.getMaxRows(); + statement.setEscapeProcessing(true); + statement.setFetchSize(1); + statement.getFetchSize(); + statement.setQueryTimeout(1); + statement.getQueryTimeout(); + Connection connection = statement.getConnection(); + + statement.execute("SELECT * FROM test"); + statement.getMoreResults(); + statement.getMoreResults(1); + statement.getResultSetHoldability(); + statement.getResultSet(); + + statement.close(); + verify(mysqlStatement, times(1)).getUpdateCount(); + verify(mysqlStatement, times(1)).getMoreResults(); + verify(mysqlStatement, times(1)).setFetchDirection(anyInt()); + verify(mysqlStatement, times(1)).getFetchDirection(); + verify(mysqlStatement, times(1)).getResultSetType(); + verify(mysqlStatement, times(1)).isClosed(); + verify(mysqlStatement, times(1)).setPoolable(anyBoolean()); + verify(mysqlStatement, times(1)).getWarnings(); + verify(mysqlStatement, times(1)).clearWarnings(); + verify(mysqlStatement, times(1)).setCursorName(anyString()); + verify(mysqlStatement, times(1)).setMaxFieldSize(anyInt()); + verify(mysqlStatement, times(1)).getMaxFieldSize(); + verify(mysqlStatement, times(1)).setMaxRows(anyInt()); + verify(mysqlStatement, times(1)).getMaxRows(); + verify(mysqlStatement, times(1)).setEscapeProcessing(anyBoolean()); + verify(mysqlStatement, times(1)).getResultSetConcurrency(); + verify(mysqlStatement, times(1)).getResultSetConcurrency(); + verify(mysqlStatement, times(1)).getResultSetType(); + verify(mysqlStatement, times(1)).getMoreResults(anyInt()); + verify(mysqlStatement, times(1)).setFetchSize(anyInt()); + verify(mysqlStatement, times(1)).getFetchSize(); + verify(mysqlStatement, times(1)).getQueryTimeout(); + verify(mysqlStatement, times(1)).setQueryTimeout(anyInt()); + verify(mysqlStatement, times(1)).getResultSet(); + assertThat(connection, CoreMatchers.is(swConnection)); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/Statement/execute", "SELECT * FROM test"); + } + }); + } + + @Test + public void testExecuteWithAutoGeneratedKey() throws SQLException { + Statement statement = swConnection.createStatement(1, 1); + boolean executeSuccess = statement.execute("SELECT * FROM test", 1); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/Statement/execute", "SELECT * FROM test"); + } + }); + } + + @Test + public void testExecuteQuery() throws SQLException { + Statement statement = swConnection.createStatement(1, 1, 1); + ResultSet executeSuccess = statement.executeQuery("SELECT * FROM test"); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/Statement/executeQuery", "SELECT * FROM test"); + } + }); + } + + @Test + public void testExecuteUpdate() throws SQLException { + Statement statement = swConnection.createStatement(1, 1, 1); + int executeSuccess = statement.executeUpdate("UPDATE test SET a = 1"); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/Statement/executeUpdate", "UPDATE test SET a = 1"); + } + }); + } + + @Test + public void testExecuteUpdateWithAutoGeneratedKey() throws SQLException { + Statement statement = swConnection.createStatement(1, 1, 1); + int executeSuccess = statement.executeUpdate("UPDATE test SET a = 1", 1); + statement.getGeneratedKeys(); + + verify(mysqlStatement, times(1)).getGeneratedKeys(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/Statement/executeUpdate", "UPDATE test SET a = 1"); + } + }); + } + + @Test + public void testExecuteUpdateWithColumnIndexes() throws SQLException { + Statement statement = swConnection.createStatement(1, 1, 1); + int executeSuccess = statement.executeUpdate("UPDATE test SET a = 1", new int[]{1}); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/Statement/executeUpdate", "UPDATE test SET a = 1"); + } + }); + } + + @Test + public void testExecuteUpdateWithColumnStringIndexes() throws SQLException { + Statement statement = swConnection.createStatement(1, 1, 1); + int executeSuccess = statement.executeUpdate("UPDATE test SET a = 1", new String[]{"1"}); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/Statement/executeUpdate", "UPDATE test SET a = 1"); + } + }); + } + + @Test + public void testExecuteWithColumnIndexes() throws SQLException { + Statement statement = swConnection.createStatement(1, 1, 1); + boolean executeSuccess = statement.execute("UPDATE test SET a = 1", new int[]{1}); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/Statement/execute", "UPDATE test SET a = 1"); + } + }); + } + + @Test + public void testExecuteWithColumnStringIndexes() throws SQLException { + Statement statement = swConnection.createStatement(1, 1, 1); + boolean executeSuccess = statement.execute("UPDATE test SET a = 1", new String[]{"1"}); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/Statement/execute", "UPDATE test SET a = 1"); + } + }); + } + + @Test + public void testBatch() throws SQLException, MalformedURLException { + Statement statement = multiHostConnection.createStatement(); + statement.addBatch("UPDATE test SET a = 1 WHERE b = 2"); + int[] resultSet = statement.executeBatch(); + statement.clearBatch(); + + verify(mysqlStatement, times(1)).executeBatch(); + verify(mysqlStatement, times(1)).addBatch(anyString()); + verify(mysqlStatement, times(1)).clearBatch(); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/Statement/executeBatch", ""); + } + }); + } + + @Test(expected = SQLException.class) + public void testMultiHostWithException() throws SQLException { + when(mysqlStatement.execute(anyString())).thenThrow(new SQLException()); + try { + Statement statement = multiHostConnection.createStatement(); + statement.execute("UPDATE test SET a = 1 WHERE b = 2"); + } finally { + verify(mysqlStatement, times(1)).execute(anyString()); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/Statement/execute", "UPDATE test SET a = 1 WHERE b = 2"); + assertThat(span.getLogs().size(), is(1)); + assertDBSpanLog(span.getLogs().get(0)); + } + }); + } + } + + @After + public void tearDown() throws Exception { + TracerContext.ListenerManager.remove(mockTracerContextListener); + } +} \ No newline at end of file diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/SwPreparedStatementTest.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/SwPreparedStatementTest.java new file mode 100644 index 0000000000..f2c6822bbd --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/SwPreparedStatementTest.java @@ -0,0 +1,583 @@ +package com.a.eye.skywalking.plugin.jdbc; + +import com.a.eye.skywalking.api.context.TracerContext; +import com.a.eye.skywalking.sniffer.mock.context.MockTracerContextListener; +import com.a.eye.skywalking.sniffer.mock.context.SegmentAssert; +import com.a.eye.skywalking.trace.LogData; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.TraceSegment; +import com.a.eye.skywalking.trace.tag.Tags; +import com.mysql.cj.api.jdbc.JdbcConnection; + +import org.hamcrest.CoreMatchers; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Matchers; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.MalformedURLException; +import java.net.URL; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.Date; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.Ref; +import java.sql.ResultSet; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Calendar; +import java.util.Properties; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyByte; +import static org.mockito.Matchers.anyDouble; +import static org.mockito.Matchers.anyFloat; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyShort; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class SwPreparedStatementTest extends AbstractStatementTest { + + @Mock + private Array array; + @Mock + private SQLXML sqlxml; + @Mock + private RowId rowId; + @Mock + private Ref ref; + @Mock + private Clob clob; + @Mock + private NClob nClob; + @Mock + private Reader reader; + @Mock + private InputStream inputStream; + @Mock + private Blob blob; + @Mock + private com.mysql.cj.jdbc.PreparedStatement mysqlPreparedStatement; + @Mock + private JdbcConnection jdbcConnection; + private SWConnection swConnection; + private SWConnection multiHostConnection; + private byte[] bytesParam = new byte[]{1, 2}; + + @Before + public void setUp() throws Exception { + mockTracerContextListener = new MockTracerContextListener(); + swConnection = new SWConnection("jdbc:mysql://127.0.0.1:3306/test", new Properties(), jdbcConnection); + multiHostConnection = new SWConnection("jdbc:mysql://127.0.0.1:3306,127.0.0.1:3309/test", new Properties(), jdbcConnection); + + TracerContext.ListenerManager.add(mockTracerContextListener); + + when(jdbcConnection.prepareStatement(anyString())).thenReturn(mysqlPreparedStatement); + when(jdbcConnection.prepareStatement(anyString(), anyInt(), anyInt(), anyInt())).thenReturn(mysqlPreparedStatement); + when(jdbcConnection.prepareStatement(anyString(), anyInt(), anyInt())).thenReturn(mysqlPreparedStatement); + when(jdbcConnection.prepareStatement(anyString(), anyInt())).thenReturn(mysqlPreparedStatement); + } + + @Test + public void testSetParam() throws SQLException, MalformedURLException { + PreparedStatement preparedStatement = multiHostConnection.prepareStatement("SELECT * FROM test WHERE a = ? or b = ? or c=? or d = ? or e = ?" + + " or e = ? or f = ? or g = ? or h = ? or i = ? or j = ? or k = ? or l = ? or m = ? or n = ? or o = ? or p = ? " + + " or r = ? or s = ? or t = ? or u = ? or v = ? or w = ? or x = ? or y = ? or z = ? or a1 = ? or a2 = ? or a3 = ?" + + " or a4 = ? or a5 = ? or a6 = ? or a7 = ? or a8 = ? or a9 = ? or b1 = ? or b2 = ? or b3 = ? or b4 = ? or b5 = ?" + + " or b6 = ? or b7 = ? or b8 = ? or b9 = ? or c1 = ? or c2 = ? or c3 = ?"); + preparedStatement.clearParameters(); + preparedStatement.setAsciiStream(1, inputStream); + preparedStatement.setAsciiStream(2, inputStream, 10); + preparedStatement.setAsciiStream(3, inputStream, 1000000L); + preparedStatement.setCharacterStream(4, reader); + preparedStatement.setCharacterStream(4, reader, 10); + preparedStatement.setCharacterStream(5, reader, 10L); + preparedStatement.setShort(6, (short) 12); + preparedStatement.setInt(7, 1); + preparedStatement.setString(8, "test"); + preparedStatement.setBoolean(9, true); + preparedStatement.setLong(10, 100L); + preparedStatement.setDouble(11, 12.0); + preparedStatement.setFloat(12, 12.0f); + preparedStatement.setByte(13, (byte) 1); + preparedStatement.setBytes(14, bytesParam); + preparedStatement.setDate(15, new Date(System.currentTimeMillis())); + preparedStatement.setNull(16, 1); + preparedStatement.setNull(17, 1, "test"); + preparedStatement.setBigDecimal(18, new BigDecimal(10000)); + preparedStatement.setBlob(19, inputStream); + preparedStatement.setBlob(20, inputStream, 1000000L); + preparedStatement.setClob(21, clob); + preparedStatement.setClob(22, reader); + preparedStatement.setClob(23, reader, 100L); + preparedStatement.setNString(24, "test"); + preparedStatement.setNCharacterStream(25, reader); + preparedStatement.setNCharacterStream(26, reader, 1); + preparedStatement.setNClob(27, nClob); + preparedStatement.setNClob(28, reader, 1); + preparedStatement.setObject(29, new Object()); + preparedStatement.setObject(30, new Object(), 1); + preparedStatement.setObject(31, new Object(), 1, 1); + preparedStatement.setRef(32, ref); + preparedStatement.setRowId(33, rowId); + preparedStatement.setSQLXML(34, sqlxml); + preparedStatement.setTime(35, new Time(System.currentTimeMillis())); + preparedStatement.setTimestamp(36, new Timestamp(System.currentTimeMillis())); + preparedStatement.setTimestamp(37, new Timestamp(System.currentTimeMillis()), Calendar.getInstance()); + preparedStatement.setURL(38, new URL("http", "127.0.0.1", "test")); + preparedStatement.setBinaryStream(39, inputStream); + preparedStatement.setBinaryStream(40, inputStream, 1); + preparedStatement.setBinaryStream(41, inputStream, 1L); + preparedStatement.setNClob(42, reader); + preparedStatement.setTime(43, new Time(System.currentTimeMillis()), Calendar.getInstance()); + preparedStatement.setArray(45, array); + preparedStatement.setBlob(46, blob); + preparedStatement.setDate(47, new Date(System.currentTimeMillis()), Calendar.getInstance()); + + ResultSet resultSet = preparedStatement.executeQuery(); + preparedStatement.close(); + + verify(mysqlPreparedStatement, times(1)).clearParameters(); + verify(mysqlPreparedStatement, times(1)).executeQuery(); + verify(mysqlPreparedStatement, times(1)).close(); + verify(mysqlPreparedStatement, times(1)).setAsciiStream(anyInt(), any(InputStream.class)); + verify(mysqlPreparedStatement, times(1)).setAsciiStream(anyInt(), any(InputStream.class), anyInt()); + verify(mysqlPreparedStatement, times(1)).setAsciiStream(anyInt(), any(InputStream.class), anyLong()); + verify(mysqlPreparedStatement, times(1)).setCharacterStream(anyInt(), any(Reader.class)); + verify(mysqlPreparedStatement, times(1)).setCharacterStream(anyInt(), any(Reader.class), anyInt()); + verify(mysqlPreparedStatement, times(1)).setCharacterStream(anyInt(), any(Reader.class), anyLong()); + verify(mysqlPreparedStatement, times(1)).setShort(anyInt(), anyShort()); + verify(mysqlPreparedStatement, times(1)).setInt(anyInt(), anyInt()); + verify(mysqlPreparedStatement, times(1)).setString(anyInt(), anyString()); + verify(mysqlPreparedStatement, times(1)).setBoolean(anyInt(), anyBoolean()); + verify(mysqlPreparedStatement, times(1)).setLong(anyInt(), anyLong()); + verify(mysqlPreparedStatement, times(1)).setDouble(anyInt(), anyDouble()); + verify(mysqlPreparedStatement, times(1)).setFloat(anyInt(), anyFloat()); + verify(mysqlPreparedStatement, times(1)).setByte(anyInt(), anyByte()); + verify(mysqlPreparedStatement, times(1)).setBytes(14, bytesParam); + verify(mysqlPreparedStatement, times(1)).setDate(anyInt(), any(Date.class)); + verify(mysqlPreparedStatement, times(1)).setNull(anyInt(), anyInt()); + verify(mysqlPreparedStatement, times(1)).setNull(anyInt(), anyInt(), anyString()); + verify(mysqlPreparedStatement, times(1)).setBigDecimal(anyInt(), any(BigDecimal.class)); + verify(mysqlPreparedStatement, times(1)).setBlob(anyInt(), any(InputStream.class)); + verify(mysqlPreparedStatement, times(1)).setBlob(anyInt(), any(InputStream.class), anyLong()); + verify(mysqlPreparedStatement, times(1)).setClob(anyInt(), any(Clob.class)); + verify(mysqlPreparedStatement, times(1)).setClob(anyInt(), any(Reader.class)); + verify(mysqlPreparedStatement, times(1)).setClob(anyInt(), any(Reader.class), anyInt()); + verify(mysqlPreparedStatement, times(1)).setNString(anyInt(), anyString()); + verify(mysqlPreparedStatement, times(1)).setNCharacterStream(anyInt(), any(Reader.class)); + verify(mysqlPreparedStatement, times(1)).setNCharacterStream(anyInt(), any(Reader.class), anyInt()); + verify(mysqlPreparedStatement, times(1)).setNClob(27, nClob); + verify(mysqlPreparedStatement, times(1)).setNClob(28, reader, 1); + verify(mysqlPreparedStatement, times(1)).setObject(anyInt(), Matchers.anyObject()); + verify(mysqlPreparedStatement, times(1)).setObject(anyInt(), Matchers.anyObject(), anyInt()); + verify(mysqlPreparedStatement, times(1)).setObject(anyInt(), Matchers.anyObject(), anyInt(), anyInt()); + verify(mysqlPreparedStatement, times(1)).setRef(anyInt(), any(Ref.class)); + verify(mysqlPreparedStatement, times(1)).setRowId(anyInt(), any(RowId.class)); + verify(mysqlPreparedStatement, times(1)).setSQLXML(anyInt(), any(SQLXML.class)); + verify(mysqlPreparedStatement, times(1)).setTime(anyInt(), any(Time.class)); + verify(mysqlPreparedStatement, times(1)).setTimestamp(anyInt(), any(Timestamp.class)); + verify(mysqlPreparedStatement, times(1)).setTimestamp(anyInt(), any(Timestamp.class), any(Calendar.class)); + verify(mysqlPreparedStatement, times(1)).setURL(anyInt(), any(URL.class)); + verify(mysqlPreparedStatement, times(1)).setBinaryStream(anyInt(), any(InputStream.class)); + verify(mysqlPreparedStatement, times(1)).setBinaryStream(anyInt(), any(InputStream.class), anyInt()); + verify(mysqlPreparedStatement, times(1)).setBinaryStream(anyInt(), any(InputStream.class), anyLong()); + verify(mysqlPreparedStatement, times(1)).setNClob(42, reader); + verify(mysqlPreparedStatement, times(1)).setTime(anyInt(), any(Time.class), any(Calendar.class)); + verify(mysqlPreparedStatement, times(1)).setTimestamp(anyInt(), any(Timestamp.class), any(Calendar.class)); + verify(mysqlPreparedStatement, times(1)).setArray(anyInt(), any(Array.class)); + verify(mysqlPreparedStatement, times(1)).setBlob(anyInt(), any(Blob.class)); + verify(mysqlPreparedStatement, times(1)).setDate(anyInt(), any(Date.class), any(Calendar.class)); + } + + @Test + public void testPreparedStatementConfig() throws SQLException { + PreparedStatement preparedStatement = swConnection.prepareStatement("INSERT INTO test VALUES( ? , ?)", 1); + preparedStatement.setInt(1, 1); + preparedStatement.setString(2, "a"); + preparedStatement.getUpdateCount(); + preparedStatement.setFetchDirection(1); + preparedStatement.getFetchDirection(); + preparedStatement.getResultSetConcurrency(); + preparedStatement.getResultSetType(); + preparedStatement.isClosed(); + preparedStatement.setPoolable(false); + preparedStatement.isPoolable(); + preparedStatement.getWarnings(); + preparedStatement.clearWarnings(); + preparedStatement.setCursorName("test"); + preparedStatement.setMaxFieldSize(11); + preparedStatement.getMaxFieldSize(); + preparedStatement.setMaxRows(10); + preparedStatement.getMaxRows(); + preparedStatement.getParameterMetaData(); + preparedStatement.setEscapeProcessing(true); + preparedStatement.setFetchSize(1); + preparedStatement.getFetchSize(); + preparedStatement.setQueryTimeout(1); + preparedStatement.getQueryTimeout(); + Connection connection = preparedStatement.getConnection(); + + preparedStatement.execute(); + + preparedStatement.getMoreResults(); + preparedStatement.getMoreResults(1); + preparedStatement.getResultSetHoldability(); + preparedStatement.getMetaData(); + preparedStatement.getResultSet(); + + preparedStatement.close(); + verify(mysqlPreparedStatement, times(1)).getUpdateCount(); + verify(mysqlPreparedStatement, times(1)).getMoreResults(); + verify(mysqlPreparedStatement, times(1)).setFetchDirection(anyInt()); + verify(mysqlPreparedStatement, times(1)).getFetchDirection(); + verify(mysqlPreparedStatement, times(1)).getResultSetType(); + verify(mysqlPreparedStatement, times(1)).isClosed(); + verify(mysqlPreparedStatement, times(1)).setPoolable(anyBoolean()); + verify(mysqlPreparedStatement, times(1)).getWarnings(); + verify(mysqlPreparedStatement, times(1)).clearWarnings(); + verify(mysqlPreparedStatement, times(1)).setCursorName(anyString()); + verify(mysqlPreparedStatement, times(1)).setMaxFieldSize(anyInt()); + verify(mysqlPreparedStatement, times(1)).getMaxFieldSize(); + verify(mysqlPreparedStatement, times(1)).setMaxRows(anyInt()); + verify(mysqlPreparedStatement, times(1)).getMaxRows(); + verify(mysqlPreparedStatement, times(1)).setEscapeProcessing(anyBoolean()); + verify(mysqlPreparedStatement, times(1)).getResultSetConcurrency(); + verify(mysqlPreparedStatement, times(1)).getResultSetConcurrency(); + verify(mysqlPreparedStatement, times(1)).getResultSetType(); + verify(mysqlPreparedStatement, times(1)).getMetaData(); + verify(mysqlPreparedStatement, times(1)).getParameterMetaData(); + verify(mysqlPreparedStatement, times(1)).getMoreResults(anyInt()); + verify(mysqlPreparedStatement, times(1)).setFetchSize(anyInt()); + verify(mysqlPreparedStatement, times(1)).getFetchSize(); + verify(mysqlPreparedStatement, times(1)).getQueryTimeout(); + verify(mysqlPreparedStatement, times(1)).setQueryTimeout(anyInt()); + verify(mysqlPreparedStatement, times(1)).getResultSet(); + assertThat(connection, CoreMatchers.is(swConnection)); + } + + @Test + public void testExecuteQuery() throws SQLException { + PreparedStatement preparedStatement = swConnection.prepareStatement("SELECT * FROM test", 1, 1, 1); + ResultSet resultSet = preparedStatement.executeQuery(); + + preparedStatement.close(); + + verify(mysqlPreparedStatement, times(1)).executeQuery(); + verify(mysqlPreparedStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/PreparedStatement/executeQuery", "SELECT * FROM test"); + } + }); + } + + @Test + public void testQuerySqlWithSql() throws SQLException { + PreparedStatement preparedStatement = swConnection.prepareStatement("SELECT * FROM test", 1); + ResultSet resultSet = preparedStatement.executeQuery("SELECT * FROM test"); + + preparedStatement.getGeneratedKeys(); + preparedStatement.close(); + + verify(mysqlPreparedStatement, times(1)).executeQuery(anyString()); + verify(mysqlPreparedStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/PreparedStatement/executeQuery", "SELECT * FROM test"); + } + }); + } + + @Test + public void testInsertWithAutoGeneratedKey() throws SQLException { + PreparedStatement preparedStatement = swConnection.prepareStatement("INSERT INTO test VALUES(?)", 1); + boolean insertCount = preparedStatement.execute("INSERT INTO test VALUES(1)", 1); + preparedStatement.close(); + + verify(mysqlPreparedStatement, times(1)).execute(anyString(), anyInt()); + verify(mysqlPreparedStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/PreparedStatement/execute", "INSERT INTO test VALUES(1)"); + } + }); + } + + @Test + public void testInsertWithIntColumnIndexes() throws SQLException { + PreparedStatement preparedStatement = swConnection.prepareStatement("INSERT INTO test VALUES(?)", 1); + boolean insertCount = preparedStatement.execute("INSERT INTO test VALUES(1)", new int[]{1, 2}); + preparedStatement.close(); + + verify(mysqlPreparedStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/PreparedStatement/execute", "INSERT INTO test VALUES(1)"); + } + }); + } + + @Test + public void testInsertWithStringColumnIndexes() throws SQLException { + PreparedStatement preparedStatement = swConnection.prepareStatement("INSERT INTO test VALUES(?)", 1); + boolean insertCount = preparedStatement.execute("INSERT INTO test VALUES(1)", new String[]{"1", "2"}); + preparedStatement.close(); + + verify(mysqlPreparedStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/PreparedStatement/execute", "INSERT INTO test VALUES(1)"); + } + }); + } + + @Test + public void testExecute() throws SQLException { + PreparedStatement preparedStatement = swConnection.prepareStatement("UPDATE test SET a = ?"); + preparedStatement.setString(1, "a"); + boolean updateCount = preparedStatement.execute("UPDATE test SET a = 1"); + preparedStatement.cancel(); + preparedStatement.close(); + + verify(mysqlPreparedStatement, times(1)).execute(anyString()); + verify(mysqlPreparedStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/PreparedStatement/execute", "UPDATE test SET a = 1"); + } + }); + } + + @Test + public void testExecuteUpdate() throws SQLException { + PreparedStatement preparedStatement = swConnection.prepareStatement("UPDATE test SET a = ?"); + preparedStatement.setString(1, "a"); + int updateCount = preparedStatement.executeUpdate(); + preparedStatement.cancel(); + preparedStatement.close(); + + verify(mysqlPreparedStatement, times(1)).executeUpdate(); + verify(mysqlPreparedStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/PreparedStatement/executeUpdate", "UPDATE test SET a = ?"); + } + }); + } + + @Test + public void testUpdateSql() throws SQLException { + PreparedStatement preparedStatement = swConnection.prepareStatement("UPDATE test SET a = ?"); + + int updateCount = preparedStatement.executeUpdate("UPDATE test SET a = 1"); + preparedStatement.cancel(); + preparedStatement.close(); + + verify(mysqlPreparedStatement, times(1)).executeUpdate(anyString()); + verify(mysqlPreparedStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/PreparedStatement/executeUpdate", "UPDATE test SET a = 1"); + } + }); + } + + @Test + public void testUpdateWithAutoGeneratedKey() throws SQLException { + PreparedStatement preparedStatement = swConnection.prepareStatement("UPDATE test SET a = ?"); + + int updateCount = preparedStatement.executeUpdate("UPDATE test SET a = 1", 1); + preparedStatement.cancel(); + preparedStatement.close(); + + verify(mysqlPreparedStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/PreparedStatement/executeUpdate", "UPDATE test SET a = 1"); + } + }); + } + + @Test + public void testUpdateWithIntColumnIndexes() throws SQLException { + PreparedStatement preparedStatement = swConnection.prepareStatement("UPDATE test SET a = ?"); + + int updateCount = preparedStatement.executeUpdate("UPDATE test SET a = 1", new int[]{1}); + preparedStatement.cancel(); + preparedStatement.close(); + + verify(mysqlPreparedStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/PreparedStatement/executeUpdate", "UPDATE test SET a = 1"); + } + }); + } + + @Test + public void testUpdateWithStringColumnIndexes() throws SQLException { + PreparedStatement preparedStatement = swConnection.prepareStatement("UPDATE test SET a = ?"); + + int updateCount = preparedStatement.executeUpdate("UPDATE test SET a = 1", new String[]{"1"}); + preparedStatement.cancel(); + preparedStatement.close(); + + verify(mysqlPreparedStatement, times(1)).close(); + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/PreparedStatement/executeUpdate", "UPDATE test SET a = 1"); + } + }); + } + + + @Test + public void testBatch() throws SQLException, MalformedURLException { + PreparedStatement preparedStatement = multiHostConnection.prepareStatement("UPDATE test SET a = ? WHERE b = ?"); + preparedStatement.setShort(1, (short) 12); + preparedStatement.setTime(2, new Time(System.currentTimeMillis())); + preparedStatement.addBatch(); + int[] resultSet = preparedStatement.executeBatch(); + preparedStatement.clearBatch(); + + verify(mysqlPreparedStatement, times(1)).executeBatch(); + verify(mysqlPreparedStatement, times(1)).addBatch(); + verify(mysqlPreparedStatement, times(1)).clearBatch(); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/PreparedStatement/executeBatch", ""); + } + }); + } + + @Test + public void testQueryWithMultiHost() throws SQLException { + PreparedStatement preparedStatement = multiHostConnection.prepareStatement("SELECT * FROM test WHERE a = ? or b = ? or c=? or d = ?", 1, 1); + preparedStatement.setAsciiStream(1, inputStream); + preparedStatement.setAsciiStream(2, inputStream, 10); + preparedStatement.setAsciiStream(3, inputStream, 1000000L); + preparedStatement.setCharacterStream(4, reader); + ResultSet resultSet = preparedStatement.executeQuery(); + + preparedStatement.close(); + + verify(mysqlPreparedStatement, times(1)).executeQuery(); + verify(mysqlPreparedStatement, times(1)).close(); + } + + + @Test(expected = SQLException.class) + public void testMultiHostWithException() throws SQLException { + when(mysqlPreparedStatement.executeQuery()).thenThrow(new SQLException()); + try { + PreparedStatement preparedStatement = multiHostConnection.prepareStatement("SELECT * FROM test WHERE a = ? or b = ? or c=? or d = ? or e=?"); + preparedStatement.setBigDecimal(1, new BigDecimal(10000)); + preparedStatement.setBlob(2, inputStream); + preparedStatement.setBlob(3, inputStream, 1000000L); + preparedStatement.setByte(3, (byte) 1); + preparedStatement.setBytes(4, new byte[]{1, 2}); + preparedStatement.setLong(5, 100L); + + ResultSet resultSet = preparedStatement.executeQuery(); + + + preparedStatement.close(); + } finally { + verify(mysqlPreparedStatement, times(1)).executeQuery(); + verify(mysqlPreparedStatement, times(0)).close(); + verify(mysqlPreparedStatement, times(1)).setBigDecimal(anyInt(), any(BigDecimal.class)); + verify(mysqlPreparedStatement, times(1)).setBlob(anyInt(), any(InputStream.class)); + verify(mysqlPreparedStatement, times(1)).setBlob(anyInt(), any(InputStream.class), anyLong()); + verify(mysqlPreparedStatement, times(1)).setByte(anyInt(), anyByte()); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertDBSpan(span, "JDBC/PreparedStatement/executeQuery", "SELECT * FROM test WHERE a = ? or b = ? or c=? or d = ? or e=?"); + assertThat(span.getLogs().size(), is(1)); + assertDBSpanLog(span.getLogs().get(0)); + } + }); + } + } + + @After + public void tearDown() throws Exception { + TracerContext.ListenerManager.remove(mockTracerContextListener); + } +} \ No newline at end of file -- GitLab