Browse Source
tests, fixes, new feature and tests for some discovered but not yet fixed issuespull/148/head
kallestenflo
9 years ago
15 changed files with 557 additions and 45 deletions
@ -0,0 +1,118 @@
|
||||
package com.jayway.jsonpath; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
import static com.jayway.jsonpath.JsonPath.using; |
||||
import static com.jayway.jsonpath.TestUtils.assertEvaluationThrows; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Deep scan is indefinite, so certain "illegal" actions become a no-op instead of a path evaluation exception. |
||||
*/ |
||||
public class DeepScanTest extends BaseTest { |
||||
|
||||
@Test |
||||
public void when_deep_scanning_non_array_subscription_is_ignored() { |
||||
Object result = JsonPath.parse("{\"x\": [0,1,[0,1,2,3,null],null]}").read("$..[2][3]"); |
||||
assertThat(result).asList().containsOnly(3); |
||||
result = JsonPath.parse("{\"x\": [0,1,[0,1,2,3,null],null], \"y\": [0,1,2]}").read("$..[2][3]"); |
||||
assertThat(result).asList().containsOnly(3); |
||||
|
||||
result = JsonPath.parse("{\"x\": [0,1,[0,1,2],null], \"y\": [0,1,2]}").read("$..[2][3]"); |
||||
assertThat(result).asList().isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void when_deep_scanning_null_subscription_is_ignored() { |
||||
Object result = JsonPath.parse("{\"x\": [null,null,[0,1,2,3,null],null]}").read("$..[2][3]"); |
||||
assertThat(result).asList().containsOnly(3); |
||||
result = JsonPath.parse("{\"x\": [null,null,[0,1,2,3,null],null], \"y\": [0,1,null]}").read("$..[2][3]"); |
||||
assertThat(result).asList().containsOnly(3); |
||||
} |
||||
|
||||
@Test |
||||
public void when_deep_scanning_array_index_oob_is_ignored() { |
||||
Object result = JsonPath.parse("{\"x\": [0,1,[0,1,2,3,10],null]}").read("$..[4]"); |
||||
assertThat(result).asList().containsOnly(10); |
||||
|
||||
result = JsonPath.parse("{\"x\": [null,null,[0,1,2,3]], \"y\": [null,null,[0,1]]}").read("$..[2][3]"); |
||||
assertThat(result).asList().containsOnly(3); |
||||
} |
||||
|
||||
@Test |
||||
public void definite_upstream_illegal_array_access_throws() { |
||||
assertEvaluationThrows("{\"foo\": {\"bar\": null}}", "$.foo.bar.[5]", PathNotFoundException.class); |
||||
assertEvaluationThrows("{\"foo\": {\"bar\": null}}", "$.foo.bar.[5, 10]", PathNotFoundException.class); |
||||
|
||||
assertEvaluationThrows("{\"foo\": {\"bar\": 4}}", "$.foo.bar.[5]", InvalidPathException.class); |
||||
assertEvaluationThrows("{\"foo\": {\"bar\": 4}}", "$.foo.bar.[5, 10]", InvalidPathException.class); |
||||
|
||||
assertEvaluationThrows("{\"foo\": {\"bar\": []}}", "$.foo.bar.[5]", PathNotFoundException.class); |
||||
} |
||||
|
||||
@Test |
||||
public void when_deep_scanning_illegal_property_access_is_ignored() { |
||||
Object result = JsonPath.parse("{\"x\": {\"foo\": {\"bar\": 4}}, \"y\": {\"foo\": 1}}").read("$..foo"); |
||||
assertThat(result).asList().hasSize(2); |
||||
|
||||
result = JsonPath.parse("{\"x\": {\"foo\": {\"bar\": 4}}, \"y\": {\"foo\": 1}}").read("$..foo.bar"); |
||||
assertThat(result).asList().containsOnly(4); |
||||
result = JsonPath.parse("{\"x\": {\"foo\": {\"bar\": 4}}, \"y\": {\"foo\": 1}}").read("$..[*].foo.bar"); |
||||
assertThat(result).asList().containsOnly(4); |
||||
result = JsonPath.parse("{\"x\": {\"foo\": {\"baz\": 4}}, \"y\": {\"foo\": 1}}").read("$..[*].foo.bar"); |
||||
assertThat(result).asList().isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void when_deep_scanning_illegal_predicate_is_ignored() { |
||||
Object result = JsonPath.parse("{\"x\": {\"foo\": {\"bar\": 4}}, \"y\": {\"foo\": 1}}").read( |
||||
"$..foo[?(@.bar)].bar"); |
||||
assertThat(result).asList().containsOnly(4); |
||||
|
||||
result = JsonPath.parse("{\"x\": {\"foo\": {\"bar\": 4}}, \"y\": {\"foo\": 1}}").read( |
||||
"$..[*]foo[?(@.bar)].bar"); |
||||
assertThat(result).asList().containsOnly(4); |
||||
} |
||||
|
||||
@Test |
||||
public void when_deep_scanning_require_properties_still_counts() { |
||||
final Configuration conf = Configuration.defaultConfiguration().addOptions(Option.REQUIRE_PROPERTIES); |
||||
|
||||
Object result = JsonPath.parse("[{\"x\": {\"foo\": {\"x\": 4}, \"x\": null}, \"y\": {\"x\": 1}}, {\"x\": []}]").read( |
||||
"$..x"); |
||||
assertThat(result).asList().hasSize(5); |
||||
|
||||
// foo.bar must be found in every object node after deep scan (which is impossible)
|
||||
assertEvaluationThrows("{\"foo\": {\"bar\": 4}}", "$..foo.bar", PathNotFoundException.class, conf); |
||||
|
||||
assertEvaluationThrows("{\"foo\": {\"bar\": 4}, \"baz\": 2}", "$..['foo', 'baz']", PathNotFoundException.class, conf); |
||||
} |
||||
|
||||
@Test |
||||
public void when_deep_scanning_leaf_multi_props_work() { |
||||
Object result = JsonPath.parse("[{\"a\": \"a-val\", \"b\": \"b-val\", \"c\": \"c-val\"}, [1, 5], {\"a\": \"a-val\"}]").read( |
||||
"$..['a', 'c']"); |
||||
// This is current deep scan semantics: only objects containing all properties specified in multiprops token are
|
||||
// considered.
|
||||
assertThat(result).asList().hasSize(1); |
||||
result = ((List)result).get(0); |
||||
|
||||
assertThat(result).isInstanceOf(Map.class); |
||||
assertThat((Map)result).hasSize(2).containsEntry("a", "a-val").containsEntry("c", "c-val"); |
||||
|
||||
// But this semantics changes when DEFAULT_PATH_LEAF_TO_NULL comes into play.
|
||||
Configuration conf = Configuration.defaultConfiguration().addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL); |
||||
result = using(conf).parse("[{\"a\": \"a-val\", \"b\": \"b-val\", \"c\": \"c-val\"}, [1, 5], {\"a\": \"a-val\"}]").read( |
||||
"$..['a', 'c']"); |
||||
// todo: deep equality test, but not tied to any json provider
|
||||
assertThat(result).asList().hasSize(2); |
||||
for (final Object node : (List)result) { |
||||
assertThat(node).isInstanceOf(Map.class); |
||||
assertThat((Map)node).hasSize(2).containsEntry("a", "a-val"); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,32 @@
|
||||
package com.jayway.jsonpath; |
||||
|
||||
import static com.jayway.jsonpath.JsonPath.using; |
||||
import static org.assertj.core.api.Assertions.fail; |
||||
|
||||
public final class TestUtils { |
||||
private TestUtils() {} |
||||
|
||||
public static void assertEvaluationThrows(final String json, final String path, |
||||
Class<? extends JsonPathException> expected) { |
||||
assertEvaluationThrows(json, path, expected, Configuration.defaultConfiguration()); |
||||
} |
||||
|
||||
/** |
||||
* Shortcut for expected exception testing during path evaluation. |
||||
* |
||||
* @param conf conf to use during evaluation |
||||
* @param json json to parse |
||||
* @param path jsonpath do evaluate |
||||
* @param expected expected exception class (reference comparison, not an instanceof) |
||||
*/ |
||||
public static void assertEvaluationThrows(final String json, final String path, |
||||
Class<? extends JsonPathException> expected, final Configuration conf) { |
||||
try { |
||||
using(conf).parse(json).read(path); |
||||
fail("Should throw " + expected.getName()); |
||||
} catch (JsonPathException exc) { |
||||
if (exc.getClass() != expected) |
||||
throw exc; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,54 @@
|
||||
package com.jayway.jsonpath.internal.token; |
||||
|
||||
import com.jayway.jsonpath.BaseTest; |
||||
import com.jayway.jsonpath.internal.token.PathToken; |
||||
import com.jayway.jsonpath.internal.token.PropertyPathToken; |
||||
import com.jayway.jsonpath.internal.token.ScanPathToken; |
||||
import com.jayway.jsonpath.internal.token.WildcardPathToken; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
public class PathTokenTest extends BaseTest { |
||||
|
||||
@Test |
||||
public void is_upstream_definite_in_simple_case() { |
||||
assertThat(makePathReturningTail(makePPT("foo")).isUpstreamDefinite()).isTrue(); |
||||
|
||||
assertThat(makePathReturningTail(makePPT("foo"), makePPT("bar")).isUpstreamDefinite()).isTrue(); |
||||
|
||||
assertThat(makePathReturningTail(makePPT("foo", "foo2"), makePPT("bar")).isUpstreamDefinite()).isFalse(); |
||||
|
||||
assertThat(makePathReturningTail(new WildcardPathToken(), makePPT("bar")).isUpstreamDefinite()).isFalse(); |
||||
|
||||
assertThat(makePathReturningTail(new ScanPathToken(), makePPT("bar")).isUpstreamDefinite()).isFalse(); |
||||
} |
||||
|
||||
@Test |
||||
public void is_upstream_definite_in_complex_case() { |
||||
assertThat(makePathReturningTail(makePPT("foo"), makePPT("bar"), makePPT("baz")).isUpstreamDefinite()).isTrue(); |
||||
|
||||
assertThat(makePathReturningTail(makePPT("foo"), new WildcardPathToken()).isUpstreamDefinite()).isTrue(); |
||||
|
||||
assertThat(makePathReturningTail(new WildcardPathToken(), makePPT("bar"), makePPT("baz")).isUpstreamDefinite()).isFalse(); |
||||
} |
||||
|
||||
|
||||
private PathToken makePPT(final String ... properties) { |
||||
return new PropertyPathToken(Arrays.asList(properties)); |
||||
} |
||||
|
||||
private PathToken makePathReturningTail(final PathToken ... tokens) { |
||||
PathToken last = null; |
||||
for (final PathToken token : tokens) { |
||||
if (last != null) { |
||||
last.appendTailToken(token); |
||||
} |
||||
last = token; |
||||
} |
||||
return last; |
||||
} |
||||
} |
Loading…
Reference in new issue