From c6f4421c8e59c896ed9887ced256a73b920f4ccb Mon Sep 17 00:00:00 2001 From: Koji Kawamura Date: Mon, 14 Aug 2017 11:19:50 +0900 Subject: [PATCH] NIFI-2829: Fixed PutSQL time unit test. The unit test for DATE type used GMT timezone, that causes an assertion error in timezones such as EST (-5). We need to use local timezone instead of GMT, as Derby and PutSQL uses local timezone. The unit test failed before as follows: - Unit test code, passed: '2002-02-02 GMT' - PutSQL code convertedi it to local: '2002-02-01 EST', and stored as '2002-02-01' in Derby database without timezone info - Unit test code SELECT the inserted value, passed a GMT calender, then got epoch timestamp, which was '2002-01-31' Support negative long value for timezones ahead of UTC. - For timezones such as '+0800', it's possible that a local time e.g. '02:03:04' can be a negative epoch value. This commit changes LONG_PATTERN so that it can accept nevative values. - Changed time values in unit tests to verify negative epoch values, and avoid using the same digits among different time unit for better readability. This closes #2082 --- .../nifi/processors/standard/PutSQL.java | 2 +- .../nifi/processors/standard/TestPutSQL.java | 56 ++++++++----------- 2 files changed, 25 insertions(+), 33 deletions(-) diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/PutSQL.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/PutSQL.java index c35377a7e1..f75ccaa021 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/PutSQL.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/PutSQL.java @@ -191,7 +191,7 @@ public class PutSQL extends AbstractSessionFactoryProcessor { private static final String FRAGMENT_INDEX_ATTR = FragmentAttributes.FRAGMENT_INDEX.key(); private static final String FRAGMENT_COUNT_ATTR = FragmentAttributes.FRAGMENT_COUNT.key(); - private static final Pattern LONG_PATTERN = Pattern.compile("^\\d{1,19}$"); + private static final Pattern LONG_PATTERN = Pattern.compile("^-?\\d{1,19}$"); @Override protected List getSupportedPropertyDescriptors() { diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestPutSQL.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestPutSQL.java index 88d47ee392..5a2909b1b2 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestPutSQL.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestPutSQL.java @@ -38,11 +38,11 @@ import java.time.LocalTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.Arrays; -import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Map; -import java.util.TimeZone; + +import javax.xml.bind.DatatypeConverter; import org.apache.commons.lang3.RandomUtils; import org.apache.nifi.controller.AbstractControllerService; @@ -59,9 +59,6 @@ import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.mockito.Mockito; -import javax.xml.bind.DatatypeConverter; -import org.junit.Ignore; - public class TestPutSQL { private static final String createPersons = "CREATE TABLE PERSONS (id integer primary key, name varchar(100), code integer)"; private static final String createPersonsAutoId = "CREATE TABLE PERSONS_AI (id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1), name VARCHAR(100), code INTEGER check(code <= 100))"; @@ -460,7 +457,6 @@ public class TestPutSQL { } } - @Ignore("this test needs fixing due to TestPutSQL.testUsingDateTimeValuesWithFormatAttribute:551 expected:<1012608000000> but was:<1012521600000>") @Test public void testUsingDateTimeValuesWithFormatAttribute() throws InitializationException, ProcessException, SQLException, IOException, ParseException { final TestRunner runner = TestRunners.newTestRunner(PutSQL.class); @@ -474,8 +470,8 @@ public class TestPutSQL { runner.enableControllerService(service); runner.setProperty(PutSQL.CONNECTION_POOL, "dbcp"); - final String dateStr = "2002-02-02"; - final String timeStr = "12:02:02"; + final String dateStr = "2002-03-04"; + final String timeStr = "02:03:04"; final String timeFormatString = "HH:mm:ss"; final String dateFormatString ="yyyy-MM-dd"; @@ -492,19 +488,7 @@ public class TestPutSQL { final long expectedTimeInLong = expectedTime.getTime(); final long expectedDateInLong = expectedDate.getTime(); - //test with time zone GMT to avoid negative value unmatched with long pattern problem. - SimpleDateFormat timeFormat = new SimpleDateFormat(timeFormatString); - timeFormat.setTimeZone(TimeZone.getTimeZone("GMT")); - java.util.Date parsedTimeGMT = timeFormat.parse(timeStr); - - SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatString); - dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); - java.util.Date parsedDateGMT = dateFormat.parse(dateStr); - - Calendar gmtCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT")); - - - //test with ISO LOCAL format attribute + // test with ISO LOCAL format attribute Map attributes = new HashMap<>(); attributes.put("sql.args.1.type", String.valueOf(Types.TIME)); attributes.put("sql.args.1.value", timeStr); @@ -515,22 +499,31 @@ public class TestPutSQL { runner.enqueue("INSERT INTO TIMESTAMPTEST3 (ID, ts1, ts2) VALUES (1, ?, ?)".getBytes(), attributes); - //test Long pattern without format attribute + // Since Derby database which is used for unit test does not have timezone in DATE and TIME type, + // and PutSQL converts date string into long representation using local timezone, + // we need to use local timezone. + SimpleDateFormat timeFormat = new SimpleDateFormat(timeFormatString); + java.util.Date parsedLocalTime = timeFormat.parse(timeStr); + + SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatString); + java.util.Date parsedLocalDate = dateFormat.parse(dateStr); + + // test Long pattern without format attribute attributes = new HashMap<>(); attributes.put("sql.args.1.type", String.valueOf(Types.TIME)); - attributes.put("sql.args.1.value", Long.toString(parsedTimeGMT.getTime())); + attributes.put("sql.args.1.value", Long.toString(parsedLocalTime.getTime())); attributes.put("sql.args.2.type", String.valueOf(Types.DATE)); - attributes.put("sql.args.2.value", Long.toString(parsedDateGMT.getTime())); + attributes.put("sql.args.2.value", Long.toString(parsedLocalDate.getTime())); runner.enqueue("INSERT INTO TIMESTAMPTEST3 (ID, ts1, ts2) VALUES (2, ?, ?)".getBytes(), attributes); - //test with format attribute + // test with format attribute attributes = new HashMap<>(); attributes.put("sql.args.1.type", String.valueOf(Types.TIME)); - attributes.put("sql.args.1.value", "120202000"); + attributes.put("sql.args.1.value", "020304000"); attributes.put("sql.args.1.format", "HHmmssSSS"); attributes.put("sql.args.2.type", String.valueOf(Types.DATE)); - attributes.put("sql.args.2.value", "20020202"); + attributes.put("sql.args.2.value", "20020304"); attributes.put("sql.args.2.format", "yyyyMMdd"); runner.enqueue("INSERT INTO TIMESTAMPTEST3 (ID, ts1, ts2) VALUES (3, ?, ?)".getBytes(), attributes); @@ -549,8 +542,8 @@ public class TestPutSQL { assertTrue(rs.next()); assertEquals(2, rs.getInt(1)); - assertEquals(parsedTimeGMT.getTime(), rs.getTime(2).getTime()); - assertEquals(parsedDateGMT.getTime(), rs.getDate(3,gmtCalendar).getTime()); + assertEquals(parsedLocalTime.getTime(), rs.getTime(2).getTime()); + assertEquals(parsedLocalDate.getTime(), rs.getDate(3).getTime()); assertTrue(rs.next()); assertEquals(3, rs.getInt(1)); @@ -692,11 +685,10 @@ public class TestPutSQL { runner.enableControllerService(service); runner.setProperty(PutSQL.CONNECTION_POOL, "dbcp"); - final String arg2TS = "00:01:01"; - final String art3TS = "12:02:02"; + final String arg2TS = "00:01:02"; + final String art3TS = "02:03:04"; final String timeFormatString = "HH:mm:ss"; SimpleDateFormat dateFormat = new SimpleDateFormat(timeFormatString); - dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); java.util.Date parsedDate = dateFormat.parse(arg2TS);