You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by pm...@apache.org on 2017/12/01 20:50:47 UTC

svn commit: r1816906 - in /jmeter/trunk: bin/ src/components/org/apache/jmeter/assertions/ src/components/org/apache/jmeter/assertions/gui/ src/core/org/apache/jmeter/resources/ src/core/org/apache/jmeter/save/ test/src/org/apache/jmeter/assertions/ xd...

Author: pmouawad
Date: Fri Dec  1 20:50:46 2017
New Revision: 1816906

URL: http://svn.apache.org/viewvc?rev=1816906&view=rev
Log:
Bug 61845 - New Component JSON Assertion
Based on AtlanBH component donated to JMeter-Plugins.
Migration to JMeter Core contributed by Artem Fedorov
This closes #344
Bugzilla Id: 61845

Added:
    jmeter/trunk/src/components/org/apache/jmeter/assertions/JSONPathAssertion.java   (with props)
    jmeter/trunk/src/components/org/apache/jmeter/assertions/gui/JSONPathAssertionGui.java   (with props)
    jmeter/trunk/test/src/org/apache/jmeter/assertions/TestJSONPathAssertion.java   (with props)
    jmeter/trunk/test/src/org/apache/jmeter/assertions/TestJSONPathAssertionGui.java   (with props)
Modified:
    jmeter/trunk/bin/saveservice.properties
    jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
    jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties
    jmeter/trunk/src/core/org/apache/jmeter/save/SaveService.java
    jmeter/trunk/xdocs/changes.xml
    jmeter/trunk/xdocs/usermanual/component_reference.xml

Modified: jmeter/trunk/bin/saveservice.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/bin/saveservice.properties?rev=1816906&r1=1816905&r2=1816906&view=diff
==============================================================================
--- jmeter/trunk/bin/saveservice.properties (original)
+++ jmeter/trunk/bin/saveservice.properties Fri Dec  1 20:50:46 2017
@@ -196,6 +196,8 @@ JMSPublisherGui=org.apache.jmeter.protoc
 JMSSampler=org.apache.jmeter.protocol.jms.sampler.JMSSampler
 JMSSamplerGui=org.apache.jmeter.protocol.jms.control.gui.JMSSamplerGui
 JMSSubscriberGui=org.apache.jmeter.protocol.jms.control.gui.JMSSubscriberGui
+JSONPathAssertion=org.apache.jmeter.assertions.JSONPathAssertion
+JSONPathAssertionGui=org.apache.jmeter.assertions.gui.JSONPathAssertionGui
 JSONPostProcessor=org.apache.jmeter.extractor.json.jsonpath.JSONPostProcessor
 JSONPostProcessorGui=org.apache.jmeter.extractor.json.jsonpath.gui.JSONPostProcessorGui
 # Removed in r545311 as Jndi no longer present; keep for compat.

