View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.juneau.utils;
18  
19  import static org.apache.juneau.common.utils.Utils.*;
20  import static org.junit.jupiter.api.Assertions.*;
21  
22  import java.text.*;
23  
24  import org.apache.juneau.*;
25  import org.junit.jupiter.api.*;
26  
27  /**
28   * Tests {@link StringExpressionMatcher}.
29   */
30  class StringExpressionMatcher_Test extends TestBase {
31  
32  	private void test(String expression, String toString, String[] shouldMatch, String[] shouldNotMatch) {
33  		var m = safe(()->new StringExpressionMatcher(expression));
34  		assertEquals(toString, m.toString());
35  		for (var i : shouldMatch)
36  			if (! m.matches(i))
37  				fail("Matcher "+m+" should have matched '"+i+"' but didn't.");
38  		for (var i : shouldNotMatch)
39  			if (m.matches(i))
40  				fail("Matcher "+m+" should not have matched '"+i+"' but did.");
41  	}
42  
43  	//------------------------------------------------------------------------------------------------------------------
44  	// No operand
45  	//------------------------------------------------------------------------------------------------------------------
46  
47  	@Test void a01_noOperand() {
48  		test("", "(NEVER)", a(), a("foo", "foox", "xfoo", "fo", null));
49  		test(null, "(NEVER)", a(), a("foo", "foox", "xfoo", "fo", null));
50  		test("  ", "(NEVER)", a(), a("foo", "foox", "xfoo", "fo", null));
51  		test("()", "(NEVER)", a(), a("foo", "foox", "xfoo", "fo", null));
52  		test("(())", "(NEVER)", a(), a("foo", "foox", "xfoo", "fo", null));
53  		test("  (  (  )  )  ", "(NEVER)", a(), a("foo", "foox", "xfoo", "fo", null));
54  	}
55  
56  	//------------------------------------------------------------------------------------------------------------------
57  	// Single operand equals
58  	//------------------------------------------------------------------------------------------------------------------
59  
60  	@Test void a02_singleOperand_eq() {
61  		test("foo", "[= foo]", a("foo"), a("foox", "xfoo", "fo", null));
62  		test("  foo  ", "[= foo]", a("foo"), a("foox", "xfoo", "fo", null));
63  		test("(foo)", "[= foo]", a("foo"), a("foox", "xfoo", "fo", null));
64  		test("((foo))", "[= foo]", a("foo"), a("foox", "xfoo", "fo", null));
65  		test(" ( foo ) ", "[= foo]", a("foo"), a("foox", "xfoo", "fo", null));
66  		test("  (  (  foo  )  )  ", "[= foo]", a("foo"), a("foox", "xfoo", "fo", null));
67  	}
68  
69  	//------------------------------------------------------------------------------------------------------------------
70  	// Single operand equals
71  	//------------------------------------------------------------------------------------------------------------------
72  
73  	@Test void a03_singleOperand_pattern() {
74  		test("foo*", "[* foo.*]", a("foo", "foox"), a("xfoo", "fo", null));
75  		test("  foo*  ", "[* foo.*]", a("foo", "foox"), a("xfoo", "fo", null));
76  		test("(foo*)", "[* foo.*]", a("foo", "foox"), a("xfoo", "fo", null));
77  		test("((foo*))", "[* foo.*]", a("foo", "foox"), a("xfoo", "fo", null));
78  		test(" ( foo* ) ", "[* foo.*]", a("foo", "foox"), a("xfoo", "fo", null));
79  		test("  (  (  foo*  )  )  ", "[* foo.*]", a("foo", "foox"), a("xfoo", "fo", null));
80  	}
81  
82  	//------------------------------------------------------------------------------------------------------------------
83  	// | operator
84  	//------------------------------------------------------------------------------------------------------------------
85  
86  	@Test void a04_or_singlePipe() {
87  		test("foo|bar|baz", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
88  		test("  foo  |  bar  |  baz  ", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
89  		test("(foo|bar|baz)", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
90  		test("(foo)|(bar)|(baz)", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
91  		test("  (  foo  |  bar  |  baz  )  ", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
92  		test("((foo)|(bar)|(baz))", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
93  		test("((((foo))|((bar))|((baz))))", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
94  		test("  (  (  (  (  foo  )  )  |  (  (  bar  )  )  |  (  (  baz  )  )  )  )  ", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
95  	}
96  
97  	//------------------------------------------------------------------------------------------------------------------
98  	// || operator
99  	//------------------------------------------------------------------------------------------------------------------
100 
101 	@Test void a05_or_doublePipe() {
102 		test("foo||bar||baz", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
103 		test("  foo  ||  bar  ||  baz  ", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
104 		test("(foo||bar||baz)", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
105 		test("(foo)||(bar)||(baz)", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
106 		test("  (  foo  ||  bar  ||  baz  )  ", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
107 		test("((foo)||(bar)||(baz))", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
108 		test("((((foo))||((bar))||((baz))))", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
109 		test("  (  (  (  (  foo  )  )  ||  (  (  bar  )  )  ||  (  (  baz  )  )  )  )  ", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
110 	}
111 
112 	//------------------------------------------------------------------------------------------------------------------
113 	// , operator
114 	//------------------------------------------------------------------------------------------------------------------
115 
116 	@Test void a06_or_comma() {
117 		test("foo,bar,baz", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
118 		test("  foo  ,  bar  ,  baz  ", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
119 		test("(foo,bar,baz)", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
120 		test("(foo),(bar),(baz)", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
121 		test("  (  foo  ,  bar  ,  baz  )  ", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
122 		test("((foo),(bar),(baz))", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
123 		test("((((foo)),((bar)),((baz))))", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
124 		test("  (  (  (  (  foo  )  )  ,  (  (  bar  )  )  ,  (  (  baz  )  )  )  )  ", "(| [= foo] [= bar] [= baz])", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
125 	}
126 
127 	//------------------------------------------------------------------------------------------------------------------
128 	// & operator
129 	//------------------------------------------------------------------------------------------------------------------
130 
131 	@Test void a07_and_singleAmp() {
132 		test("fo*&*oo&foo", "(& [* fo.*] [* .*oo] [= foo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
133 		test("  fo*  &  *oo  &  foo  ", "(& [* fo.*] [* .*oo] [= foo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
134 		test("(fo*&*oo&foo)", "(& [* fo.*] [* .*oo] [= foo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
135 		test("(fo*)&(*oo)&(foo)", "(& [* fo.*] [* .*oo] [= foo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
136 		test("  (  fo*  &  *oo  &  foo  )  ", "(& [* fo.*] [* .*oo] [= foo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
137 		test("((fo*)&(*oo)&(foo))", "(& [* fo.*] [* .*oo] [= foo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
138 		test("((((fo*))&((*oo))&((foo))))", "(& [* fo.*] [* .*oo] [= foo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
139 		test("  (  (  (  (  fo*  )  )  &  (  (  *oo  )  )  &  (  (  foo  )  )  )  )  ", "(& [* fo.*] [* .*oo] [= foo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
140 	}
141 
142 	//------------------------------------------------------------------------------------------------------------------
143 	// && operator
144 	//------------------------------------------------------------------------------------------------------------------
145 
146 	@Test void a08_and_doubleAmp() {
147 		test("fo*&&*oo&&foo", "(& [* fo.*] [* .*oo] [= foo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
148 		test("  fo*  &&  *oo  &&  foo  ", "(& [* fo.*] [* .*oo] [= foo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
149 		test("(fo*&&*oo&&foo)", "(& [* fo.*] [* .*oo] [= foo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
150 		test("(fo*)&&(*oo)&&(foo)", "(& [* fo.*] [* .*oo] [= foo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
151 		test("  (  fo*  &&  *oo  &&  foo  )  ", "(& [* fo.*] [* .*oo] [= foo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
152 		test("((fo*)&&(*oo)&&(foo))", "(& [* fo.*] [* .*oo] [= foo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
153 		test("((((fo*))&&((*oo))&&((foo))))", "(& [* fo.*] [* .*oo] [= foo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
154 		test("  (  (  (  (  fo*  )  )  &&  (  (  *oo  )  )  &&  (  (  foo  )  )  )  )  ", "(& [* fo.*] [* .*oo] [= foo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
155 	}
156 
157 	//------------------------------------------------------------------------------------------------------------------
158 	// | and & operators
159 	//------------------------------------------------------------------------------------------------------------------
160 
161 	@Test void a09_and_singleMixed() {
162 		test("fo*&*oo|bar", "(| (& [* fo.*] [* .*oo]) [= bar])", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
163 		test("bar|fo*&*oo", "(| [= bar] (& [* fo.*] [* .*oo]))", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
164 		test("  fo*  &  *oo  |  bar  ", "(| (& [* fo.*] [* .*oo]) [= bar])", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
165 		test("  bar  |  fo*  &  *oo  ", "(| [= bar] (& [* fo.*] [* .*oo]))", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
166 		test("(fo*&*oo|bar)", "(| (& [* fo.*] [* .*oo]) [= bar])", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
167 		test("(bar|fo*&*oo)", "(| [= bar] (& [* fo.*] [* .*oo]))", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
168 		test("(fo*)&(*oo)|(bar)", "(| (& [* fo.*] [* .*oo]) [= bar])", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
169 		test("(bar)|(fo*)&(*oo)", "(| [= bar] (& [* fo.*] [* .*oo]))", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
170 		test("  (  fo*  &  *oo  |  bar  )  ", "(| (& [* fo.*] [* .*oo]) [= bar])", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
171 		test("  (  bar  |  fo*  &  *oo  )  ", "(| [= bar] (& [* fo.*] [* .*oo]))", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
172 		test("((fo*)&(*oo)|(bar))", "(| (& [* fo.*] [* .*oo]) [= bar])", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
173 		test("((bar)|(fo*)&(*oo))", "(| [= bar] (& [* fo.*] [* .*oo]))", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
174 		test("((((fo*))&((*oo))|((bar))))", "(| (& [* fo.*] [* .*oo]) [= bar])", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
175 		test("((((bar))|((fo*))&((*oo))))", "(| [= bar] (& [* fo.*] [* .*oo]))", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
176 		test("  (  (  (  (  fo*  )  )  &  (  (  *oo  )  )  |  (  (  bar  )  )  )  )  ", "(| (& [* fo.*] [* .*oo]) [= bar])", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
177 		test("  (  (  (  (  bar  )  )  |  (  (  fo*  )  )  &  (  (  *oo  )  )  )  )  ", "(| [= bar] (& [* fo.*] [* .*oo]))", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
178 	}
179 
180 	//------------------------------------------------------------------------------------------------------------------
181 	// "||" and "&&" operators
182 	//------------------------------------------------------------------------------------------------------------------
183 
184 	@Test void a10_and_doubleMixed() {
185 		test("fo*&&*oo||bar", "(| (& [* fo.*] [* .*oo]) [= bar])", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
186 		test("bar||fo*&&*oo", "(| [= bar] (& [* fo.*] [* .*oo]))", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
187 		test("  fo*  &&  *oo  ||  bar  ", "(| (& [* fo.*] [* .*oo]) [= bar])", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
188 		test("  bar  ||  fo*  &&  *oo  ", "(| [= bar] (& [* fo.*] [* .*oo]))", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
189 		test("(fo*&&*oo||bar)", "(| (& [* fo.*] [* .*oo]) [= bar])", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
190 		test("(bar||fo*&&*oo)", "(| [= bar] (& [* fo.*] [* .*oo]))", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
191 		test("(fo*)&&(*oo)||(bar)", "(| (& [* fo.*] [* .*oo]) [= bar])", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
192 		test("(bar)||(fo*)&&(*oo)", "(| [= bar] (& [* fo.*] [* .*oo]))", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
193 		test("  (  fo*  &&  *oo  ||  bar  )  ", "(| (& [* fo.*] [* .*oo]) [= bar])", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
194 		test("  (  bar  ||  fo*  &&  *oo  )  ", "(| [= bar] (& [* fo.*] [* .*oo]))", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
195 		test("((fo*)&&(*oo)||(bar))", "(| (& [* fo.*] [* .*oo]) [= bar])", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
196 		test("((bar)||(fo*)&&(*oo))", "(| [= bar] (& [* fo.*] [* .*oo]))", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
197 		test("((((fo*))&&((*oo))||((bar))))", "(| (& [* fo.*] [* .*oo]) [= bar])", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
198 		test("((((bar))||((fo*))&&((*oo))))", "(| [= bar] (& [* fo.*] [* .*oo]))", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
199 		test("  (  (  (  (  fo*  )  )  &&  (  (  *oo  )  )  ||  (  (  bar  )  )  )  )  ", "(| (& [* fo.*] [* .*oo]) [= bar])", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
200 		test("  (  (  (  (  bar  )  )  ||  (  (  fo*  )  )  &&  (  (  *oo  )  )  )  )  ", "(| [= bar] (& [* fo.*] [* .*oo]))", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
201 	}
202 
203 	//------------------------------------------------------------------------------------------------------------------
204 	// | and & and () operators
205 	//------------------------------------------------------------------------------------------------------------------
206 
207 	@Test void a11_and_singleMixedParentheses() {
208 		test("fo*&(*oo|bar)", "(& [* fo.*] (| [* .*oo] [= bar]))", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
209 		test("(bar|fo*)&*oo", "(& (| [= bar] [* fo.*]) [* .*oo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
210 		test("  fo*  &  (  *oo  |  bar  )  ", "(& [* fo.*] (| [* .*oo] [= bar]))", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
211 		test("  (  bar  |  fo*  )  &  *oo  ", "(& (| [= bar] [* fo.*]) [* .*oo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
212 		test("(fo*&(*oo|bar))", "(& [* fo.*] (| [* .*oo] [= bar]))", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
213 		test("((bar|fo*)&*oo)", "(& (| [= bar] [* fo.*]) [* .*oo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
214 		test("(fo*)&((*oo)|(bar))", "(& [* fo.*] (| [* .*oo] [= bar]))", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
215 		test("((bar)|(fo*))&(*oo)", "(& (| [= bar] [* fo.*]) [* .*oo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
216 		test("  (  fo*  &  (  *oo  |  bar  )  )  ", "(& [* fo.*] (| [* .*oo] [= bar]))", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
217 		test("  (  (  bar  |  fo*  )  &  *oo  )  ", "(& (| [= bar] [* fo.*]) [* .*oo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
218 		test("((fo*)&((*oo)|(bar)))", "(& [* fo.*] (| [* .*oo] [= bar]))", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
219 		test("(((bar)|(fo*))&(*oo))", "(& (| [= bar] [* fo.*]) [* .*oo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
220 		test("((((fo*))&(((*oo))|((bar)))))", "(& [* fo.*] (| [* .*oo] [= bar]))", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
221 		test("(((((bar))|((fo*)))&((*oo))))", "(& (| [= bar] [* fo.*]) [* .*oo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
222 		test("  (  (  (  (  fo*  )  )  &  (  (  (  *oo  )  )  |  (  (  bar  )  )  )  )  )  ", "(& [* fo.*] (| [* .*oo] [= bar]))", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
223 		test("  (  (  (  (  (  bar  )  )  |  (  (  fo*  )  )  )  &  (  (  *oo  )  )  )  )  ", "(& (| [= bar] [* fo.*]) [* .*oo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
224 	}
225 
226 	//------------------------------------------------------------------------------------------------------------------
227 	// "||" and "&&" and "()" operators
228 	//------------------------------------------------------------------------------------------------------------------
229 
230 	@Test void a12_and_doubleMixedParentheses() {
231 		test("fo*&&(*oo||bar)", "(& [* fo.*] (| [* .*oo] [= bar]))", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
232 		test("(bar||fo*)&&*oo", "(& (| [= bar] [* fo.*]) [* .*oo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
233 		test("  fo*  &&  (  *oo  ||  bar  )  ", "(& [* fo.*] (| [* .*oo] [= bar]))", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
234 		test("  (  bar  ||  fo*  )  &&  *oo  ", "(& (| [= bar] [* fo.*]) [* .*oo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
235 		test("(fo*&&(*oo||bar))", "(& [* fo.*] (| [* .*oo] [= bar]))", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
236 		test("((bar||fo*)&&*oo)", "(& (| [= bar] [* fo.*]) [* .*oo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
237 		test("(fo*)&((*oo)||(bar))", "(& [* fo.*] (| [* .*oo] [= bar]))", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
238 		test("((bar)||(fo*))&&(*oo)", "(& (| [= bar] [* fo.*]) [* .*oo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
239 		test("  (  fo*  &&  (  *oo  ||  bar  )  )  ", "(& [* fo.*] (| [* .*oo] [= bar]))", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
240 		test("  (  (  bar  ||  fo*  )  &&  *oo  )  ", "(& (| [= bar] [* fo.*]) [* .*oo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
241 		test("((fo*)&&((*oo)||(bar)))", "(& [* fo.*] (| [* .*oo] [= bar]))", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
242 		test("(((bar)||(fo*))&&(*oo))", "(& (| [= bar] [* fo.*]) [* .*oo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
243 		test("((((fo*))&&(((*oo))||((bar)))))", "(& [* fo.*] (| [* .*oo] [= bar]))", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
244 		test("(((((bar))||((fo*)))&&((*oo))))", "(& (| [= bar] [* fo.*]) [* .*oo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
245 		test("  (  (  (  (  fo*  )  )  &&  (  (  (  *oo  )  )  ||  (  (  bar  )  )  )  )  )  ", "(& [* fo.*] (| [* .*oo] [= bar]))", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
246 		test("  (  (  (  (  (  bar  )  )  ||  (  (  fo*  )  )  )  &&  (  (  *oo  )  )  )  )  ", "(& (| [= bar] [* fo.*]) [* .*oo])", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
247 	}
248 
249 	//------------------------------------------------------------------------------------------------------------------
250 	// Error conditions
251 	//------------------------------------------------------------------------------------------------------------------
252 
253 	@Test void b01_errors() {
254 		assertThrows(ParseException.class, ()->new StringExpressionMatcher("&foo"));
255 		assertThrows(ParseException.class, ()->new StringExpressionMatcher("foo bar"));
256 		assertThrows(ParseException.class, ()->new StringExpressionMatcher("(foo"));
257 		assertThrows(ParseException.class, ()->new StringExpressionMatcher("foo &"));
258 		assertThrows(ParseException.class, ()->new StringExpressionMatcher("foo ||"));
259 		assertThrows(ParseException.class, ()->new StringExpressionMatcher("foo ,"));
260 		assertThrows(ParseException.class, ()->new StringExpressionMatcher("foo & "));
261 		assertThrows(ParseException.class, ()->new StringExpressionMatcher("foo || "));
262 		assertThrows(ParseException.class, ()->new StringExpressionMatcher("foo , "));
263 	}
264 }