From 9d9a28cbe1ee32afb93c88a520ded7d01d4f43f3 Mon Sep 17 00:00:00 2001 From: Simone Avogadro Date: Sat, 31 Mar 2018 15:41:54 +0200 Subject: [PATCH 01/29] Update README.md --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index aea186d..7de6447 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,13 @@ # dummyjdbc [![CircleCI](https://circleci.com/gh/kaiwinter/dummyjdbc.svg?style=svg)](https://circleci.com/gh/kaiwinter/dummyjdbc) +This fork is intended to support: +- in-memory CSV +- capturing of input parameters + +The main purposed of this fork is to simplify the development of UnitTests with [Boomi](https://boomi.com) iPaaS. +Using this fork you can create unit tests -without- access to the Atom's filesystem. All the test data will be stored inside the UnitTest processes. + dummyjdbc answers database requests of any application with dummy data to be independent of an existing database. The library can either return dummy values, or values defined by you in a CSV file. The files are determined by the SQL query which makes this a very flexible tool. Also results of Stored Procedures can be mocked with data from CSV files. @@ -18,4 +25,4 @@ For more details please see the [Wiki](https://github.com/kaiwinter/dummyjdbc/wi ## Overview -![Design](https://raw.githubusercontent.com/wiki/kaiwinter/dummyjdbc/images/dummyjdbc-design.png) \ No newline at end of file +![Design](https://raw.githubusercontent.com/wiki/kaiwinter/dummyjdbc/images/dummyjdbc-design.png) From 4d1c520f87cf5c68198263c138ea71d756f0375a Mon Sep 17 00:00:00 2001 From: SimoneAvogadro Date: Sat, 31 Mar 2018 17:09:25 +0200 Subject: [PATCH 02/29] Initial supporto for Dell Boomi --- .../dummyjdbc/statement/impl/InMemoryCSV.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/main/java/com/googlecode/dummyjdbc/statement/impl/InMemoryCSV.java diff --git a/src/main/java/com/googlecode/dummyjdbc/statement/impl/InMemoryCSV.java b/src/main/java/com/googlecode/dummyjdbc/statement/impl/InMemoryCSV.java new file mode 100644 index 0000000..b7e204b --- /dev/null +++ b/src/main/java/com/googlecode/dummyjdbc/statement/impl/InMemoryCSV.java @@ -0,0 +1,35 @@ +package com.googlecode.dummyjdbc.statement.impl; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Scanner; + +public class InMemoryCSV { + + /** + * + */ + static Map values = new HashMap(); + + static void register(String testID, String value) { + values.put(testID.toLowerCase().trim(), value.trim()); + } + + @SuppressWarnings("resource") + static void register(String testID, InputStream valueStream) { + // search for "end of stream" => read all the stream into the string ! + Scanner s = new Scanner(valueStream).useDelimiter("\\A"); + String value = s.hasNext() ? s.next() : ""; + s.close(); + register(testID,value); + } + + static void clear() { + values.clear(); + } + + static String get(String testID) { + return values.get(testID.toLowerCase().trim()); + } +} From 1e58c4dcdf31af6cf8e2469de70d2ecd451b142c Mon Sep 17 00:00:00 2001 From: SimoneAvogadro Date: Sat, 31 Mar 2018 17:14:24 +0200 Subject: [PATCH 03/29] Initial support for Dell Boomi testing --- .../googlecode/dummyjdbc/DummyJdbcDriver.java | 61 +++++++- .../resultset/impl/CSVResultSet.java | 75 ++++++++-- .../statement/impl/CsvPreparedStatement.java | 139 ++++++++++++++++++ .../statement/impl/CsvStatement.java | 35 ++++- .../impl/CsvPreparedStatementTest.java | 74 ++++++++++ 5 files changed, 364 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/googlecode/dummyjdbc/DummyJdbcDriver.java b/src/main/java/com/googlecode/dummyjdbc/DummyJdbcDriver.java index 6dcef5a..5ab6931 100644 --- a/src/main/java/com/googlecode/dummyjdbc/DummyJdbcDriver.java +++ b/src/main/java/com/googlecode/dummyjdbc/DummyJdbcDriver.java @@ -11,6 +11,8 @@ import java.sql.DriverPropertyInfo; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -26,6 +28,34 @@ */ public final class DummyJdbcDriver implements Driver { + /** + * The date format for parsing a date from a CSV file. + */ + private static final String DATE_FORMAT = "dd-MMM-yy"; + private static final String TIME_FORMAT = "HH:mm"; + private static final String TIMESTAMP_FORMAT = "yyyyMMdd HHmmss.SSS"; + + public static final ThreadLocal THREAD_LOCAL_DATEFORMAT = new ThreadLocal() { + @Override + protected DateFormat initialValue() { + return new SimpleDateFormat(DATE_FORMAT); + } + }; + + public static final ThreadLocal THREAD_LOCAL_TIMEFORMAT = new ThreadLocal() { + @Override + protected DateFormat initialValue() { + return new SimpleDateFormat(TIME_FORMAT); + } + }; + + public static final ThreadLocal THREAD_LOCAL_TIMESTAMPFORMAT = new ThreadLocal() { + @Override + protected DateFormat initialValue() { + return new SimpleDateFormat(TIMESTAMP_FORMAT); + } + }; + private final static String DEFAULT_DATABASE = "any"; private static Map> tableResources = Collections.synchronizedMap(new HashMap>()); @@ -71,7 +101,9 @@ public boolean jdbcCompliant() { @Override public boolean acceptsURL(String url) throws SQLException { - return true; + return + url.equals("any") || // used by JUnit test cases + url.toLowerCase().startsWith("jdbc::mock::"); } @Override @@ -93,6 +125,33 @@ public Logger getParentLogger() throws SQLFeatureNotSupportedException { return null; } + /** + * Used for parsing CSV + * + * @param format {@link SimpleDataFormat} pattern + */ + public static void setDateFormat(String format) { + THREAD_LOCAL_DATEFORMAT.set(new SimpleDateFormat(format)); + } + + /** + * Used for parsing CSV + * + * @param format {@link SimpleDataFormat} pattern + */ + public static void setTimeFormat(String format) { + THREAD_LOCAL_TIMEFORMAT.set(new SimpleDateFormat(format)); + } + + /** + * Used for parsing CSV + * + * @param format {@link SimpleDataFormat} pattern + */ + public static void setTimestampFormat(String format) { + THREAD_LOCAL_TIMESTAMPFORMAT.set(new SimpleDateFormat(format)); + } + /** * Parse jdbc url to database file path * diff --git a/src/main/java/com/googlecode/dummyjdbc/resultset/impl/CSVResultSet.java b/src/main/java/com/googlecode/dummyjdbc/resultset/impl/CSVResultSet.java index cce030c..f52129c 100644 --- a/src/main/java/com/googlecode/dummyjdbc/resultset/impl/CSVResultSet.java +++ b/src/main/java/com/googlecode/dummyjdbc/resultset/impl/CSVResultSet.java @@ -4,6 +4,8 @@ import java.sql.Date; import java.sql.ResultSetMetaData; import java.sql.SQLException; +import java.sql.Time; +import java.sql.Timestamp; import java.text.DateFormat; import java.text.MessageFormat; import java.text.ParseException; @@ -12,6 +14,7 @@ import java.util.Iterator; import java.util.LinkedHashMap; +import com.googlecode.dummyjdbc.DummyJdbcDriver; import com.googlecode.dummyjdbc.resultset.DummyResultSet; import com.googlecode.dummyjdbc.resultset.DummyResultSetMetaData; @@ -22,17 +25,7 @@ */ public class CSVResultSet extends DummyResultSet { - /** - * The date format for parsing a date from a CSV file. - */ - private static final String DATE_FORMAT = "dd-MMM-yy"; - private static final ThreadLocal THREAD_LOCAL_DATEFORMAT = new ThreadLocal() { - @Override - protected DateFormat initialValue() { - return new SimpleDateFormat(DATE_FORMAT); - } - }; /** Table schema */ private DummyResultSetMetaData metaData; @@ -156,9 +149,37 @@ public Date getDate(String columnLabel) throws SQLException { return parseDate(string); } + + @Override + public Time getTime(int columnIndex) throws SQLException { + String string = getValueForColumnIndex(columnIndex, Time.class); + + return parseTime(string); + } + + @Override + public Time getTime(String columnLabel) throws SQLException { + String string = getValueForColumnLabel(columnLabel, Time.class); + + return parseTime(string); + } + + @Override + public Timestamp getTimestamp(int columnIndex) throws SQLException { + String string = getValueForColumnIndex(columnIndex, Date.class); + + return parseTimestamp(string); + } + + @Override + public Timestamp getTimestamp(String columnLabel) throws SQLException { + String string = getValueForColumnLabel(columnLabel, Timestamp.class); + + return parseTimestamp(string); + } private Date parseDate(String string) throws SQLException { - DateFormat sdf = THREAD_LOCAL_DATEFORMAT.get(); + DateFormat sdf = DummyJdbcDriver.THREAD_LOCAL_DATEFORMAT.get(); Date date = null; try { java.util.Date utilDate = sdf.parse(string); @@ -166,7 +187,37 @@ private Date parseDate(String string) throws SQLException { } catch (ParseException e) { String message = MessageFormat.format("Could not parse date: ''{0}'' using format ''{1}''", string, - DATE_FORMAT); + sdf.toString()); + throw new SQLException(message, e); + } + return date; + } + + private Time parseTime(String string) throws SQLException { + DateFormat sdf = DummyJdbcDriver.THREAD_LOCAL_TIMEFORMAT.get(); + Time date = null; + try { + java.util.Date utilDate = sdf.parse(string); + date = new Time(utilDate.getTime()); + + } catch (ParseException e) { + String message = MessageFormat.format("Could not parse date: ''{0}'' using format ''{1}''", string, + sdf.toString()); + throw new SQLException(message, e); + } + return date; + } + + private Timestamp parseTimestamp(String string) throws SQLException { + DateFormat sdf = DummyJdbcDriver.THREAD_LOCAL_TIMESTAMPFORMAT.get(); + Timestamp date = null; + try { + java.util.Date utilDate = sdf.parse(string); + date = new Timestamp(utilDate.getTime()); + + } catch (ParseException e) { + String message = MessageFormat.format("Could not parse date: ''{0}'' using format ''{1}''", string, + sdf.toString()); throw new SQLException(message, e); } return date; diff --git a/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatement.java b/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatement.java index c74ebee..fb4ac8f 100644 --- a/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatement.java +++ b/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatement.java @@ -1,9 +1,15 @@ package com.googlecode.dummyjdbc.statement.impl; import java.io.File; +import java.math.BigDecimal; +import java.sql.Date; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Time; +import java.sql.Timestamp; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import com.googlecode.dummyjdbc.statement.PreparedStatementAdapter; @@ -14,6 +20,22 @@ */ public class CsvPreparedStatement extends PreparedStatementAdapter { + private static final Pattern INSERT_INTO_PATTERN = Pattern.compile("(?:--[^\\n]*)?\\s*insert\\s*into\\s*([a-zA-Z]*)\\s*\\(.*", Pattern.CASE_INSENSITIVE|Pattern.MULTILINE); + + private static final Pattern UPDATE_TABLE_PATTERN = Pattern.compile("(?:--[^\\\\n]*)?\\s*update\\s*([a-zA-Z]*)\\s*", Pattern.CASE_INSENSITIVE|Pattern.MULTILINE); + + static final int MAX_PARAMS = 500; + + /** + * Params received during the insert/update operation + */ + Object[] params = new Object[MAX_PARAMS]; + + /** + * Target table for insert/update operations + */ + private String targetTable4Updates = null; + private final CsvStatement statement; private final String sql; @@ -31,6 +53,120 @@ public CsvPreparedStatement(Map tableResources, String sql) { this.sql = sql; } + + /** + * Always reply that 1 row was affected (most common case) if we can identify the target table name + * otherwise return 0 + */ + @Override + public int executeUpdate(String sql) throws SQLException { + + // Try to check for a special heading comment within SQL + Matcher commentMatcher = CsvStatement.COMMENT_HEADLINE_PATTERN.matcher(sql); + if (commentMatcher.matches()) { + targetTable4Updates = commentMatcher.group(1); + InMemoryCSV.register( targetTable4Updates, buildParamsString() ); + return 1; + } + + // Try to interpret SQL as a SELECT on a table + Matcher insertMatcher = INSERT_INTO_PATTERN.matcher(sql); + if (insertMatcher.matches()) { + targetTable4Updates = insertMatcher.group(1); + InMemoryCSV.register( targetTable4Updates, buildParamsString() ); + return 1; + } + + // Try to interpret SQL as call of a stored procedure + Matcher updateMatcher = UPDATE_TABLE_PATTERN.matcher(sql); + if (updateMatcher.matches()) { + targetTable4Updates = updateMatcher.group(1); + InMemoryCSV.register( targetTable4Updates, buildParamsString() ); + return 1; + } + + return 0; + } + + /** + * build a string representing the objects which have been received + * @return + */ + private String buildParamsString() { + // 1: build the string (space separated) + StringBuilder s = new StringBuilder(); + for (int i = 0; i < params.length; i++) { + s.append(params[i]).append(' '); + } + + // 2: trim and add commas between parameters + String res = s.toString().trim(); + res = res.replace(' ', ','); + + return res; + } + + @Override + public void setObject(int parameterIndex, Object x) throws SQLException { + params[parameterIndex]=x; + } + + @Override + public void setString(int parameterIndex, String x) throws SQLException { + params[parameterIndex]=x; + } + + @Override + public void setInt(int parameterIndex, int x) throws SQLException { + params[parameterIndex]=x; + } + + @Override + public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { + params[parameterIndex]=x; + } + + @Override + public void setDouble(int parameterIndex, double x) throws SQLException { + params[parameterIndex]=x; + } + + @Override + public void setTime(int parameterIndex, Time x) throws SQLException { + params[parameterIndex]=x; + } + + @Override + public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { + params[parameterIndex]=x; + } + + @Override + public void setDate(int parameterIndex, Date x) throws SQLException { + params[parameterIndex]=x; + } + + @Override + public int executeUpdate() throws SQLException { + return executeUpdate(sql); + } + + @Override + public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { + return executeUpdate(sql); + } + + @Override + public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { + return executeUpdate(sql); + } + + @Override + public int executeUpdate(String sql, String[] columnNames) throws SQLException { + return executeUpdate(sql); + } + + @Override public ResultSet executeQuery() throws SQLException { return (currentResultSet = statement.executeQuery(sql)); @@ -43,7 +179,10 @@ public ResultSet executeQuery(String sql) throws SQLException { @Override public boolean execute() throws SQLException { + // try to generate output row currentResultSet = statement.executeQuery(sql); + // try up update (generate params) + executeUpdate(sql); return true; } diff --git a/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvStatement.java b/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvStatement.java index 10beef7..c1d82b6 100644 --- a/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvStatement.java +++ b/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvStatement.java @@ -1,11 +1,13 @@ package com.googlecode.dummyjdbc.statement.impl; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; import java.net.URISyntaxException; import java.net.URL; import java.security.CodeSource; @@ -22,12 +24,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import au.com.bytecode.opencsv.CSVReader; - import com.googlecode.dummyjdbc.resultset.DummyResultSet; +import com.googlecode.dummyjdbc.resultset.DummyResultSetMetaData; import com.googlecode.dummyjdbc.resultset.impl.CSVResultSet; import com.googlecode.dummyjdbc.statement.StatementAdapter; -import com.googlecode.dummyjdbc.resultset.DummyResultSetMetaData; + +import au.com.bytecode.opencsv.CSVReader; /** * This class does the actual work of the Generic... classes. It tries to open a CSV file for the table name in the @@ -39,6 +41,11 @@ public final class CsvStatement extends StatementAdapter { private static final Logger LOGGER = LoggerFactory.getLogger(CsvStatement.class); + /** + * Pattern used to recognize explicitly declared table names inside an heading comment + */ + static final Pattern COMMENT_HEADLINE_PATTERN = Pattern.compile("\\s*--\\s*TESTCASE:\\s*(.*)\\n.*", Pattern.CASE_INSENSITIVE); + /** Pattern to get table name from an SQL statement. */ private static final Pattern TABLENAME_PATTERN = Pattern.compile(".*from (\\S*)\\s?.*", Pattern.CASE_INSENSITIVE); @@ -59,10 +66,17 @@ public final class CsvStatement extends StatementAdapter { public CsvStatement(Map tableResources) { this.tableResources = tableResources; } - + @Override public ResultSet executeQuery(String sql) throws SQLException { + // Try to check for a special heading comment within SQL + Matcher commentMatcher = COMMENT_HEADLINE_PATTERN.matcher(sql); + if (commentMatcher.matches()) { + String tableName = commentMatcher.group(1); + return createResultSet(tableName); + } + // Try to interpret SQL as a SELECT on a table Matcher tableMatcher = TABLENAME_PATTERN.matcher(sql); if (tableMatcher.matches()) { @@ -89,7 +103,7 @@ public ResultSet executeQuery(String sql) throws SQLException { private ResultSet createResultSet(String tableName) { // Does a text file for the dummy table exist? File resource = tableResources.get(tableName.toLowerCase()); - if (resource == null) { + if (resource == null && InMemoryCSV.get(tableName) == null) { // Try to load a file from the ./tables/ directory CodeSource src = CsvStatement.class.getProtectionDomain().getCodeSource(); @@ -108,12 +122,19 @@ private ResultSet createResultSet(String tableName) { } } - FileInputStream dummyTableDataStream = null; + InputStream dummyTableDataStream = null; try { - dummyTableDataStream = new FileInputStream(resource); + if (resource==null) { + String is = InMemoryCSV.get(tableName); + dummyTableDataStream = new ByteArrayInputStream(is.getBytes("ISO-8859-1")); + } else { + dummyTableDataStream = new FileInputStream(resource); + } return createGenericResultSet(tableName, dummyTableDataStream); } catch (FileNotFoundException e) { LOGGER.info("No table definition found for '{}', using DummyResultSet.", tableName); + } catch (UnsupportedEncodingException e) { + LOGGER.error(e.getMessage(),e); } finally { if (dummyTableDataStream != null) { try { diff --git a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java b/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java index e937762..467f172 100644 --- a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java +++ b/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java @@ -1,6 +1,8 @@ package com.googlecode.dummyjdbc.statement.impl; +import java.io.ByteArrayInputStream; import java.io.File; +import java.io.UnsupportedEncodingException; import java.net.URISyntaxException; import java.sql.Connection; import java.sql.DriverManager; @@ -69,4 +71,76 @@ public void testGetInvalidColumnindex() throws SQLException { Assert.fail("Expected exception not thrown"); } + + @Test + public void testInMemoryCSVFromString() throws ClassNotFoundException, URISyntaxException, SQLException { + Class.forName(DummyJdbcDriver.class.getCanonicalName()); + + InMemoryCSV.register("TEST1", + "\n"+ + "name, age\n"+ + "John, 20"+ + "\n" + ); + + Connection connection = DriverManager.getConnection("any"); + PreparedStatement statement = connection.prepareStatement( + "-- TESTCASE:test1\n"+ + "SELECT * FROM test_table"); + + Assert.assertTrue(statement instanceof CsvPreparedStatement); + resultSet = statement.executeQuery(); + + Assert.assertTrue(resultSet.next()); + Assert.assertEquals("John", resultSet.getString(1)); + Assert.assertEquals(20, resultSet.getInt(2)); + Assert.assertEquals("John", resultSet.getString("name")); + Assert.assertEquals(20, resultSet.getInt("age")); + } + + @Test + public void testInMemoryCSVFromInputStream() throws ClassNotFoundException, URISyntaxException, SQLException, UnsupportedEncodingException { + Class.forName(DummyJdbcDriver.class.getCanonicalName()); + + InMemoryCSV.register("TEST1", + new ByteArrayInputStream( + ("name, age\n"+ + "John, 20").getBytes("ISO-8859-1") + ) + ); + + Connection connection = DriverManager.getConnection("any"); + PreparedStatement statement = connection.prepareStatement( + "-- TESTCASE:test1\n"+ + "SELECT * FROM test_table"); + + Assert.assertTrue(statement instanceof CsvPreparedStatement); + resultSet = statement.executeQuery(); + + Assert.assertTrue(resultSet.next()); + Assert.assertEquals("John", resultSet.getString(1)); + Assert.assertEquals(20, resultSet.getInt(2)); + Assert.assertEquals("John", resultSet.getString("name")); + Assert.assertEquals(20, resultSet.getInt("age")); + } + + @Test + public void testInsertWithInMemoryCSVFromInputStream() throws ClassNotFoundException, URISyntaxException, SQLException, UnsupportedEncodingException { + Class.forName(DummyJdbcDriver.class.getCanonicalName()); + + InMemoryCSV.register("TEST1", + new ByteArrayInputStream( + ("name, age\n"+ + "John, 20").getBytes("ISO-8859-1") + ) + ); + + Connection connection = DriverManager.getConnection("any"); + PreparedStatement statement = connection.prepareStatement( + "INSERT INTO Target(nome,cognome)" + + "VALUES (?, ?)"); + + Assert.assertTrue(statement instanceof CsvPreparedStatement); + int rows = statement.executeUpdate(); + } } From 469dfcebc960d7c552f260d7fba11ec61de23a2a Mon Sep 17 00:00:00 2001 From: Simone Avogadro Date: Sat, 31 Mar 2018 17:18:23 +0200 Subject: [PATCH 04/29] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7de6447..d63540b 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ The library can either return dummy values, or values defined by you in a CSV fi For more details please see the [Wiki](https://github.com/kaiwinter/dummyjdbc/wiki) -## dummyjdbc at Maven Central +## dummyjdbc at Maven Central (OLD: must redefine this section or merge into original repository) ```xml com.googlecode.dummyjdbc From 33acd397f46fa341d9ed865c4af8ac1366029729 Mon Sep 17 00:00:00 2001 From: simoneavogadro Date: Fri, 6 Apr 2018 15:19:45 +0200 Subject: [PATCH 05/29] support for table names plus parameters --- .../googlecode/dummyjdbc/DummyJdbcDriver.java | 34 ++++++++ .../statement/PreparedStatementAdapter.java | 1 + .../statement/impl/CsvPreparedStatement.java | 85 ++++++++++++------- .../statement/impl/CsvStatement.java | 48 +++++++++-- .../dummyjdbc/statement/impl/InMemoryCSV.java | 45 +++------- .../impl/CsvGenericStatementTest.java | 13 +++ .../impl/CsvPreparedStatementTest.java | 63 +++++++++++++- .../statement/impl/CsvStatementTest.java | 2 + 8 files changed, 212 insertions(+), 79 deletions(-) diff --git a/src/main/java/com/googlecode/dummyjdbc/DummyJdbcDriver.java b/src/main/java/com/googlecode/dummyjdbc/DummyJdbcDriver.java index 5ab6931..8275b09 100644 --- a/src/main/java/com/googlecode/dummyjdbc/DummyJdbcDriver.java +++ b/src/main/java/com/googlecode/dummyjdbc/DummyJdbcDriver.java @@ -4,6 +4,7 @@ import com.googlecode.dummyjdbc.utils.StringUtils; import java.io.File; import java.io.FileFilter; +import java.io.InputStream; import java.net.URL; import java.sql.Connection; import java.sql.Driver; @@ -17,6 +18,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Properties; +import java.util.Scanner; import java.util.logging.Logger; import com.googlecode.dummyjdbc.connection.impl.DummyConnection; @@ -35,6 +37,12 @@ public final class DummyJdbcDriver implements Driver { private static final String TIME_FORMAT = "HH:mm"; private static final String TIMESTAMP_FORMAT = "yyyyMMdd HHmmss.SSS"; + /** + * CSV files stored into memory + */ + public static Map inMemoryTableResources = new HashMap(); + + public static final ThreadLocal THREAD_LOCAL_DATEFORMAT = new ThreadLocal() { @Override protected DateFormat initialValue() { @@ -84,6 +92,7 @@ public static void addTableResource(String tablename, File csvFile) { tableResources.put(DEFAULT_DATABASE, databaseMap); } + @Override public int getMajorVersion() { return 1; @@ -223,4 +232,29 @@ public boolean accept(File pathname) { } + public static String getInMemoryTableResource(String testID) { + return inMemoryTableResources.get(testID.toLowerCase().trim()); + } + + + public static void clearInMemoryTableResources() { + inMemoryTableResources.clear(); + } + + + public static void addInMemoryTableResource(String testID, String value) { + inMemoryTableResources.put(testID.toLowerCase().trim(), value.trim()); + } + + + @SuppressWarnings("resource") + public static void addInMemoryTableResource(String testID, InputStream valueStream) { + // search for "end of stream" => read all the stream into the string ! + Scanner s = new Scanner(valueStream).useDelimiter("\\A"); + String value = s.hasNext() ? s.next() : ""; + s.close(); + DummyJdbcDriver.addInMemoryTableResource(testID,value); + } + + } diff --git a/src/main/java/com/googlecode/dummyjdbc/statement/PreparedStatementAdapter.java b/src/main/java/com/googlecode/dummyjdbc/statement/PreparedStatementAdapter.java index 666c13f..e6181eb 100644 --- a/src/main/java/com/googlecode/dummyjdbc/statement/PreparedStatementAdapter.java +++ b/src/main/java/com/googlecode/dummyjdbc/statement/PreparedStatementAdapter.java @@ -19,6 +19,7 @@ import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.SQLXML; +import java.sql.Statement; import java.sql.Time; import java.sql.Timestamp; import java.util.Calendar; diff --git a/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatement.java b/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatement.java index fb4ac8f..7394324 100644 --- a/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatement.java +++ b/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatement.java @@ -11,6 +11,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import com.googlecode.dummyjdbc.DummyJdbcDriver; import com.googlecode.dummyjdbc.statement.PreparedStatementAdapter; /** @@ -24,6 +25,11 @@ public class CsvPreparedStatement extends PreparedStatementAdapter { private static final Pattern UPDATE_TABLE_PATTERN = Pattern.compile("(?:--[^\\\\n]*)?\\s*update\\s*([a-zA-Z]*)\\s*", Pattern.CASE_INSENSITIVE|Pattern.MULTILINE); + /** + * Suffix used for storing the parameters last seen when running a query + */ + public static final String PARAMS_SUFFIX = "_PARAMS"; + static final int MAX_PARAMS = 500; /** @@ -61,31 +67,39 @@ public CsvPreparedStatement(Map tableResources, String sql) { @Override public int executeUpdate(String sql) throws SQLException { - // Try to check for a special heading comment within SQL - Matcher commentMatcher = CsvStatement.COMMENT_HEADLINE_PATTERN.matcher(sql); - if (commentMatcher.matches()) { - targetTable4Updates = commentMatcher.group(1); - InMemoryCSV.register( targetTable4Updates, buildParamsString() ); - return 1; - } + targetTable4Updates = null; + try { - // Try to interpret SQL as a SELECT on a table - Matcher insertMatcher = INSERT_INTO_PATTERN.matcher(sql); - if (insertMatcher.matches()) { - targetTable4Updates = insertMatcher.group(1); - InMemoryCSV.register( targetTable4Updates, buildParamsString() ); - return 1; - } - - // Try to interpret SQL as call of a stored procedure - Matcher updateMatcher = UPDATE_TABLE_PATTERN.matcher(sql); - if (updateMatcher.matches()) { - targetTable4Updates = updateMatcher.group(1); - InMemoryCSV.register( targetTable4Updates, buildParamsString() ); - return 1; + // Try to check for a special heading comment within SQL + Matcher commentMatcher = CsvStatement.COMMENT_HEADLINE_PATTERN.matcher(sql); + if (commentMatcher.matches()) { + targetTable4Updates = commentMatcher.group(1); + return 1; + } + + // Try to interpret SQL as a SELECT on a table + Matcher insertMatcher = INSERT_INTO_PATTERN.matcher(sql); + if (insertMatcher.matches()) { + targetTable4Updates = insertMatcher.group(1); + return 1; + } + + // Try to interpret SQL as call of a stored procedure + Matcher updateMatcher = UPDATE_TABLE_PATTERN.matcher(sql); + if (updateMatcher.matches()) { + targetTable4Updates = updateMatcher.group(1); + return 1; + } + + return 0; + + } finally { + if (targetTable4Updates!=null) + DummyJdbcDriver.addInMemoryTableResource( targetTable4Updates+PARAMS_SUFFIX, buildParamsString() ); + + params = new Object[MAX_PARAMS]; } - return 0; } /** @@ -96,7 +110,9 @@ private String buildParamsString() { // 1: build the string (space separated) StringBuilder s = new StringBuilder(); for (int i = 0; i < params.length; i++) { - s.append(params[i]).append(' '); + if (params[i]!=null) + s.append(params[i]); + s.append(" "); } // 2: trim and add commas between parameters @@ -169,27 +185,32 @@ public int executeUpdate(String sql, String[] columnNames) throws SQLException { @Override public ResultSet executeQuery() throws SQLException { - return (currentResultSet = statement.executeQuery(sql)); + execute(sql); + return currentResultSet; } @Override public ResultSet executeQuery(String sql) throws SQLException { - return (currentResultSet = statement.executeQuery(sql)); + execute(sql); + return currentResultSet; } @Override public boolean execute() throws SQLException { - // try to generate output row - currentResultSet = statement.executeQuery(sql); - // try up update (generate params) - executeUpdate(sql); - return true; + return execute(sql); } @Override public boolean execute(String sql) throws SQLException { - currentResultSet = statement.executeQuery(sql); - return true; + try { + statement.paramsString = buildParamsString(); + currentResultSet = statement.executeQuery(sql); + // try up update (generate params) + executeUpdate(sql); + return true; + } finally { + statement.paramsString = null; + } } @Override diff --git a/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvStatement.java b/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvStatement.java index c1d82b6..ec422e3 100644 --- a/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvStatement.java +++ b/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvStatement.java @@ -24,6 +24,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.googlecode.dummyjdbc.DummyJdbcDriver; import com.googlecode.dummyjdbc.resultset.DummyResultSet; import com.googlecode.dummyjdbc.resultset.DummyResultSetMetaData; import com.googlecode.dummyjdbc.resultset.impl.CSVResultSet; @@ -44,19 +45,24 @@ public final class CsvStatement extends StatementAdapter { /** * Pattern used to recognize explicitly declared table names inside an heading comment */ - static final Pattern COMMENT_HEADLINE_PATTERN = Pattern.compile("\\s*--\\s*TESTCASE:\\s*(.*)\\n.*", Pattern.CASE_INSENSITIVE); + static final Pattern COMMENT_HEADLINE_PATTERN = Pattern.compile("\\s*--\\s*TESTCASE:\\s*(.*)\\n.*", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); /** Pattern to get table name from an SQL statement. */ - private static final Pattern TABLENAME_PATTERN = Pattern.compile(".*from (\\S*)\\s?.*", Pattern.CASE_INSENSITIVE); + private static final Pattern TABLENAME_PATTERN = Pattern.compile(".*from\\s*(\\S*)\\s?.*", Pattern.CASE_INSENSITIVE | Pattern.DOTALL ); /** Pattern to get the name of a stored procedure from an SQL statement. */ - private static final Pattern STORED_PROCEDURE_PATTERN = Pattern.compile(".*(EXEC|EXECUTE) (\\S*)\\s?.*", - Pattern.CASE_INSENSITIVE); + private static final Pattern STORED_PROCEDURE_PATTERN = Pattern.compile(".*(EXEC|EXECUTE) (\\S*)\\s?.*", Pattern.CASE_INSENSITIVE); private static final Pattern PURE_SELECT_PATTERN = Pattern.compile("select .*", Pattern.CASE_INSENSITIVE); private final Map tableResources; + /** + * used to describe the "current" params. + * Always null when invoked from {@link CsvStatement} and may hold values when used from {@link CsvPreparedStatement} + */ + String paramsString = null; + /** * Constructs a new {@link CsvStatement}. * @@ -99,11 +105,38 @@ public ResultSet executeQuery(String sql) throws SQLException { return new DummyResultSet(); } + + static String matchTablename(String sql) { + Matcher tableMatcher = TABLENAME_PATTERN.matcher(sql); + if (tableMatcher.matches()) { + return tableMatcher.group(1); + } else { + return null; + } + } private ResultSet createResultSet(String tableName) { + InputStream inMemoryDataStream = null; + String inMemoryCSV = null; + + // search for "tablename?param1,param2" etc... + if (paramsString!=null) { + inMemoryCSV = DummyJdbcDriver.getInMemoryTableResource(tableName+"?"+paramsString); + } // then search just for "tablename" + if (inMemoryCSV==null) { + inMemoryCSV = DummyJdbcDriver.getInMemoryTableResource(tableName); + } // if any in memory CSV is found convert to InputStream + if (inMemoryCSV!=null) { + try { + inMemoryDataStream = new ByteArrayInputStream(inMemoryCSV.getBytes("ISO-8859-1")); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + // Does a text file for the dummy table exist? File resource = tableResources.get(tableName.toLowerCase()); - if (resource == null && InMemoryCSV.get(tableName) == null) { + if (resource == null && inMemoryDataStream == null) { // Try to load a file from the ./tables/ directory CodeSource src = CsvStatement.class.getProtectionDomain().getCodeSource(); @@ -125,16 +158,13 @@ private ResultSet createResultSet(String tableName) { InputStream dummyTableDataStream = null; try { if (resource==null) { - String is = InMemoryCSV.get(tableName); - dummyTableDataStream = new ByteArrayInputStream(is.getBytes("ISO-8859-1")); + dummyTableDataStream = inMemoryDataStream; // might be null => no inMemoryCSV } else { dummyTableDataStream = new FileInputStream(resource); } return createGenericResultSet(tableName, dummyTableDataStream); } catch (FileNotFoundException e) { LOGGER.info("No table definition found for '{}', using DummyResultSet.", tableName); - } catch (UnsupportedEncodingException e) { - LOGGER.error(e.getMessage(),e); } finally { if (dummyTableDataStream != null) { try { diff --git a/src/main/java/com/googlecode/dummyjdbc/statement/impl/InMemoryCSV.java b/src/main/java/com/googlecode/dummyjdbc/statement/impl/InMemoryCSV.java index b7e204b..2c98873 100644 --- a/src/main/java/com/googlecode/dummyjdbc/statement/impl/InMemoryCSV.java +++ b/src/main/java/com/googlecode/dummyjdbc/statement/impl/InMemoryCSV.java @@ -1,35 +1,10 @@ -package com.googlecode.dummyjdbc.statement.impl; - -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; -import java.util.Scanner; - -public class InMemoryCSV { - - /** - * - */ - static Map values = new HashMap(); - - static void register(String testID, String value) { - values.put(testID.toLowerCase().trim(), value.trim()); - } - - @SuppressWarnings("resource") - static void register(String testID, InputStream valueStream) { - // search for "end of stream" => read all the stream into the string ! - Scanner s = new Scanner(valueStream).useDelimiter("\\A"); - String value = s.hasNext() ? s.next() : ""; - s.close(); - register(testID,value); - } - - static void clear() { - values.clear(); - } - - static String get(String testID) { - return values.get(testID.toLowerCase().trim()); - } -} +package com.googlecode.dummyjdbc.statement.impl; + +/** + * Removed + * + * @author Simone + * + */ +public class InMemoryCSV { +} diff --git a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvGenericStatementTest.java b/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvGenericStatementTest.java index 8954110..f9ca7b1 100644 --- a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvGenericStatementTest.java +++ b/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvGenericStatementTest.java @@ -69,4 +69,17 @@ public void testGetInvalidColumnindex() throws SQLException { Assert.fail("Expected exception not thrown"); } + + + @Test + public void testMatchTablename() { + String query = "SELECT *\n" + + "FROM TEST1\n" + + "WHERE age= ? AND other = ?"; + Assert.assertEquals( + "TEST1", + CsvStatement.matchTablename(query) + ); + } + } diff --git a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java b/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java index 467f172..e461210 100644 --- a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java +++ b/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java @@ -9,6 +9,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Statement; import org.junit.Assert; import org.junit.Before; @@ -76,7 +77,7 @@ public void testGetInvalidColumnindex() throws SQLException { public void testInMemoryCSVFromString() throws ClassNotFoundException, URISyntaxException, SQLException { Class.forName(DummyJdbcDriver.class.getCanonicalName()); - InMemoryCSV.register("TEST1", + DummyJdbcDriver.addInMemoryTableResource("TEST1", "\n"+ "name, age\n"+ "John, 20"+ @@ -102,7 +103,7 @@ public void testInMemoryCSVFromString() throws ClassNotFoundException, URISyntax public void testInMemoryCSVFromInputStream() throws ClassNotFoundException, URISyntaxException, SQLException, UnsupportedEncodingException { Class.forName(DummyJdbcDriver.class.getCanonicalName()); - InMemoryCSV.register("TEST1", + DummyJdbcDriver.addInMemoryTableResource("TEST1", new ByteArrayInputStream( ("name, age\n"+ "John, 20").getBytes("ISO-8859-1") @@ -128,7 +129,7 @@ public void testInMemoryCSVFromInputStream() throws ClassNotFoundException, URIS public void testInsertWithInMemoryCSVFromInputStream() throws ClassNotFoundException, URISyntaxException, SQLException, UnsupportedEncodingException { Class.forName(DummyJdbcDriver.class.getCanonicalName()); - InMemoryCSV.register("TEST1", + DummyJdbcDriver.addInMemoryTableResource("TEST1", new ByteArrayInputStream( ("name, age\n"+ "John, 20").getBytes("ISO-8859-1") @@ -143,4 +144,60 @@ public void testInsertWithInMemoryCSVFromInputStream() throws ClassNotFoundExcep Assert.assertTrue(statement instanceof CsvPreparedStatement); int rows = statement.executeUpdate(); } + + @Test + public void testInsertWithInMemoryCSVFromInputStreamWithParameters() throws ClassNotFoundException, URISyntaxException, SQLException, UnsupportedEncodingException { + Class.forName(DummyJdbcDriver.class.getCanonicalName()); + + DummyJdbcDriver.addInMemoryTableResource("TEST1?20,hello", + new ByteArrayInputStream( + ("name, age\n"+ + "John, 20").getBytes("ISO-8859-1") + ) + ); + + Connection connection = DriverManager.getConnection("any"); + PreparedStatement statement = connection.prepareStatement( + "SELECT *\n" + + "FROM TEST1\n" + + "WHERE age= ? AND other = ?"); + + statement.setInt(1, 20); + statement.setString(2, "hello"); + + resultSet = statement.executeQuery(); + + Assert.assertTrue(resultSet.next()); + Assert.assertEquals("John", resultSet.getString(1)); + Assert.assertEquals(20, resultSet.getInt(2)); + Assert.assertEquals("John", resultSet.getString("name")); + Assert.assertEquals(20, resultSet.getInt("age")); + } + + @Test + public void insertSQL() throws Exception { + Class.forName(DummyJdbcDriver.class.getCanonicalName()); + + Connection connection = DriverManager.getConnection("any"); + PreparedStatement statement = connection.prepareStatement("INSERT INTO test (a,b) VALUES ('a','b') "); + + // 1: 0 params + Assert.assertTrue(statement instanceof CsvPreparedStatement); + boolean status = statement.execute(); + String params = DummyJdbcDriver.getInMemoryTableResource("test_PARAMS"); + Assert.assertEquals("", params); + + // 2: 2 params + statement.setString(1, "hello"); + statement.setInt(2, 30); + status = statement.execute(); + params = DummyJdbcDriver.getInMemoryTableResource("test_PARAMS"); + Assert.assertEquals("hello,30", params); + + // 3: test params reset + status = statement.execute(); + params = DummyJdbcDriver.getInMemoryTableResource("test_PARAMS"); + Assert.assertEquals("", params); + + } } diff --git a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvStatementTest.java b/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvStatementTest.java index 44d9501..acb16d0 100644 --- a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvStatementTest.java +++ b/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvStatementTest.java @@ -40,4 +40,6 @@ public void validSql() throws Exception { ResultSet resultSet = statement.executeQuery("SELECT 1"); boolean next = resultSet.next(); } + + } From 3051ff9fef749bf521fe2133112fc40e81f8f1a1 Mon Sep 17 00:00:00 2001 From: SimoneAvogadro Date: Thu, 12 Apr 2018 20:26:20 +0200 Subject: [PATCH 06/29] minor updates --- README.md | 11 +- .../impl/CsvPreparedStatementTest.java | 407 +++++++++--------- 2 files changed, 206 insertions(+), 212 deletions(-) diff --git a/README.md b/README.md index d63540b..aea186d 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,13 @@ # dummyjdbc [![CircleCI](https://circleci.com/gh/kaiwinter/dummyjdbc.svg?style=svg)](https://circleci.com/gh/kaiwinter/dummyjdbc) -This fork is intended to support: -- in-memory CSV -- capturing of input parameters - -The main purposed of this fork is to simplify the development of UnitTests with [Boomi](https://boomi.com) iPaaS. -Using this fork you can create unit tests -without- access to the Atom's filesystem. All the test data will be stored inside the UnitTest processes. - dummyjdbc answers database requests of any application with dummy data to be independent of an existing database. The library can either return dummy values, or values defined by you in a CSV file. The files are determined by the SQL query which makes this a very flexible tool. Also results of Stored Procedures can be mocked with data from CSV files. For more details please see the [Wiki](https://github.com/kaiwinter/dummyjdbc/wiki) -## dummyjdbc at Maven Central (OLD: must redefine this section or merge into original repository) +## dummyjdbc at Maven Central ```xml com.googlecode.dummyjdbc @@ -25,4 +18,4 @@ For more details please see the [Wiki](https://github.com/kaiwinter/dummyjdbc/wi ## Overview -![Design](https://raw.githubusercontent.com/wiki/kaiwinter/dummyjdbc/images/dummyjdbc-design.png) +![Design](https://raw.githubusercontent.com/wiki/kaiwinter/dummyjdbc/images/dummyjdbc-design.png) \ No newline at end of file diff --git a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java b/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java index e461210..e1ebdc3 100644 --- a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java +++ b/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java @@ -1,203 +1,204 @@ -package com.googlecode.dummyjdbc.statement.impl; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.UnsupportedEncodingException; -import java.net.URISyntaxException; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.googlecode.dummyjdbc.DummyJdbcDriver; - -public final class CsvPreparedStatementTest { - - private ResultSet resultSet; - - @Before - public void setup() throws ClassNotFoundException, SQLException, URISyntaxException { - Class.forName(DummyJdbcDriver.class.getCanonicalName()); - - DummyJdbcDriver.addTableResource("test_table", new File(CsvGenericStatementTest.class.getResource( - "test_table.csv").toURI())); - Connection connection = DriverManager.getConnection("any"); - PreparedStatement statement = connection.prepareStatement("SELECT * FROM test_table"); - - Assert.assertTrue(statement instanceof CsvPreparedStatement); - resultSet = statement.executeQuery(); - } - - @Test - public void testGetByColumnName() throws SQLException { - - Assert.assertTrue(resultSet.next()); - - Assert.assertEquals(1, resultSet.getInt("id")); - Assert.assertEquals("Germany", resultSet.getString("country_name")); - Assert.assertEquals("DE", resultSet.getString("country_iso")); - } - - @Test - public void testGetByColumnIndex() throws SQLException { - - Assert.assertTrue(resultSet.next()); - - Assert.assertEquals(1, resultSet.getInt(1)); - Assert.assertEquals("Germany", resultSet.getString(2)); - Assert.assertEquals("DE", resultSet.getString(3)); - } - - @Test(expected = SQLException.class) - public void testGetInvalidColumnName() throws SQLException { - - Assert.assertTrue(resultSet.next()); - - resultSet.getInt("undefined"); - - Assert.fail("Expected exception not thrown"); - } - - @Test(expected = SQLException.class) - public void testGetInvalidColumnindex() throws SQLException { - - Assert.assertTrue(resultSet.next()); - resultSet.getInt(17); - - Assert.fail("Expected exception not thrown"); - } - - @Test - public void testInMemoryCSVFromString() throws ClassNotFoundException, URISyntaxException, SQLException { - Class.forName(DummyJdbcDriver.class.getCanonicalName()); - - DummyJdbcDriver.addInMemoryTableResource("TEST1", - "\n"+ - "name, age\n"+ - "John, 20"+ - "\n" - ); - - Connection connection = DriverManager.getConnection("any"); - PreparedStatement statement = connection.prepareStatement( - "-- TESTCASE:test1\n"+ - "SELECT * FROM test_table"); - - Assert.assertTrue(statement instanceof CsvPreparedStatement); - resultSet = statement.executeQuery(); - - Assert.assertTrue(resultSet.next()); - Assert.assertEquals("John", resultSet.getString(1)); - Assert.assertEquals(20, resultSet.getInt(2)); - Assert.assertEquals("John", resultSet.getString("name")); - Assert.assertEquals(20, resultSet.getInt("age")); - } - - @Test - public void testInMemoryCSVFromInputStream() throws ClassNotFoundException, URISyntaxException, SQLException, UnsupportedEncodingException { - Class.forName(DummyJdbcDriver.class.getCanonicalName()); - - DummyJdbcDriver.addInMemoryTableResource("TEST1", - new ByteArrayInputStream( - ("name, age\n"+ - "John, 20").getBytes("ISO-8859-1") - ) - ); - - Connection connection = DriverManager.getConnection("any"); - PreparedStatement statement = connection.prepareStatement( - "-- TESTCASE:test1\n"+ - "SELECT * FROM test_table"); - - Assert.assertTrue(statement instanceof CsvPreparedStatement); - resultSet = statement.executeQuery(); - - Assert.assertTrue(resultSet.next()); - Assert.assertEquals("John", resultSet.getString(1)); - Assert.assertEquals(20, resultSet.getInt(2)); - Assert.assertEquals("John", resultSet.getString("name")); - Assert.assertEquals(20, resultSet.getInt("age")); - } - - @Test - public void testInsertWithInMemoryCSVFromInputStream() throws ClassNotFoundException, URISyntaxException, SQLException, UnsupportedEncodingException { - Class.forName(DummyJdbcDriver.class.getCanonicalName()); - - DummyJdbcDriver.addInMemoryTableResource("TEST1", - new ByteArrayInputStream( - ("name, age\n"+ - "John, 20").getBytes("ISO-8859-1") - ) - ); - - Connection connection = DriverManager.getConnection("any"); - PreparedStatement statement = connection.prepareStatement( - "INSERT INTO Target(nome,cognome)" - + "VALUES (?, ?)"); - - Assert.assertTrue(statement instanceof CsvPreparedStatement); - int rows = statement.executeUpdate(); - } - - @Test - public void testInsertWithInMemoryCSVFromInputStreamWithParameters() throws ClassNotFoundException, URISyntaxException, SQLException, UnsupportedEncodingException { - Class.forName(DummyJdbcDriver.class.getCanonicalName()); - - DummyJdbcDriver.addInMemoryTableResource("TEST1?20,hello", - new ByteArrayInputStream( - ("name, age\n"+ - "John, 20").getBytes("ISO-8859-1") - ) - ); - - Connection connection = DriverManager.getConnection("any"); - PreparedStatement statement = connection.prepareStatement( - "SELECT *\n" - + "FROM TEST1\n" - + "WHERE age= ? AND other = ?"); - - statement.setInt(1, 20); - statement.setString(2, "hello"); - - resultSet = statement.executeQuery(); - - Assert.assertTrue(resultSet.next()); - Assert.assertEquals("John", resultSet.getString(1)); - Assert.assertEquals(20, resultSet.getInt(2)); - Assert.assertEquals("John", resultSet.getString("name")); - Assert.assertEquals(20, resultSet.getInt("age")); - } - - @Test - public void insertSQL() throws Exception { - Class.forName(DummyJdbcDriver.class.getCanonicalName()); - - Connection connection = DriverManager.getConnection("any"); - PreparedStatement statement = connection.prepareStatement("INSERT INTO test (a,b) VALUES ('a','b') "); - - // 1: 0 params - Assert.assertTrue(statement instanceof CsvPreparedStatement); - boolean status = statement.execute(); - String params = DummyJdbcDriver.getInMemoryTableResource("test_PARAMS"); - Assert.assertEquals("", params); - - // 2: 2 params - statement.setString(1, "hello"); - statement.setInt(2, 30); - status = statement.execute(); - params = DummyJdbcDriver.getInMemoryTableResource("test_PARAMS"); - Assert.assertEquals("hello,30", params); - - // 3: test params reset - status = statement.execute(); - params = DummyJdbcDriver.getInMemoryTableResource("test_PARAMS"); - Assert.assertEquals("", params); - - } -} +package com.googlecode.dummyjdbc.statement.impl; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.googlecode.dummyjdbc.DummyJdbcDriver; + +public final class CsvPreparedStatementTest { + + private ResultSet resultSet; + + @Before + public void setup() throws ClassNotFoundException, SQLException, URISyntaxException { + Class.forName(DummyJdbcDriver.class.getCanonicalName()); + + DummyJdbcDriver.addTableResource("test_table", new File(CsvGenericStatementTest.class.getResource( + "test_table.csv").toURI())); + Connection connection = DriverManager.getConnection("any"); + PreparedStatement statement = connection.prepareStatement("SELECT * FROM test_table"); + + Assert.assertTrue(statement instanceof CsvPreparedStatement); + resultSet = statement.executeQuery(); + } + + @Test + public void testGetByColumnName() throws SQLException { + + Assert.assertTrue(resultSet.next()); + + Assert.assertEquals(1, resultSet.getInt("id")); + Assert.assertEquals("Germany", resultSet.getString("country_name")); + Assert.assertEquals("DE", resultSet.getString("country_iso")); + } + + @Test + public void testGetByColumnIndex() throws SQLException { + + Assert.assertTrue(resultSet.next()); + + Assert.assertEquals(1, resultSet.getInt(1)); + Assert.assertEquals("Germany", resultSet.getString(2)); + Assert.assertEquals("DE", resultSet.getString(3)); + } + + @Test(expected = SQLException.class) + public void testGetInvalidColumnName() throws SQLException { + + Assert.assertTrue(resultSet.next()); + + resultSet.getInt("undefined"); + + Assert.fail("Expected exception not thrown"); + } + + @Test(expected = SQLException.class) + public void testGetInvalidColumnindex() throws SQLException { + + Assert.assertTrue(resultSet.next()); + resultSet.getInt(17); + + Assert.fail("Expected exception not thrown"); + } + + @Test + public void testInMemoryCSVFromString() throws ClassNotFoundException, URISyntaxException, SQLException { + Class.forName(DummyJdbcDriver.class.getCanonicalName()); + + DummyJdbcDriver.addInMemoryTableResource("TEST1", + "\n"+ + "name, age\n"+ + "John, 20"+ + "\n" + ); + + Connection connection = DriverManager.getConnection("any"); + PreparedStatement statement = connection.prepareStatement( + "-- TESTCASE:test1\n"+ + "SELECT * FROM test_table"); + + Assert.assertTrue(statement instanceof CsvPreparedStatement); + resultSet = statement.executeQuery(); + + Assert.assertTrue(resultSet.next()); + Assert.assertEquals("John", resultSet.getString(1)); + Assert.assertEquals(20, resultSet.getInt(2)); + Assert.assertEquals("John", resultSet.getString("name")); + Assert.assertEquals(20, resultSet.getInt("age")); + } + + + @Test + public void testInMemoryCSVFromInputStream() throws ClassNotFoundException, URISyntaxException, SQLException, UnsupportedEncodingException { + Class.forName(DummyJdbcDriver.class.getCanonicalName()); + + DummyJdbcDriver.addInMemoryTableResource("TEST1", + new ByteArrayInputStream( + ("name, age\n"+ + "John, 20").getBytes("ISO-8859-1") + ) + ); + + Connection connection = DriverManager.getConnection("any"); + PreparedStatement statement = connection.prepareStatement( + "-- TESTCASE:test1\n"+ + "SELECT * FROM test_table"); + + Assert.assertTrue(statement instanceof CsvPreparedStatement); + resultSet = statement.executeQuery(); + + Assert.assertTrue(resultSet.next()); + Assert.assertEquals("John", resultSet.getString(1)); + Assert.assertEquals(20, resultSet.getInt(2)); + Assert.assertEquals("John", resultSet.getString("name")); + Assert.assertEquals(20, resultSet.getInt("age")); + } + + @Test + public void testInsertWithInMemoryCSVFromInputStream() throws ClassNotFoundException, URISyntaxException, SQLException, UnsupportedEncodingException { + Class.forName(DummyJdbcDriver.class.getCanonicalName()); + + DummyJdbcDriver.addInMemoryTableResource("TEST1", + new ByteArrayInputStream( + ("name, age\n"+ + "John, 20").getBytes("ISO-8859-1") + ) + ); + + Connection connection = DriverManager.getConnection("any"); + PreparedStatement statement = connection.prepareStatement( + "INSERT INTO Target(nome,cognome)" + + "VALUES (?, ?)"); + + Assert.assertTrue(statement instanceof CsvPreparedStatement); + int rows = statement.executeUpdate(); + } + + @Test + public void testInsertWithInMemoryCSVFromInputStreamWithParameters() throws ClassNotFoundException, URISyntaxException, SQLException, UnsupportedEncodingException { + Class.forName(DummyJdbcDriver.class.getCanonicalName()); + + DummyJdbcDriver.addInMemoryTableResource("TEST1?20,hello", + new ByteArrayInputStream( + ("name, age\n"+ + "John, 20").getBytes("ISO-8859-1") + ) + ); + + Connection connection = DriverManager.getConnection("any"); + PreparedStatement statement = connection.prepareStatement( + "SELECT *\n" + + "FROM TEST1\n" + + "WHERE age= ? AND other = ?"); + + statement.setInt(1, 20); + statement.setString(2, "hello"); + + resultSet = statement.executeQuery(); + + Assert.assertTrue(resultSet.next()); + Assert.assertEquals("John", resultSet.getString(1)); + Assert.assertEquals(20, resultSet.getInt(2)); + Assert.assertEquals("John", resultSet.getString("name")); + Assert.assertEquals(20, resultSet.getInt("age")); + } + + @Test + public void insertSQL() throws Exception { + Class.forName(DummyJdbcDriver.class.getCanonicalName()); + + Connection connection = DriverManager.getConnection("any"); + PreparedStatement statement = connection.prepareStatement("INSERT INTO test (a,b) VALUES ('a','b') "); + + // 1: 0 params + Assert.assertTrue(statement instanceof CsvPreparedStatement); + boolean status = statement.execute(); + String params = DummyJdbcDriver.getInMemoryTableResource("test_PARAMS"); + Assert.assertEquals("", params); + + // 2: 2 params + statement.setString(1, "hello"); + statement.setInt(2, 30); + status = statement.execute(); + params = DummyJdbcDriver.getInMemoryTableResource("test_PARAMS"); + Assert.assertEquals("hello,30", params); + + // 3: test params reset + status = statement.execute(); + params = DummyJdbcDriver.getInMemoryTableResource("test_PARAMS"); + Assert.assertEquals("", params); + + } +} From bf261ad2abedc2c8351f06eb7d9eafb1a504d033 Mon Sep 17 00:00:00 2001 From: Simone Avogadro Date: Thu, 12 Apr 2018 20:29:22 +0200 Subject: [PATCH 07/29] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index aea186d..25f895f 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # dummyjdbc -[![CircleCI](https://circleci.com/gh/kaiwinter/dummyjdbc.svg?style=svg)](https://circleci.com/gh/kaiwinter/dummyjdbc) +[![CircleCI](https://circleci.com/gh/SimoneAvogadro/dummyjdbc.svg?style=svg)](https://circleci.com/gh/SimoneAvogadro/dummyjdbc) dummyjdbc answers database requests of any application with dummy data to be independent of an existing database. The library can either return dummy values, or values defined by you in a CSV file. The files are determined by the SQL query which makes this a very flexible tool. Also results of Stored Procedures can be mocked with data from CSV files. -For more details please see the [Wiki](https://github.com/kaiwinter/dummyjdbc/wiki) +For more details please see the [Wiki](https://github.com/SimoneAvogadro/dummyjdbc/wiki) ## dummyjdbc at Maven Central ```xml @@ -18,4 +18,4 @@ For more details please see the [Wiki](https://github.com/kaiwinter/dummyjdbc/wi ## Overview -![Design](https://raw.githubusercontent.com/wiki/kaiwinter/dummyjdbc/images/dummyjdbc-design.png) \ No newline at end of file +![Design](https://raw.githubusercontent.com/wiki/SimoneAvogadro/dummyjdbc/images/dummyjdbc-design.png) From 6e80d92c9a08b2c889631ca7f1cb51cc4c5eaa52 Mon Sep 17 00:00:00 2001 From: Simone Avogadro Date: Thu, 12 Apr 2018 20:30:04 +0200 Subject: [PATCH 08/29] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 25f895f..15035ae 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ dummyjdbc answers database requests of any application with dummy data to be ind The library can either return dummy values, or values defined by you in a CSV file. The files are determined by the SQL query which makes this a very flexible tool. Also results of Stored Procedures can be mocked with data from CSV files. -For more details please see the [Wiki](https://github.com/SimoneAvogadro/dummyjdbc/wiki) +For more details please see the [Wiki](https://github.com/kaiwinter/dummyjdbc/wiki) ## dummyjdbc at Maven Central ```xml @@ -18,4 +18,4 @@ For more details please see the [Wiki](https://github.com/SimoneAvogadro/dummyjd ## Overview -![Design](https://raw.githubusercontent.com/wiki/SimoneAvogadro/dummyjdbc/images/dummyjdbc-design.png) +![Design](https://raw.githubusercontent.com/wiki/kaiwinter/dummyjdbc/images/dummyjdbc-design.png) From 770fdb2a5ba8272e96ef9d69b368d2e5255d9a39 Mon Sep 17 00:00:00 2001 From: Simone Avogadro Date: Thu, 12 Apr 2018 20:36:41 +0200 Subject: [PATCH 09/29] Document the new recource-matching rules --- README.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/README.md b/README.md index 15035ae..bf8de11 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,32 @@ The library can either return dummy values, or values defined by you in a CSV fi For more details please see the [Wiki](https://github.com/kaiwinter/dummyjdbc/wiki) +## Sample Usage + +## How in memory resources are selected + +### Explicit comment in SQL +InMemory resource 'name' will be inferred by using some logic + +```SQL +-- TESTCASE: Hello1 +SELECT * +FROM TableUsedEverywhere +``` +will search for resource: "Hello1" (case insensitive) + +### Table name deduction +This is derived from the original dumymjdbc design, with some added REGEX for INSERT/UPDATE queries + +```SQL +SELECT name +FROM mytable +WHERE surname='Happy' +``` +will search for resource: "mytable" (case insensitive) + + + ## dummyjdbc at Maven Central ```xml From 6b7af91914a91064bc5f9486d6b5b84311d3821e Mon Sep 17 00:00:00 2001 From: Simone Avogadro Date: Thu, 12 Apr 2018 20:41:22 +0200 Subject: [PATCH 10/29] Docmented the specialization for queryes with parameters --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index bf8de11..0fc88d0 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,23 @@ WHERE surname='Happy' ``` will search for resource: "mytable" (case insensitive) +### Parameters +In order to make possible more sophisticated test cases the driver now will try to match also parameters +So the following query: +```SQL +SELECT name +FROM mytable +WHERE surname=? AND age=? +``` +with parameters "Smith" and "34" will search for resources in the following order (always case-insensitive): +* mytable +* mytable?Smith,34 + +## Testing INSERT/DELETE queries +One key part of testing how the application interacts with the DB is to capture if it performed the right INSERT/UPDATE queries, this is not possible. + +### How to know which parameters have been used for a query +### Sample code ## dummyjdbc at Maven Central From a21e46f9288678408868fc9d06880fbae614363b Mon Sep 17 00:00:00 2001 From: Simone Avogadro Date: Thu, 12 Apr 2018 20:41:50 +0200 Subject: [PATCH 11/29] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0fc88d0..b65e3d8 100644 --- a/README.md +++ b/README.md @@ -40,8 +40,8 @@ FROM mytable WHERE surname=? AND age=? ``` with parameters "Smith" and "34" will search for resources in the following order (always case-insensitive): -* mytable -* mytable?Smith,34 +* `mytable` +* `mytable?Smith,34` ## Testing INSERT/DELETE queries One key part of testing how the application interacts with the DB is to capture if it performed the right INSERT/UPDATE queries, this is not possible. From 9bc9753965b4a323f122214bef75b166ad6fe6ba Mon Sep 17 00:00:00 2001 From: Simone Avogadro Date: Thu, 12 Apr 2018 21:35:54 +0200 Subject: [PATCH 12/29] Documentation for new 1.4.0 features --- README.md | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b65e3d8..246df1b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # dummyjdbc -[![CircleCI](https://circleci.com/gh/SimoneAvogadro/dummyjdbc.svg?style=svg)](https://circleci.com/gh/SimoneAvogadro/dummyjdbc) +[![CircleCI](https://circleci.com/gh/kaiwinter/dummyjdbc.svg?style=svg)](https://circleci.com/gh/kaiwinter/dummyjdbc) dummyjdbc answers database requests of any application with dummy data to be independent of an existing database. @@ -7,7 +7,57 @@ The library can either return dummy values, or values defined by you in a CSV fi For more details please see the [Wiki](https://github.com/kaiwinter/dummyjdbc/wiki) +## New Methods in 1.4.0 +Three new methods have been added to `com.googlecode.dummyjdbc.DummyJdbcDriver` in order to support: +* InMemory resources for resultsets +* differentiated resultsers depending on query parameters +* capturing INSERT/UPDATE parameters + +```Java +/** + * Add the CSV contained the string 'value' to the list of available resultsets + */ +public static void addInMemoryTableResource(String testID, String value); + +/** + * Add the CSV contained the InputStream 'valueStream' to the list of available resultsets + */ +public static void addInMemoryTableResource(String testID, InputStream valueStream); + +/** + * Get the current value of the resource, used mainly to examine the parameters used for INSERT/UPDATE queries + */ +public static String getInMemoryTableResource(String testID); +``` + ## Sample Usage +```java +@Test +public void testInMemoryCSVFromString() throws ClassNotFoundException, URISyntaxException, SQLException { + Class.forName(DummyJdbcDriver.class.getCanonicalName()); + + DummyJdbcDriver.addInMemoryTableResource("TEST1", + "\n"+ + "name, age\n"+ + "John, 20"+ + "\n" + ); + + Connection connection = DriverManager.getConnection("any"); + PreparedStatement statement = connection.prepareStatement( + "-- TESTCASE:test1\n"+ + "SELECT * FROM test_table"); + + Assert.assertTrue(statement instanceof CsvPreparedStatement); + resultSet = statement.executeQuery(); + + Assert.assertTrue(resultSet.next()); + Assert.assertEquals("John", resultSet.getString(1)); + Assert.assertEquals(20, resultSet.getInt(2)); + Assert.assertEquals("John", resultSet.getString("name")); + Assert.assertEquals(20, resultSet.getInt("age")); +} +``` ## How in memory resources are selected @@ -45,10 +95,27 @@ with parameters "Smith" and "34" will search for resources in the following orde ## Testing INSERT/DELETE queries One key part of testing how the application interacts with the DB is to capture if it performed the right INSERT/UPDATE queries, this is not possible. +When updating a table now the parameters are captured and stored into a String which will be accessible for testing purposes ### How to know which parameters have been used for a query +A new InMemory resource will be created with name euals to the name of the table + `_PARAMS` +E.g: when updating table `users` a new key will be added with name `users_PARAMS` + ### Sample code +```java + Class.forName(DummyJdbcDriver.class.getCanonicalName()); + + Connection connection = DriverManager.getConnection("any"); + PreparedStatement statement = connection.prepareStatement("INSERT INTO users (name,age) VALUES (?,?) "); + + statement.setString(1, "hello"); + statement.setInt(2, 30); + status = statement.execute(); + params = DummyJdbcDriver.getInMemoryTableResource("users_PARAMS"); + Assert.assertEquals("hello,30", params); +``` + ## dummyjdbc at Maven Central ```xml From e944adaac280312ec2056268234dbd5cde64cee7 Mon Sep 17 00:00:00 2001 From: Simone Avogadro Date: Thu, 12 Apr 2018 21:36:43 +0200 Subject: [PATCH 13/29] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 246df1b..29844af 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ InMemory resource 'name' will be inferred by using some logic SELECT * FROM TableUsedEverywhere ``` -will search for resource: "Hello1" (case insensitive) +will search for resource: `Hello1` (case insensitive) ### Table name deduction This is derived from the original dumymjdbc design, with some added REGEX for INSERT/UPDATE queries @@ -79,7 +79,7 @@ SELECT name FROM mytable WHERE surname='Happy' ``` -will search for resource: "mytable" (case insensitive) +will search for resource: `mytable` (case insensitive) ### Parameters In order to make possible more sophisticated test cases the driver now will try to match also parameters From 109945f6a42c0fdf0eedd0bd401b4eed592932f0 Mon Sep 17 00:00:00 2001 From: SimoneAvogadro Date: Thu, 12 Apr 2018 21:37:25 +0200 Subject: [PATCH 14/29] updated documentation and tests --- .../googlecode/dummyjdbc/DummyJdbcDriver.java | 17 +++++++++++++++++ .../impl/CsvPreparedStatementTest.java | 8 ++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/googlecode/dummyjdbc/DummyJdbcDriver.java b/src/main/java/com/googlecode/dummyjdbc/DummyJdbcDriver.java index 8275b09..618def7 100644 --- a/src/main/java/com/googlecode/dummyjdbc/DummyJdbcDriver.java +++ b/src/main/java/com/googlecode/dummyjdbc/DummyJdbcDriver.java @@ -232,6 +232,11 @@ public boolean accept(File pathname) { } + /** + * Get the current value of the resource, used mainly to examine the parameters used for INSERT/UPDATE queries + * @param testID + * @return + */ public static String getInMemoryTableResource(String testID) { return inMemoryTableResources.get(testID.toLowerCase().trim()); } @@ -242,11 +247,23 @@ public static void clearInMemoryTableResources() { } + /** + * Add the CSV contained the string 'value' to the list of available resultsets + * + * @param testID + * @param value + */ public static void addInMemoryTableResource(String testID, String value) { inMemoryTableResources.put(testID.toLowerCase().trim(), value.trim()); } + /** + * Add the CSV contained the InputStream 'valueStream' to the list of available resultsets + * + * @param testID + * @param value + */ @SuppressWarnings("resource") public static void addInMemoryTableResource(String testID, InputStream valueStream) { // search for "end of stream" => read all the stream into the string ! diff --git a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java b/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java index e1ebdc3..66c54fd 100644 --- a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java +++ b/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java @@ -180,24 +180,24 @@ public void insertSQL() throws Exception { Class.forName(DummyJdbcDriver.class.getCanonicalName()); Connection connection = DriverManager.getConnection("any"); - PreparedStatement statement = connection.prepareStatement("INSERT INTO test (a,b) VALUES ('a','b') "); + PreparedStatement statement = connection.prepareStatement("INSERT INTO users (name,age) VALUES (?,?) "); // 1: 0 params Assert.assertTrue(statement instanceof CsvPreparedStatement); boolean status = statement.execute(); - String params = DummyJdbcDriver.getInMemoryTableResource("test_PARAMS"); + String params = DummyJdbcDriver.getInMemoryTableResource("users_PARAMS"); Assert.assertEquals("", params); // 2: 2 params statement.setString(1, "hello"); statement.setInt(2, 30); status = statement.execute(); - params = DummyJdbcDriver.getInMemoryTableResource("test_PARAMS"); + params = DummyJdbcDriver.getInMemoryTableResource("users_PARAMS"); Assert.assertEquals("hello,30", params); // 3: test params reset status = statement.execute(); - params = DummyJdbcDriver.getInMemoryTableResource("test_PARAMS"); + params = DummyJdbcDriver.getInMemoryTableResource("users_PARAMS"); Assert.assertEquals("", params); } From da0d70e2143fa6d6fcc984a9b85fce76b0cce14b Mon Sep 17 00:00:00 2001 From: Simone Avogadro Date: Tue, 24 Apr 2018 11:04:46 +0200 Subject: [PATCH 15/29] Update README.md --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 29844af..cc4b1e1 100644 --- a/README.md +++ b/README.md @@ -90,15 +90,16 @@ FROM mytable WHERE surname=? AND age=? ``` with parameters "Smith" and "34" will search for resources in the following order (always case-insensitive): -* `mytable` * `mytable?Smith,34` +* `mytable` ## Testing INSERT/DELETE queries -One key part of testing how the application interacts with the DB is to capture if it performed the right INSERT/UPDATE queries, this is not possible. +One key part of testing how the application interacts with the DB is to capture if it performed the right INSERT/UPDATE queries, this is now possible. + When updating a table now the parameters are captured and stored into a String which will be accessible for testing purposes ### How to know which parameters have been used for a query -A new InMemory resource will be created with name euals to the name of the table + `_PARAMS` +A new InMemory resource will be created with name equals to the name of the table + `_PARAMS` E.g: when updating table `users` a new key will be added with name `users_PARAMS` ### Sample code From b73ab1d0a07dac880d12e670b0bf0e10bdf1d78b Mon Sep 17 00:00:00 2001 From: Simone Avogadro Date: Thu, 26 Sep 2019 09:25:17 +0200 Subject: [PATCH 16/29] Update README.md --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cc4b1e1..5075bd6 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,9 @@ E.g: when updating table `users` a new key will be added with name `users_PARAMS ``` -## dummyjdbc at Maven Central +## dummyjdbc at Maven Central [OUTDATED] + +In order to use the official 1.3 version you can use Maven ```xml com.googlecode.dummyjdbc @@ -127,6 +129,9 @@ E.g: when updating table `users` a new key will be added with name `users_PARAMS ``` +In order to use v 1.4.0 at present you must download it directly from GitHub + + ## Overview ![Design](https://raw.githubusercontent.com/wiki/kaiwinter/dummyjdbc/images/dummyjdbc-design.png) From e602b471ed324d22ef845b548a8a7251f7600d58 Mon Sep 17 00:00:00 2001 From: Simone Avogadro Date: Tue, 8 Oct 2019 17:03:41 +0200 Subject: [PATCH 17/29] Update to use CircleCI --- pom.xml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index bca481d..008947d 100644 --- a/pom.xml +++ b/pom.xml @@ -2,14 +2,14 @@ 4.0.0 com.googlecode.dummyjdbc dummyjdbc - 1.3.1-SNAPSHOT + 1.4.0 jar DummyJDBC DummyJDBC is a mock JDBC driver which can return data from CSV files - https://github.com/kaiwinter/dummyjdbc + https://github.com/SimoneAvogadro/dummyjdbc Apache 2 @@ -19,9 +19,9 @@ - https://github.com/kaiwinter/dummyjdbc - scm:git:https://github.com/kaiwinter/dummyjdbc.git - scm:git:git@github.com:kaiwinter/dummyjdbc.git + https://github.com/SimoneAvogadro/dummyjdbc + scm:git:https://github.com/SimoneAvogadro/dummyjdbc.git + scm:git:git@github.com:SimoneAvogadro/dummyjdbc.git @@ -29,11 +29,15 @@ kai Kai Winter + + simone + Simone Avogadro + GitHub Issues - https://github.com/kaiwinter/dummyjdbc/issues + https://github.com/SimoneAvogadro/dummyjdbc/issues @@ -171,4 +175,4 @@ - \ No newline at end of file + From b740acece05af0f96b9c3729c5667f935f9a33d8 Mon Sep 17 00:00:00 2001 From: Simone Avogadro Date: Tue, 8 Oct 2019 17:08:14 +0200 Subject: [PATCH 18/29] Create config.yml --- .circleci/config.yml | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..c6c06e6 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,41 @@ +# Java Maven CircleCI 2.0 configuration file +# +# Check https://circleci.com/docs/2.0/language-java/ for more details +# +version: 2 +jobs: + build: + docker: + # specify the version you desire here + - image: circleci/openjdk:8-jdk + + # Specify service dependencies here if necessary + # CircleCI maintains a library of pre-built images + # documented at https://circleci.com/docs/2.0/circleci-images/ + # - image: circleci/postgres:9.4 + + working_directory: ~/repo + + environment: + # Customize the JVM maximum heap limit + MAVEN_OPTS: -Xmx3200m + + steps: + - checkout + + # Download and cache dependencies + - restore_cache: + keys: + - v1-dependencies-{{ checksum "pom.xml" }} + # fallback to using the latest cache if no exact match is found + - v1-dependencies- + + - run: mvn dependency:go-offline + + - save_cache: + paths: + - ~/.m2 + key: v1-dependencies-{{ checksum "pom.xml" }} + + # run tests! + - run: mvn integration-test From 35044c25b73b19ae270c5e411bd241f60d7c9d79 Mon Sep 17 00:00:00 2001 From: Simone Avogadro Date: Tue, 8 Oct 2019 17:09:00 +0200 Subject: [PATCH 19/29] Update config.yml --- .circleci/config.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c6c06e6..f8dc0aa 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,4 +1,4 @@ -# Java Maven CircleCI 2.0 configuration file +# Java Gradle CircleCI 2.0 configuration file # # Check https://circleci.com/docs/2.0/language-java/ for more details # @@ -18,7 +18,8 @@ jobs: environment: # Customize the JVM maximum heap limit - MAVEN_OPTS: -Xmx3200m + # JVM_OPTS: -Xmx3200m + TERM: dumb steps: - checkout @@ -26,16 +27,16 @@ jobs: # Download and cache dependencies - restore_cache: keys: - - v1-dependencies-{{ checksum "pom.xml" }} + - v1-dependencies-{{ checksum "build.gradle" }} # fallback to using the latest cache if no exact match is found - v1-dependencies- - - run: mvn dependency:go-offline + - run: gradle dependencies - save_cache: paths: - - ~/.m2 - key: v1-dependencies-{{ checksum "pom.xml" }} + - ~/.gradle + key: v1-dependencies-{{ checksum "build.gradle" }} # run tests! - - run: mvn integration-test + - run: gradle test From f869d91cb80137c00f7748161be41562a708b2f3 Mon Sep 17 00:00:00 2001 From: Simone Avogadro Date: Tue, 8 Oct 2019 17:11:34 +0200 Subject: [PATCH 20/29] Update config.yml --- .circleci/config.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f8dc0aa..93c9e84 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,4 +1,4 @@ -# Java Gradle CircleCI 2.0 configuration file +# Java Maven CircleCI 2.0 configuration file # # Check https://circleci.com/docs/2.0/language-java/ for more details # @@ -18,8 +18,7 @@ jobs: environment: # Customize the JVM maximum heap limit - # JVM_OPTS: -Xmx3200m - TERM: dumb + # MAVEN_OPTS: -Xmx3200m steps: - checkout @@ -27,16 +26,16 @@ jobs: # Download and cache dependencies - restore_cache: keys: - - v1-dependencies-{{ checksum "build.gradle" }} + - v1-dependencies-{{ checksum "pom.xml" }} # fallback to using the latest cache if no exact match is found - v1-dependencies- - - run: gradle dependencies + - run: mvn dependency:go-offline - save_cache: paths: - - ~/.gradle - key: v1-dependencies-{{ checksum "build.gradle" }} + - ~/.m2 + key: v1-dependencies-{{ checksum "pom.xml" }} # run tests! - - run: gradle test + - run: mvn integration-test From 5759e6e9dd097c79178a210d503d19ef9855462c Mon Sep 17 00:00:00 2001 From: Simone Avogadro Date: Tue, 8 Oct 2019 17:13:32 +0200 Subject: [PATCH 21/29] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5075bd6..4f301f5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # dummyjdbc -[![CircleCI](https://circleci.com/gh/kaiwinter/dummyjdbc.svg?style=svg)](https://circleci.com/gh/kaiwinter/dummyjdbc) +[![CircleCI](https://circleci.com/gh/SimoneAvogadro/dummyjdbc.svg?style=svg)](https://circleci.com/gh/SimoneAvogadro/dummyjdbc) dummyjdbc answers database requests of any application with dummy data to be independent of an existing database. From 85ffd14b61ea14146e891eaff2d97ac6846b4ec7 Mon Sep 17 00:00:00 2001 From: simoneavogadro Date: Wed, 9 Oct 2019 14:35:44 +0200 Subject: [PATCH 22/29] Improved Statement parameters logging --- .../statement/impl/CsvPreparedStatement.java | 24 ++++++++++++++----- .../impl/CsvPreparedStatementTest.java | 13 ++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatement.java b/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatement.java index 7394324..af8b2f3 100644 --- a/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatement.java +++ b/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatement.java @@ -106,18 +106,30 @@ public int executeUpdate(String sql) throws SQLException { * build a string representing the objects which have been received * @return */ - private String buildParamsString() { + String buildParamsString() { // 1: build the string (space separated) StringBuilder s = new StringBuilder(); for (int i = 0; i < params.length; i++) { - if (params[i]!=null) - s.append(params[i]); - s.append(" "); + if (i>0) + s.append(","); + if (params[i]!=null) { + if (params[i] instanceof java.util.Date) { + if (params[i] instanceof java.sql.Date) { + s.append(DummyJdbcDriver.THREAD_LOCAL_DATEFORMAT.get().format((java.util.Date)params[i])); + } else if (params[i] instanceof java.sql.Time) { + s.append(DummyJdbcDriver.THREAD_LOCAL_TIMEFORMAT.get().format((java.util.Date)params[i])); + } else { + s.append(DummyJdbcDriver.THREAD_LOCAL_TIMESTAMPFORMAT.get().format((java.util.Date)params[i])); + } + } else { + s.append(params[i]); + } + } } - // 2: trim and add commas between parameters + // 2: trim and replace tailing commas String res = s.toString().trim(); - res = res.replace(' ', ','); + res = res.replaceAll(",*$", ""); return res; } diff --git a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java b/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java index 66c54fd..6930b34 100644 --- a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java +++ b/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java @@ -20,6 +20,7 @@ public final class CsvPreparedStatementTest { private ResultSet resultSet; + CsvPreparedStatement csvStatement; @Before public void setup() throws ClassNotFoundException, SQLException, URISyntaxException { @@ -31,6 +32,7 @@ public void setup() throws ClassNotFoundException, SQLException, URISyntaxExcept PreparedStatement statement = connection.prepareStatement("SELECT * FROM test_table"); Assert.assertTrue(statement instanceof CsvPreparedStatement); + csvStatement = (CsvPreparedStatement)statement; resultSet = statement.executeQuery(); } @@ -44,6 +46,17 @@ public void testGetByColumnName() throws SQLException { Assert.assertEquals("DE", resultSet.getString("country_iso")); } + @Test + public void testBuildParamsString() { + csvStatement.params[0]=new java.sql.Timestamp(1570623440352L); // 2019-10-09,14:17:20.352 + csvStatement.params[1]=new Integer(920); + csvStatement.params[2]="hello"; + + String res = csvStatement.buildParamsString(); + // System.out.println("RES: "+res); + Assert.assertEquals("20191009 141720.352,920,hello", res); + } + @Test public void testGetByColumnIndex() throws SQLException { From da5f8850ba4fb55fce2068c48d6c4b00c4d15d3a Mon Sep 17 00:00:00 2001 From: simoneavogadro Date: Wed, 9 Oct 2019 14:39:26 +0200 Subject: [PATCH 23/29] fixed regression --- .../dummyjdbc/statement/impl/CsvPreparedStatement.java | 4 ++-- .../dummyjdbc/statement/impl/CsvPreparedStatementTest.java | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatement.java b/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatement.java index af8b2f3..6773460 100644 --- a/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatement.java +++ b/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatement.java @@ -109,8 +109,8 @@ public int executeUpdate(String sql) throws SQLException { String buildParamsString() { // 1: build the string (space separated) StringBuilder s = new StringBuilder(); - for (int i = 0; i < params.length; i++) { - if (i>0) + for (int i = 1; i < params.length; i++) { // SQL param index starts from 1 !! + if (i>1) s.append(","); if (params[i]!=null) { if (params[i] instanceof java.util.Date) { diff --git a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java b/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java index 6930b34..2ca5619 100644 --- a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java +++ b/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java @@ -48,9 +48,9 @@ public void testGetByColumnName() throws SQLException { @Test public void testBuildParamsString() { - csvStatement.params[0]=new java.sql.Timestamp(1570623440352L); // 2019-10-09,14:17:20.352 - csvStatement.params[1]=new Integer(920); - csvStatement.params[2]="hello"; + csvStatement.params[1]=new java.sql.Timestamp(1570623440352L); // 2019-10-09,14:17:20.352 + csvStatement.params[2]=new Integer(920); + csvStatement.params[3]="hello"; String res = csvStatement.buildParamsString(); // System.out.println("RES: "+res); From d65f9767c0c5f10274f656ffbc03323a7b2b9b4b Mon Sep 17 00:00:00 2001 From: simoneavogadro Date: Wed, 9 Oct 2019 14:43:26 +0200 Subject: [PATCH 24/29] fixed timezone-dependent CircleCI regression --- .../dummyjdbc/statement/impl/CsvPreparedStatementTest.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java b/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java index 2ca5619..10134eb 100644 --- a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java +++ b/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java @@ -10,6 +10,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.TimeZone; import org.junit.Assert; import org.junit.Before; @@ -24,6 +25,8 @@ public final class CsvPreparedStatementTest { @Before public void setup() throws ClassNotFoundException, SQLException, URISyntaxException { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + Class.forName(DummyJdbcDriver.class.getCanonicalName()); DummyJdbcDriver.addTableResource("test_table", new File(CsvGenericStatementTest.class.getResource( @@ -48,13 +51,13 @@ public void testGetByColumnName() throws SQLException { @Test public void testBuildParamsString() { - csvStatement.params[1]=new java.sql.Timestamp(1570623440352L); // 2019-10-09,14:17:20.352 + csvStatement.params[1]=new java.sql.Timestamp(1570623440352L); // 2019-10-09,14:17:20.352 GMT+2 csvStatement.params[2]=new Integer(920); csvStatement.params[3]="hello"; String res = csvStatement.buildParamsString(); // System.out.println("RES: "+res); - Assert.assertEquals("20191009 141720.352,920,hello", res); + Assert.assertEquals("20191009 121720.352,920,hello", res); } @Test From d125e6c6fa3ddb235f9d5537f1e3a52b3bd1345e Mon Sep 17 00:00:00 2001 From: simoneavogadro Date: Mon, 28 Oct 2019 17:30:41 +0100 Subject: [PATCH 25/29] v1.5.0 * Rebased to com.mindmercatis in order to continue development and provide separate CirceCI integration testing * Added methods to simplify testing by just saying which result will be given at which step --- CHANGELOG.md | 14 ++++ README.md | 32 +++++++- pom.xml | 2 +- .../dummyjdbc/AspectLogger.aj | 2 +- .../dummyjdbc/DummyJdbcDriver.java | 68 +++++++++++++++-- .../connection/ConnectionAdapter.java | 2 +- .../connection/DummyDatabaseMetaData.java | 2 +- .../connection/impl/DummyConnection.java | 8 +- .../dummyjdbc/resultset/DummyResultSet.java | 2 +- .../resultset/DummyResultSetMetaData.java | 2 +- .../resultset/impl/CSVResultSet.java | 8 +- .../statement/PreparedStatementAdapter.java | 2 +- .../dummyjdbc/statement/StatementAdapter.java | 2 +- .../statement/impl/CsvPreparedStatement.java | 25 +++++-- .../statement/impl/CsvStatement.java | 75 +++++++++++-------- .../dummyjdbc/statement/impl/InMemoryCSV.java | 2 +- .../dummyjdbc/utils/FilenameUtils.java | 2 +- .../dummyjdbc/utils/StringUtils.java | 2 +- .../dummyjdbc/DummyJdbcDriverTest.java | 5 +- .../impl/CsvGenericStatementTest.java | 57 +++++++++++++- .../impl/CsvPreparedStatementTest.java | 5 +- .../statement/impl/CsvStatementTest.java | 5 +- .../statement/impl/DatatypesTest.java | 4 +- .../statement/impl/ResultSetMetaDataTest.java | 4 +- .../dummyjdbc/statement/impl/datatypes.csv | 0 .../dummyjdbc/statement/impl/metadata.csv | 0 .../dummyjdbc/statement/impl/test_table.csv | 0 src/test/resources/logback-test.xml | 2 +- 28 files changed, 252 insertions(+), 82 deletions(-) rename src/main/java/com/{googlecode => mindmercatis}/dummyjdbc/AspectLogger.aj (94%) rename src/main/java/com/{googlecode => mindmercatis}/dummyjdbc/DummyJdbcDriver.java (77%) rename src/main/java/com/{googlecode => mindmercatis}/dummyjdbc/connection/ConnectionAdapter.java (94%) rename src/main/java/com/{googlecode => mindmercatis}/dummyjdbc/connection/DummyDatabaseMetaData.java (99%) rename src/main/java/com/{googlecode => mindmercatis}/dummyjdbc/connection/impl/DummyConnection.java (90%) rename src/main/java/com/{googlecode => mindmercatis}/dummyjdbc/resultset/DummyResultSet.java (95%) rename src/main/java/com/{googlecode => mindmercatis}/dummyjdbc/resultset/DummyResultSetMetaData.java (99%) rename src/main/java/com/{googlecode => mindmercatis}/dummyjdbc/resultset/impl/CSVResultSet.java (93%) rename src/main/java/com/{googlecode => mindmercatis}/dummyjdbc/statement/PreparedStatementAdapter.java (94%) rename src/main/java/com/{googlecode => mindmercatis}/dummyjdbc/statement/StatementAdapter.java (93%) rename src/main/java/com/{googlecode => mindmercatis}/dummyjdbc/statement/impl/CsvPreparedStatement.java (88%) rename src/main/java/com/{googlecode => mindmercatis}/dummyjdbc/statement/impl/CsvStatement.java (77%) rename src/main/java/com/{googlecode => mindmercatis}/dummyjdbc/statement/impl/InMemoryCSV.java (54%) rename src/main/java/com/{googlecode => mindmercatis}/dummyjdbc/utils/FilenameUtils.java (99%) rename src/main/java/com/{googlecode => mindmercatis}/dummyjdbc/utils/StringUtils.java (92%) rename src/test/java/com/{googlecode => mindmercatis}/dummyjdbc/DummyJdbcDriverTest.java (83%) rename src/test/java/com/{googlecode => mindmercatis}/dummyjdbc/statement/impl/CsvGenericStatementTest.java (57%) rename src/test/java/com/{googlecode => mindmercatis}/dummyjdbc/statement/impl/CsvPreparedStatementTest.java (95%) rename src/test/java/com/{googlecode => mindmercatis}/dummyjdbc/statement/impl/CsvStatementTest.java (88%) rename src/test/java/com/{googlecode => mindmercatis}/dummyjdbc/statement/impl/DatatypesTest.java (96%) rename src/test/java/com/{googlecode => mindmercatis}/dummyjdbc/statement/impl/ResultSetMetaDataTest.java (94%) rename src/test/resources/com/{googlecode => mindmercatis}/dummyjdbc/statement/impl/datatypes.csv (100%) rename src/test/resources/com/{googlecode => mindmercatis}/dummyjdbc/statement/impl/metadata.csv (100%) rename src/test/resources/com/{googlecode => mindmercatis}/dummyjdbc/statement/impl/test_table.csv (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c493ef..82f0532 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,20 @@ Change Log ========== +Version 1.5.0 +---------------------------- + + * Rebased to com.mindmercatis in order to continue development and provide separate CirceCI integration testing + * Added methods to simplify testing by just saying which result will be given at which step + +Version 1.4.0 +---------------------------- + + * Support for in-memory result sets + * Support for insert/update queries + * Support for capturing query parameters for test purposes + * Support for providing different resultsets depending on the query parameters + Version 1.3.0 (2018-03-14) ---------------------------- diff --git a/README.md b/README.md index 4f301f5..4f37637 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,30 @@ The library can either return dummy values, or values defined by you in a CSV fi For more details please see the [Wiki](https://github.com/kaiwinter/dummyjdbc/wiki) +## New Methods in 1.5.0 +Refactored package in order to use `com.mindmercatis` instead of `com.googlecode` in order to proceed with the fork and keep releasing new versions. + +Three new methods have been added to `com.mindmercatis.dummyjdbc.DummyJdbcDriver` in order to support: +* Preparing tests as a simple sequence of expected table results + +```java +@Test + Class.forName(DummyJdbcDriver.class.getCanonicalName()); + DummyJdbcDriver.reset(); //reset the step counter + DummyJdbcDriver.addInMemoryTableResource(0, // result set for the first query which will be executed + "name, age\n"+ + "John, 20" ); + DummyJdbcDriver.addInMemoryTableResource(1, // result set for the second query which will be executed + "id, country\n"+ + "1, Italy\n"+ + "2, USA" ); + DummyJdbcDriver.addInMemoryTableResource(2, // result set for the third query which will be executed + "id, make, model, owner\n"+ + "1, Mazda, CX-5, Mark Twain\n"+ + "2, Ford, Focus, JF Kennedy" ); +``` + + ## New Methods in 1.4.0 Three new methods have been added to `com.googlecode.dummyjdbc.DummyJdbcDriver` in order to support: * InMemory resources for resultsets @@ -93,7 +117,7 @@ with parameters "Smith" and "34" will search for resources in the following orde * `mytable?Smith,34` * `mytable` -## Testing INSERT/DELETE queries +## Testing INSERT/UPDATE/DELETE queries One key part of testing how the application interacts with the DB is to capture if it performed the right INSERT/UPDATE queries, this is now possible. When updating a table now the parameters are captured and stored into a String which will be accessible for testing purposes @@ -120,12 +144,12 @@ E.g: when updating table `users` a new key will be added with name `users_PARAMS ## dummyjdbc at Maven Central [OUTDATED] -In order to use the official 1.3 version you can use Maven +In order to use the official version you can use Maven ```xml - com.googlecode.dummyjdbc + com.mindmercastis.dummyjdbc dummyjdbc - 1.3.0 + 1.5.0 ``` diff --git a/pom.xml b/pom.xml index 008947d..979dca0 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - com.googlecode.dummyjdbc + com.mindmercatis.dummyjdbc dummyjdbc 1.4.0 jar diff --git a/src/main/java/com/googlecode/dummyjdbc/AspectLogger.aj b/src/main/java/com/mindmercatis/dummyjdbc/AspectLogger.aj similarity index 94% rename from src/main/java/com/googlecode/dummyjdbc/AspectLogger.aj rename to src/main/java/com/mindmercatis/dummyjdbc/AspectLogger.aj index aa44592..ad66ca9 100644 --- a/src/main/java/com/googlecode/dummyjdbc/AspectLogger.aj +++ b/src/main/java/com/mindmercatis/dummyjdbc/AspectLogger.aj @@ -1,4 +1,4 @@ -package com.googlecode.dummyjdbc; +package com.mindmercatis.dummyjdbc; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.Signature; diff --git a/src/main/java/com/googlecode/dummyjdbc/DummyJdbcDriver.java b/src/main/java/com/mindmercatis/dummyjdbc/DummyJdbcDriver.java similarity index 77% rename from src/main/java/com/googlecode/dummyjdbc/DummyJdbcDriver.java rename to src/main/java/com/mindmercatis/dummyjdbc/DummyJdbcDriver.java index 618def7..2138e50 100644 --- a/src/main/java/com/googlecode/dummyjdbc/DummyJdbcDriver.java +++ b/src/main/java/com/mindmercatis/dummyjdbc/DummyJdbcDriver.java @@ -1,7 +1,5 @@ -package com.googlecode.dummyjdbc; +package com.mindmercatis.dummyjdbc; -import com.googlecode.dummyjdbc.utils.FilenameUtils; -import com.googlecode.dummyjdbc.utils.StringUtils; import java.io.File; import java.io.FileFilter; import java.io.InputStream; @@ -21,7 +19,9 @@ import java.util.Scanner; import java.util.logging.Logger; -import com.googlecode.dummyjdbc.connection.impl.DummyConnection; +import com.mindmercatis.dummyjdbc.connection.impl.DummyConnection; +import com.mindmercatis.dummyjdbc.utils.FilenameUtils; +import com.mindmercatis.dummyjdbc.utils.StringUtils; /** * The {@link DummyJdbcDriver}. The {@link #connect(String, Properties)} method returns the {@link DummyConnection}. @@ -37,12 +37,19 @@ public final class DummyJdbcDriver implements Driver { private static final String TIME_FORMAT = "HH:mm"; private static final String TIMESTAMP_FORMAT = "yyyyMMdd HHmmss.SSS"; + public static final String STEP_PREFIX = "##STEP"; + + /** + * Counter for the number of statements being executed + * Used to + */ + static int step = 0; + /** * CSV files stored into memory */ - public static Map inMemoryTableResources = new HashMap(); + static Map inMemoryTableResources = new HashMap(); - public static final ThreadLocal THREAD_LOCAL_DATEFORMAT = new ThreadLocal() { @Override protected DateFormat initialValue() { @@ -76,6 +83,19 @@ protected DateFormat initialValue() { // ignore } } + + /** + * Reset the internal data structures to restart counting + */ + public static void reset() { + step = 0; + inMemoryTableResources = new HashMap(); + tableResources = Collections.synchronizedMap(new HashMap>()); + } + + public static String getStepName() { + return STEP_PREFIX+step; + } /** * Registers a CSV file for a database table. When a Query is executed like SELECT * FROM ADDRESSES the @@ -240,6 +260,23 @@ public boolean accept(File pathname) { public static String getInMemoryTableResource(String testID) { return inMemoryTableResources.get(testID.toLowerCase().trim()); } + + /** + * Get the current value of the resource, used mainly to examine the parameters used for INSERT/UPDATE queries + * @param testID + * @return + */ + public static String getInMemoryTableResourceForCurrentStep() { + return getInMemoryTableResource(getStepName()); + } + + /** + * Signal to update to the next step + */ + public static void nextStep() { + step++; + } + public static void clearInMemoryTableResources() { @@ -257,6 +294,15 @@ public static void addInMemoryTableResource(String testID, String value) { inMemoryTableResources.put(testID.toLowerCase().trim(), value.trim()); } + /** + * Add the CSV contained the string 'value' to the list of available resultsets + * + * @param testID + * @param value + */ + public static void addInMemoryTableResource(int step, String value) { + addInMemoryTableResource(STEP_PREFIX+step, value); + } /** * Add the CSV contained the InputStream 'valueStream' to the list of available resultsets @@ -272,6 +318,16 @@ public static void addInMemoryTableResource(String testID, InputStream valueStre s.close(); DummyJdbcDriver.addInMemoryTableResource(testID,value); } + + /** + * Add the CSV contained the InputStream 'valueStream' to the list of available resultsets + * + * @param step number of step for using this resource + * @param value + */ + public static void addInMemoryTableResource(int step, InputStream valueStream) { + addInMemoryTableResource(STEP_PREFIX+step,valueStream); + } } diff --git a/src/main/java/com/googlecode/dummyjdbc/connection/ConnectionAdapter.java b/src/main/java/com/mindmercatis/dummyjdbc/connection/ConnectionAdapter.java similarity index 94% rename from src/main/java/com/googlecode/dummyjdbc/connection/ConnectionAdapter.java rename to src/main/java/com/mindmercatis/dummyjdbc/connection/ConnectionAdapter.java index 1d6b39f..d7ff089 100644 --- a/src/main/java/com/googlecode/dummyjdbc/connection/ConnectionAdapter.java +++ b/src/main/java/com/mindmercatis/dummyjdbc/connection/ConnectionAdapter.java @@ -1,4 +1,4 @@ -package com.googlecode.dummyjdbc.connection; +package com.mindmercatis.dummyjdbc.connection; import java.sql.Array; import java.sql.Blob; diff --git a/src/main/java/com/googlecode/dummyjdbc/connection/DummyDatabaseMetaData.java b/src/main/java/com/mindmercatis/dummyjdbc/connection/DummyDatabaseMetaData.java similarity index 99% rename from src/main/java/com/googlecode/dummyjdbc/connection/DummyDatabaseMetaData.java rename to src/main/java/com/mindmercatis/dummyjdbc/connection/DummyDatabaseMetaData.java index 3d4503a..7cc2c84 100644 --- a/src/main/java/com/googlecode/dummyjdbc/connection/DummyDatabaseMetaData.java +++ b/src/main/java/com/mindmercatis/dummyjdbc/connection/DummyDatabaseMetaData.java @@ -1,4 +1,4 @@ -package com.googlecode.dummyjdbc.connection; +package com.mindmercatis.dummyjdbc.connection; import java.sql.Connection; import java.sql.DatabaseMetaData; diff --git a/src/main/java/com/googlecode/dummyjdbc/connection/impl/DummyConnection.java b/src/main/java/com/mindmercatis/dummyjdbc/connection/impl/DummyConnection.java similarity index 90% rename from src/main/java/com/googlecode/dummyjdbc/connection/impl/DummyConnection.java rename to src/main/java/com/mindmercatis/dummyjdbc/connection/impl/DummyConnection.java index 4545e34..a6aeb4e 100644 --- a/src/main/java/com/googlecode/dummyjdbc/connection/impl/DummyConnection.java +++ b/src/main/java/com/mindmercatis/dummyjdbc/connection/impl/DummyConnection.java @@ -1,4 +1,4 @@ -package com.googlecode.dummyjdbc.connection.impl; +package com.mindmercatis.dummyjdbc.connection.impl; import java.io.File; import java.sql.PreparedStatement; @@ -7,9 +7,9 @@ import java.util.Collections; import java.util.Map; -import com.googlecode.dummyjdbc.connection.ConnectionAdapter; -import com.googlecode.dummyjdbc.statement.impl.CsvPreparedStatement; -import com.googlecode.dummyjdbc.statement.impl.CsvStatement; +import com.mindmercatis.dummyjdbc.connection.ConnectionAdapter; +import com.mindmercatis.dummyjdbc.statement.impl.CsvPreparedStatement; +import com.mindmercatis.dummyjdbc.statement.impl.CsvStatement; /** * Connection which implements the methods {@link #createStatement()} and {@link #prepareStatement(String)}. The diff --git a/src/main/java/com/googlecode/dummyjdbc/resultset/DummyResultSet.java b/src/main/java/com/mindmercatis/dummyjdbc/resultset/DummyResultSet.java similarity index 95% rename from src/main/java/com/googlecode/dummyjdbc/resultset/DummyResultSet.java rename to src/main/java/com/mindmercatis/dummyjdbc/resultset/DummyResultSet.java index 434a6ba..cfbe778 100644 --- a/src/main/java/com/googlecode/dummyjdbc/resultset/DummyResultSet.java +++ b/src/main/java/com/mindmercatis/dummyjdbc/resultset/DummyResultSet.java @@ -1,4 +1,4 @@ -package com.googlecode.dummyjdbc.resultset; +package com.mindmercatis.dummyjdbc.resultset; import java.io.InputStream; import java.io.Reader; diff --git a/src/main/java/com/googlecode/dummyjdbc/resultset/DummyResultSetMetaData.java b/src/main/java/com/mindmercatis/dummyjdbc/resultset/DummyResultSetMetaData.java similarity index 99% rename from src/main/java/com/googlecode/dummyjdbc/resultset/DummyResultSetMetaData.java rename to src/main/java/com/mindmercatis/dummyjdbc/resultset/DummyResultSetMetaData.java index 9cd6708..0b1fe24 100644 --- a/src/main/java/com/googlecode/dummyjdbc/resultset/DummyResultSetMetaData.java +++ b/src/main/java/com/mindmercatis/dummyjdbc/resultset/DummyResultSetMetaData.java @@ -1,4 +1,4 @@ -package com.googlecode.dummyjdbc.resultset; +package com.mindmercatis.dummyjdbc.resultset; import java.sql.ResultSetMetaData; import java.sql.SQLException; diff --git a/src/main/java/com/googlecode/dummyjdbc/resultset/impl/CSVResultSet.java b/src/main/java/com/mindmercatis/dummyjdbc/resultset/impl/CSVResultSet.java similarity index 93% rename from src/main/java/com/googlecode/dummyjdbc/resultset/impl/CSVResultSet.java rename to src/main/java/com/mindmercatis/dummyjdbc/resultset/impl/CSVResultSet.java index f52129c..2b10e86 100644 --- a/src/main/java/com/googlecode/dummyjdbc/resultset/impl/CSVResultSet.java +++ b/src/main/java/com/mindmercatis/dummyjdbc/resultset/impl/CSVResultSet.java @@ -1,4 +1,4 @@ -package com.googlecode.dummyjdbc.resultset.impl; +package com.mindmercatis.dummyjdbc.resultset.impl; import java.math.BigDecimal; import java.sql.Date; @@ -14,9 +14,9 @@ import java.util.Iterator; import java.util.LinkedHashMap; -import com.googlecode.dummyjdbc.DummyJdbcDriver; -import com.googlecode.dummyjdbc.resultset.DummyResultSet; -import com.googlecode.dummyjdbc.resultset.DummyResultSetMetaData; +import com.mindmercatis.dummyjdbc.DummyJdbcDriver; +import com.mindmercatis.dummyjdbc.resultset.DummyResultSet; +import com.mindmercatis.dummyjdbc.resultset.DummyResultSetMetaData; /** * The {@link CSVResultSet} which iterates over the CSV file data. diff --git a/src/main/java/com/googlecode/dummyjdbc/statement/PreparedStatementAdapter.java b/src/main/java/com/mindmercatis/dummyjdbc/statement/PreparedStatementAdapter.java similarity index 94% rename from src/main/java/com/googlecode/dummyjdbc/statement/PreparedStatementAdapter.java rename to src/main/java/com/mindmercatis/dummyjdbc/statement/PreparedStatementAdapter.java index e6181eb..a5c5d8a 100644 --- a/src/main/java/com/googlecode/dummyjdbc/statement/PreparedStatementAdapter.java +++ b/src/main/java/com/mindmercatis/dummyjdbc/statement/PreparedStatementAdapter.java @@ -1,4 +1,4 @@ -package com.googlecode.dummyjdbc.statement; +package com.mindmercatis.dummyjdbc.statement; import java.io.InputStream; import java.io.Reader; diff --git a/src/main/java/com/googlecode/dummyjdbc/statement/StatementAdapter.java b/src/main/java/com/mindmercatis/dummyjdbc/statement/StatementAdapter.java similarity index 93% rename from src/main/java/com/googlecode/dummyjdbc/statement/StatementAdapter.java rename to src/main/java/com/mindmercatis/dummyjdbc/statement/StatementAdapter.java index f82322a..044d211 100644 --- a/src/main/java/com/googlecode/dummyjdbc/statement/StatementAdapter.java +++ b/src/main/java/com/mindmercatis/dummyjdbc/statement/StatementAdapter.java @@ -1,4 +1,4 @@ -package com.googlecode.dummyjdbc.statement; +package com.mindmercatis.dummyjdbc.statement; import java.sql.Connection; import java.sql.ResultSet; diff --git a/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatement.java b/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatement.java similarity index 88% rename from src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatement.java rename to src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatement.java index 6773460..d06ad8a 100644 --- a/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatement.java +++ b/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatement.java @@ -1,4 +1,4 @@ -package com.googlecode.dummyjdbc.statement.impl; +package com.mindmercatis.dummyjdbc.statement.impl; import java.io.File; import java.math.BigDecimal; @@ -11,8 +11,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import com.googlecode.dummyjdbc.DummyJdbcDriver; -import com.googlecode.dummyjdbc.statement.PreparedStatementAdapter; +import com.mindmercatis.dummyjdbc.DummyJdbcDriver; +import com.mindmercatis.dummyjdbc.statement.PreparedStatementAdapter; /** * Wraps the {@link CsvStatement} as a prepared statement. @@ -69,26 +69,33 @@ public int executeUpdate(String sql) throws SQLException { targetTable4Updates = null; try { - + int res = 1; + String stepRes = DummyJdbcDriver.getInMemoryTableResourceForCurrentStep(); + + if (stepRes!=null) { + targetTable4Updates = DummyJdbcDriver.getStepName(); + return Integer.parseInt(stepRes); + } + // Try to check for a special heading comment within SQL Matcher commentMatcher = CsvStatement.COMMENT_HEADLINE_PATTERN.matcher(sql); if (commentMatcher.matches()) { targetTable4Updates = commentMatcher.group(1); - return 1; + return res; } // Try to interpret SQL as a SELECT on a table Matcher insertMatcher = INSERT_INTO_PATTERN.matcher(sql); if (insertMatcher.matches()) { targetTable4Updates = insertMatcher.group(1); - return 1; + return res; } // Try to interpret SQL as call of a stored procedure Matcher updateMatcher = UPDATE_TABLE_PATTERN.matcher(sql); if (updateMatcher.matches()) { targetTable4Updates = updateMatcher.group(1); - return 1; + return res; } return 0; @@ -98,6 +105,8 @@ public int executeUpdate(String sql) throws SQLException { DummyJdbcDriver.addInMemoryTableResource( targetTable4Updates+PARAMS_SUFFIX, buildParamsString() ); params = new Object[MAX_PARAMS]; + + DummyJdbcDriver.nextStep(); } } @@ -221,7 +230,7 @@ public boolean execute(String sql) throws SQLException { executeUpdate(sql); return true; } finally { - statement.paramsString = null; + statement.paramsString = null; } } diff --git a/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvStatement.java b/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvStatement.java similarity index 77% rename from src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvStatement.java rename to src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvStatement.java index ec422e3..05ef231 100644 --- a/src/main/java/com/googlecode/dummyjdbc/statement/impl/CsvStatement.java +++ b/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvStatement.java @@ -1,4 +1,4 @@ -package com.googlecode.dummyjdbc.statement.impl; +package com.mindmercatis.dummyjdbc.statement.impl; import java.io.ByteArrayInputStream; import java.io.File; @@ -24,11 +24,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.googlecode.dummyjdbc.DummyJdbcDriver; -import com.googlecode.dummyjdbc.resultset.DummyResultSet; -import com.googlecode.dummyjdbc.resultset.DummyResultSetMetaData; -import com.googlecode.dummyjdbc.resultset.impl.CSVResultSet; -import com.googlecode.dummyjdbc.statement.StatementAdapter; +import com.mindmercatis.dummyjdbc.DummyJdbcDriver; +import com.mindmercatis.dummyjdbc.resultset.DummyResultSet; +import com.mindmercatis.dummyjdbc.resultset.DummyResultSetMetaData; +import com.mindmercatis.dummyjdbc.resultset.impl.CSVResultSet; +import com.mindmercatis.dummyjdbc.statement.StatementAdapter; import au.com.bytecode.opencsv.CSVReader; @@ -76,34 +76,47 @@ public CsvStatement(Map tableResources) { @Override public ResultSet executeQuery(String sql) throws SQLException { - // Try to check for a special heading comment within SQL - Matcher commentMatcher = COMMENT_HEADLINE_PATTERN.matcher(sql); - if (commentMatcher.matches()) { - String tableName = commentMatcher.group(1); - return createResultSet(tableName); - } - - // Try to interpret SQL as a SELECT on a table - Matcher tableMatcher = TABLENAME_PATTERN.matcher(sql); - if (tableMatcher.matches()) { - String tableName = tableMatcher.group(1); - return createResultSet(tableName); - } + try { + String stepRes = DummyJdbcDriver.getInMemoryTableResourceForCurrentStep(); + + // match based on the current step (sequence number) + if (stepRes!=null) { + String tableName = DummyJdbcDriver.getStepName(); + return createResultSet(tableName); + } + + // Try to check for a special heading comment within SQL + Matcher commentMatcher = COMMENT_HEADLINE_PATTERN.matcher(sql); + if (commentMatcher.matches()) { + String tableName = commentMatcher.group(1); + return createResultSet(tableName); + } + + // Try to interpret SQL as a SELECT on a table + Matcher tableMatcher = TABLENAME_PATTERN.matcher(sql); + if (tableMatcher.matches()) { + String tableName = tableMatcher.group(1); + return createResultSet(tableName); + } - // Try to interpret SQL as call of a stored procedure - Matcher storedProcedureMatcher = STORED_PROCEDURE_PATTERN.matcher(sql); - if (storedProcedureMatcher.matches()) { - String storedProcedureName = storedProcedureMatcher.group(2); - return createResultSet(storedProcedureName); - } + // Try to interpret SQL as call of a stored procedure + Matcher storedProcedureMatcher = STORED_PROCEDURE_PATTERN.matcher(sql); + if (storedProcedureMatcher.matches()) { + String storedProcedureName = storedProcedureMatcher.group(2); + return createResultSet(storedProcedureName); + } - // Try to interpret SQL as a pure select - Matcher pureSelectMatcher = PURE_SELECT_PATTERN.matcher(sql); - if (pureSelectMatcher.matches()) { - return createPureResultSet(); - } + // Try to interpret SQL as a pure select + Matcher pureSelectMatcher = PURE_SELECT_PATTERN.matcher(sql); + if (pureSelectMatcher.matches()) { + return createPureResultSet(); + } - return new DummyResultSet(); + return new DummyResultSet(); + + } finally { + DummyJdbcDriver.nextStep(); + } } static String matchTablename(String sql) { diff --git a/src/main/java/com/googlecode/dummyjdbc/statement/impl/InMemoryCSV.java b/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/InMemoryCSV.java similarity index 54% rename from src/main/java/com/googlecode/dummyjdbc/statement/impl/InMemoryCSV.java rename to src/main/java/com/mindmercatis/dummyjdbc/statement/impl/InMemoryCSV.java index 2c98873..21f6d4a 100644 --- a/src/main/java/com/googlecode/dummyjdbc/statement/impl/InMemoryCSV.java +++ b/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/InMemoryCSV.java @@ -1,4 +1,4 @@ -package com.googlecode.dummyjdbc.statement.impl; +package com.mindmercatis.dummyjdbc.statement.impl; /** * Removed diff --git a/src/main/java/com/googlecode/dummyjdbc/utils/FilenameUtils.java b/src/main/java/com/mindmercatis/dummyjdbc/utils/FilenameUtils.java similarity index 99% rename from src/main/java/com/googlecode/dummyjdbc/utils/FilenameUtils.java rename to src/main/java/com/mindmercatis/dummyjdbc/utils/FilenameUtils.java index e394d44..fd0bf0c 100644 --- a/src/main/java/com/googlecode/dummyjdbc/utils/FilenameUtils.java +++ b/src/main/java/com/mindmercatis/dummyjdbc/utils/FilenameUtils.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.googlecode.dummyjdbc.utils; +package com.mindmercatis.dummyjdbc.utils; import java.io.File; import java.io.IOException; diff --git a/src/main/java/com/googlecode/dummyjdbc/utils/StringUtils.java b/src/main/java/com/mindmercatis/dummyjdbc/utils/StringUtils.java similarity index 92% rename from src/main/java/com/googlecode/dummyjdbc/utils/StringUtils.java rename to src/main/java/com/mindmercatis/dummyjdbc/utils/StringUtils.java index d637adb..20cce5d 100644 --- a/src/main/java/com/googlecode/dummyjdbc/utils/StringUtils.java +++ b/src/main/java/com/mindmercatis/dummyjdbc/utils/StringUtils.java @@ -1,4 +1,4 @@ -package com.googlecode.dummyjdbc.utils; +package com.mindmercatis.dummyjdbc.utils; /** * String Utils Class diff --git a/src/test/java/com/googlecode/dummyjdbc/DummyJdbcDriverTest.java b/src/test/java/com/mindmercatis/dummyjdbc/DummyJdbcDriverTest.java similarity index 83% rename from src/test/java/com/googlecode/dummyjdbc/DummyJdbcDriverTest.java rename to src/test/java/com/mindmercatis/dummyjdbc/DummyJdbcDriverTest.java index 43b8842..5f8f1eb 100644 --- a/src/test/java/com/googlecode/dummyjdbc/DummyJdbcDriverTest.java +++ b/src/test/java/com/mindmercatis/dummyjdbc/DummyJdbcDriverTest.java @@ -1,4 +1,4 @@ -package com.googlecode.dummyjdbc; +package com.mindmercatis.dummyjdbc; import java.sql.Connection; import java.sql.DriverManager; @@ -7,7 +7,8 @@ import org.junit.Assert; import org.junit.Test; -import com.googlecode.dummyjdbc.connection.impl.DummyConnection; +import com.mindmercatis.dummyjdbc.DummyJdbcDriver; +import com.mindmercatis.dummyjdbc.connection.impl.DummyConnection; public final class DummyJdbcDriverTest { diff --git a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvGenericStatementTest.java b/src/test/java/com/mindmercatis/dummyjdbc/statement/impl/CsvGenericStatementTest.java similarity index 57% rename from src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvGenericStatementTest.java rename to src/test/java/com/mindmercatis/dummyjdbc/statement/impl/CsvGenericStatementTest.java index f9ca7b1..c8e8807 100644 --- a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvGenericStatementTest.java +++ b/src/test/java/com/mindmercatis/dummyjdbc/statement/impl/CsvGenericStatementTest.java @@ -1,4 +1,4 @@ -package com.googlecode.dummyjdbc.statement.impl; +package com.mindmercatis.dummyjdbc.statement.impl; import java.io.File; import java.net.URISyntaxException; @@ -12,7 +12,7 @@ import org.junit.Before; import org.junit.Test; -import com.googlecode.dummyjdbc.DummyJdbcDriver; +import com.mindmercatis.dummyjdbc.DummyJdbcDriver; public final class CsvGenericStatementTest { @@ -22,6 +22,7 @@ public final class CsvGenericStatementTest { public void setup() throws ClassNotFoundException, SQLException, URISyntaxException { Class.forName(DummyJdbcDriver.class.getCanonicalName()); + DummyJdbcDriver.reset(); DummyJdbcDriver.addTableResource("test_table", new File(CsvGenericStatementTest.class.getResource("test_table.csv").toURI())); Connection connection = DriverManager.getConnection("any"); @@ -30,7 +31,59 @@ public void setup() throws ClassNotFoundException, SQLException, URISyntaxExcept Assert.assertTrue(statement instanceof CsvStatement); resultSet = statement.executeQuery("SELECT * FROM test_table"); } + + /** + * Within this text we expect the results to be read from memory based on the number of the execution step, + * ignoring the table name and comments + * + * @throws SQLException + * @throws URISyntaxException + */ + @Test + public void testQueryByStep() throws SQLException, URISyntaxException { + + DummyJdbcDriver.reset(); + DummyJdbcDriver.addInMemoryTableResource(0, + "\n" + + "name, age\n"+ + "John, 20"+ + "\n" + ); + DummyJdbcDriver.addInMemoryTableResource(1, + "\n" + + "where, who\n"+ + "London, Sherlock"+ + "\n" + ); + + Connection connection = DriverManager.getConnection("any"); + Statement statement = connection.createStatement(); + + Assert.assertTrue(statement instanceof CsvStatement); + resultSet = statement.executeQuery( + "-- TESTCASE:test1\n" + + "SELECT *\n" + + "FROM test_table"); + + Assert.assertTrue(resultSet.next()); + Assert.assertEquals("John", resultSet.getString("name")); + Assert.assertEquals(20, resultSet.getInt("age")); + + // test 2nd step + statement = connection.createStatement(); + + Assert.assertTrue(statement instanceof CsvStatement); + resultSet = statement.executeQuery( + "-- TESTCASE:test2\n" + + "SELECT *\n" + + "FROM test_table"); + + Assert.assertTrue(resultSet.next()); + Assert.assertEquals("London", resultSet.getString("where")); + Assert.assertEquals("Sherlock", resultSet.getString("who")); + } + @Test public void testGetByColumnName() throws SQLException { diff --git a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java b/src/test/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatementTest.java similarity index 95% rename from src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java rename to src/test/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatementTest.java index 10134eb..503733a 100644 --- a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvPreparedStatementTest.java +++ b/src/test/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatementTest.java @@ -1,4 +1,4 @@ -package com.googlecode.dummyjdbc.statement.impl; +package com.mindmercatis.dummyjdbc.statement.impl; import java.io.ByteArrayInputStream; import java.io.File; @@ -9,14 +9,13 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.Statement; import java.util.TimeZone; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import com.googlecode.dummyjdbc.DummyJdbcDriver; +import com.mindmercatis.dummyjdbc.DummyJdbcDriver; public final class CsvPreparedStatementTest { diff --git a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvStatementTest.java b/src/test/java/com/mindmercatis/dummyjdbc/statement/impl/CsvStatementTest.java similarity index 88% rename from src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvStatementTest.java rename to src/test/java/com/mindmercatis/dummyjdbc/statement/impl/CsvStatementTest.java index acb16d0..28d7bc9 100644 --- a/src/test/java/com/googlecode/dummyjdbc/statement/impl/CsvStatementTest.java +++ b/src/test/java/com/mindmercatis/dummyjdbc/statement/impl/CsvStatementTest.java @@ -1,4 +1,4 @@ -package com.googlecode.dummyjdbc.statement.impl; +package com.mindmercatis.dummyjdbc.statement.impl; import java.sql.Connection; import java.sql.DriverManager; @@ -8,7 +8,8 @@ import org.junit.Assert; import org.junit.Test; -import com.googlecode.dummyjdbc.DummyJdbcDriver; +import com.mindmercatis.dummyjdbc.DummyJdbcDriver; +import com.mindmercatis.dummyjdbc.statement.impl.CsvStatement; public final class CsvStatementTest { diff --git a/src/test/java/com/googlecode/dummyjdbc/statement/impl/DatatypesTest.java b/src/test/java/com/mindmercatis/dummyjdbc/statement/impl/DatatypesTest.java similarity index 96% rename from src/test/java/com/googlecode/dummyjdbc/statement/impl/DatatypesTest.java rename to src/test/java/com/mindmercatis/dummyjdbc/statement/impl/DatatypesTest.java index a7940d5..b1f7fbe 100644 --- a/src/test/java/com/googlecode/dummyjdbc/statement/impl/DatatypesTest.java +++ b/src/test/java/com/mindmercatis/dummyjdbc/statement/impl/DatatypesTest.java @@ -1,4 +1,4 @@ -package com.googlecode.dummyjdbc.statement.impl; +package com.mindmercatis.dummyjdbc.statement.impl; import java.io.File; import java.math.BigDecimal; @@ -16,7 +16,7 @@ import org.junit.Before; import org.junit.Test; -import com.googlecode.dummyjdbc.DummyJdbcDriver; +import com.mindmercatis.dummyjdbc.DummyJdbcDriver; public final class DatatypesTest { diff --git a/src/test/java/com/googlecode/dummyjdbc/statement/impl/ResultSetMetaDataTest.java b/src/test/java/com/mindmercatis/dummyjdbc/statement/impl/ResultSetMetaDataTest.java similarity index 94% rename from src/test/java/com/googlecode/dummyjdbc/statement/impl/ResultSetMetaDataTest.java rename to src/test/java/com/mindmercatis/dummyjdbc/statement/impl/ResultSetMetaDataTest.java index 30b22f3..d58096f 100644 --- a/src/test/java/com/googlecode/dummyjdbc/statement/impl/ResultSetMetaDataTest.java +++ b/src/test/java/com/mindmercatis/dummyjdbc/statement/impl/ResultSetMetaDataTest.java @@ -1,4 +1,4 @@ -package com.googlecode.dummyjdbc.statement.impl; +package com.mindmercatis.dummyjdbc.statement.impl; import java.io.File; import java.net.URISyntaxException; @@ -13,7 +13,7 @@ import org.junit.Before; import org.junit.Test; -import com.googlecode.dummyjdbc.DummyJdbcDriver; +import com.mindmercatis.dummyjdbc.DummyJdbcDriver; public class ResultSetMetaDataTest { diff --git a/src/test/resources/com/googlecode/dummyjdbc/statement/impl/datatypes.csv b/src/test/resources/com/mindmercatis/dummyjdbc/statement/impl/datatypes.csv similarity index 100% rename from src/test/resources/com/googlecode/dummyjdbc/statement/impl/datatypes.csv rename to src/test/resources/com/mindmercatis/dummyjdbc/statement/impl/datatypes.csv diff --git a/src/test/resources/com/googlecode/dummyjdbc/statement/impl/metadata.csv b/src/test/resources/com/mindmercatis/dummyjdbc/statement/impl/metadata.csv similarity index 100% rename from src/test/resources/com/googlecode/dummyjdbc/statement/impl/metadata.csv rename to src/test/resources/com/mindmercatis/dummyjdbc/statement/impl/metadata.csv diff --git a/src/test/resources/com/googlecode/dummyjdbc/statement/impl/test_table.csv b/src/test/resources/com/mindmercatis/dummyjdbc/statement/impl/test_table.csv similarity index 100% rename from src/test/resources/com/googlecode/dummyjdbc/statement/impl/test_table.csv rename to src/test/resources/com/mindmercatis/dummyjdbc/statement/impl/test_table.csv diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index e5315fb..fb2d2a7 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -5,7 +5,7 @@ - + From b5006d6cf1b67c55de786e0c4562b82f7c380612 Mon Sep 17 00:00:00 2001 From: simoneavogadro Date: Mon, 28 Oct 2019 17:34:31 +0100 Subject: [PATCH 26/29] typo in readme --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 4f37637..341e957 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,6 @@ Three new methods have been added to `com.mindmercatis.dummyjdbc.DummyJdbcDriver * Preparing tests as a simple sequence of expected table results ```java -@Test Class.forName(DummyJdbcDriver.class.getCanonicalName()); DummyJdbcDriver.reset(); //reset the step counter DummyJdbcDriver.addInMemoryTableResource(0, // result set for the first query which will be executed From cc97bd59c0dee089f5cb9dfc6958e92c3de2564e Mon Sep 17 00:00:00 2001 From: simoneavogadro Date: Tue, 5 Nov 2019 16:57:08 +0100 Subject: [PATCH 27/29] - FIX: wrong sequence counter on some scenarios --- .../statement/impl/CsvPreparedStatement.java | 14 ++++++++++++-- .../dummyjdbc/statement/impl/CsvStatement.java | 8 +++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatement.java b/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatement.java index d06ad8a..5380af8 100644 --- a/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatement.java +++ b/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatement.java @@ -74,7 +74,12 @@ public int executeUpdate(String sql) throws SQLException { if (stepRes!=null) { targetTable4Updates = DummyJdbcDriver.getStepName(); - return Integer.parseInt(stepRes); + try { + return Integer.parseInt(stepRes); + } catch (NumberFormatException nfe) { + // that's ok, it's a simple resultset rather then an update query + return 0; + } } // Try to check for a special heading comment within SQL @@ -106,7 +111,7 @@ public int executeUpdate(String sql) throws SQLException { params = new Object[MAX_PARAMS]; - DummyJdbcDriver.nextStep(); + } } @@ -253,4 +258,9 @@ public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { public ResultSet getResultSet() throws SQLException { return currentResultSet; } + + @Override + public void close() throws SQLException { + DummyJdbcDriver.nextStep(); + } } diff --git a/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvStatement.java b/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvStatement.java index 05ef231..b417267 100644 --- a/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvStatement.java +++ b/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvStatement.java @@ -115,7 +115,7 @@ public ResultSet executeQuery(String sql) throws SQLException { return new DummyResultSet(); } finally { - DummyJdbcDriver.nextStep(); + // DummyJdbcDriver.nextStep(); } } @@ -260,4 +260,10 @@ private DummyResultSet createPureResultSet() { private String resolveHeaderName(String str) { return str.trim().toUpperCase(); } + + @Override + public void close() throws SQLException { + DummyJdbcDriver.nextStep(); + } + } From 8074b64597d44ace96ce0e3434a610324cb21280 Mon Sep 17 00:00:00 2001 From: simoneavogadro Date: Wed, 6 Nov 2019 09:49:52 +0100 Subject: [PATCH 28/29] - fixes to the step logic --- CHANGELOG.md | 5 +++++ pom.xml | 2 +- .../mindmercatis/dummyjdbc/DummyJdbcDriver.java | 7 ++++--- .../statement/impl/CsvPreparedStatement.java | 13 +++++++++---- .../dummyjdbc/statement/impl/CsvStatement.java | 15 ++++++++++----- 5 files changed, 29 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82f0532..4999f0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ Change Log ========== +Version 1.5.1 +---------------------------- + + * Fixed issues with using step number to identify testing data + Version 1.5.0 ---------------------------- diff --git a/pom.xml b/pom.xml index 979dca0..ea0bd01 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.mindmercatis.dummyjdbc dummyjdbc - 1.4.0 + 1.5.1 jar DummyJDBC diff --git a/src/main/java/com/mindmercatis/dummyjdbc/DummyJdbcDriver.java b/src/main/java/com/mindmercatis/dummyjdbc/DummyJdbcDriver.java index 2138e50..7259e9f 100644 --- a/src/main/java/com/mindmercatis/dummyjdbc/DummyJdbcDriver.java +++ b/src/main/java/com/mindmercatis/dummyjdbc/DummyJdbcDriver.java @@ -41,9 +41,10 @@ public final class DummyJdbcDriver implements Driver { /** * Counter for the number of statements being executed - * Used to + * Used to give a sequential number to each query + * Starts from -1 because it's pre-incremented once each statement is created */ - static int step = 0; + static int step = -1; /** * CSV files stored into memory @@ -88,7 +89,7 @@ protected DateFormat initialValue() { * Reset the internal data structures to restart counting */ public static void reset() { - step = 0; + step = -1; inMemoryTableResources = new HashMap(); tableResources = Collections.synchronizedMap(new HashMap>()); } diff --git a/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatement.java b/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatement.java index 5380af8..5816d2d 100644 --- a/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatement.java +++ b/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatement.java @@ -47,6 +47,14 @@ public class CsvPreparedStatement extends PreparedStatementAdapter { private ResultSet currentResultSet; + /** + * Initializer + * + */ + { + DummyJdbcDriver.nextStep(); + } + /** * Constructs a new {@link CsvPreparedStatement}. * @@ -259,8 +267,5 @@ public ResultSet getResultSet() throws SQLException { return currentResultSet; } - @Override - public void close() throws SQLException { - DummyJdbcDriver.nextStep(); - } + } diff --git a/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvStatement.java b/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvStatement.java index b417267..2a0f1d4 100644 --- a/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvStatement.java +++ b/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvStatement.java @@ -63,6 +63,15 @@ public final class CsvStatement extends StatementAdapter { */ String paramsString = null; + + /** + * Initializer + * + */ + { + DummyJdbcDriver.nextStep(); + } + /** * Constructs a new {@link CsvStatement}. * @@ -260,10 +269,6 @@ private DummyResultSet createPureResultSet() { private String resolveHeaderName(String str) { return str.trim().toUpperCase(); } - - @Override - public void close() throws SQLException { - DummyJdbcDriver.nextStep(); - } + } From 1d564d896f2e38dc56ab4da02300c2cf2c6bdafe Mon Sep 17 00:00:00 2001 From: simoneavogadro Date: Wed, 6 Nov 2019 13:07:25 +0100 Subject: [PATCH 29/29] - fix to steps --- .../statement/impl/CsvPreparedStatement.java | 8 --- .../impl/CsvPreparedStatementTest.java | 54 +++++++++++++++++++ 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatement.java b/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatement.java index 5816d2d..b669b5b 100644 --- a/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatement.java +++ b/src/main/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatement.java @@ -46,14 +46,6 @@ public class CsvPreparedStatement extends PreparedStatementAdapter { private final String sql; private ResultSet currentResultSet; - - /** - * Initializer - * - */ - { - DummyJdbcDriver.nextStep(); - } /** * Constructs a new {@link CsvPreparedStatement}. diff --git a/src/test/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatementTest.java b/src/test/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatementTest.java index 503733a..a334e38 100644 --- a/src/test/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatementTest.java +++ b/src/test/java/com/mindmercatis/dummyjdbc/statement/impl/CsvPreparedStatementTest.java @@ -9,6 +9,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Statement; import java.util.TimeZone; import org.junit.Assert; @@ -216,4 +217,57 @@ public void insertSQL() throws Exception { Assert.assertEquals("", params); } + + /** + * Within this text we expect the results to be read from memory based on the number of the execution step, + * ignoring the table name and comments + * + * @throws SQLException + * @throws URISyntaxException + */ + @Test + public void testQueryByStep() throws SQLException, URISyntaxException { + + DummyJdbcDriver.reset(); + DummyJdbcDriver.addInMemoryTableResource(0, + "\n" + + "name, age\n"+ + "John, 20"+ + "\n" + ); + DummyJdbcDriver.addInMemoryTableResource(1, + "\n" + + "where, who\n"+ + "London, Sherlock"+ + "\n" + ); + + Connection connection = DriverManager.getConnection("any"); + Statement statement = connection.prepareStatement("ignore me"); + + Assert.assertTrue(statement instanceof CsvPreparedStatement); + resultSet = statement.executeQuery( + "-- TESTCASE:test1\n" + + "SELECT *\n" + + "FROM test_table"); + + Assert.assertTrue(resultSet.next()); + Assert.assertEquals("John", resultSet.getString("name")); + Assert.assertEquals(20, resultSet.getInt("age")); + + // test 2nd step + statement = connection.prepareStatement("ignore me"); + + Assert.assertTrue(statement instanceof CsvPreparedStatement); + resultSet = statement.executeQuery( + "-- TESTCASE:test2\n" + + "SELECT *\n" + + "FROM test_table"); + + Assert.assertTrue(resultSet.next()); + Assert.assertEquals("London", resultSet.getString("where")); + Assert.assertEquals("Sherlock", resultSet.getString("who")); + } + + }