Added: jmeter/trunk/src/components/org/apache/jmeter/assertions/JSONPathAssertion.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/assertions/JSONPathAssertion.java?rev=1816906&view=auto
==============================================================================
--- jmeter/trunk/src/components/org/apache/jmeter/assertions/JSONPathAssertion.java (added)
+++ jmeter/trunk/src/components/org/apache/jmeter/assertions/JSONPathAssertion.java Fri Dec  1 20:50:46 2017
@@ -0,0 +1,221 @@
+/*
+ * 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.assertions;
+
+import java.io.Serializable;
+import java.text.DecimalFormat;
+import java.util.Map;
+
+import org.apache.jmeter.extractor.json.jsonpath.JSONPostProcessor;
+import org.apache.jmeter.samplers.SampleResult;
+import org.apache.jmeter.testelement.AbstractTestElement;
+import org.apache.jmeter.util.JMeterUtils;
+import org.apache.oro.text.regex.Pattern;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.jayway.jsonpath.JsonPath;
+
+import net.minidev.json.JSONArray;
+import net.minidev.json.JSONObject;
+
+/**
+ * This is main class for JSONPath Assertion which verifies assertion on
+ * previous sample result using JSON path expression
+ * @since 4.0
+ */
+public class JSONPathAssertion extends AbstractTestElement implements Serializable, Assertion {
+    private static final Logger log = LoggerFactory.getLogger(JSONPostProcessor.class);
+    private static final long serialVersionUID = 1L;
+    public static final String JSONPATH = "JSON_PATH";
+    public static final String EXPECTEDVALUE = "EXPECTED_VALUE";
+    public static final String JSONVALIDATION = "JSONVALIDATION";
+    public static final String EXPECT_NULL = "EXPECT_NULL";
+    public static final String INVERT = "INVERT";
+    public static final String ISREGEX = "ISREGEX";
+
+    private static ThreadLocal<DecimalFormat> decimalFormatter = 
+            ThreadLocal.withInitial(JSONPathAssertion::createDecimalFormat);
+
+    private static DecimalFormat createDecimalFormat() {
+        DecimalFormat decimalFormatter = new DecimalFormat("#.#");
+        decimalFormatter.setMaximumFractionDigits(340); // java.text.DecimalFormat.DOUBLE_FRACTION_DIGITS == 340
+        decimalFormatter.setMinimumFractionDigits(1);
+        return decimalFormatter;
+    }
+    public String getJsonPath() {
+        return getPropertyAsString(JSONPATH);
+    }
+
+    public void setJsonPath(String jsonPath) {
+        setProperty(JSONPATH, jsonPath);
+    }
+
+    public String getExpectedValue() {
+        return getPropertyAsString(EXPECTEDVALUE);
+    }
+
+    public void setExpectedValue(String expectedValue) {
+        setProperty(EXPECTEDVALUE, expectedValue);
+    }
+
+    public void setJsonValidationBool(boolean jsonValidation) {
+        setProperty(JSONVALIDATION, jsonValidation);
+    }
+
+    public void setExpectNull(boolean val) {
+        setProperty(EXPECT_NULL, val);
+    }
+
+    public boolean isExpectNull() {
+        return getPropertyAsBoolean(EXPECT_NULL);
+    }
+
+    public boolean isJsonValidationBool() {
+        return getPropertyAsBoolean(JSONVALIDATION);
+    }
+
+    public void setInvert(boolean invert) {
+        setProperty(INVERT, invert);
+    }
+
+    public boolean isInvert() {
+        return getPropertyAsBoolean(INVERT);
+    }
+
+    public void setIsRegex(boolean flag) {
+        setProperty(ISREGEX, flag);
+    }
+
+    public boolean isUseRegex() {
+        return getPropertyAsBoolean(ISREGEX, true);
+    }
+
+    private void doAssert(String jsonString) {
+        Object value = JsonPath.read(jsonString, getJsonPath());
+
+        if (isJsonValidationBool()) {
+            if (value instanceof JSONArray) {
+                if (arrayMatched((JSONArray) value)) {
+                    return;
+                }
+            } else {
+                if (isExpectNull() && value == null) {
+                    return;
+                } else if (isEquals(value)) {
+                    return;
+                }
+            }
+
+            if (isExpectNull()) {
+                throw new IllegalStateException(String.format("Value expected to be null, but found '%s'", value));
+            } else {
+                String msg;
+                if (isUseRegex()) {
+                    msg="Value expected to match regexp '%s', but it did not match: '%s'";
+                } else {
+                    msg="Value expected to be '%s', but found '%s'";
+                }
+                throw new IllegalStateException(String.format(msg, getExpectedValue(), objectToString(value)));
+            }
+        }
+    }
+
+    private boolean arrayMatched(JSONArray value) {
+        if (value.isEmpty() && getExpectedValue().equals("[]")) {
+            return true;
+        }
+
+        for (Object subj : value.toArray()) {
+            if ((subj == null && isExpectNull()) ||
+                    isEquals(subj)) {
+                return true;
+            }
+        }
+
+        return isEquals(value);
+    }
+
+    private boolean isEquals(Object subj) {
+        String str = objectToString(subj);
+        if (isUseRegex()) {
+            Pattern pattern = JMeterUtils.getPatternCache().getPattern(getExpectedValue());
+            return JMeterUtils.getMatcher().matches(str, pattern);
+        } else {
+            return str.equals(getExpectedValue());
+        }
+    }
+
+    @Override
+    public AssertionResult getResult(SampleResult samplerResult) {
+        AssertionResult result = new AssertionResult(getName());
+        String responseData = samplerResult.getResponseDataAsString();
+        if (responseData.isEmpty()) {
+            return result.setResultForNull();
+        }
+
+        result.setFailure(false);
+        result.setFailureMessage("");
+
+        if (!isInvert()) {
+            try {
+                doAssert(responseData);
+            } catch (Exception e) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Assertion failed", e);
+                }
+                result.setFailure(true);
+                result.setFailureMessage(e.getMessage());
+            }
+        } else {
+            try {
+                doAssert(responseData);
+                result.setFailure(true);
+                if (isJsonValidationBool()) {
+                    if (isExpectNull()) {
+                        result.setFailureMessage("Failed that JSONPath " + getJsonPath() + " not matches null");
+                    } else {
+                        result.setFailureMessage("Failed that JSONPath " + getJsonPath() + " not matches " + getExpectedValue());
+                    }
+                } else {
+                    result.setFailureMessage("Failed that JSONPath not exists: " + getJsonPath());
+                }
+            } catch (Exception e) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Assertion failed", e);
+                }
+            }
+        }
+        return result;
+    }
+
+    public static String objectToString(Object subj) {
+        String str;
+        if (subj == null) {
+            str = "null";
+        } else if (subj instanceof Map) {
+            //noinspection unchecked
+            str = new JSONObject((Map<String, ?>) subj).toJSONString();
+        } else if (subj instanceof Double || subj instanceof Float) {
+            str = decimalFormatter.get().format(subj);
+        } else {
+            str = subj.toString();
+        }
+        return str;
+    }
+}

