From d855c178990147a4acb75c8d4321fba55d2f2d8d Mon Sep 17 00:00:00 2001 From: freestrings Date: Sun, 23 Feb 2020 14:45:14 +0900 Subject: [PATCH 1/2] split unit-tests --- tests/array_filter.rs | 218 +++++++++++++ tests/filter.rs | 646 ++----------------------------------- tests/jsonpath_examples.rs | 242 ++++++++++++++ tests/op.rs | 378 ++++++++++++++++++++++ tests/return_type.rs | 97 ++++++ 5 files changed, 969 insertions(+), 612 deletions(-) create mode 100644 tests/array_filter.rs create mode 100644 tests/jsonpath_examples.rs create mode 100644 tests/op.rs create mode 100644 tests/return_type.rs diff --git a/tests/array_filter.rs b/tests/array_filter.rs new file mode 100644 index 0000000..707336e --- /dev/null +++ b/tests/array_filter.rs @@ -0,0 +1,218 @@ +#[macro_use] +extern crate serde_json; + +use common::{read_json, select_and_then_compare, setup}; + +mod common; + +#[test] +fn array_range_default() { + setup(); + + select_and_then_compare( + "$.school.friends[1, 2]", + read_json("./benchmark/data_obj.json"), + json!([ + {"id": 1, "name": "Vincent Cannon" }, + {"id": 2, "name": "Gray Berry"} + ]), + ); +} + +#[test] +fn array_range_all() { + setup(); + + select_and_then_compare( + "$[ : ]", + json!(["first", "second"]), + json!(["first", "second"]), + ); +} + +#[test] +fn array_range_step_all() { + setup(); + + select_and_then_compare( + "$[::]", + json!(["first", "second", "third", "forth", "fifth"]), + json!(["first", "second", "third", "forth", "fifth"]), + ); +} + +#[test] +fn array_range_step_only_step_value() { + setup(); + + select_and_then_compare( + "$[::2]", + json!(["first", "second", "third", "forth", "fifth"]), + json!(["first", "third", "fifth"]), + ); +} + +#[test] +fn array_range_step_only_start_index() { + setup(); + + select_and_then_compare( + "$[1::]", + json!(["first", "second", "third", "forth", "fifth"]), + json!(["second", "third", "forth", "fifth"]), + ); +} + +#[test] +fn array_range_step_empty_step_value() { + setup(); + + select_and_then_compare( + "$[1:2:]", + json!(["first", "second", "third", "forth", "fifth"]), + json!(["second"]), + ); +} + +#[test] +fn array_range_step_empty_end_index() { + setup(); + + select_and_then_compare( + "$[1::2]", + json!(["first", "second", "third", "forth", "fifth"]), + json!(["second", "forth"]), + ); +} + +#[test] +fn array_range_step_by_1() { + setup(); + + select_and_then_compare( + "$[0:3:1]", + json!(["first", "second", "third", "forth", "fifth"]), + json!(["first", "second", "third"]), + ); +} + +#[test] +fn array_range_step_by_2() { + setup(); + + select_and_then_compare( + "$[0:3:2]", + json!(["first", "second", "third", "forth", "fifth"]), + json!(["first", "third"]), + ); +} + +#[test] +fn array_range_only_negative_index() { + setup(); + + select_and_then_compare( + "$[-4:]", + json!(["first", "second", "third"]), + json!(["first", "second", "third"]), + ); +} + +#[test] +fn array_range_only_end_index() { + setup(); + + select_and_then_compare( + "$[:4]", + json!(["first", "second", "third"]), + json!(["first", "second", "third"]), + ); +} + +#[test] +fn array_range_only_from_index() { + setup(); + + select_and_then_compare( + "$.school.friends[1: ]", + read_json("./benchmark/data_obj.json"), + json!([ + {"id": 1, "name": "Vincent Cannon" }, + {"id": 2, "name": "Gray Berry"} + ]), + ); +} + +#[test] +fn array_range_only_nagative_end_index() { + setup(); + + select_and_then_compare( + "$.school.friends[:-2]", + read_json("./benchmark/data_obj.json"), + json!([ + {"id": 0, "name": "Millicent Norman"} + ]), + ); +} + +#[test] +fn array_index() { + setup(); + + select_and_then_compare( + "$..friends[2].name", + read_json("./benchmark/data_obj.json"), + json!(["Gray Berry", "Gray Berry"]), + ); +} + +#[test] +fn array_all_index() { + setup(); + + select_and_then_compare( + "$..friends[*].name", + read_json("./benchmark/data_obj.json"), + json!([ + "Vincent Cannon", + "Gray Berry", + "Millicent Norman", + "Vincent Cannon", + "Gray Berry" + ]), + ); +} + +#[test] +fn array_all_and_then_key() { + setup(); + + select_and_then_compare( + "$['school']['friends'][*].['name']", + read_json("./benchmark/data_obj.json"), + json!(["Millicent Norman", "Vincent Cannon", "Gray Berry"]), + ); +} + +#[test] +fn array_index_and_then_key() { + setup(); + + select_and_then_compare( + "$['school']['friends'][0].['name']", + read_json("./benchmark/data_obj.json"), + json!(["Millicent Norman"]), + ); +} + +#[test] +fn array_multiple_key() { + setup(); + + select_and_then_compare( + r#"$.["eyeColor", "name"]"#, + read_json("./benchmark/data_obj.json"), + json!(["blue", "Leonor Herman"]), + ); +} diff --git a/tests/filter.rs b/tests/filter.rs index d1c94a6..249350f 100644 --- a/tests/filter.rs +++ b/tests/filter.rs @@ -1,619 +1,10 @@ #[macro_use] extern crate serde_json; -use serde_json::Value; - use common::{read_json, select_and_then_compare, setup}; mod common; -#[test] -fn array() { - setup(); - - select_and_then_compare( - "$.school.friends[1, 2]", - read_json("./benchmark/data_obj.json"), - json!([ - {"id": 1, "name": "Vincent Cannon" }, - {"id": 2, "name": "Gray Berry"} - ]), - ); - - select_and_then_compare( - "$.school.friends[1: ]", - read_json("./benchmark/data_obj.json"), - json!([ - {"id": 1, "name": "Vincent Cannon" }, - {"id": 2, "name": "Gray Berry"} - ]), - ); - - select_and_then_compare( - "$.school.friends[:-2]", - read_json("./benchmark/data_obj.json"), - json!([ - {"id": 0, "name": "Millicent Norman"} - ]), - ); - - select_and_then_compare( - "$..friends[2].name", - read_json("./benchmark/data_obj.json"), - json!(["Gray Berry", "Gray Berry"]), - ); - - select_and_then_compare( - "$..friends[*].name", - read_json("./benchmark/data_obj.json"), - json!([ - "Vincent Cannon", - "Gray Berry", - "Millicent Norman", - "Vincent Cannon", - "Gray Berry" - ]), - ); - - select_and_then_compare( - "$['school']['friends'][*].['name']", - read_json("./benchmark/data_obj.json"), - json!(["Millicent Norman", "Vincent Cannon", "Gray Berry"]), - ); - - select_and_then_compare( - "$['school']['friends'][0].['name']", - read_json("./benchmark/data_obj.json"), - json!(["Millicent Norman"]), - ); - - select_and_then_compare( - r#"$.["eyeColor", "name"]"#, - read_json("./benchmark/data_obj.json"), - json!(["blue", "Leonor Herman"]), - ); -} - -#[test] -fn return_type() { - setup(); - - select_and_then_compare( - "$.school", - read_json("./benchmark/data_obj.json"), - json!([{ - "friends": [ - {"id": 0, "name": "Millicent Norman"}, - {"id": 1, "name": "Vincent Cannon" }, - {"id": 2, "name": "Gray Berry"} - ] - }]), - ); - - select_and_then_compare( - "$.school[?(@.friends[0])]", - read_json("./benchmark/data_obj.json"), - json!([{ - "friends": [ - {"id": 0, "name": "Millicent Norman"}, - {"id": 1, "name": "Vincent Cannon" }, - {"id": 2, "name": "Gray Berry"} - ] - }]), - ); - - select_and_then_compare( - "$.school[?(@.friends[10])]", - read_json("./benchmark/data_obj.json"), - json!([{ - "friends": [ - {"id": 0, "name": "Millicent Norman"}, - {"id": 1, "name": "Vincent Cannon" }, - {"id": 2, "name": "Gray Berry"} - ] - }]), - ); - - select_and_then_compare( - "$.school[?(1==1)]", - read_json("./benchmark/data_obj.json"), - json!([{ - "friends": [ - {"id": 0, "name": "Millicent Norman"}, - {"id": 1, "name": "Vincent Cannon" }, - {"id": 2, "name": "Gray Berry"} - ] - }]), - ); - - select_and_then_compare( - "$.school.friends[?(1==1)]", - read_json("./benchmark/data_obj.json"), - json!([[ - {"id": 0, "name": "Millicent Norman"}, - {"id": 1, "name": "Vincent Cannon" }, - {"id": 2, "name": "Gray Berry"} - ]]), - ); -} - -#[test] -fn op_default() { - setup(); - - select_and_then_compare( - "$.school[?(@.friends == @.friends)]", - read_json("./benchmark/data_obj.json"), - json!([{ - "friends": [ - {"id": 0, "name": "Millicent Norman"}, - {"id": 1, "name": "Vincent Cannon" }, - {"id": 2, "name": "Gray Berry"} - ] - }]), - ); - - select_and_then_compare( - "$.friends[?(@.name)]", - read_json("./benchmark/data_obj.json"), - json!([ - { "id" : 1, "name" : "Vincent Cannon" }, - { "id" : 2, "name" : "Gray Berry" } - ]), - ); - - select_and_then_compare( - "$.friends[?(@.id >= 2)]", - read_json("./benchmark/data_obj.json"), - json!([ - { "id" : 2, "name" : "Gray Berry" } - ]), - ); - - select_and_then_compare( - "$.friends[?(@.id >= 2 || @.id == 1)]", - read_json("./benchmark/data_obj.json"), - json!([ - { "id" : 2, "name" : "Gray Berry" }, - { "id" : 1, "name" : "Vincent Cannon" } - ]), - ); - - select_and_then_compare( - "$.friends[?( (@.id >= 2 || @.id == 1) && @.id == 0)]", - read_json("./benchmark/data_obj.json"), - json!([Value::Null]), - ); - - select_and_then_compare( - "$..friends[?(@.id == $.index)].id", - read_json("./benchmark/data_obj.json"), - json!([0, 0]), - ); - - select_and_then_compare( - "$..book[?($.store.bicycle.price < @.price)].price", - read_json("./benchmark/example.json"), - json!([22.99]), - ); - - select_and_then_compare( - "$..book[?( (@.price == 12.99 || @.category == 'reference') && @.price > 10)].price", - read_json("./benchmark/example.json"), - json!([12.99]), - ); - - select_and_then_compare( - "$..[?(@.age > 40)]", - json!([ - { "name": "이름1", "age": 40, "phone": "+33 12341234" }, - { "name": "이름2", "age": 42, "phone": "++44 12341234" } - ]), - json!([ - { "name" : "이름2", "age" : 42, "phone" : "++44 12341234" } - ]), - ); - - select_and_then_compare( - "$..[?(@.age >= 30)]", - json!({ - "school": { - "friends": [ - {"name": "친구1", "age": 20}, - {"name": "친구2", "age": 20} - ] - }, - "friends": [ - {"name": "친구3", "age": 30}, - {"name": "친구4"} - ]}), - json!([ - { "name" : "친구3", "age" : 30 } - ]), - ); -} - -#[test] -fn op_number() { - setup(); - - select_and_then_compare("$.[?(@.a == 1)]", json!({ "a": 1 }), json!([{ "a": 1 }])); - select_and_then_compare("$.[?(@.a != 2)]", json!({ "a": 1 }), json!([{ "a": 1 }])); - select_and_then_compare("$.[?(@.a < 2)]", json!({ "a": 1 }), json!([{ "a": 1 }])); - select_and_then_compare("$.[?(@.a <= 1)]", json!({ "a": 1 }), json!([{ "a": 1 }])); - select_and_then_compare("$.[?(@.a > 0)]", json!({ "a": 1 }), json!([{ "a": 1 }])); - select_and_then_compare("$.[?(@.a >= 0)]", json!({ "a": 1 }), json!([{ "a": 1 }])); -} - -#[test] -fn op_string() { - setup(); - - select_and_then_compare( - r#"$.[?(@.a == "b")]"#, - json!({ "a": "b" }), - json!([{ "a": "b" }]), - ); - select_and_then_compare( - r#"$.[?(@.a != "c")]"#, - json!({ "a": "b" }), - json!([{ "a": "b" }]), - ); - select_and_then_compare( - r#"$.[?(@.a < "b")]"#, - json!({ "a": "b" }), - json!([Value::Null]), - ); - select_and_then_compare( - r#"$.[?(@.a <= "b")]"#, - json!({ "a": "b" }), - json!([{ "a": "b" }]), - ); - select_and_then_compare( - r#"$.[?(@.a > "b")]"#, - json!({ "a": "b" }), - json!([Value::Null]), - ); - select_and_then_compare( - r#"$.[?(@.a >= "b")]"#, - json!({ "a": "b" }), - json!([{ "a": "b" }]), - ); -} - -#[test] -fn op_object() { - setup(); - - select_and_then_compare( - r#"$.[?(@.a == @.c)]"#, - json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}), - json!([{"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}]), - ); - select_and_then_compare( - r#"$.[?(@.a != @.c)]"#, - json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}), - json!([Value::Null]), - ); - select_and_then_compare( - r#"$.[?(@.a < @.c)]"#, - json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}), - json!([Value::Null]), - ); - select_and_then_compare( - r#"$.[?(@.a <= @.c)]"#, - json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}), - json!([Value::Null]), - ); - select_and_then_compare( - r#"$.[?(@.a > @.c)]"#, - json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}), - json!([Value::Null]), - ); - select_and_then_compare( - r#"$.[?(@.a >= @.c)]"#, - json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}), - json!([Value::Null]), - ); -} - -#[test] -fn op_complex() { - setup(); - - select_and_then_compare( - r#"$.[?(1 == @.a)]"#, - json!({ "a": { "b": 1 } }), - json!([Value::Null]), - ); - select_and_then_compare( - r#"$.[?("1" != @.a)]"#, - json!({ "a": { "b": 1 } }), - json!([Value::Null]), - ); - select_and_then_compare( - r#"$.[?(@.a <= 1)]"#, - json!({ "a": { "b": 1 } }), - json!([Value::Null]), - ); - select_and_then_compare( - r#"$.[?(@.a > "1")]"#, - json!({ "a": { "b": 1 } }), - json!([Value::Null]), - ); -} - -#[test] -fn op_compare() { - setup(); - - for path in [ - r#"$[?("1" == 1)]"#, - r#"$[?(1 == "1")]"#, - r#"$[?(true == 1)]"#, - r#"$[?(@ == 1)]"#, - ] - .iter() - { - select_and_then_compare(path, json!({}), json!([Value::Null])); - } -} - -#[test] -fn example() { - setup(); - - select_and_then_compare( - r#"$.store.book[*].author"#, - read_json("./benchmark/example.json"), - json!([ - "Nigel Rees", - "Evelyn Waugh", - "Herman Melville", - "J. R. R. Tolkien" - ]), - ); - - select_and_then_compare( - r#"$..author"#, - read_json("./benchmark/example.json"), - json!([ - "Nigel Rees", - "Evelyn Waugh", - "Herman Melville", - "J. R. R. Tolkien" - ]), - ); - - select_and_then_compare( - r#"$.store.*"#, - read_json("./benchmark/example.json"), - json!([ - [ - {"category" : "reference", "author" : "Nigel Rees","title" : "Sayings of the Century", "price" : 8.95}, - {"category" : "fiction", "author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99}, - {"category" : "fiction", "author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99}, - {"category" : "fiction", "author" : "J. R. R. Tolkien","title" : "The Lord of the Rings","isbn" : "0-395-19395-8","price" : 22.99} - ], - {"color" : "red","price" : 19.95}, - ]), - ); - - select_and_then_compare( - r#"$.store..price"#, - read_json("./benchmark/example.json"), - json!([8.95, 12.99, 8.99, 22.99, 19.95]), - ); - - select_and_then_compare( - r#"$..book[2]"#, - read_json("./benchmark/example.json"), - json!([ - { - "category" : "fiction", - "author" : "Herman Melville", - "title" : "Moby Dick", - "isbn" : "0-553-21311-3", - "price" : 8.99 - } - ]), - ); - - select_and_then_compare( - r#"$..book[-2]"#, - read_json("./benchmark/example.json"), - json!([ - { - "category" : "fiction", - "author" : "Herman Melville", - "title" : "Moby Dick", - "isbn" : "0-553-21311-3", - "price" : 8.99 - } - ]), - ); - - select_and_then_compare( - r#"$..book[0, 1]"#, - read_json("./benchmark/example.json"), - json!([ - { - "category" : "reference", - "author" : "Nigel Rees", - "title" : "Sayings of the Century", - "price" : 8.95 - }, - { - "category" : "fiction", - "author" : "Evelyn Waugh", - "title" : "Sword of Honour", - "price" : 12.99 - } - ]), - ); - - select_and_then_compare( - r#"$..book[:2]"#, - read_json("./benchmark/example.json"), - json!([ - { - "category" : "reference", - "author" : "Nigel Rees", - "title" : "Sayings of the Century", - "price" : 8.95 - }, - { - "category" : "fiction", - "author" : "Evelyn Waugh", - "title" : "Sword of Honour", - "price" : 12.99 - } - ]), - ); - - select_and_then_compare( - r#"$..book[2:]"#, - read_json("./benchmark/example.json"), - json!([ - { - "category" : "fiction", - "author" : "Herman Melville", - "title" : "Moby Dick", - "isbn" : "0-553-21311-3", - "price" : 8.99 - }, - { - "category" : "fiction", - "author" : "J. R. R. Tolkien", - "title" : "The Lord of the Rings", - "isbn" : "0-395-19395-8", - "price" : 22.99 - } - ]), - ); - - select_and_then_compare( - r#"$..book[?(@.isbn)]"#, - read_json("./benchmark/example.json"), - json!([ - { - "category" : "fiction", - "author" : "Herman Melville", - "title" : "Moby Dick", - "isbn" : "0-553-21311-3", - "price" : 8.99 - }, - { - "category" : "fiction", - "author" : "J. R. R. Tolkien", - "title" : "The Lord of the Rings", - "isbn" : "0-395-19395-8", - "price" : 22.99 - } - ]), - ); - - select_and_then_compare( - r#"$.store.book[?(@.price < 10)]"#, - read_json("./benchmark/example.json"), - json!([ - { - "category" : "reference", - "author" : "Nigel Rees", - "title" : "Sayings of the Century", - "price" : 8.95 - }, - { - "category" : "fiction", - "author" : "Herman Melville", - "title" : "Moby Dick", - "isbn" : "0-553-21311-3", - "price" : 8.99 - } - ]), - ); - - select_and_then_compare( - r#"$..*"#, - read_json("./benchmark/example.json"), - read_json("./benchmark/giveme_every_thing_result.json"), - ); -} - -#[test] -fn filer_same_obj() { - setup(); - - select_and_then_compare( - r#"$..[?(@.a == 1)]"#, - json!({ - "a": 1, - "b" : {"a": 1}, - "c" : {"a": 1} - }), - json!([ - {"a": 1}, - {"a": 1} - ]), - ); -} - -#[test] -fn range() { - setup(); - - select_and_then_compare( - "$[ : ]", - json!(["first", "second"]), - json!(["first", "second"]), - ); - select_and_then_compare( - "$[::]", - json!(["first", "second", "third", "forth", "fifth"]), - json!(["first", "second", "third", "forth", "fifth"]), - ); - select_and_then_compare( - "$[::2]", - json!(["first", "second", "third", "forth", "fifth"]), - json!(["first", "third", "fifth"]), - ); - select_and_then_compare( - "$[1::]", - json!(["first", "second", "third", "forth", "fifth"]), - json!(["second", "third", "forth", "fifth"]), - ); - select_and_then_compare( - "$[1:2:]", - json!(["first", "second", "third", "forth", "fifth"]), - json!(["second"]), - ); - select_and_then_compare( - "$[1::2]", - json!(["first", "second", "third", "forth", "fifth"]), - json!(["second", "forth"]), - ); - select_and_then_compare( - "$[0:3:1]", - json!(["first", "second", "third", "forth", "fifth"]), - json!(["first", "second", "third"]), - ); - select_and_then_compare( - "$[0:3:2]", - json!(["first", "second", "third", "forth", "fifth"]), - json!(["first", "third"]), - ); - select_and_then_compare( - "$[-4:]", - json!(["first", "second", "third"]), - json!(["first", "second", "third"]), - ); - select_and_then_compare( - "$[:4]", - json!(["first", "second", "third"]), - json!(["first", "second", "third"]), - ); -} - #[test] fn quote() { setup(); @@ -631,7 +22,7 @@ fn quote() { } #[test] -fn all_filter() { +fn filter_next_all() { setup(); for path in &[r#"$.*"#, r#"$[*]"#] { @@ -641,6 +32,11 @@ fn all_filter() { json!(["string", 42, { "key": "value" }, [0, 1]]), ); } +} + +#[test] +fn filter_all() { + setup(); for path in &[r#"$..*"#, r#"$..[*]"#] { select_and_then_compare( @@ -649,6 +45,11 @@ fn all_filter() { json!([ "string", 42, { "key" : "value" }, [ 0, 1 ], "value", 0, 1 ]), ); } +} + +#[test] +fn filter_array_next_all() { + setup(); for path in &[r#"$.*.*"#, r#"$[*].*"#, r#"$.*[*]"#, r#"$[*][*]"#] { select_and_then_compare( @@ -657,6 +58,11 @@ fn all_filter() { json!(["value", 0, 1]), ); } +} + +#[test] +fn filter_all_complex() { + setup(); for path in &[r#"$..friends.*"#, r#"$[*].friends.*"#] { select_and_then_compare( @@ -675,8 +81,9 @@ fn all_filter() { } #[test] -fn current_path() { +fn filter_parent_with_matched_child() { setup(); + select_and_then_compare( "$.a[?(@.b.c == 1)]", json!({ @@ -694,6 +101,11 @@ fn current_path() { } ]), ); +} + +#[test] +fn filter_parent_exist_child() { + setup(); select_and_then_compare( "$.a[?(@.b.c)]", @@ -715,7 +127,7 @@ fn current_path() { } #[test] -fn bugs33() { +fn bugs33_exist_in_all() { setup(); select_and_then_compare( @@ -738,6 +150,11 @@ fn bugs33() { } ]), ); +} + +#[test] +fn bugs33_exist_left_in_all_with_and_condition() { + setup(); select_and_then_compare( "$..[?(@.first && @.first.second)]", @@ -759,6 +176,11 @@ fn bugs33() { } ]), ); +} + +#[test] +fn bugs33_exist_right_in_all_with_and_condition() { + setup(); select_and_then_compare( "$..[?(@.b.c.d && @.b)]", diff --git a/tests/jsonpath_examples.rs b/tests/jsonpath_examples.rs new file mode 100644 index 0000000..35e84a3 --- /dev/null +++ b/tests/jsonpath_examples.rs @@ -0,0 +1,242 @@ +#[macro_use] +extern crate serde_json; + +use common::{read_json, select_and_then_compare, setup}; + +mod common; + +#[test] +fn example_authros_of_all_books() { + setup(); + + select_and_then_compare( + r#"$.store.book[*].author"#, + read_json("./benchmark/example.json"), + json!([ + "Nigel Rees", + "Evelyn Waugh", + "Herman Melville", + "J. R. R. Tolkien" + ]), + ); +} + +#[test] +fn all_authors() { + setup(); + + select_and_then_compare( + r#"$..author"#, + read_json("./benchmark/example.json"), + json!([ + "Nigel Rees", + "Evelyn Waugh", + "Herman Melville", + "J. R. R. Tolkien" + ]), + ); +} + +#[test] +fn all_things_both_books_and_bicycles() { + setup(); + + select_and_then_compare( + r#"$.store.*"#, + read_json("./benchmark/example.json"), + json!([ + [ + {"category" : "reference", "author" : "Nigel Rees","title" : "Sayings of the Century", "price" : 8.95}, + {"category" : "fiction", "author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99}, + {"category" : "fiction", "author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99}, + {"category" : "fiction", "author" : "J. R. R. Tolkien","title" : "The Lord of the Rings","isbn" : "0-395-19395-8","price" : 22.99} + ], + {"color" : "red","price" : 19.95}, + ]), + ); +} + +#[test] +fn the_price_of_everything() { + setup(); + + select_and_then_compare( + r#"$.store..price"#, + read_json("./benchmark/example.json"), + json!([8.95, 12.99, 8.99, 22.99, 19.95]), + ); +} + +#[test] +fn the_third_book() { + setup(); + + select_and_then_compare( + r#"$..book[2]"#, + read_json("./benchmark/example.json"), + json!([ + { + "category" : "fiction", + "author" : "Herman Melville", + "title" : "Moby Dick", + "isbn" : "0-553-21311-3", + "price" : 8.99 + } + ]), + ); +} + +#[test] +fn the_second_to_last_book() { + setup(); + + select_and_then_compare( + r#"$..book[-2]"#, + read_json("./benchmark/example.json"), + json!([ + { + "category" : "fiction", + "author" : "Herman Melville", + "title" : "Moby Dick", + "isbn" : "0-553-21311-3", + "price" : 8.99 + } + ]), + ); +} + +#[test] +fn the_first_two_books() { + setup(); + + select_and_then_compare( + r#"$..book[0, 1]"#, + read_json("./benchmark/example.json"), + json!([ + { + "category" : "reference", + "author" : "Nigel Rees", + "title" : "Sayings of the Century", + "price" : 8.95 + }, + { + "category" : "fiction", + "author" : "Evelyn Waugh", + "title" : "Sword of Honour", + "price" : 12.99 + } + ]), + ); +} + +#[test] +fn all_books_from_index_0_inclusive_until_index_2_exclusive() { + setup(); + + select_and_then_compare( + r#"$..book[:2]"#, + read_json("./benchmark/example.json"), + json!([ + { + "category" : "reference", + "author" : "Nigel Rees", + "title" : "Sayings of the Century", + "price" : 8.95 + }, + { + "category" : "fiction", + "author" : "Evelyn Waugh", + "title" : "Sword of Honour", + "price" : 12.99 + } + ]), + ); +} + +#[test] +fn all_books_from_index_1_inclusive_until_index_2_exclusive() { + setup(); + + select_and_then_compare( + r#"$..book[2:]"#, + read_json("./benchmark/example.json"), + json!([ + { + "category" : "fiction", + "author" : "Herman Melville", + "title" : "Moby Dick", + "isbn" : "0-553-21311-3", + "price" : 8.99 + }, + { + "category" : "fiction", + "author" : "J. R. R. Tolkien", + "title" : "The Lord of the Rings", + "isbn" : "0-395-19395-8", + "price" : 22.99 + } + ]), + ); +} + +#[test] +fn all_books_with_an_isbn_number() { + setup(); + + select_and_then_compare( + r#"$..book[?(@.isbn)]"#, + read_json("./benchmark/example.json"), + json!([ + { + "category" : "fiction", + "author" : "Herman Melville", + "title" : "Moby Dick", + "isbn" : "0-553-21311-3", + "price" : 8.99 + }, + { + "category" : "fiction", + "author" : "J. R. R. Tolkien", + "title" : "The Lord of the Rings", + "isbn" : "0-395-19395-8", + "price" : 22.99 + } + ]), + ); +} + +#[test] +fn all_books_in_store_cheaper_than_10() { + setup(); + + select_and_then_compare( + r#"$.store.book[?(@.price < 10)]"#, + read_json("./benchmark/example.json"), + json!([ + { + "category" : "reference", + "author" : "Nigel Rees", + "title" : "Sayings of the Century", + "price" : 8.95 + }, + { + "category" : "fiction", + "author" : "Herman Melville", + "title" : "Moby Dick", + "isbn" : "0-553-21311-3", + "price" : 8.99 + } + ]), + ); +} + +#[test] +fn give_me_every_thing() { + setup(); + + select_and_then_compare( + r#"$..*"#, + read_json("./benchmark/example.json"), + read_json("./benchmark/giveme_every_thing_result.json"), + ); +} diff --git a/tests/op.rs b/tests/op.rs new file mode 100644 index 0000000..1146ac0 --- /dev/null +++ b/tests/op.rs @@ -0,0 +1,378 @@ +#[macro_use] +extern crate serde_json; + +use serde_json::Value; + +use common::{read_json, select_and_then_compare, setup}; + +mod common; + +#[test] +fn op_object_eq() { + setup(); + + select_and_then_compare( + "$.school[?(@.friends == @.friends)]", + read_json("./benchmark/data_obj.json"), + json!([{ + "friends": [ + {"id": 0, "name": "Millicent Norman"}, + {"id": 1, "name": "Vincent Cannon" }, + {"id": 2, "name": "Gray Berry"} + ] + }]), + ); +} + +#[test] +fn op_object_ge() { + setup(); + + select_and_then_compare( + "$.friends[?(@.id >= 2)]", + read_json("./benchmark/data_obj.json"), + json!([ + { "id" : 2, "name" : "Gray Berry" } + ]), + ); +} + +#[test] +fn op_object_or_default() { + setup(); + + select_and_then_compare( + "$.friends[?(@.id >= 2 || @.id == 1)]", + read_json("./benchmark/data_obj.json"), + json!([ + { "id" : 2, "name" : "Gray Berry" }, + { "id" : 1, "name" : "Vincent Cannon" } + ]), + ); +} + +#[test] +fn op_object_and_or() { + setup(); + + select_and_then_compare( + "$.friends[?( (@.id >= 2 || @.id == 1) && @.id == 0)]", + read_json("./benchmark/data_obj.json"), + json!([Value::Null]), + ); +} + +#[test] +fn op_result_type() { + setup(); + + select_and_then_compare( + "$..friends[?(@.id == $.index)].id", + read_json("./benchmark/data_obj.json"), + json!([0, 0]), + ); +} + +#[test] +fn op_absolute_path_result_type() { + setup(); + + select_and_then_compare( + "$..book[?($.store.bicycle.price < @.price)].price", + read_json("./benchmark/example.json"), + json!([22.99]), + ); +} + +#[test] +fn op_complicated() { + setup(); + + select_and_then_compare( + "$..book[?( (@.price == 12.99 || @.category == 'reference') && @.price > 10)].price", + read_json("./benchmark/example.json"), + json!([12.99]), + ); +} + +#[test] +fn op_gt() { + setup(); + + select_and_then_compare( + "$..[?(@.age > 40)]", + json!([ + { "name": "이름1", "age": 40, "phone": "+33 12341234" }, + { "name": "이름2", "age": 42, "phone": "++44 12341234" } + ]), + json!([ + { "name" : "이름2", "age" : 42, "phone" : "++44 12341234" } + ]), + ); +} + +#[test] +fn op_ge() { + setup(); + + select_and_then_compare( + "$..[?(@.age >= 30)]", + json!({ + "school": { + "friends": [ + {"name": "친구1", "age": 20}, + {"name": "친구2", "age": 20} + ] + }, + "friends": [ + {"name": "친구3", "age": 30}, + {"name": "친구4"} + ]}), + json!([ + { "name" : "친구3", "age" : 30 } + ]), + ); +} + +#[test] +fn op_eq_for_number() { + setup(); + + select_and_then_compare("$.[?(@.a == 1)]", json!({ "a": 1 }), json!([{ "a": 1 }])); +} + +#[test] +fn op_ne_for_number() { + setup(); + + select_and_then_compare("$.[?(@.a != 2)]", json!({ "a": 1 }), json!([{ "a": 1 }])); +} + +#[test] +fn op_lt_for_number() { + setup(); + + select_and_then_compare("$.[?(@.a < 2)]", json!({ "a": 1 }), json!([{ "a": 1 }])); +} + +#[test] +fn op_le_for_number() { + setup(); + + select_and_then_compare("$.[?(@.a <= 1)]", json!({ "a": 1 }), json!([{ "a": 1 }])); +} + +#[test] +fn op_gt_for_number() { + setup(); + + select_and_then_compare("$.[?(@.a > 0)]", json!({ "a": 1 }), json!([{ "a": 1 }])); +} + +#[test] +fn op_ge_for_number() { + setup(); + + select_and_then_compare("$.[?(@.a >= 0)]", json!({ "a": 1 }), json!([{ "a": 1 }])); +} + + + +#[test] +fn op_eq_for_string_value() { + setup(); + + select_and_then_compare( + r#"$.[?(@.a == "b")]"#, json!({ "a": "b" }), json!([{ "a": "b" }]), + ); +} + +#[test] +fn op_ne_for_string_value() { + setup(); + + select_and_then_compare( + r#"$.[?(@.a != "c")]"#, json!({ "a": "b" }), json!([{ "a": "b" }]), + ); + +} + +#[test] +fn op_lt_for_string_value() { + setup(); + + select_and_then_compare( + r#"$.[?(@.a < "b")]"#, json!({ "a": "b" }), json!([Value::Null]), + ); +} + +#[test] +fn op_le_for_string_value() { + setup(); + + select_and_then_compare( + r#"$.[?(@.a <= "b")]"#, json!({ "a": "b" }), json!([{ "a": "b" }]), + ); +} + +#[test] +fn op_gt_for_string_value() { + setup(); + + select_and_then_compare( + r#"$.[?(@.a > "b")]"#, json!({ "a": "b" }), json!([Value::Null]), + ); +} + +#[test] +fn op_ge_for_string_value() { + setup(); + + select_and_then_compare( + r#"$.[?(@.a >= "b")]"#, json!({ "a": "b" }), json!([{ "a": "b" }]), + ); +} + +#[test] +fn op_eq_for_object_value() { + setup(); + + select_and_then_compare( + r#"$.[?(@.a == @.c)]"#, + json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}), + json!([{"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}]), + ); +} + +#[test] +fn op_ne_for_object_value() { + setup(); + + select_and_then_compare( + r#"$.[?(@.a != @.c)]"#, + json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}), + json!([Value::Null]), + ); +} + +#[test] +fn op_lt_for_object_value() { + setup(); + + select_and_then_compare( + r#"$.[?(@.a < @.c)]"#, + json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}), + json!([Value::Null]), + ); +} + +#[test] +fn op_le_for_object_value() { + setup(); + + select_and_then_compare( + r#"$.[?(@.a <= @.c)]"#, + json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}), + json!([Value::Null]), + ); +} + +#[test] +fn op_gt_for_object_value() { + setup(); + + select_and_then_compare( + r#"$.[?(@.a > @.c)]"#, + json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}), + json!([Value::Null]), + ); +} + +#[test] +fn op_ge_for_object_value() { + setup(); + + select_and_then_compare( + r#"$.[?(@.a >= @.c)]"#, + json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}), + json!([Value::Null]), + ); +} + +#[test] +fn op_eq_for_complex_value() { + setup(); + + select_and_then_compare( + r#"$.[?(1 == @.a)]"#, + json!({ "a": { "b": 1 } }), + json!([Value::Null]), + ); +} + +#[test] +fn op_ne_for_complex_value() { + setup(); + + select_and_then_compare( + r#"$.[?("1" != @.a)]"#, + json!({ "a": { "b": 1 } }), + json!([Value::Null]), + ); +} + +#[test] +fn op_le_for_complex_value() { + setup(); + + select_and_then_compare( + r#"$.[?(@.a <= 1)]"#, + json!({ "a": { "b": 1 } }), + json!([Value::Null]), + ); +} + +#[test] +fn op_gt_for_complex_value() { + setup(); + + select_and_then_compare( + r#"$.[?(@.a > "1")]"#, + json!({ "a": { "b": 1 } }), + json!([Value::Null]), + ); +} + +#[test] +fn op_compare_different_types() { + setup(); + + for path in [ + r#"$[?("1" == 1)]"#, + r#"$[?(1 == "1")]"#, + r#"$[?(true == 1)]"#, + r#"$[?(@ == 1)]"#, + ] + .iter() + { + select_and_then_compare(path, json!({}), json!([Value::Null])); + } +} + +#[test] +fn op_for_same_type() { + setup(); + + select_and_then_compare( + r#"$..[?(@.a == 1)]"#, + json!({ + "a": 1, + "b" : {"a": 1}, + "c" : {"a": 1} + }), + json!([ + {"a": 1}, + {"a": 1} + ]), + ); +} \ No newline at end of file diff --git a/tests/return_type.rs b/tests/return_type.rs new file mode 100644 index 0000000..a1e0e40 --- /dev/null +++ b/tests/return_type.rs @@ -0,0 +1,97 @@ +#[macro_use] +extern crate serde_json; + +use common::{read_json, select_and_then_compare, setup}; + +mod common; + +#[test] +fn return_type_for_single_object() { + setup(); + + select_and_then_compare( + "$.school", + read_json("./benchmark/data_obj.json"), + json!([{ + "friends": [ + {"id": 0, "name": "Millicent Norman"}, + {"id": 1, "name": "Vincent Cannon" }, + {"id": 2, "name": "Gray Berry"} + ] + }]), + ); +} + +#[test] +fn return_type_for_single_object_key_matched() { + setup(); + + select_and_then_compare( + "$.friends[?(@.name)]", + read_json("./benchmark/data_obj.json"), + json!([ + { "id" : 1, "name" : "Vincent Cannon" }, + { "id" : 2, "name" : "Gray Berry" } + ]), + ); +} + +#[test] +fn return_type_for_child_object_matched() { + setup(); + + select_and_then_compare( + "$.school[?(@.friends[0])]", + read_json("./benchmark/data_obj.json"), + json!([{ + "friends": [ + {"id": 0, "name": "Millicent Norman"}, + {"id": 1, "name": "Vincent Cannon" }, + {"id": 2, "name": "Gray Berry"} + ] + }]), + ); +} + +// #[test] +fn return_type_for_child_object_not_matched() { + setup(); + + select_and_then_compare( + "$.school[?(@.friends[10])]", + read_json("./benchmark/data_obj.json"), + json!([]), + ); +} + +#[test] +fn return_type_for_object_filter_true() { + setup(); + + select_and_then_compare( + "$.school[?(1==1)]", + read_json("./benchmark/data_obj.json"), + json!([{ + "friends": [ + {"id": 0, "name": "Millicent Norman"}, + {"id": 1, "name": "Vincent Cannon" }, + {"id": 2, "name": "Gray Berry"} + ] + }]), + ); +} + +#[test] +fn return_type_for_array_filter_true() { + setup(); + + select_and_then_compare( + "$.school.friends[?(1==1)]", + read_json("./benchmark/data_obj.json"), + json!([[ + {"id": 0, "name": "Millicent Norman"}, + {"id": 1, "name": "Vincent Cannon" }, + {"id": 2, "name": "Gray Berry"} + ]]), + ); +} \ No newline at end of file From 218321a4bd967965a80ede3b9fde91c0629f9dd2 Mon Sep 17 00:00:00 2001 From: freestrings Date: Sun, 23 Feb 2020 19:18:13 +0900 Subject: [PATCH 2/2] fix return_type_for_child_object_not_matched --- .idea/runConfigurations/filter.xml | 12 ----- .idea/runConfigurations/lib.xml | 12 ----- .idea/runConfigurations/mutable.xml | 12 ----- .idea/runConfigurations/readme.xml | 12 ----- .travis.yml | 10 +--- clippy.sh | 11 +++++ src/select/mod.rs | 77 +++++++++++++++++++---------- tests/return_type.rs | 6 ++- 8 files changed, 68 insertions(+), 84 deletions(-) delete mode 100644 .idea/runConfigurations/filter.xml delete mode 100644 .idea/runConfigurations/lib.xml delete mode 100644 .idea/runConfigurations/mutable.xml delete mode 100644 .idea/runConfigurations/readme.xml create mode 100755 clippy.sh diff --git a/.idea/runConfigurations/filter.xml b/.idea/runConfigurations/filter.xml deleted file mode 100644 index 157a24b..0000000 --- a/.idea/runConfigurations/filter.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/runConfigurations/lib.xml b/.idea/runConfigurations/lib.xml deleted file mode 100644 index 6bd36ec..0000000 --- a/.idea/runConfigurations/lib.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/runConfigurations/mutable.xml b/.idea/runConfigurations/mutable.xml deleted file mode 100644 index 765dcaf..0000000 --- a/.idea/runConfigurations/mutable.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/runConfigurations/readme.xml b/.idea/runConfigurations/readme.xml deleted file mode 100644 index 02c612e..0000000 --- a/.idea/runConfigurations/readme.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 3a56064..543e927 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,15 +24,9 @@ matrix: before_script: - rustup component add clippy script: - - cargo clean - - cargo clippy -- -D warnings - - cargo build --verbose --all - - cargo clippy --all-targets --all-features -- -D warnings -A clippy::cognitive_complexity - - cargo test --verbose --all - - cd wasm && cargo clippy -- -D warnings -A clippy::suspicious_else_formatting - - cd ../../ + - ./clippy.sh after_success: | - cargo tarpaulin --exclude-files nodejs wasm parser/mod.rs --out Xml + cargo tarpaulin --exclude-files wasm parser/mod.rs --out Xml bash <(curl -s https://codecov.io/bash) - rust: stable os: osx diff --git a/clippy.sh b/clippy.sh new file mode 100755 index 0000000..9bf44eb --- /dev/null +++ b/clippy.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +set -e + +cargo clean +cargo clippy -- -D warnings +cargo build --verbose --all +cargo clippy --all-targets --all-features -- -D warnings -A clippy::cognitive_complexity +cargo test --verbose --all +cd wasm && cargo clippy -- -D warnings -A clippy::suspicious_else_formatting +cd ../ \ No newline at end of file diff --git a/src/select/mod.rs b/src/select/mod.rs index c6f7716..142b973 100644 --- a/src/select/mod.rs +++ b/src/select/mod.rs @@ -710,17 +710,37 @@ impl<'a, 'b> Selector<'a, 'b> { } fn next_from_current_with_num(&mut self, index: f64) { + fn _collect<'a>(tmp: &mut Vec<&'a Value>, vec: &'a [Value], index: f64) { + let index = abs_index(index as isize, vec.len()); + if let Some(v) = vec.get(index) { + tmp.push(v); + } + } + if let Some(current) = self.current.take() { let mut tmp = Vec::new(); for c in current { - if let Value::Array(vec) = c { - let index = abs_index(index as isize, vec.len()); - if let Some(v) = c.get(index) { - tmp.push(v); + match c { + Value::Object(map) => { + for k in map.keys() { + if let Some(Value::Array(vec)) = map.get(k) { + _collect(&mut tmp, vec, index); + } + } } + Value::Array(vec) => { + _collect(&mut tmp, vec, index); + } + _ => {} } } - self.current = Some(tmp); + + if tmp.is_empty() { + self.terms.pop(); + self.current = Some(vec![&Value::Null]); + } else { + self.current = Some(tmp); + } } debug!( @@ -729,27 +749,6 @@ impl<'a, 'b> Selector<'a, 'b> { ); } - fn next_from_current_with_str(&mut self, keys: &[String]) { - if let Some(current) = self.current.take() { - let mut tmp = Vec::new(); - for c in current { - if let Value::Object(map) = c { - for key in keys { - if let Some(v) = map.get(key) { - tmp.push(v) - } - } - } - } - self.current = Some(tmp); - } - - debug!( - "next_from_current_with_str : {:?}, {:?}", - keys, self.current - ); - } - fn next_all_from_current(&mut self) { if let Some(current) = self.current.take() { let mut tmp = Vec::new(); @@ -774,6 +773,32 @@ impl<'a, 'b> Selector<'a, 'b> { debug!("next_all_from_current : {:?}", self.current); } + fn next_from_current_with_str(&mut self, keys: &[String]) { + if let Some(current) = self.current.take() { + let mut tmp = Vec::new(); + for c in current { + if let Value::Object(map) = c { + for key in keys { + if let Some(v) = map.get(key) { + tmp.push(v) + } + } + } + } + + if tmp.is_empty() { + self.current = Some(vec![&Value::Null]); + } else { + self.current = Some(tmp); + } + } + + debug!( + "next_from_current_with_str : {:?}, {:?}", + keys, self.current + ); + } + fn all_from_current(&mut self) { if let Some(current) = self.current.take() { let mut tmp = Vec::new(); diff --git a/tests/return_type.rs b/tests/return_type.rs index a1e0e40..04a5fed 100644 --- a/tests/return_type.rs +++ b/tests/return_type.rs @@ -1,6 +1,8 @@ #[macro_use] extern crate serde_json; +use serde_json::Value; + use common::{read_json, select_and_then_compare, setup}; mod common; @@ -53,14 +55,14 @@ fn return_type_for_child_object_matched() { ); } -// #[test] +#[test] fn return_type_for_child_object_not_matched() { setup(); select_and_then_compare( "$.school[?(@.friends[10])]", read_json("./benchmark/data_obj.json"), - json!([]), + json!([Value::Null]), ); }