1 | use crate::parser::model::slice_from;
|
2 | use crate::parser::model::Comparison;
|
3 | use crate::parser::model::FilterAtom;
|
4 | use crate::parser::model::FnArg;
|
5 | use crate::parser::model::JpQuery;
|
6 | use crate::parser::model::Literal;
|
7 | use crate::parser::model::Segment;
|
8 | use crate::parser::model::Selector;
|
9 | use crate::parser::model::SingularQuery;
|
10 | use crate::parser::model::SingularQuerySegment;
|
11 | use crate::parser::model::TestFunction;
|
12 | use crate::parser::model::{Comparable, Filter};
|
13 | use crate::parser::Test;
|
14 | use crate::parser::{
|
15 | comp_expr, comparable, filter_atom, function_expr, jp_query, literal, parse_json_path, segment,
|
16 | selector, singular_query, singular_query_segments, slice_selector, test, JSPathParser, Parsed,
|
17 | Rule,
|
18 | };
|
19 | use crate::{
|
20 | arg, atom, cmp, comparable, jq, lit, or, q_segment, q_segments, segment, selector,
|
21 | singular_query, slice, test, test_fn,
|
22 | };
|
23 | use pest::error::Error;
|
24 | use pest::iterators::Pair;
|
25 | use pest::Parser;
|
26 | use std::fmt::Debug;
|
27 | use std::{panic, vec};
|
28 |
|
29 | struct TestPair<T> {
|
30 | rule: Rule,
|
31 | parse_fn: fn(Pair<Rule>) -> Parsed<T>,
|
32 | }
|
33 |
|
34 | impl<T: PartialEq + Debug> TestPair<T> {
|
35 | fn new(rule: Rule, parse_fn: fn(Pair<Rule>) -> Parsed<T>) -> Self {
|
36 | Self { rule, parse_fn }
|
37 | }
|
38 | fn assert(self, input: &str, expected: T) -> Self {
|
39 | match parse(input, self.rule) {
|
40 | Ok(e) => {
|
41 | assert((self.parse_fn)(e), expected);
|
42 | }
|
43 | Err(e) => {
|
44 | panic!("parsing error ` {}`" , e);
|
45 | }
|
46 | }
|
47 | self
|
48 | }
|
49 | fn assert_fail(self, input: &str) -> Self {
|
50 | match parse(input, self.rule) {
|
51 | Ok(e) => {
|
52 | if let Ok(r) = (self.parse_fn)(e) {
|
53 | panic!("expected error, got {:?}" , r);
|
54 | }
|
55 | }
|
56 | Err(e) => {
|
57 | println!("parsing error ` {}`" , e);
|
58 | }
|
59 | }
|
60 | self
|
61 | }
|
62 | }
|
63 |
|
64 | fn parse(input: &str, rule: Rule) -> Result<Pair<Rule>, Error<Rule>> {
|
65 | match JSPathParser::parse(rule, input) {
|
66 | Ok(e) => Ok(e.into_iter().next().expect(msg:"no pairs found" )),
|
67 | Err(e: Error<{unknown}>) => Err(e),
|
68 | }
|
69 | }
|
70 |
|
71 | fn assert<T>(result: Parsed<T>, expected: T)
|
72 | where
|
73 | T: PartialEq + Debug,
|
74 | {
|
75 | match result {
|
76 | Ok(e: T) => assert_eq!(e, expected),
|
77 | Err(e: JsonPathError) => {
|
78 | panic!("parsing error ` {}`" , e);
|
79 | }
|
80 | }
|
81 | }
|
82 |
|
83 | #[test ]
|
84 | fn singular_query_segment_test() {
|
85 | TestPair::new(Rule::singular_query_segments, singular_query_segments)
|
86 | .assert("[ \"b \"][ \"b \"]" , q_segments!([b][b]))
|
87 | .assert("[2][1]" , q_segments!([2][1]))
|
88 | .assert("[2][ \"a \"]" , q_segments!([2][a]))
|
89 | .assert(".a.b" , q_segments!(a b))
|
90 | .assert(".a.b[ \"c \"][1]" , q_segments!(a b [c][1]));
|
91 | }
|
92 | #[test ]
|
93 | fn singular_query_test() {
|
94 | TestPair::new(Rule::singular_query, singular_query)
|
95 | .assert("@.a.b" , singular_query!(@ a b))
|
96 | .assert("@" , SingularQuery::Current(vec![]))
|
97 | .assert("$" , SingularQuery::Root(vec![]))
|
98 | .assert("$.a.b.c" , singular_query!(a b c))
|
99 | .assert("$[ \"a \"].b[3]" , singular_query!([a] b [3]));
|
100 | }
|
101 |
|
102 | #[test ]
|
103 | fn slice_selector_test() {
|
104 | TestPair::new(Rule::slice_selector, slice_selector)
|
105 | .assert(":" , slice!())
|
106 | .assert("::" , slice!())
|
107 | .assert("1:" , slice!(1))
|
108 | .assert("1:1" , slice!(1, 1))
|
109 | .assert("1:1:1" , slice!(1, 1, 1))
|
110 | .assert(":1:1" , slice!(,1,1))
|
111 | .assert("::1" , slice!(,,1))
|
112 | .assert("1::1" , slice!(1,,1))
|
113 | .assert_fail("-0:" )
|
114 | .assert_fail("9007199254740995" );
|
115 | }
|
116 |
|
117 | #[test ]
|
118 | fn function_expr_test() {
|
119 | TestPair::new(Rule::function_expr, function_expr)
|
120 | .assert("length(1)" , test_fn!(length arg!(lit!(i 1))))
|
121 | .assert("length(true)" , test_fn!(length arg!(lit!(b true))))
|
122 | .assert(
|
123 | "search(@, \"abc \")" ,
|
124 | test_fn!(search arg!(t test!(@ ) ), arg!(lit!(s "abc" ))),
|
125 | )
|
126 | .assert(
|
127 | "count(@.a)" ,
|
128 | test_fn!(count arg!(t test!(@ segment!(selector!(a))))),
|
129 | )
|
130 | .assert_fail("count \t(@.*)" );
|
131 | }
|
132 |
|
133 | #[test ]
|
134 | fn jq_test() {
|
135 | let atom = Filter::Atom(atom!(
|
136 | comparable!(> singular_query!(@ a b)),
|
137 | ">" ,
|
138 | comparable!(lit!(i 1))
|
139 | ));
|
140 | TestPair::new(Rule::jp_query, jp_query).assert(
|
141 | "$.a.b[?@.a.b > 1]" ,
|
142 | jq!(
|
143 | segment!(selector!(a)),
|
144 | segment!(selector!(b)),
|
145 | segment!(selector!(?atom))
|
146 | ),
|
147 | );
|
148 | }
|
149 |
|
150 | #[test ]
|
151 | fn comp_expr_test() {
|
152 | TestPair::new(Rule::comp_expr, comp_expr).assert(
|
153 | "@.a.b.c == 1" ,
|
154 | cmp!(
|
155 | comparable!(> singular_query!(@ a b c)),
|
156 | "==" ,
|
157 | comparable!(lit!(i 1))
|
158 | ),
|
159 | );
|
160 | }
|
161 |
|
162 | #[test ]
|
163 | fn literal_test() {
|
164 | TestPair::new(Rule::literal, literal)
|
165 | .assert("'☺'" , lit!(s "☺" ))
|
166 | .assert_fail(" \"\n\"" )
|
167 | .assert("' '" , lit!(s " " ))
|
168 | .assert("' \"'" , lit!(s " \"" ))
|
169 | .assert("null" , lit!())
|
170 | .assert("false" , lit!(b false))
|
171 | .assert("true" , lit!(b true))
|
172 | .assert(" \"hello \"" , lit!(s "hello" ))
|
173 | .assert(" \'hello \'" , lit!(s "hello" ))
|
174 | .assert(" \'hel \\'lo \'" , lit!(s "hel \\'lo" ))
|
175 | .assert(" \'hel \"lo \'" , lit!(s "hel \"lo" ))
|
176 | .assert(" \'hel \\nlo \'" , lit!(s "hel \\nlo" ))
|
177 | .assert("1" , lit!(i 1))
|
178 | .assert("0" , lit!(i 0))
|
179 | .assert("-0" , lit!(i 0))
|
180 | .assert("1.2" , lit!(f 1.2))
|
181 | .assert("9007199254740990" , lit!(i 9007199254740990))
|
182 | .assert_fail("hel \\\"lo" )
|
183 | .assert_fail("9007199254740995" );
|
184 | }
|
185 |
|
186 | #[test ]
|
187 | fn filter_atom_test() {
|
188 | TestPair::new(Rule::atom_expr, filter_atom)
|
189 | .assert(
|
190 | "1 > 2" ,
|
191 | atom!(comparable!(lit!(i 1)), ">" , comparable!(lit!(i 2))),
|
192 | )
|
193 | .assert(
|
194 | "!(@.a ==1 || @.b == 2)" ,
|
195 | atom!(!or!(
|
196 | Filter::Atom(atom!(
|
197 | comparable!(> singular_query!(@ a)),
|
198 | "==" ,
|
199 | comparable!(lit!(i 1))
|
200 | )),
|
201 | Filter::Atom(atom!(
|
202 | comparable!(> singular_query!(@ b)),
|
203 | "==" ,
|
204 | comparable!(lit!(i 2))
|
205 | ))
|
206 | )),
|
207 | );
|
208 | }
|
209 | #[test ]
|
210 | fn comparable_test() {
|
211 | TestPair::new(Rule::comparable, comparable)
|
212 | .assert("1" , comparable!(lit!(i 1)))
|
213 | .assert(" \"a \"" , comparable!(lit!(s "a" )))
|
214 | .assert("@.a.b.c" , comparable!(> singular_query!(@ a b c)))
|
215 | .assert("$.a.b.c" , comparable!(> singular_query!(a b c)))
|
216 | .assert("$[1]" , comparable!(> singular_query!([1])))
|
217 | .assert("length(1)" , comparable!(f test_fn!(length arg!(lit!(i 1)))));
|
218 | }
|
219 |
|
220 | #[test ]
|
221 | fn parse_path() {
|
222 | let result = parse_json_path("$" );
|
223 | assert!(result.is_ok());
|
224 | assert_eq!(result.unwrap(), JpQuery::new(vec![]));
|
225 | }
|
226 |
|
227 | #[test ]
|
228 | fn parse_i64() {
|
229 | TestPair::new(Rule::literal, literal).assert("1e2" , lit!(f 100.0));
|
230 | }
|
231 | #[test ]
|
232 | fn parse_selector() {
|
233 | TestPair::new(Rule::selector, selector).assert("1:1" , Selector::Slice(Some(1), Some(1), None));
|
234 | }
|
235 | #[test ]
|
236 | fn parse_global() {
|
237 | let sel_a = segment!(selector!(a));
|
238 | TestPair::new(Rule::jp_query, jp_query)
|
239 | // .assert("$", JpQuery::new(vec![]))
|
240 | // .assert("$.a", JpQuery::new(vec![sel_a.clone()]))
|
241 | // .assert("$..a", JpQuery::new(vec![segment!(..sel_a)]))
|
242 | // .assert(
|
243 | // "$..*",
|
244 | // JpQuery::new(vec![segment!(..segment!(selector!(*)))]),
|
245 | // )
|
246 | // .assert(
|
247 | // "$[1 :5:2]",
|
248 | // JpQuery::new(vec![segment!(selector!(slice slice!(1, 5, 2)))]),
|
249 | // )
|
250 | // .assert(
|
251 | // "$['a']['b']",
|
252 | // JpQuery::new(vec![segment!(Selector::Name("'a'".to_string())), segment!(Selector::Name("'b'".to_string()))]),
|
253 | // )
|
254 | //
|
255 | // .assert(
|
256 | // "$[1, 1:1]",
|
257 | // JpQuery::new(vec![Segment::Selectors(vec![
|
258 | // Selector::Index(1),
|
259 | // Selector::Slice(Some(1), Some(1), None),
|
260 | // ])]),
|
261 | // )
|
262 | // .assert_fail("$..\ra")
|
263 | ;
|
264 | }
|
265 | |