Add support for strings comparison.

This commit is contained in:
jcamiel 2022-09-09 16:54:28 +02:00
parent 29babc8ebb
commit c1684f60b3
No known key found for this signature in database
GPG Key ID: 07FF11CFD55356CC
10 changed files with 127 additions and 38 deletions

View File

@ -144,10 +144,10 @@ Short description:
<span class="grammar-symbol">|</span><a href="#collection-predicate">collection-predicate</a></div></div>
<div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="equal-predicate">equal-predicate</span><span class="grammar-usedby">(used by <a href="#predicate-func">predicate-func</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-symbol">(</span><span class="grammar-literal">equals</span><span class="grammar-symbol">|</span><span class="grammar-literal">==</span><span class="grammar-symbol">)</span>&nbsp;<a href="#sp">sp</a>&nbsp;<a href="#predicate-value">predicate-value</a></div></div>
<div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="not-equal-predicate">not-equal-predicate</span><span class="grammar-usedby">(used by <a href="#predicate-func">predicate-func</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-symbol">(</span><span class="grammar-literal">notEquals</span><span class="grammar-symbol">|</span><span class="grammar-literal">!=</span><span class="grammar-symbol">)</span>&nbsp;<a href="#sp">sp</a>&nbsp;<a href="#predicate-value">predicate-value</a></div></div>
<div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="greater-predicate">greater-predicate</span><span class="grammar-usedby">(used by <a href="#predicate-func">predicate-func</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-symbol">(</span><span class="grammar-literal">greaterThan</span><span class="grammar-symbol">|</span><span class="grammar-literal">&gt;</span><span class="grammar-symbol">)</span>&nbsp;<a href="#sp">sp</a>&nbsp;<span class="grammar-symbol">(</span><a href="#integer">integer</a><span class="grammar-symbol">|</span><a href="#float">float</a><span class="grammar-symbol">)</span></div></div>
<div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="greater-or-equal-predicate">greater-or-equal-predicate</span><span class="grammar-usedby">(used by <a href="#predicate-func">predicate-func</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-symbol">(</span><span class="grammar-literal">greaterThanOrEquals</span><span class="grammar-symbol">|</span><span class="grammar-literal">&gt;=</span><span class="grammar-symbol">)</span>&nbsp;<a href="#sp">sp</a>&nbsp;<a href="#sp">sp</a><span class="grammar-symbol">*</span>&nbsp;<span class="grammar-symbol">(</span><a href="#integer">integer</a><span class="grammar-symbol">|</span><a href="#float">float</a><span class="grammar-symbol">)</span></div></div>
<div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="less-predicate">less-predicate</span><span class="grammar-usedby">(used by <a href="#predicate-func">predicate-func</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-symbol">(</span><span class="grammar-literal">lessThan</span><span class="grammar-symbol">|</span><span class="grammar-literal">&lt;</span><span class="grammar-symbol">)</span>&nbsp;<a href="#sp">sp</a>&nbsp;<span class="grammar-symbol">(</span><a href="#integer">integer</a><span class="grammar-symbol">|</span><a href="#float">float</a><span class="grammar-symbol">)</span></div></div>
<div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="less-or-equal-predicate">less-or-equal-predicate</span><span class="grammar-usedby">(used by <a href="#predicate-func">predicate-func</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-symbol">(</span><span class="grammar-literal">lessThanOrEquals</span><span class="grammar-symbol">|</span><span class="grammar-literal">&lt;=</span><span class="grammar-symbol">)</span>&nbsp;<a href="#sp">sp</a>&nbsp;<span class="grammar-symbol">(</span><a href="#integer">integer</a><span class="grammar-symbol">|</span><a href="#float">float</a><span class="grammar-symbol">)</span></div></div>
<div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="greater-predicate">greater-predicate</span><span class="grammar-usedby">(used by <a href="#predicate-func">predicate-func</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-symbol">(</span><span class="grammar-literal">greaterThan</span><span class="grammar-symbol">|</span><span class="grammar-literal">&gt;</span><span class="grammar-symbol">)</span>&nbsp;<a href="#sp">sp</a>&nbsp;<span class="grammar-symbol">(</span><a href="#integer">integer</a><span class="grammar-symbol">|</span><a href="#float">float</a><span class="grammar-symbol">|</span><a href="#quoted-string">quoted-string</a><span class="grammar-symbol">)</span></div></div>
<div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="greater-or-equal-predicate">greater-or-equal-predicate</span><span class="grammar-usedby">(used by <a href="#predicate-func">predicate-func</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-symbol">(</span><span class="grammar-literal">greaterThanOrEquals</span><span class="grammar-symbol">|</span><span class="grammar-literal">&gt;=</span><span class="grammar-symbol">)</span>&nbsp;<a href="#sp">sp</a>&nbsp;<a href="#sp">sp</a><span class="grammar-symbol">*</span>&nbsp;<span class="grammar-symbol">(</span><a href="#integer">integer</a><span class="grammar-symbol">|</span><a href="#float">float</a><span class="grammar-symbol">|</span><a href="#quoted-string">quoted-string</a><span class="grammar-symbol">)</span></div></div>
<div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="less-predicate">less-predicate</span><span class="grammar-usedby">(used by <a href="#predicate-func">predicate-func</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-symbol">(</span><span class="grammar-literal">lessThan</span><span class="grammar-symbol">|</span><span class="grammar-literal">&lt;</span><span class="grammar-symbol">)</span>&nbsp;<a href="#sp">sp</a>&nbsp;<span class="grammar-symbol">(</span><a href="#integer">integer</a><span class="grammar-symbol">|</span><a href="#float">float</a><span class="grammar-symbol">|</span><a href="#quoted-string">quoted-string</a><span class="grammar-symbol">)</span></div></div>
<div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="less-or-equal-predicate">less-or-equal-predicate</span><span class="grammar-usedby">(used by <a href="#predicate-func">predicate-func</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-symbol">(</span><span class="grammar-literal">lessThanOrEquals</span><span class="grammar-symbol">|</span><span class="grammar-literal">&lt;=</span><span class="grammar-symbol">)</span>&nbsp;<a href="#sp">sp</a>&nbsp;<span class="grammar-symbol">(</span><a href="#integer">integer</a><span class="grammar-symbol">|</span><a href="#float">float</a><span class="grammar-symbol">|</span><a href="#quoted-string">quoted-string</a><span class="grammar-symbol">)</span></div></div>
<div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="start-with-predicate">start-with-predicate</span><span class="grammar-usedby">(used by <a href="#predicate-func">predicate-func</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-literal">startsWith</span>&nbsp;<a href="#sp">sp</a>&nbsp;<span class="grammar-symbol">(</span><a href="#quoted-string">quoted-string</a><span class="grammar-symbol">|</span><a href="#oneline-hex">oneline-hex</a><span class="grammar-symbol">|</span><a href="#oneline-base64">oneline-base64</a><span class="grammar-symbol">)</span></div></div>
<div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="end-with-predicate">end-with-predicate</span><span class="grammar-usedby">(used by <a href="#predicate-func">predicate-func</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-literal">endsWith</span>&nbsp;<a href="#sp">sp</a>&nbsp;<span class="grammar-symbol">(</span><a href="#quoted-string">quoted-string</a><span class="grammar-symbol">|</span><a href="#oneline-hex">oneline-hex</a><span class="grammar-symbol">|</span><a href="#oneline-base64">oneline-base64</a><span class="grammar-symbol">)</span></div></div>
<div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="contain-predicate">contain-predicate</span><span class="grammar-usedby">(used by <a href="#predicate-func">predicate-func</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-literal">contains</span>&nbsp;<a href="#sp">sp</a>&nbsp;<a href="#quoted-string">quoted-string</a></div></div>
@ -180,7 +180,7 @@ Short description:
<div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="oneline-base64">oneline-base64</span><span class="grammar-usedby">(used by <a href="#start-with-predicate">start-with-predicate</a>,&nbsp;<a href="#end-with-predicate">end-with-predicate</a>,&nbsp;<a href="#predicate-value">predicate-value</a>,&nbsp;<a href="#bytes">bytes</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-literal">base64,</span>&nbsp;<span class="grammar-regex">[A-Z0-9+-= \n]+</span>&nbsp;<span class="grammar-literal">;</span></div></div>
<div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="oneline-file">oneline-file</span><span class="grammar-usedby">(used by <a href="#predicate-value">predicate-value</a>,&nbsp;<a href="#bytes">bytes</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-literal">file,</span>&nbsp;<a href="#filename">filename</a>&nbsp;<span class="grammar-literal">;</span></div></div>
<div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="oneline-hex">oneline-hex</span><span class="grammar-usedby">(used by <a href="#start-with-predicate">start-with-predicate</a>,&nbsp;<a href="#end-with-predicate">end-with-predicate</a>,&nbsp;<a href="#predicate-value">predicate-value</a>,&nbsp;<a href="#bytes">bytes</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-literal">hex,</span>&nbsp;<a href="#hexdigit">hexdigit</a><span class="grammar-symbol">*</span>&nbsp;<span class="grammar-literal">;</span></div></div>
</div><div class="grammar-ruleset"><h3 id="strings">Strings</h3><div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="quoted-string">quoted-string</span><span class="grammar-usedby">(used by <a href="#variable-value">variable-value</a>,&nbsp;<a href="#header-query">header-query</a>,&nbsp;<a href="#cookie-query">cookie-query</a>,&nbsp;<a href="#xpath-query">xpath-query</a>,&nbsp;<a href="#jsonpath-query">jsonpath-query</a>,&nbsp;<a href="#regex-query">regex-query</a>,&nbsp;<a href="#variable-query">variable-query</a>,&nbsp;<a href="#regex-subquery">regex-subquery</a>,&nbsp;<a href="#start-with-predicate">start-with-predicate</a>,&nbsp;<a href="#end-with-predicate">end-with-predicate</a>,&nbsp;<a href="#contain-predicate">contain-predicate</a>,&nbsp;<a href="#match-predicate">match-predicate</a>,&nbsp;<a href="#predicate-value">predicate-value</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-literal">"</span>&nbsp;<span class="grammar-symbol">(</span><a href="#quoted-string-content">quoted-string-content</a><span class="grammar-symbol">|</span><a href="#template">template</a><span class="grammar-symbol">)</span><span class="grammar-symbol">*</span>&nbsp;<span class="grammar-literal">"</span></div></div>
</div><div class="grammar-ruleset"><h3 id="strings">Strings</h3><div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="quoted-string">quoted-string</span><span class="grammar-usedby">(used by <a href="#variable-value">variable-value</a>,&nbsp;<a href="#header-query">header-query</a>,&nbsp;<a href="#cookie-query">cookie-query</a>,&nbsp;<a href="#xpath-query">xpath-query</a>,&nbsp;<a href="#jsonpath-query">jsonpath-query</a>,&nbsp;<a href="#regex-query">regex-query</a>,&nbsp;<a href="#variable-query">variable-query</a>,&nbsp;<a href="#regex-subquery">regex-subquery</a>,&nbsp;<a href="#greater-predicate">greater-predicate</a>,&nbsp;<a href="#greater-or-equal-predicate">greater-or-equal-predicate</a>,&nbsp;<a href="#less-predicate">less-predicate</a>,&nbsp;<a href="#less-or-equal-predicate">less-or-equal-predicate</a>,&nbsp;<a href="#start-with-predicate">start-with-predicate</a>,&nbsp;<a href="#end-with-predicate">end-with-predicate</a>,&nbsp;<a href="#contain-predicate">contain-predicate</a>,&nbsp;<a href="#match-predicate">match-predicate</a>,&nbsp;<a href="#predicate-value">predicate-value</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-literal">"</span>&nbsp;<span class="grammar-symbol">(</span><a href="#quoted-string-content">quoted-string-content</a><span class="grammar-symbol">|</span><a href="#template">template</a><span class="grammar-symbol">)</span><span class="grammar-symbol">*</span>&nbsp;<span class="grammar-literal">"</span></div></div>
<div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="quoted-string-content">quoted-string-content</span><span class="grammar-usedby">(used by <a href="#quoted-string">quoted-string</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-symbol">(</span><a href="#quoted-string-text">quoted-string-text</a><span class="grammar-symbol">|</span><a href="#quoted-string-escaped-char">quoted-string-escaped-char</a><span class="grammar-symbol">)</span><span class="grammar-symbol">*</span></div></div>
<div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="quoted-string-text">quoted-string-text</span><span class="grammar-usedby">(used by <a href="#quoted-string-content">quoted-string-content</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-regex">~["\\]+</span></div></div>
<div class="grammar-rule"><div class="grammar-rule-declaration"><span class="grammar-rule-id" id="quoted-string-escaped-char">quoted-string-escaped-char</span><span class="grammar-usedby">(used by <a href="#quoted-string-content">quoted-string-content</a>)</span></div><div class="grammar-rule-expression"><span class="grammar-literal">\</span>&nbsp;<span class="grammar-symbol">(</span><span class="grammar-literal">"</span><span class="grammar-symbol">|</span><span class="grammar-literal">\</span><span class="grammar-symbol">|</span><span class="grammar-literal">\b</span><span class="grammar-symbol">|</span><span class="grammar-literal">\f</span><span class="grammar-symbol">|</span><span class="grammar-literal">\n</span><span class="grammar-symbol">|</span><span class="grammar-literal">\r</span><span class="grammar-symbol">|</span><span class="grammar-literal">\t</span><span class="grammar-symbol">|</span><span class="grammar-literal">\u</span>&nbsp;<a href="#unicode-char">unicode-char</a><span class="grammar-symbol">)</span></div></div>

View File

@ -229,13 +229,13 @@ equal-predicate: ("equals" | "==") sp predicate-value
not-equal-predicate: ("notEquals" | "!=") sp predicate-value
greater-predicate: ("greaterThan" | ">") sp (integer | float)
greater-predicate: ("greaterThan" | ">") sp (integer | float | quoted-string)
greater-or-equal-predicate: ("greaterThanOrEquals" | ">=") sp sp* (integer | float)
greater-or-equal-predicate: ("greaterThanOrEquals" | ">=") sp sp* (integer | float | quoted-string)
less-predicate: ("lessThan" | "<") sp (integer | float)
less-predicate: ("lessThan" | "<") sp (integer | float | quoted-string)
less-or-equal-predicate: ("lessThanOrEquals" | "<=") sp (integer | float)
less-or-equal-predicate: ("lessThanOrEquals" | "<=") sp (integer | float | quoted-string)
start-with-predicate: "startsWith" sp (quoted-string | oneline-hex | oneline-base64)

View File

@ -5,6 +5,7 @@
<span class="line"><span class="string">variable</span><span>:</span> three<span>=</span><span class="number">3</span></span>
<span class="line"><span class="string">variable</span><span>:</span> four<span>=</span><span class="number">4</span></span>
<span class="line"><span class="string">variable</span><span>:</span> five<span>=</span><span class="number">5</span></span>
<span class="line"><span class="string">variable</span><span>:</span> foo<span>=</span>abc</span>
<span class="line"><span class="string">insecure</span><span>:</span> <span class="boolean">false</span></span>
</span><span class="response"><span class="line"></span>
<span class="line"><span class="version">HTTP/1.0</span> <span class="number">200</span></span>
@ -47,6 +48,12 @@
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.duration"</span> <span class="predicate-type">isFloat</span></span>
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.duration"</span> <span class="not">not</span> <span class="predicate-type">isInteger</span></span>
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.nullable"</span> <span class="predicate-type">==</span> <span class="null">null</span></span>
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.tags[0]"</span> <span class="predicate-type">==</span> <span class="string">"test"</span></span>
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.tags[0]"</span> <span class="predicate-type">&gt;</span> <span class="string">"te"</span></span>
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.tags[0]"</span> <span class="predicate-type">&lt;</span> <span class="string">"testabc"</span></span>
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.tags[0]"</span> <span class="predicate-type">&lt;=</span> <span class="string">"test"</span></span>
<span class="line"><span class="query-type">jsonpath</span> <span class="string">"$.tags[0]"</span> <span class="predicate-type">&gt;</span> <span class="string">"{{foo}}"</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="json"><span class="line">{</span>
<span class="line"> "count": 5,</span>

View File

@ -5,6 +5,7 @@ variable: two=2
variable: three=3
variable: four=4
variable: five=5
variable: foo=abc
insecure: false
HTTP/1.0 200
@ -47,6 +48,12 @@ jsonpath "$.duration" lessThan 2
jsonpath "$.duration" isFloat
jsonpath "$.duration" not isInteger
jsonpath "$.nullable" == null
jsonpath "$.tags[0]" == "test"
jsonpath "$.tags[0]" > "te"
jsonpath "$.tags[0]" < "testabc"
jsonpath "$.tags[0]" <= "test"
jsonpath "$.tags[0]" > "{{foo}}"
{
"count": 5,

File diff suppressed because one or more lines are too long

View File

@ -4,6 +4,7 @@
<span class="line section-header">[Asserts]</span>
<span class="line"><span class="query-type">xpath</span> <span class="string">"normalize-space(//data)"</span> <span class="predicate-type">==</span> <span class="string">"café"</span></span>
<span class="line"><span class="query-type">xpath</span> <span class="string">"normalize-space(//data)"</span> <span class="predicate-type">==</span> <span class="string">"caf\u{00e9}"</span></span>
<span class="line"><span class="query-type">xpath</span> <span class="string">"normalize-space(//data)"</span> <span class="predicate-type">&gt;</span> <span class="string">"CAFÉ"</span></span>
<span class="line"><span class="query-type">xpath</span> <span class="string">"//toto"</span> <span class="not">not</span> <span class="predicate-type">exists</span></span>
<span class="line"></span>
<span class="xml"><span class="line">&lt;data&gt;café&lt;/data&gt;</span></span>
@ -42,6 +43,7 @@
<span class="line"><span class="version">HTTP/1.0</span> <span class="number">200</span></span>
<span class="line section-header">[Asserts]</span>
<span class="line"><span class="query-type">xpath</span> <span class="string">"string(//_:book/_:title)"</span> <span class="predicate-type">==</span> <span class="string">"Cheaper by the Dozen"</span></span>
<span class="line"><span class="query-type">xpath</span> <span class="string">"string(//_:book/_:title)"</span> <span class="predicate-type">&gt;</span> <span class="string">"Cheaper"</span></span>
<span class="line"><span class="query-type">xpath</span> <span class="string">"string(//_:book/isbn:number)"</span> <span class="predicate-type">==</span> <span class="string">"1568491379"</span></span>
<span class="line"><span class="query-type">xpath</span> <span class="string">"//*[name()='book']/*[name()='notes']"</span> <span class="subquery-type">count</span> <span class="predicate-type">==</span> <span class="number">1</span></span>
<span class="line"><span class="query-type">xpath</span> <span class="string">"//*[local-name()='book']/*[local-name()='notes']"</span> <span class="subquery-type">count</span> <span class="predicate-type">==</span> <span class="number">1</span></span>

View File

@ -4,6 +4,7 @@ HTTP/1.0 200
[Asserts]
xpath "normalize-space(//data)" == "café"
xpath "normalize-space(//data)" == "caf\u{00e9}"
xpath "normalize-space(//data)" > "CAFÉ"
xpath "//toto" not exists
<data>café</data>
@ -42,6 +43,7 @@ GET http://localhost:8000/assert-xpath-namespaces
HTTP/1.0 200
[Asserts]
xpath "string(//_:book/_:title)" == "Cheaper by the Dozen"
xpath "string(//_:book/_:title)" > "Cheaper"
xpath "string(//_:book/isbn:number)" == "1568491379"
xpath "//*[name()='book']/*[name()='notes']" count == 1
xpath "//*[local-name()='book']/*[local-name()='notes']" count == 1

View File

@ -1 +1 @@
{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/assert-xpath"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"xpath","expr":"normalize-space(//data)"},"predicate":{"type":"equal","value":"café"}},{"query":{"type":"xpath","expr":"normalize-space(//data)"},"predicate":{"type":"equal","value":"café"}},{"query":{"type":"xpath","expr":"//toto"},"predicate":{"not":true,"type":"exist"}}],"body":{"type":"xml","value":"<data>café</data>"}}},{"request":{"method":"GET","url":"http://localhost:8000/assert-xpath-simple-namespaces"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"xpath","expr":"string(//bk:book/bk:title)"},"predicate":{"type":"equal","value":"Cheaper by the Dozen"}},{"query":{"type":"xpath","expr":"string(//*[name()='bk:book']/*[name()='bk:title'])"},"predicate":{"type":"equal","value":"Cheaper by the Dozen"}},{"query":{"type":"xpath","expr":"string(//*[local-name()='book']/*[local-name()='title'])"},"predicate":{"type":"equal","value":"Cheaper by the Dozen"}},{"query":{"type":"xpath","expr":"string(//bk:book/isbn:number)"},"predicate":{"type":"equal","value":"1568491379"}},{"query":{"type":"xpath","expr":"string(//*[name()='bk:book']/*[name()='isbn:number'])"},"predicate":{"type":"equal","value":"1568491379"}},{"query":{"type":"xpath","expr":"string(//*[local-name()='book']/*[local-name()='number'])"},"predicate":{"type":"equal","value":"1568491379"}}]}},{"request":{"method":"GET","url":"http://localhost:8000/assert-xpath-svg"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"xpath","expr":"//_:svg/_:g/_:circle","subquery":{"type":"count"}},"predicate":{"type":"equal","value":3}},{"query":{"type":"xpath","expr":"//*[local-name()='svg']/*[local-name()='g']/*[local-name()='circle']","subquery":{"type":"count"}},"predicate":{"type":"equal","value":3}},{"query":{"type":"xpath","expr":"//*[name()='svg']/*[name()='g']/*[name()='circle']","subquery":{"type":"count"}},"predicate":{"type":"equal","value":3}}]}},{"request":{"method":"GET","url":"http://localhost:8000/assert-xpath-namespaces"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"xpath","expr":"string(//_:book/_:title)"},"predicate":{"type":"equal","value":"Cheaper by the Dozen"}},{"query":{"type":"xpath","expr":"string(//_:book/isbn:number)"},"predicate":{"type":"equal","value":"1568491379"}},{"query":{"type":"xpath","expr":"//*[name()='book']/*[name()='notes']","subquery":{"type":"count"}},"predicate":{"type":"equal","value":1}},{"query":{"type":"xpath","expr":"//*[local-name()='book']/*[local-name()='notes']","subquery":{"type":"count"}},"predicate":{"type":"equal","value":1}},{"query":{"type":"xpath","expr":"//_:book/_:notes/*[local-name()='p']","subquery":{"type":"count"}},"predicate":{"type":"equal","value":1}}]}}]}
{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/assert-xpath"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"xpath","expr":"normalize-space(//data)"},"predicate":{"type":"equal","value":"café"}},{"query":{"type":"xpath","expr":"normalize-space(//data)"},"predicate":{"type":"equal","value":"café"}},{"query":{"type":"xpath","expr":"normalize-space(//data)"},"predicate":{"type":"greater","value":"CAFÉ"}},{"query":{"type":"xpath","expr":"//toto"},"predicate":{"not":true,"type":"exist"}}],"body":{"type":"xml","value":"<data>café</data>"}}},{"request":{"method":"GET","url":"http://localhost:8000/assert-xpath-simple-namespaces"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"xpath","expr":"string(//bk:book/bk:title)"},"predicate":{"type":"equal","value":"Cheaper by the Dozen"}},{"query":{"type":"xpath","expr":"string(//*[name()='bk:book']/*[name()='bk:title'])"},"predicate":{"type":"equal","value":"Cheaper by the Dozen"}},{"query":{"type":"xpath","expr":"string(//*[local-name()='book']/*[local-name()='title'])"},"predicate":{"type":"equal","value":"Cheaper by the Dozen"}},{"query":{"type":"xpath","expr":"string(//bk:book/isbn:number)"},"predicate":{"type":"equal","value":"1568491379"}},{"query":{"type":"xpath","expr":"string(//*[name()='bk:book']/*[name()='isbn:number'])"},"predicate":{"type":"equal","value":"1568491379"}},{"query":{"type":"xpath","expr":"string(//*[local-name()='book']/*[local-name()='number'])"},"predicate":{"type":"equal","value":"1568491379"}}]}},{"request":{"method":"GET","url":"http://localhost:8000/assert-xpath-svg"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"xpath","expr":"//_:svg/_:g/_:circle","subquery":{"type":"count"}},"predicate":{"type":"equal","value":3}},{"query":{"type":"xpath","expr":"//*[local-name()='svg']/*[local-name()='g']/*[local-name()='circle']","subquery":{"type":"count"}},"predicate":{"type":"equal","value":3}},{"query":{"type":"xpath","expr":"//*[name()='svg']/*[name()='g']/*[name()='circle']","subquery":{"type":"count"}},"predicate":{"type":"equal","value":3}}]}},{"request":{"method":"GET","url":"http://localhost:8000/assert-xpath-namespaces"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"xpath","expr":"string(//_:book/_:title)"},"predicate":{"type":"equal","value":"Cheaper by the Dozen"}},{"query":{"type":"xpath","expr":"string(//_:book/_:title)"},"predicate":{"type":"greater","value":"Cheaper"}},{"query":{"type":"xpath","expr":"string(//_:book/isbn:number)"},"predicate":{"type":"equal","value":"1568491379"}},{"query":{"type":"xpath","expr":"//*[name()='book']/*[name()='notes']","subquery":{"type":"count"}},"predicate":{"type":"equal","value":1}},{"query":{"type":"xpath","expr":"//*[local-name()='book']/*[local-name()='notes']","subquery":{"type":"count"}},"predicate":{"type":"equal","value":1}},{"query":{"type":"xpath","expr":"//_:book/_:notes/*[local-name()='p']","subquery":{"type":"count"}},"predicate":{"type":"equal","value":1}}]}}]}

View File

@ -15,6 +15,7 @@
* limitations under the License.
*
*/
use std::cmp::Ordering;
use std::collections::HashMap;
use regex;
@ -643,7 +644,8 @@ fn assert_values_not_equal(actual: &Value, expected: &Value) -> AssertResult {
fn assert_values_greater(actual_value: &Value, expected_value: &Value) -> AssertResult {
let actual = actual_value.display();
let expected = format!("greater than {}", expected_value.display());
match compare_numbers(actual_value, expected_value) {
match compare_values(actual_value, expected_value) {
Some(1) => AssertResult {
success: true,
actual,
@ -668,7 +670,7 @@ fn assert_values_greater(actual_value: &Value, expected_value: &Value) -> Assert
fn assert_values_greater_or_equal(actual_value: &Value, expected_value: &Value) -> AssertResult {
let actual = actual_value.display();
let expected = format!("greater or equal than {}", expected_value.display());
match compare_numbers(actual_value, expected_value) {
match compare_values(actual_value, expected_value) {
Some(1) | Some(0) => AssertResult {
success: true,
actual,
@ -693,7 +695,7 @@ fn assert_values_greater_or_equal(actual_value: &Value, expected_value: &Value)
fn assert_values_less(actual_value: &Value, expected_value: &Value) -> AssertResult {
let actual = actual_value.display();
let expected = format!("less than {}", expected_value.display());
match compare_numbers(actual_value, expected_value) {
match compare_values(actual_value, expected_value) {
Some(-1) => AssertResult {
success: true,
actual,
@ -718,7 +720,7 @@ fn assert_values_less(actual_value: &Value, expected_value: &Value) -> AssertRes
fn assert_values_less_or_equal(actual_value: &Value, expected_value: &Value) -> AssertResult {
let actual = actual_value.display();
let expected = format!("less or equal than {}", expected_value.display());
match compare_numbers(actual_value, expected_value) {
match compare_values(actual_value, expected_value) {
Some(-1) | Some(0) => AssertResult {
success: true,
actual,
@ -740,18 +742,45 @@ fn assert_values_less_or_equal(actual_value: &Value, expected_value: &Value) ->
}
}
// return -1, 0 or 1
// none if one of the value is not a number
fn compare_numbers(actual: &Value, expected: &Value) -> Option<i32> {
/// Compares `actual` and `expected`.
///
/// Returns
/// - `Some(-1)` if `actual` > `expected`,
/// - `Some(0)` if `actual` = `expected`
/// - `Some(-1)` if `actual` = `expected`
/// - `None` if `actual` and `expected` are not comparable.
fn compare_values(actual: &Value, expected: &Value) -> Option<i32> {
match (actual, expected) {
(Value::Integer(i1), Value::Integer(i2)) => Some(compare_float(*i1 as f64, *i2 as f64)),
(Value::Float(f1), Value::Float(f2)) => Some(compare_float(*f1, *f2)),
(Value::Float(f1), Value::Integer(i2)) => Some(compare_float(*f1, *i2 as f64)),
(Value::Integer(i1), Value::Float(f2)) => Some(compare_float(*i1 as f64, *f2)),
(Value::String(s1), Value::String(s2)) => Some(compare_string(s1, s2)),
_ => None,
}
}
/// Compares strings `s1` and `s2` lexicographically.
///
/// Returns
/// - `-1` if `s1` > `s2`,
/// - `0` if `s1` = `s2`
/// - `-1` if `s1` = `s2`
fn compare_string(s1: &str, s2: &str) -> i32 {
let order = s1.cmp(s2);
match order {
Ordering::Less => -1,
Ordering::Equal => 0,
Ordering::Greater => 1,
}
}
/// Compares floats `f1` and `f2`.
///
/// Returns
/// - `-1` if `f1` > `f2`,
/// - `0` if `f1` = `f2`
/// - `-1` if `f1` = `f2`
fn compare_float(f1: f64, f2: f64) -> i32 {
if f1 > f2 {
1
@ -1225,71 +1254,113 @@ mod tests {
fn test_compare_numbers() {
// 2 integers
assert_eq!(
compare_numbers(&Value::Integer(2), &Value::Integer(1)).unwrap(),
compare_values(&Value::Integer(2), &Value::Integer(1)).unwrap(),
1
);
assert_eq!(
compare_numbers(&Value::Integer(1), &Value::Integer(1)).unwrap(),
compare_values(&Value::Integer(1), &Value::Integer(1)).unwrap(),
0
);
assert_eq!(
compare_numbers(&Value::Integer(1), &Value::Integer(2)).unwrap(),
compare_values(&Value::Integer(1), &Value::Integer(2)).unwrap(),
-1
);
assert_eq!(
compare_numbers(&Value::Integer(-1), &Value::Integer(-2)).unwrap(),
compare_values(&Value::Integer(-1), &Value::Integer(-2)).unwrap(),
1
);
// 2 floats
assert_eq!(
compare_numbers(&Value::Float(2.3), &Value::Float(1.2)).unwrap(),
compare_values(&Value::Float(2.3), &Value::Float(1.2)).unwrap(),
1
);
assert_eq!(
compare_numbers(&Value::Float(2.3), &Value::Float(2.2)).unwrap(),
compare_values(&Value::Float(2.3), &Value::Float(2.2)).unwrap(),
1
);
assert_eq!(
compare_numbers(&Value::Float(1.2), &Value::Float(1.5)).unwrap(),
compare_values(&Value::Float(1.2), &Value::Float(1.5)).unwrap(),
-1
);
assert_eq!(
compare_numbers(&Value::Float(-2.1), &Value::Float(-3.1)).unwrap(),
compare_values(&Value::Float(-2.1), &Value::Float(-3.1)).unwrap(),
1
);
assert_eq!(
compare_numbers(&Value::Float(1.1), &Value::Float(-2.1)).unwrap(),
compare_values(&Value::Float(1.1), &Value::Float(-2.1)).unwrap(),
1
);
assert_eq!(
compare_numbers(&Value::Float(1.1), &Value::Float(1.1)).unwrap(),
compare_values(&Value::Float(1.1), &Value::Float(1.1)).unwrap(),
0
);
// 1 float and 1 integer
assert_eq!(
compare_numbers(&Value::Float(2.3), &Value::Integer(2)).unwrap(),
compare_values(&Value::Float(2.3), &Value::Integer(2)).unwrap(),
1
);
assert_eq!(
compare_numbers(&Value::Float(2.3), &Value::Integer(3)).unwrap(),
compare_values(&Value::Float(2.3), &Value::Integer(3)).unwrap(),
-1
);
assert_eq!(
compare_numbers(&Value::Float(2.0), &Value::Integer(2)).unwrap(),
compare_values(&Value::Float(2.0), &Value::Integer(2)).unwrap(),
0
);
// 1 integer and 1 float
assert_eq!(
compare_numbers(&Value::Integer(2), &Value::Float(2.0)).unwrap(),
compare_values(&Value::Integer(2), &Value::Float(2.0)).unwrap(),
0
);
// with a non number
assert!(
compare_numbers(&Value::Integer(-1), &Value::String("hello".to_string())).is_none()
assert!(compare_values(&Value::Integer(-1), &Value::String("hello".to_string())).is_none());
}
#[test]
fn test_compare_strings() {
assert_eq!(
compare_values(
&Value::String("foo".to_string()),
&Value::String("bar".to_string())
)
.unwrap(),
1
);
assert_eq!(
compare_values(
&Value::String("bar".to_string()),
&Value::String("foo".to_string())
)
.unwrap(),
-1
);
assert_eq!(
compare_values(
&Value::String("foo".to_string()),
&Value::String("foo".to_string())
)
.unwrap(),
0
);
assert_eq!(
compare_values(
&Value::String("foo".to_string()),
&Value::String("FOO".to_string())
)
.unwrap(),
1
);
assert_eq!(
compare_values(
&Value::String("foobar".to_string()),
&Value::String("foo".to_string())
)
.unwrap(),
1
);
}

View File

@ -160,7 +160,7 @@ fn greater_predicate(reader: &mut Reader) -> ParseResult<'static, PredicateFuncV
};
let start = reader.state.clone();
let value = predicate_value(reader)?;
if value.is_number() || value.is_expression() {
if value.is_number() || value.is_string() || value.is_expression() {
Ok(PredicateFuncValue::GreaterThan {
space0,
value,
@ -184,7 +184,7 @@ fn greater_or_equal_predicate(reader: &mut Reader) -> ParseResult<'static, Predi
};
let start = reader.state.clone();
let value = predicate_value(reader)?;
if value.is_number() || value.is_expression() {
if value.is_number() || value.is_string() || value.is_expression() {
Ok(PredicateFuncValue::GreaterThanOrEqual {
space0,
value,
@ -208,7 +208,7 @@ fn less_predicate(reader: &mut Reader) -> ParseResult<'static, PredicateFuncValu
};
let start = reader.state.clone();
let value = predicate_value(reader)?;
if value.is_number() || value.is_expression() {
if value.is_number() || value.is_string() || value.is_expression() {
Ok(PredicateFuncValue::LessThan {
space0,
value,
@ -232,7 +232,7 @@ fn less_or_equal_predicate(reader: &mut Reader) -> ParseResult<'static, Predicat
};
let start = reader.state.clone();
let value = predicate_value(reader)?;
if value.is_number() || value.is_expression() {
if value.is_number() || value.is_string() || value.is_expression() {
Ok(PredicateFuncValue::LessThanOrEqual {
space0,
value,