Propchange: jmeter/trunk/src/components/org/apache/jmeter/assertions/JSONPathAssertion.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jmeter/trunk/src/components/org/apache/jmeter/assertions/JSONPathAssertion.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jmeter/trunk/src/components/org/apache/jmeter/assertions/gui/JSONPathAssertionGui.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/assertions/gui/JSONPathAssertionGui.java?rev=1816906&view=auto
==============================================================================
--- jmeter/trunk/src/components/org/apache/jmeter/assertions/gui/JSONPathAssertionGui.java (added)
+++ jmeter/trunk/src/components/org/apache/jmeter/assertions/gui/JSONPathAssertionGui.java Fri Dec  1 20:50:46 2017
@@ -0,0 +1,137 @@
+/*
+ * 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.assertions.gui;
+
+import org.apache.jmeter.assertions.JSONPathAssertion;
+import org.apache.jmeter.gui.util.VerticalPanel;
+import org.apache.jmeter.testelement.TestElement;
+import org.apache.jmeter.util.JMeterUtils;
+import org.apache.jorphan.gui.JLabeledTextArea;
+import org.apache.jorphan.gui.JLabeledTextField;
+
+
+import javax.swing.JCheckBox;
+import javax.swing.BorderFactory;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import java.awt.BorderLayout;
+
+/**
+ * Java class representing GUI for the {@link JSONPathAssertion} component in JMeter
+ * @since 4.0
+ */
+public class JSONPathAssertionGui extends AbstractAssertionGui implements ChangeListener {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = -6008018002423594040L;
+    private JLabeledTextField jsonPath = null;
+    private JLabeledTextArea jsonValue = null;
+    private JCheckBox jsonValidation = null;
+    private JCheckBox expectNull = null;
+    private JCheckBox invert = null;
+    private JCheckBox isRegex;
+
+    public JSONPathAssertionGui() {
+        init();
+    }
+
+    public void init() {
+        setLayout(new BorderLayout());
+        setBorder(makeBorder());
+        add(makeTitlePanel(), BorderLayout.NORTH);
+
+        VerticalPanel panel = new VerticalPanel();
+        panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
+
+        jsonPath = new JLabeledTextField(JMeterUtils.getResString("json_assertion_path"));
+        jsonValidation = new JCheckBox(JMeterUtils.getResString("json_assertion_validation"));
+        isRegex = new JCheckBox(JMeterUtils.getResString("json_assertion_regex"));
+        jsonValue = new JLabeledTextArea(JMeterUtils.getResString("json_assertion_expected_value"));
+        expectNull = new JCheckBox(JMeterUtils.getResString("json_assertion_null"));
+        invert = new JCheckBox(JMeterUtils.getResString("json_assertion_invert"));
+
+        jsonValidation.addChangeListener(this);
+        expectNull.addChangeListener(this);
+
+        panel.add(jsonPath);
+        panel.add(jsonValidation);
+        panel.add(isRegex);
+        panel.add(jsonValue);
+        panel.add(expectNull);
+        panel.add(invert);
+
+        add(panel, BorderLayout.CENTER);
+    }
+
+    @Override
+    public void clearGui() {
+        super.clearGui();
+        jsonPath.setText("$.");
+        jsonValue.setText("");
+        jsonValidation.setSelected(false);
+        expectNull.setSelected(false);
+        invert.setSelected(false);
+        isRegex.setSelected(true);
+    }
+
+    @Override
+    public TestElement createTestElement() {
+        JSONPathAssertion jpAssertion = new JSONPathAssertion();
+        modifyTestElement(jpAssertion);
+        return jpAssertion;
+    }
+
+    @Override
+    public String getLabelResource() {
+        return "json_assertion_title";
+    }
+
+    @Override
+    public void modifyTestElement(TestElement element) {
+        super.configureTestElement(element);
+        if (element instanceof JSONPathAssertion) {
+            JSONPathAssertion jpAssertion = (JSONPathAssertion) element;
+            jpAssertion.setJsonPath(jsonPath.getText());
+            jpAssertion.setExpectedValue(jsonValue.getText());
+            jpAssertion.setJsonValidationBool(jsonValidation.isSelected());
+            jpAssertion.setExpectNull(expectNull.isSelected());
+            jpAssertion.setInvert(invert.isSelected());
+            jpAssertion.setIsRegex(isRegex.isSelected());
+        }
+    }
+
+    @Override
+    public void configure(TestElement element) {
+        super.configure(element);
+        JSONPathAssertion jpAssertion = (JSONPathAssertion) element;
+        jsonPath.setText(jpAssertion.getJsonPath());
+        jsonValue.setText(jpAssertion.getExpectedValue());
+        jsonValidation.setSelected(jpAssertion.isJsonValidationBool());
+        expectNull.setSelected(jpAssertion.isExpectNull());
+        invert.setSelected(jpAssertion.isInvert());
+        isRegex.setSelected(jpAssertion.isUseRegex());
+    }
+
+    @Override
+    public void stateChanged(ChangeEvent e) {
+        jsonValue.setEnabled(jsonValidation.isSelected() && !expectNull.isSelected());
+        isRegex.setEnabled(jsonValidation.isSelected() && !expectNull.isSelected());
+    }
+}

