jmeter-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mchassagn...@apache.org
Subject svn commit: r1794517 - in /jmeter/trunk: ./ licenses/bin/ res/maven/ src/core/org/apache/jmeter/resources/ src/functions/org/apache/jmeter/functions/ test/src/org/apache/jmeter/functions/ xdocs/ xdocs/usermanual/
Date Tue, 09 May 2017 09:49:35 GMT
Author: mchassagneux
Date: Tue May  9 09:49:35 2017
New Revision: 1794517

URL: http://svn.apache.org/viewvc?rev=1794517&view=rev
Log:
Add a time shifting function
Bugzilla Id: 61040

Added:
    jmeter/trunk/licenses/bin/hamcrest-date-2.0.4.txt
    jmeter/trunk/src/functions/org/apache/jmeter/functions/TimeShift.java
    jmeter/trunk/test/src/org/apache/jmeter/functions/TestTimeShiftFunction.java
Modified:
    jmeter/trunk/LICENSE
    jmeter/trunk/build.properties
    jmeter/trunk/build.xml
    jmeter/trunk/eclipse.classpath
    jmeter/trunk/res/maven/ApacheJMeter_parent.pom
    jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
    jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties
    jmeter/trunk/test/src/org/apache/jmeter/functions/FunctionTestHelper.java
    jmeter/trunk/xdocs/changes.xml
    jmeter/trunk/xdocs/usermanual/functions.xml

Modified: jmeter/trunk/LICENSE
URL: http://svn.apache.org/viewvc/jmeter/trunk/LICENSE?rev=1794517&r1=1794516&r2=1794517&view=diff
==============================================================================
--- jmeter/trunk/LICENSE [utf-8] (original)
+++ jmeter/trunk/LICENSE [utf-8] Tue May  9 09:49:35 2017
@@ -277,3 +277,4 @@ For details, please see the files under:
 * xmlpull-1.1.3.1.jar (Public Domain)
 * xpp3-1.1.4c.jar (Indiana University Extreme! Lab Software License 1.1.1)
 * xstream-1.4.9.jar (BSD)
+* hamcrest-date-2.0.4.jar (BSD)