Propchange: jmeter/trunk/src/components/org/apache/jmeter/assertions/gui/JSONPathAssertionGui.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jmeter/trunk/src/components/org/apache/jmeter/assertions/gui/JSONPathAssertionGui.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

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=1816906&r1=1816905&r2=1816906&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties Fri Dec  1 20:50:46 2017
@@ -563,6 +563,13 @@ jsonpath_tester_field=JSON Path Expressi
 jsonpath_tester_button_test=Test
 jsonpath_render_no_text=No Text
 json_post_processor_title=JSON Extractor
+json_assertion_title=JSON Assertion
+json_assertion_path=Assert JSON Path exists\:
+json_assertion_validation=Additionally assert value
+json_assertion_regex=Match as regular expression
+json_assertion_expected_value=Expected Value\:
+json_assertion_null=Expect null
+json_assertion_invert=Invert assertion (will fail if above conditions met)
 jsonpp_variable_names=Names of created variables\:
 jsonpp_json_path_expressions=JSON Path expressions\:
 jsonpp_default_values=Default Values\:

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=1816906&r1=1816905&r2=1816906&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 Fri Dec  1 20:50:46 2017
@@ -558,6 +558,13 @@ jsonpath_renderer=Testeur JSON Path
 jsonpath_tester_button_test=Tester
 jsonpath_tester_field=Expression JSON Path
 jsonpath_tester_title=Testeur JSON Path
+json_assertion_title=Assertion JSON
+json_assertion_path=V\u00e9rifier que le chemin JSON existe\:
+json_assertion_validation=V\u00e9rification suppl\u00e9mentaire
+json_assertion_regex=Correspondance selon expression r\u00e9guli\u00e8re
+json_assertion_expected_value=Valeur attendue\:
+json_assertion_null=Valeur nulle attendue
+json_assertion_invert=Inverser l'assertion (\u00E9chouera si les conditions ci-dessus sont remplies)
 jsonpp_compute_concat=Calculer la variable de concat\u00E9nation (suffix _ALL)\:
 jsonpp_default_values=Valeur par d\u00E9fault\:
 jsonpp_error_number_arguments_mismatch_error=D\u00E9calage entre nombre de variables, expressions et valeurs par d\u00E9faut

Modified: jmeter/trunk/src/core/org/apache/jmeter/save/SaveService.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/save/SaveService.java?rev=1816906&r1=1816905&r2=1816906&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/save/SaveService.java (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/save/SaveService.java Fri Dec  1 20:50:46 2017
@@ -155,7 +155,7 @@ public class SaveService {
     private static String fileVersion = ""; // computed from saveservice.properties file// $NON-NLS-1$
     // Must match the sha1 checksum of the file saveservice.properties (without newline character),
     // used to ensure saveservice.properties and SaveService are updated simultaneously
-    static final String FILEVERSION = "54a9f5b36af5922f2d58cc4938a800fc2ca3f3c5"; // Expected value $NON-NLS-1$
+    static final String FILEVERSION = "0acd8200bf252acf41d5eeca6aa56b0eaee06f0f"; // Expected value $NON-NLS-1$
 
     private static String fileEncoding = ""; // read from properties file// $NON-NLS-1$
 

Added: jmeter/trunk/test/src/org/apache/jmeter/assertions/TestJSONPathAssertion.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/test/src/org/apache/jmeter/assertions/TestJSONPathAssertion.java?rev=1816906&view=auto
==============================================================================
--- jmeter/trunk/test/src/org/apache/jmeter/assertions/TestJSONPathAssertion.java (added)
+++ jmeter/trunk/test/src/org/apache/jmeter/assertions/TestJSONPathAssertion.java Fri Dec  1 20:50:46 2017
@@ -0,0 +1,383 @@
+/*
+ * 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.assertions;
+
+import org.apache.jmeter.samplers.SampleResult;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestJSONPathAssertion {
+
+    @Test
+    public void testGetJsonPath() {
+        JSONPathAssertion instance = new JSONPathAssertion();
+        String expResult = "";
+        String result = instance.getJsonPath();
+        assertEquals(expResult, result);
+    }
+
+    @Test
+    public void testSetJsonPath() {
+        String jsonPath = "";
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonPath(jsonPath);
+    }
+
+    @Test
+    public void testGetExpectedValue() {
+        JSONPathAssertion instance = new JSONPathAssertion();
+        String expResult = "";
+        String result = instance.getExpectedValue();
+        assertEquals(expResult, result);
+    }
+
+    @Test
+    public void testSetExpectedValue() {
+        String expectedValue = "";
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setExpectedValue(expectedValue);
+    }
+
+    @Test
+    public void testSetJsonValidationBool() {
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonValidationBool(false);
+    }
+
+    @Test
+    public void testIsJsonValidationBool() {
+        JSONPathAssertion instance = new JSONPathAssertion();
+        boolean result = instance.isJsonValidationBool();
+        assertEquals(false, result);
+    }
+
+    @Test
+    public void testGetResult_positive() {
+        SampleResult samplerResult = new SampleResult();
+        samplerResult.setResponseData("{\"myval\": 123}".getBytes());
+
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonPath("$.myval");
+        instance.setJsonValidationBool(true);
+        instance.setExpectedValue("123");
+        AssertionResult expResult = new AssertionResult("");
+        AssertionResult result = instance.getResult(samplerResult);
+        assertEquals(expResult.getName(), result.getName());
+        assertEquals(false, result.isFailure());
+    }
+
+    @Test
+    public void testGetResult_positive_regexp() {
+        SampleResult samplerResult = new SampleResult();
+        samplerResult.setResponseData("{\"myval\": 123}".getBytes());
+
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonPath("$.myval");
+        instance.setJsonValidationBool(true);
+        instance.setExpectedValue("(123|456)");
+        AssertionResult expResult = new AssertionResult("");
+        AssertionResult result = instance.getResult(samplerResult);
+        assertEquals(expResult.getName(), result.getName());
+        assertEquals(false, result.isFailure());
+
+        samplerResult.setResponseData("{\"myval\": 456}".getBytes());
+        AssertionResult result2 = instance.getResult(samplerResult);
+        assertEquals(false, result2.isFailure());
+    }
+
+    @Test
+    public void testGetResult_positive_invert() {
+        SampleResult samplerResult = new SampleResult();
+        samplerResult.setResponseData("{\"myval\": 123}".getBytes());
+
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonPath("$.myval");
+        instance.setJsonValidationBool(true);
+        instance.setExpectedValue("123");
+        instance.setInvert(true);
+        AssertionResult expResult = new AssertionResult("");
+        AssertionResult result = instance.getResult(samplerResult);
+        assertEquals(true, result.isFailure());
+        assertEquals(expResult.getName(), result.getName());
+    }
+
+    @Test
+    public void testGetResult_not_regexp() {
+        SampleResult samplerResult = new SampleResult();
+        samplerResult.setResponseData("{\"myval\": \"some complicated value\"}".getBytes());
+
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonPath("$.myval");
+        instance.setJsonValidationBool(true);
+        instance.setExpectedValue("some.+");
+        AssertionResult result = instance.getResult(samplerResult);
+        assertEquals(false, result.isFailure());
+
+        instance.setIsRegex(false);
+        AssertionResult result2 = instance.getResult(samplerResult);
+        assertEquals(true, result2.isFailure());
+    }
+
+    @Test
+    public void testGetResult_negative() {
+        SampleResult samplerResult = new SampleResult();
+        samplerResult.setResponseData("{\"myval\": 123}".getBytes());
+
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonPath("$.myval");
+        instance.setJsonValidationBool(true);
+        instance.setExpectedValue("1234");
+        AssertionResult expResult = new AssertionResult("");
+        AssertionResult result = instance.getResult(samplerResult);
+        assertEquals(expResult.getName(), result.getName());
+        assertEquals(true, result.isFailure());
+    }
+
+    @Test
+    public void testGetResult_negative_invert() {
+        SampleResult samplerResult = new SampleResult();
+        samplerResult.setResponseData("{\"myval\": 123}".getBytes());
+
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonPath("$.myval");
+        instance.setJsonValidationBool(true);
+        instance.setExpectedValue("1234");
+        instance.setInvert(true);
+        AssertionResult expResult = new AssertionResult("");
+        AssertionResult result = instance.getResult(samplerResult);
+        assertEquals(false, result.isFailure());
+        assertEquals(expResult.getName(), result.getName());
+    }
+
+    @Test
+    public void testGetResult_null() {
+        SampleResult samplerResult = new SampleResult();
+        samplerResult.setResponseData("{\"myval\": null}".getBytes());
+
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonPath("$.myval");
+        instance.setExpectNull(true);
+        instance.setJsonValidationBool(true);
+        AssertionResult expResult = new AssertionResult("");
+        AssertionResult result = instance.getResult(samplerResult);
+        assertEquals(expResult.getName(), result.getName());
+        assertEquals(false, result.isFailure());
+    }
+
+    @Test
+    public void testGetResult_null_not_found() {
+        SampleResult samplerResult = new SampleResult();
+        samplerResult.setResponseData("{\"myval\": 123}".getBytes());
+
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonPath("$.myval");
+        instance.setExpectNull(true);
+        instance.setJsonValidationBool(true);
+        AssertionResult expResult = new AssertionResult("");
+        AssertionResult result = instance.getResult(samplerResult);
+        assertEquals(expResult.getName(), result.getName());
+        assertEquals(true, result.isFailure());
+    }
+
+    @Test
+    public void testGetResult_null_novalidate() {
+        SampleResult samplerResult = new SampleResult();
+        samplerResult.setResponseData("{\"myval\": null}".getBytes());
+
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonPath("$.myval");
+        instance.setJsonValidationBool(false);
+        AssertionResult expResult = new AssertionResult("");
+        AssertionResult result = instance.getResult(samplerResult);
+        assertEquals(expResult.getName(), result.getName());
+        assertEquals(false, result.isFailure());
+    }
+
+    @Test
+    public void testGetResult_no_such_path() {
+        SampleResult samplerResult = new SampleResult();
+        samplerResult.setResponseData("{\"myval\": null}".getBytes());
+
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonPath("$.notexist");
+        instance.setJsonValidationBool(false);
+        AssertionResult expResult = new AssertionResult("");
+        AssertionResult result = instance.getResult(samplerResult);
+        assertEquals(expResult.getName(), result.getName());
+        assertEquals(true, result.isFailure());
+    }
+
+    @Test
+    public void testGetResult_list_val() {
+        SampleResult samplerResult = new SampleResult();
+        samplerResult.setResponseData("{\"myval\": [{\"test\":1},{\"test\":2},{\"test\":3}]}".getBytes());
+
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonPath("$.myval[*].test");
+        instance.setJsonValidationBool(true);
+        instance.setExpectedValue("2");
+        AssertionResult expResult = new AssertionResult("");
+        AssertionResult result = instance.getResult(samplerResult);
+        assertEquals(expResult.getName(), result.getName());
+        assertEquals(false, result.isFailure());
+    }
+
+    @Test
+    public void testGetResult_list_negative() {
+        SampleResult samplerResult = new SampleResult();
+        samplerResult.setResponseData("{\"myval\": [{\"test\":1},{\"test\":2},{\"test\":3}]}".getBytes());
+
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonPath("$.myval[*].test");
+        instance.setJsonValidationBool(true);
+        instance.setExpectedValue("5");
+        AssertionResult expResult = new AssertionResult("");
+        AssertionResult result = instance.getResult(samplerResult);
+        assertEquals(expResult.getName(), result.getName());
+        assertEquals(true, result.isFailure());
+    }
+
+    @Test
+    public void testGetResult_list_empty_novalidate() {
+        SampleResult samplerResult = new SampleResult();
+        samplerResult.setResponseData("{\"myval\": []}".getBytes());
+
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonPath("$.myval[*]");
+        instance.setJsonValidationBool(false);
+        AssertionResult expResult = new AssertionResult("");
+        AssertionResult result = instance.getResult(samplerResult);
+        assertEquals(expResult.getName(), result.getName());
+        assertEquals(false, result.isFailure());
+    }
+
+    @Test
+    public void testGetResult_list_empty_validate() {
+        SampleResult samplerResult = new SampleResult();
+        samplerResult.setResponseData("{\"myval\": []}".getBytes());
+
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonPath("$.myval");
+        instance.setJsonValidationBool(true);
+        instance.setExpectedValue("[]");
+        AssertionResult expResult = new AssertionResult("");
+        AssertionResult result = instance.getResult(samplerResult);
+        assertEquals(expResult.getName(), result.getName());
+        assertEquals(false, result.isFailure());
+    }
+
+    @Test
+    public void testGetResult_dict() {
+        SampleResult samplerResult = new SampleResult();
+        samplerResult.setResponseData("{\"myval\": {\"key\": \"val\"}}".getBytes());
+
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonPath("$.myval");
+        instance.setJsonValidationBool(true);
+        instance.setExpectedValue("{\"key\":\"val\"}");
+        AssertionResult expResult = new AssertionResult("");
+        AssertionResult result = instance.getResult(samplerResult);
+        assertEquals(expResult.getName(), result.getName());
+        assertEquals(false, result.isFailure());
+    }
+
+    @Test
+    public void testGetResult_inverted_null() {
+        SampleResult samplerResult = new SampleResult();
+        samplerResult.setResponseData("{\"myval\": [{\"key\": null}]}".getBytes());
+
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonPath("$.myval[*].key");
+        instance.setJsonValidationBool(true);
+        instance.setExpectNull(true);
+        instance.setInvert(true);
+        AssertionResult expResult = new AssertionResult("");
+        AssertionResult result = instance.getResult(samplerResult);
+        assertEquals(expResult.getName(), result.getName());
+        assertEquals(true, result.isFailure());
+    }
+
+    @Test
+    public void testGetResult_match_msg_problem() {
+        SampleResult samplerResult = new SampleResult();
+        String str = "{\"execution\":[{\"scenario\":{\"requests\":[{\"headers\":{\"headerkey\":\"header value\"}}]}}]}";
+        samplerResult.setResponseData(str.getBytes());
+
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonPath("$.execution[0].scenario.requests[0].headers");
+        instance.setJsonValidationBool(true);
+        instance.setExpectNull(false);
+        instance.setExpectedValue("{headerkey=header value}");
+        instance.setInvert(false);
+        AssertionResult expResult = new AssertionResult("");
+        AssertionResult result = instance.getResult(samplerResult);
+        assertEquals(expResult.getName(), result.getName());
+        assertEquals(true, result.isFailure());
+        assertEquals("Value expected to match regexp '{headerkey=header value}', but it did not match: '{\"headerkey\":\"header value\"}'", result.getFailureMessage());
+    }
+
+    @Test
+    public void testGetResult_match_msg_problem2() {
+        SampleResult samplerResult = new SampleResult();
+        String str = "{\n" +
+                " \"code\":200,\n" +
+                " \"contact\":{\n" +
+                "   \"id\":28071,\n" +
+                "   \"description\":\"test description\",\n" +
+                "   \"info\":{\n" +
+                "       \"ngn_number\":[\n" +
+                "           \"2003\",\n" +
+                "           \"2004\"\n" +
+                "       ]\n" +
+                "   }\n" +
+                " }\n" +
+                "}";
+        samplerResult.setResponseData(str.getBytes());
+
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonPath("$.contact.info.ngn_number");
+        instance.setJsonValidationBool(true);
+        instance.setExpectNull(false);
+        instance.setExpectedValue("[\"2003\",\"2004\"]");
+        instance.setInvert(false);
+        instance.setIsRegex(false);
+        AssertionResult expResult = new AssertionResult("");
+        AssertionResult result = instance.getResult(samplerResult);
+        assertEquals(expResult.getName(), result.getName());
+        assertEquals(false, result.isFailure());
+    }
+
+    @Test
+    public void testGetResultFloat() {
+        SampleResult samplerResult = new SampleResult();
+
+        samplerResult.setResponseData("{\"myval\": [{\"test\":0.0000123456789}]}".getBytes());
+
+        JSONPathAssertion instance = new JSONPathAssertion();
+        instance.setJsonPath("$.myval[*].test");
+        instance.setJsonValidationBool(true);
+        instance.setIsRegex(false);
+        instance.setExpectedValue("0.0000123456789");
+
+        AssertionResult expResult = new AssertionResult("");
+        AssertionResult result = instance.getResult(samplerResult);
+        assertEquals(expResult.getName(), result.getName());
+        assertEquals(false, result.isFailure());
+    }
+}

Propchange: jmeter/trunk/test/src/org/apache/jmeter/assertions/TestJSONPathAssertion.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jmeter/trunk/test/src/org/apache/jmeter/assertions/TestJSONPathAssertion.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jmeter/trunk/test/src/org/apache/jmeter/assertions/TestJSONPathAssertionGui.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/test/src/org/apache/jmeter/assertions/TestJSONPathAssertionGui.java?rev=1816906&view=auto
==============================================================================
--- jmeter/trunk/test/src/org/apache/jmeter/assertions/TestJSONPathAssertionGui.java (added)
+++ jmeter/trunk/test/src/org/apache/jmeter/assertions/TestJSONPathAssertionGui.java Fri Dec  1 20:50:46 2017
@@ -0,0 +1,72 @@
+/*
+ * 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.assertions;
+
+import org.apache.jmeter.assertions.gui.JSONPathAssertionGui;
+import org.apache.jmeter.testelement.TestElement;
+import org.junit.Test;
+
+
+public class TestJSONPathAssertionGui {
+
+
+    @Test
+    public void testInit() {
+        JSONPathAssertionGui instance = new JSONPathAssertionGui();
+        instance.init();
+        instance.stateChanged(null);
+    }
+
+    @Test
+    public void testClearGui() {
+        JSONPathAssertionGui instance = new JSONPathAssertionGui();
+        instance.clearGui();
+    }
+
+    @Test
+    public void testCreateTestElement() {
+        JSONPathAssertionGui instance = new JSONPathAssertionGui();
+        instance.createTestElement();
+    }
+
+    @Test
+    public void testGetLabelResource() {
+        JSONPathAssertionGui instance = new JSONPathAssertionGui();
+        instance.getLabelResource();
+    }
+
+    @Test
+    public void testGetStaticLabel() {
+        JSONPathAssertionGui instance = new JSONPathAssertionGui();
+        instance.getStaticLabel();
+    }
+
+    @Test
+    public void testModifyTestElement() {
+        TestElement element = new JSONPathAssertion();
+        JSONPathAssertionGui instance = new JSONPathAssertionGui();
+        instance.modifyTestElement(element);
+    }
+
+    @Test
+    public void testConfigure() {
+        TestElement element = new JSONPathAssertion();
+        JSONPathAssertionGui instance = new JSONPathAssertionGui();
+        instance.configure(element);
+    }
+}

Propchange: jmeter/trunk/test/src/org/apache/jmeter/assertions/TestJSONPathAssertionGui.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jmeter/trunk/test/src/org/apache/jmeter/assertions/TestJSONPathAssertionGui.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jmeter/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml?rev=1816906&r1=1816905&r2=1816906&view=diff
==============================================================================
--- jmeter/trunk/xdocs/changes.xml [utf-8] (original)
+++ jmeter/trunk/xdocs/changes.xml [utf-8] Fri Dec  1 20:50:46 2017
@@ -131,6 +131,7 @@ Summary
     <li><bug>61534</bug>Convert AssertionError to a failed assertion in the JSR223Assertion allowing users to use assert in their code</li>
     <li><bug>61756</bug>Extractors : Improve label name "Reference name" to make it clear what it makes</li>
     <li><bug>61758</bug><code>Apply to:</code> field in Extractors, Assertions : When entering a value in <code>JMeter Variable Name</code>, the radio box <code>JMeter Variable Name</code> should be selected by default. Contributed by Ubik Load Pack (support at ubikloadpack.com)</li>
+    <li><bug>61845</bug>New Component JSON Assertion based on AtlanBH JSON Path Asserion donated to JMeter-Plugins and migrated into JMeter core by Artem Fedorov (artem at blazemeter.com)</li>
 </ul>
 
 <h3>Functions</h3>

Modified: jmeter/trunk/xdocs/usermanual/component_reference.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/usermanual/component_reference.xml?rev=1816906&r1=1816905&r2=1816906&view=diff
==============================================================================
--- jmeter/trunk/xdocs/usermanual/component_reference.xml (original)
+++ jmeter/trunk/xdocs/usermanual/component_reference.xml Fri Dec  1 20:50:46 2017
@@ -4981,6 +4981,26 @@ please ensure that you select "<code>Sto
     </property>
 </properties>
 </component>
+<component name="JSON Assertion" index="&sect-num;.5.14" anchor="JSON_Assertion">
+    <description>
+        <p>
+            This component allows you to perform validations of JSON documents.
+            First, it will parse the JSON and fail if the data is not JSON.
+            Second, it will search for specified path, using syntax from <a href="https://github.com/jayway/JsonPath" > Jayway JsonPath 1.2.0</a>. If the path is not found, it will fail.
+            Third, if JSON path was found in the document, and validation against expected value was requested, it will perform validation. For the <code>null</code> value there is special checkbox in the GUI.
+            Note that if the path will return array object, it will be iterated and if expected value is found, the assertion will succeed. To validate empty array use <code>[]</code> string. Also, if patch will return dictionary object, it will be converted to string before comparison.
+        </p>
+    </description>
+    <properties>
+        <property name="Assert JSON Path exists" required="Yes">Path to JSON element for assert.</property>
+        <property name="Additionally assert value" required="No">Select checkbox if you want make assert with some value</property>
+        <property name="Match as regular expression" required="No">Select checkbox if you want use regular expression</property>
+        <property name="Expected Value" required="No">Value for assert or regular expression for match</property>
+        <property name="Expect null" required="No">Select checkbox if you expect null</property>
+        <property name="Invert assertion (will fail if above conditions met)" required="No">Invert assertion (will fail if above conditions met)</property>
+    </properties>
+    <figure width="1140" height="356" image="json_path_assertion.png">JSON Assertion</figure>
+</component>
 
 <a href="#">^</a>