Modified: jmeter/trunk/build.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/build.properties?rev=1794517&r1=1794516&r2=1794517&view=diff
==============================================================================
--- jmeter/trunk/build.properties (original)
+++ jmeter/trunk/build.properties Tue May  9 09:49:35 2017
@@ -164,6 +164,12 @@ hamcrest-core.loc            = ${maven2.
 hamcrest-core.jar            = hamcrest-core-${hamcrest-core.version}.jar
 hamcrest-core.md5            = 6393363b47ddcbba82321110c3e07519
 
+# hamcrest-date
+hamcrest-date.version        = 2.0.4
+hamcrest-date.loc            = ${maven2.repo}/org/exparity/hamcrest-date/${hamcrest-date.version}
+hamcrest-date.jar            = hamcrest-date-${hamcrest-date.version}.jar
+hamcrest-date.md5            = e37d0c3e0a578f4da48d0e8fee6e4c44
+
 # Apache HttpASyncClient 4.x
 httpasyncclient.version          = 4.1.3
 httpasyncclient.jar              = httpasyncclient-${httpasyncclient.version}.jar

Modified: jmeter/trunk/build.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/build.xml?rev=1794517&r1=1794516&r2=1794517&view=diff
==============================================================================
--- jmeter/trunk/build.xml (original)
+++ jmeter/trunk/build.xml Tue May  9 09:49:35 2017
@@ -402,6 +402,7 @@
     <include name="${lib.dir}/${freemarker.jar}"/>
     <include name="${lib.dir}/${groovy-all.jar}"/>
     <include name="${lib.dir}/${hamcrest-core.jar}"/>
+    <include name="${lib.dir}/${hamcrest-date.jar}"/>
     <include name="${lib.dir}/${httpclient.jar}"/>
     <include name="${lib.dir}/${httpasyncclient.jar}"/>
     <include name="${lib.dir}/${httpcore.jar}"/>
@@ -483,6 +484,7 @@
     <pathelement location="${lib.dir}/${freemarker.jar}"/>
     <pathelement location="${lib.dir}/${groovy-all.jar}"/>
     <pathelement location="${lib.dir}/${hamcrest-core.jar}"/>
+    <pathelement location="${lib.dir}/${hamcrest-date.jar}"/>
     <pathelement location="${lib.dir}/${httpclient.jar}"/>
     <pathelement location="${lib.dir}/${httpasyncclient.jar}"/>
     <pathelement location="${lib.dir}/${httpcore.jar}"/>

Modified: jmeter/trunk/eclipse.classpath
URL: http://svn.apache.org/viewvc/jmeter/trunk/eclipse.classpath?rev=1794517&r1=1794516&r2=1794517&view=diff
==============================================================================
--- jmeter/trunk/eclipse.classpath (original)
+++ jmeter/trunk/eclipse.classpath Tue May  9 09:49:35 2017
@@ -65,6 +65,7 @@
 	<classpathentry kind="lib" path="lib/freemarker-2.3.23.jar"/>
 	<classpathentry kind="lib" path="lib/groovy-all-2.4.11.jar"/>
 	<classpathentry kind="lib" path="lib/hamcrest-core-1.3.jar"/>
+	<classpathentry kind="lib" path="lib/hamcrest-date-2.0.4.jar"/>
 	<classpathentry kind="lib" path="lib/geronimo-jms_1.1_spec-1.1.1.jar"/>
 	<classpathentry kind="lib" path="lib/httpasyncclient-4.1.3.jar"/>
 	<classpathentry kind="lib" path="lib/httpclient-4.5.3.jar"/>

Added: jmeter/trunk/licenses/bin/hamcrest-date-2.0.4.txt
URL: http://svn.apache.org/viewvc/jmeter/trunk/licenses/bin/hamcrest-date-2.0.4.txt?rev=1794517&view=auto
==============================================================================
--- jmeter/trunk/licenses/bin/hamcrest-date-2.0.4.txt (added)
+++ jmeter/trunk/licenses/bin/hamcrest-date-2.0.4.txt Tue May  9 09:49:35 2017
@@ -0,0 +1 @@
+According to https://github.com/eXparity/hamcrest-date/blob/hamcrest-date-2.0.4/pom.xml#L18-L24
Hamcrest-date is under BSD License
\ No newline at end of file

Modified: jmeter/trunk/res/maven/ApacheJMeter_parent.pom
URL: http://svn.apache.org/viewvc/jmeter/trunk/res/maven/ApacheJMeter_parent.pom?rev=1794517&r1=1794516&r2=1794517&view=diff
==============================================================================
--- jmeter/trunk/res/maven/ApacheJMeter_parent.pom (original)
+++ jmeter/trunk/res/maven/ApacheJMeter_parent.pom Tue May  9 09:49:35 2017
@@ -75,6 +75,7 @@ under the License.
       <freemarker.version>2.3.23</freemarker.version>
       <groovy-all.version>2.4.11</groovy-all.version>
       <hamcrest-core.version>1.3</hamcrest-core.version>
+      <hamcrest-date.version>2.0.4</hamcrest-date.version>
       <httpasyncclient.version>4.1.3</httpasyncclient.version>
       <httpclient.version>4.5.3</httpclient.version>
       <httpcore.version>4.4.6</httpcore.version>
@@ -433,6 +434,11 @@ under the License.
         <artifactId>hamcrest-core</artifactId>
         <version>${hamcrest-core.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.exparity</groupId>
+        <artifactId>hamcrest-date</artifactId>
+        <version>${hamcrest-date.version}</version>
+      </dependency>
     </dependencies>
 
     <repositories>

Modified: jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties?rev=1794517&r1=1794516&r2=1794517&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties Tue May  9 09:49:35
2017
@@ -243,6 +243,7 @@ database_sql_query_title=JDBC SQL Query
 database_testing_title=JDBC Request
 database_url=JDBC URL\:
 database_url_jdbc_props=Database URL and JDBC Driver
+date_to_shift=Date to shift (optional) (default \: now )
 ddn=DN
 de=German
 debug_off=Disable debug
@@ -1179,6 +1180,7 @@ throughput_control_perthread_label=Per U
 throughput_control_title=Throughput Controller
 throughput_control_tplabel=Throughput
 time_format=Format string for SimpleDateFormat (optional)
+time_format_shift=Format string for DateTimeFormatter (optional) ( default unix timestamp
in millisecond )
 timelim=Time limit
 timeout_config_box_title=Timeout configuration
 timeout_title=Timeout (ms)
@@ -1233,6 +1235,7 @@ userpw=Password
 validate_threadgroup=Validate
 value=Value
 value_to_quote_meta=Value to escape from ORO Regexp meta chars
+value_to_shift=Amount of seconds/minutes/hours/days to add ( example P2D \: plus one day
) (optional)
 var_name=Reference Name
 variable_name_param=Name of variable (may include variable and function references)
 view_graph_tree_title=View Graph Tree

Modified: jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties?rev=1794517&r1=1794516&r2=1794517&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties Tue May  9 09:49:35
2017
@@ -238,6 +238,7 @@ database_sql_query_title=Requ\u00EAte SQ
 database_testing_title=Requ\u221A\u2122te JDBC
 database_url=URL JDBC\:
 database_url_jdbc_props=URL et driver JDBC de la base de donn\u221A\u00A9es
+date_to_shift=Date sur laquelle on applique le d\u00E9callage (optionnel) (d\u00E9faut \:
maintenant )
 ddn=DN \:
 de=Allemand
 debug_off=D\u00E9sactiver le d\u00E9bogage
@@ -1168,7 +1169,8 @@ throughput_control_bypercent_label=Pourc
 throughput_control_perthread_label=Par utilisateur
 throughput_control_title=Contr\u00F4leur D\u00E9bit
 throughput_control_tplabel=D\u00E9bit \:
-time_format=Chaine de formatage sur le mod\u00E8le SimpleDateFormat (optionnel)
+time_format=Cha00EEne de formatage sur le mod\u00E8le SimpleDateFormat (optionnel)
+time_format_shift=Cha\u00EEne de formatage sur le mod\u00E8le DateTimeFormatter (optionnel)
( d\u00E9faut \: unix timestamp en millisecondes )
 timelim=Limiter le temps de r\u00E9ponses \u00E0 (ms)
 timeout_config_box_title=Configuration du d\u00E9lai d'expiration
 timeout_title=D\u00E9lai expiration (ms)
@@ -1223,6 +1225,7 @@ userpw=Mot de passe
 validate_threadgroup=Valider
 value=Valeur \:
 value_to_quote_meta=Valeur \u00E0 \u00E9chapper des caract\u00E8res sp\u00E9ciaux utilis\u00E8s
par ORO Regexp
+value_to_shift=Valeur \u00E0 ajouter ( example P2D \: plus deux jour ) (optionnel)
 var_name=Nom de r\u00E9f\u00E9rence \:
 variable_name_param=Nom de variable (peut inclure une r\u00E9f\u00E9rence de variable ou
fonction)
 view_graph_tree_title=Voir le graphique en arbre

Added: jmeter/trunk/src/functions/org/apache/jmeter/functions/TimeShift.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/functions/org/apache/jmeter/functions/TimeShift.java?rev=1794517&view=auto
==============================================================================
--- jmeter/trunk/src/functions/org/apache/jmeter/functions/TimeShift.java (added)
+++ jmeter/trunk/src/functions/org/apache/jmeter/functions/TimeShift.java Tue May  9 09:49:35
2017
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.jmeter.functions;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.Year;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.DateTimeParseException;
+import java.time.temporal.ChronoField;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.jmeter.engine.util.CompoundVariable;
+import org.apache.jmeter.samplers.SampleResult;
+import org.apache.jmeter.samplers.Sampler;
+import org.apache.jmeter.threads.JMeterVariables;
+import org.apache.jmeter.util.JMeterUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.github.benmanes.caffeine.cache.Cache;
+import com.github.benmanes.caffeine.cache.Caffeine;
+
+/**
+ * timeShifting Function permit to shift a date
+ *
+ * Parameters: - format date @see
+ * https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html
+ * (optional - defaults to epoch time in millisecond) - date to shift formated
+ * as first param (optional - defaults now) - amount of (seconds, minutes,
+ * hours, days ) to add (optional - default nothing is add ) -
+ * variable name ( optional )
+ *
+ * Returns: a formatted date with the specified number of (seconds, minutes,
+ * hours, days or months ) added. - value is also saved in the variable for
+ * later re-use.
+ *
+ * @since 3.3
+ */
+public class TimeShift extends AbstractFunction {
+    private static final Logger log = LoggerFactory.getLogger(TimeShift.class);
+
+    private static final String KEY = "__timeShift"; // $NON-NLS-1$
+
+    private static final List<String> desc = Arrays.asList(JMeterUtils.getResString("time_format_shift"),
+            JMeterUtils.getResString("date_to_shift"), JMeterUtils.getResString("value_to_shift"),
+            JMeterUtils.getResString("function_name_paropt"));
+
+    // Ensure that these are set, even if no paramters are provided
+    private String format = ""; //$NON-NLS-1$
+    private String dateToShift = ""; //$NON-NLS-1$
+    private String amountToShift = ""; //$NON-NLS-1$
+    private String variableName = ""; //$NON-NLS-1$
+    private ZoneId systemDefaultZoneID = ZoneId.systemDefault();
+
+    /** Date time format cache handler **/
+    private Cache<String, DateTimeFormatter> dateTimeFormatterCache = null;
+
+    public TimeShift() {
+        super();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String execute(SampleResult previousResult, Sampler currentSampler) throws InvalidVariableException
{
+        String dateString;
+        LocalDateTime localDateTimeToShift = LocalDateTime.now(systemDefaultZoneID);
+        DateTimeFormatter formatter = null;
+        if (!StringUtils.isEmpty(format)) {
+            try {
+                formatter = (DateTimeFormatter) dateTimeFormatterCache.get(format, key ->
createFormatter((String)key));
+            } catch (IllegalArgumentException ex) {
+                log.error("Format date pattern '{}' is invalid (see https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html)",
format, ex); // $NON-NLS-1$
+                return "";
+            }
+        }
+
+        if (!dateToShift.isEmpty()) {
+            try {
+                if (formatter != null) {
+                    localDateTimeToShift = LocalDateTime.parse(dateToShift, formatter);
+                } else {
+                    localDateTimeToShift = LocalDateTime.ofInstant(Instant.ofEpochMilli(Long.parseLong(dateToShift)),
+                            ZoneId.systemDefault());
+                }
+            } catch (DateTimeParseException | NumberFormatException ex) {
+                log.error("Failed to parse the date '{}' to shift", dateToShift, ex); //
$NON-NLS-1$
+            }
+        }
+
+        // Check amount value to shift
+        if (!StringUtils.isEmpty(amountToShift)) {
+            try {
+                Duration duration = Duration.parse(amountToShift);
+                localDateTimeToShift = localDateTimeToShift.plus(duration);
+            } catch (DateTimeParseException ex) {
+                log.error("Failed to parse the amount duration '{}' to shift (see https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html#parse-java.lang.CharSequence-)
", amountToShift, ex); // $NON-NLS-1$
+            }
+        }
+
+        if (formatter != null) {
+            dateString = localDateTimeToShift.format(formatter);
+        } else {
+            ZoneOffset offset = ZoneOffset.systemDefault().getRules().getOffset(localDateTimeToShift);
+            dateString = String.valueOf(localDateTimeToShift.toInstant(offset).toEpochMilli());
+        }
+
+        if (!StringUtils.isEmpty(variableName)) {
+            JMeterVariables vars = getVariables();
+            if (vars != null) {// vars will be null on TestPlan
+                vars.put(variableName, dateString);
+            }
+        }
+        return dateString;
+    }
+
+    private DateTimeFormatter createFormatter(String format) throws IllegalArgumentException
{
+
+        log.debug("Create a new instance of DateTimeFormatter for format '{}' in the cache",
format);
+        return new DateTimeFormatterBuilder().appendPattern(format).parseDefaulting(ChronoField.NANO_OF_SECOND,
0)
+                .parseDefaulting(ChronoField.MILLI_OF_SECOND, 0).parseDefaulting(ChronoField.SECOND_OF_MINUTE,
0)
+                .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0).parseDefaulting(ChronoField.HOUR_OF_DAY,
0)
+                .parseDefaulting(ChronoField.DAY_OF_MONTH, 1).parseDefaulting(ChronoField.MONTH_OF_YEAR,
1)
+                .parseDefaulting(ChronoField.YEAR_OF_ERA, Year.now().getValue()).toFormatter(JMeterUtils.getLocale());
+    }
+
+    protected static Cache<String, DateTimeFormatter> buildCache() {
+        Caffeine<Object, Object> cacheBuilder = Caffeine.newBuilder();
+        cacheBuilder.maximumSize(100);
+        return cacheBuilder.build();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void setParameters(Collection<CompoundVariable> parameters) throws InvalidVariableException
{
+
+        checkParameterCount(parameters, 0, 4);
+        Object[] values = parameters.toArray();
+
+        format = ((CompoundVariable) values[0]).execute().trim();
+        dateToShift = ((CompoundVariable) values[1]).execute().trim();
+        amountToShift = ((CompoundVariable) values[2]).execute().trim();
+        variableName = ((CompoundVariable) values[3]).execute().trim();
+
+        // Create the cache
+        if (dateTimeFormatterCache == null) {
+            dateTimeFormatterCache =  buildCache();
+        }
+
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String getReferenceKey() {
+        return KEY;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public List<String> getArgumentDesc() {
+        return desc;
+    }
+}

Modified: jmeter/trunk/test/src/org/apache/jmeter/functions/FunctionTestHelper.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/test/src/org/apache/jmeter/functions/FunctionTestHelper.java?rev=1794517&r1=1794516&r2=1794517&view=diff
==============================================================================
--- jmeter/trunk/test/src/org/apache/jmeter/functions/FunctionTestHelper.java (original)
+++ jmeter/trunk/test/src/org/apache/jmeter/functions/FunctionTestHelper.java Tue May  9 09:49:35
2017
@@ -25,16 +25,12 @@ import org.apache.jmeter.engine.util.Com
 
 public class FunctionTestHelper {
 
-    public static Collection<CompoundVariable> makeParams(String p1, String p2, String
p3) {
+    public static Collection<CompoundVariable> makeParams(String... params) {
         Collection<CompoundVariable> parms = new LinkedList<>();
-        if (p1 != null) {
-            parms.add(new CompoundVariable(p1));
-        }
-        if (p2 != null) {
-            parms.add(new CompoundVariable(p2));
-        }
-        if (p3 != null) {
-            parms.add(new CompoundVariable(p3));
+        for (String p : params) {
+            if (p != null) {
+                parms.add(new CompoundVariable(p));
+            }
         }
         return parms;
     }

Added: jmeter/trunk/test/src/org/apache/jmeter/functions/TestTimeShiftFunction.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/test/src/org/apache/jmeter/functions/TestTimeShiftFunction.java?rev=1794517&view=auto
==============================================================================
--- jmeter/trunk/test/src/org/apache/jmeter/functions/TestTimeShiftFunction.java (added)
+++ jmeter/trunk/test/src/org/apache/jmeter/functions/TestTimeShiftFunction.java Tue May 
9 09:49:35 2017
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+
+package org.apache.jmeter.functions;
+
+import static org.apache.jmeter.functions.FunctionTestHelper.makeParams;
+import static org.exparity.hamcrest.date.LocalDateMatchers.sameDay;
+import static org.exparity.hamcrest.date.LocalDateTimeMatchers.within;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.temporal.ChronoUnit;
+import java.util.Collection;
+import java.util.TimeZone;
+
+import org.apache.jmeter.engine.util.CompoundVariable;
+import org.apache.jmeter.junit.JMeterTestCase;
+import org.apache.jmeter.samplers.SampleResult;
+import org.apache.jmeter.threads.JMeterContext;
+import org.apache.jmeter.threads.JMeterContextService;
+import org.apache.jmeter.threads.JMeterVariables;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestTimeShiftFunction extends JMeterTestCase {
+    private Function function;
+
+    private SampleResult result;
+
+    private JMeterVariables vars;
+
+    private JMeterContext jmctx = null;
+
+    private String value;
+
+    @Before
+    public void setUp() {
+        jmctx = JMeterContextService.getContext();
+        vars = new JMeterVariables();
+        jmctx.setVariables(vars);
+        jmctx.setPreviousResult(result);
+        result = new SampleResult();
+        function = new TimeShift();
+    }
+
+    @Test
+    public void testDatePlusOneDay() throws Exception {
+        Collection<CompoundVariable> params = makeParams("yyyy-dd-MM", "2017-01-01",
"P1D", "");
+        function.setParameters(params);
+        value = function.execute(result, null);
+        assertThat(value, is(equalTo("2017-02-01")));
+    }
+
+    @Test
+    public void testDatePlusOneDayInVariable() throws Exception {
+        Collection<CompoundVariable> params = makeParams("yyyy-dd-MM", "2017-01-01",
"P1d", "VAR");
+        function.setParameters(params);
+        function.execute(result, null);
+        assertThat(vars.get("VAR"), is(equalTo("2017-02-01")));
+    }
+
+    @Test
+    public void testDatePlusComplexPeriod() throws Exception {
+        Collection<CompoundVariable> params = makeParams("yyyy-dd-MM HH:m", "2017-01-01
12:00", "P+32dT-1H-5m", "VAR");
+        function.setParameters(params);
+        String value = function.execute(result, null);
+        assertThat(value, is(equalTo("2017-02-02 10:55")));
+    }
+
+    @Test
+    public void testDefault() throws Exception {
+        Collection<CompoundVariable> params = makeParams("", "", "", "");
+        function.setParameters(params);
+        value = function.execute(result, null);
+        long resultat = Long.parseLong(value);
+        LocalDateTime  nowFromFunction = LocalDateTime.ofInstant(Instant.ofEpochMilli(resultat),
TimeZone
+                .getDefault().toZoneId());
+        assertThat(nowFromFunction, within(5, ChronoUnit.SECONDS, LocalDateTime.now()));
+    }
+
+    @Test
+    public void testNowPlusOneDay() throws Exception {
+        Collection<CompoundVariable> params = makeParams("YYYY-MM-dd", "", "P1d", "");
+        function.setParameters(params);
+        value = function.execute(result, null);
+        LocalDate tomorrow = LocalDate.now().plusDays(1);
+        LocalDate tomorrowFromFunction = LocalDate.parse(value);
+        assertThat(tomorrowFromFunction, sameDay(tomorrow));
+    }
+    
+    @Test
+    public void testNowWithComplexPeriod() throws Exception {
+        Collection<CompoundVariable> params = makeParams("YYYY-MM-dd'T'HH:mm:ss", "",
"P10DT-1H-5M5S", "");
+        function.setParameters(params);
+        value = function.execute(result, null);
+        LocalDateTime futureDate = LocalDateTime.now().plusDays(10).plusHours(-1).plusMinutes(-5).plusSeconds(5);
+        LocalDateTime futureDateFromFunction = LocalDateTime.parse(value);
+        assertThat(futureDateFromFunction, within(1, ChronoUnit.SECONDS, futureDate));
+    }
+
+    @Test
+    public void testWrongAmountToAdd() throws Exception {
+        // Nothing is add with wrong value, so check if return is now
+        Collection<CompoundVariable> params = makeParams("", "", "qefv1Psd", "");
+        function.setParameters(params);
+        value = function.execute(result, null);
+        long resultat = Long.parseLong(value);
+        LocalDateTime  nowFromFunction = LocalDateTime.ofInstant(Instant.ofEpochMilli(resultat),
TimeZone
+                .getDefault().toZoneId());
+        assertThat(nowFromFunction, within(5, ChronoUnit.SECONDS, LocalDateTime.now()));
+    }
+
+    @Test
+    public void testWrongFormatDate() throws Exception {
+        Collection<CompoundVariable> params = makeParams("hjfdjyra:fd", "", "P1D",
"");
+        function.setParameters(params);
+        value = function.execute(result, null);
+        assertThat(value, is(equalTo("")));
+    }
+
+}

Modified: jmeter/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml?rev=1794517&r1=1794516&r2=1794517&view=diff
==============================================================================
--- jmeter/trunk/xdocs/changes.xml [utf-8] (original)
+++ jmeter/trunk/xdocs/changes.xml [utf-8] Tue May  9 09:49:35 2017
@@ -107,6 +107,7 @@ Summary
 
 <h3>Functions</h3>
 <ul>
+    <li><bug>61040</bug>Add a time shifting function</li>
 </ul>
 
 <h3>I18N</h3>

Modified: jmeter/trunk/xdocs/usermanual/functions.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/usermanual/functions.xml?rev=1794517&r1=1794516&r2=1794517&view=diff
==============================================================================
--- jmeter/trunk/xdocs/usermanual/functions.xml (original)
+++ jmeter/trunk/xdocs/usermanual/functions.xml Tue May  9 09:49:35 2017
@@ -112,6 +112,7 @@ Alternatively, just use <code>/</code> i
         <tr><td>Information</td><td> <a href="#__machineIP">machineIP</a></td><td>get
the local machine IP address</td><td>2.6</td></tr>
         <tr><td>Information</td><td> <a href="#__machineName">machineName</a></td><td>get
the local machine name</td><td>1.X</td></tr>
         <tr><td>Information</td><td> <a href="#__time">time</a></td><td>return
current time in various formats</td><td>2.2</td></tr>
+        <tr><td>Information</td><td> <a href="#__timeShift">timeShift</a></td><td>return
a date in various formats with the specified amount of seconds/minutes/hours/days added</td><td>3.3</td></tr>
         <tr><td>Information</td><td> <a href="#__log">log</a></td><td>log
(or display) a message (and return the value)</td><td>2.2</td></tr>
         <tr><td>Information</td><td> <a href="#__logn">logn</a></td><td>log
(or display) a message (empty return value)</td><td>2.2</td></tr>
         <tr><td>Input</td><td> <a href="#__StringFromFile">StringFromFile</a></td><td>read
a line from a file</td><td>1.9</td></tr>
@@ -1499,6 +1500,34 @@ becomes:
 </properties>
 </component>
 
+
+<component index="&sect-num;.5.22" name="__timeShift">
+<description>
+    <p>The timeShift function returns a date in the given format with the specified
amount of seconds, minutes, hours, days or months added</p>
+    </description>
+<properties>
+        <property name="Format" required="No">
+        The format to be passed to DateTimeFormatter.
+        If omitted, the function uses milliseconds since epoch format.
+        </property>
+        <property name="Date to shift" required="No">
+        Indicate the date in the format set by the parameter 'Format' to shift
+        If omitted, the date is set to now
+        </property>
+        <property name="value to shift" required="No">
+        Indicate the specified amount of seconds, minutes, hours or days to shift according
to a textual representation of a duration such as PnDTnHnMn.nS. See https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html#parse-java.lang.CharSequence-

+        <ul>
+        <li><code>PT20.345S</code> parses as 20.345 seconds</li>
+        <li><code>PT15M</code> parses as 15 minutes</li>
+        <li><code>PT10H</code> parses as 10 hours</li>
+        <li><code>P2D</code> parses as 2 days</li>
+        <li><code>-P6H3M</code> parses as -6 hours and -3 minutes</li>
+        </ul>
+        </property>
+        <property name="Name of variable" required="No">The name of the variable to
set.</property>
+</properties>
+</component>
+
 </subsection>
 
 <subsection name="&sect-num;.6 Pre-defined Variables" anchor="predefinedvars">



Mime
View raw message