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.rest.guards;
18  
19  import static org.apache.juneau.common.utils.Utils.*;
20  import static org.junit.jupiter.api.Assertions.*;
21  
22  import java.text.*;
23  import java.util.*;
24  
25  import org.apache.juneau.*;
26  import org.apache.juneau.common.utils.*;
27  import org.apache.juneau.internal.*;
28  import org.apache.juneau.rest.guard.*;
29  import org.junit.jupiter.api.*;
30  import org.junit.jupiter.params.*;
31  import org.junit.jupiter.params.provider.*;
32  
33  /**
34   * Tests {@link RoleMatcher}.
35   */
36  class RoleMatcher_Test extends TestBase {
37  
38  	private void test(String expression, String toString, String expressionRoles, String[] shouldMatch, String[] shouldNotMatch) {
39  		var m = safe(()->new RoleMatcher(expression));
40  		assertEquals(toString, m.toString(), "m.toString() didn't match.");
41  		assertEquals(expressionRoles, Utils.join(m.getRolesInExpression(), ","), "m.getRolesInExpression() didn't match.");
42  		for (String i : shouldMatch)
43  			if (! m.matches(toSet(i)))
44  				fail("Matcher "+m+" should have matched '"+i+"' but didn't.");
45  		for (String i : shouldNotMatch)
46  			if (m.matches(toSet(i)))
47  				fail("Matcher "+m+" should not have matched '"+i+"' but did.");
48  	}
49  
50  	private Set<String> toSet(String input) {
51  		if (input == null)
52  			return null;
53  		if (input.indexOf(',') == -1)
54  			return Collections.singleton(input);
55  		if (input.isEmpty())
56  			return Collections.emptySet();
57  		return CollectionUtils.sortedSet(Utils.splita(input));
58  	}
59  
60  	//------------------------------------------------------------------------------------------------------------------
61  	// No operand
62  	//------------------------------------------------------------------------------------------------------------------
63  
64  	@ParameterizedTest
65  	@NullSource
66  	@ValueSource(strings = { "", "  ", "()", "(())", "  (  (  )  )  "})
67  	void a01_noOperandCases(String operand) {
68  		test(operand, "(NEVER)", "", a(), a("foo", "foox", "xfoo", "fo", null));
69  	}
70  
71  	//------------------------------------------------------------------------------------------------------------------
72  	// Single operand equals
73  	//------------------------------------------------------------------------------------------------------------------
74  
75  	@Test void a02_singleOperand() {
76  		test("foo", "[= foo]", "foo", a("foo"), a("foox", "xfoo", "fo", null));
77  		test("foo", "[= foo]", "foo", a("foo,bar"), a("foox,bar", "xfoo,bar", "fo,bar", ""));
78  		test("foo", "[= foo]", "foo", a(), a(""));
79  		test("  foo  ", "[= foo]", "foo", a("foo"), a("foox", "xfoo", "fo", null));
80  		test("(foo)", "[= foo]", "foo", a("foo"), a("foox", "xfoo", "fo", null));
81  		test("((foo))", "[= foo]", "foo", a("foo"), a("foox", "xfoo", "fo", null));
82  		test(" ( foo ) ", "[= foo]", "foo", a("foo"), a("foox", "xfoo", "fo", null));
83  		test("  (  (  foo  )  )  ", "[= foo]", "foo", a("foo"), a("foox", "xfoo", "fo", null));
84  	}
85  
86  	//------------------------------------------------------------------------------------------------------------------
87  	// Single operand equals
88  	//------------------------------------------------------------------------------------------------------------------
89  
90  	@Test void a03_singleOperand() {
91  		test("foo*", "[* foo.*]", "foo*", a("foo", "foox"), a("xfoo", "fo", null));
92  		test("foo*", "[* foo.*]", "foo*", a("foo,bar", "foox,bar"), a("xfoo,bar", "fo,bar"));
93  		test("foo*", "[* foo.*]", "foo*", a(), a(""));
94  		test("  foo*  ", "[* foo.*]", "foo*", a("foo", "foox"), a("xfoo", "fo", null));
95  		test("(foo*)", "[* foo.*]", "foo*", a("foo", "foox"), a("xfoo", "fo", null));
96  		test("((foo*))", "[* foo.*]", "foo*", a("foo", "foox"), a("xfoo", "fo", null));
97  		test(" ( foo* ) ", "[* foo.*]", "foo*", a("foo", "foox"), a("xfoo", "fo", null));
98  		test("  (  (  foo*  )  )  ", "[* foo.*]", "foo*", a("foo", "foox"), a("xfoo", "fo", null));
99  	}
100 
101 	//------------------------------------------------------------------------------------------------------------------
102 	// | operator
103 	//------------------------------------------------------------------------------------------------------------------
104 
105 	@Test void a04_or_singlePipe() {
106 		test("foo|bar|baz", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
107 		test("foo|bar|baz", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo,bar", "bar,baz", "baz,qux"), a("foox,barx", "xfoo,xbar", "fo,ba"));
108 		test("foo|bar|baz", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a(), a(""));
109 		test("  foo  |  bar  |  baz  ", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
110 		test("(foo|bar|baz)", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
111 		test("(foo)|(bar)|(baz)", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
112 		test("  (  foo  |  bar  |  baz  )  ", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
113 		test("((foo)|(bar)|(baz))", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
114 		test("((((foo))|((bar))|((baz))))", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
115 		test("  (  (  (  (  foo  )  )  |  (  (  bar  )  )  |  (  (  baz  )  )  )  )  ", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
116 	}
117 
118 	//------------------------------------------------------------------------------------------------------------------
119 	// || operator
120 	//------------------------------------------------------------------------------------------------------------------
121 
122 	@Test void a05_or_doublePipe() {
123 		test("foo||bar||baz", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
124 		test("foo||bar||baz", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo,bar", "bar,baz", "baz,qux"), a("foox,barx", "xfoo,xbar", "fo,ba"));
125 		test("foo||bar||baz", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a(), a(""));
126 		test("  foo  ||  bar  ||  baz  ", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
127 		test("(foo||bar||baz)", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
128 		test("(foo)||(bar)||(baz)", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
129 		test("  (  foo  ||  bar  ||  baz  )  ", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
130 		test("((foo)||(bar)||(baz))", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
131 		test("((((foo))||((bar))||((baz))))", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
132 		test("  (  (  (  (  foo  )  )  ||  (  (  bar  )  )  ||  (  (  baz  )  )  )  )  ", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
133 	}
134 
135 	//------------------------------------------------------------------------------------------------------------------
136 	// , operator
137 	//------------------------------------------------------------------------------------------------------------------
138 
139 	@Test void a06_or_comma() {
140 		test("foo,bar,baz", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
141 		test("foo,bar,baz", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo,bar", "bar,baz", "baz,qux"), a("foox,barx", "xfoo,xbar", "fo,ba"));
142 		test("foo,bar,baz", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a(), a(""));
143 		test("  foo  ,  bar  ,  baz  ", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
144 		test("(foo,bar,baz)", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
145 		test("(foo),(bar),(baz)", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
146 		test("  (  foo  ,  bar  ,  baz  )  ", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
147 		test("((foo),(bar),(baz))", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
148 		test("((((foo)),((bar)),((baz))))", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
149 		test("  (  (  (  (  foo  )  )  ,  (  (  bar  )  )  ,  (  (  baz  )  )  )  )  ", "(| [= foo] [= bar] [= baz])", "bar,baz,foo", a("foo", "bar", "baz"), a("foox", "xfoo", "fo", null));
150 	}
151 
152 	//------------------------------------------------------------------------------------------------------------------
153 	// & operator
154 	//------------------------------------------------------------------------------------------------------------------
155 
156 	@Test void a07_and_singleAmp() {
157 		test("fo*&*oo&foo", "(& [* fo.*] [* .*oo] [= foo])", "*oo,fo*,foo", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
158 		test("foo&bar", "(& [= foo] [= bar])", "bar,foo", a("foo,bar", "foo,bar,baz"), a("foo", "foo,baz", "bar", "bar,baz"));
159 		test("foo&bar", "(& [= foo] [= bar])", "bar,foo", a(), a(""));
160 		test("  fo*  &  *oo  &  foo  ", "(& [* fo.*] [* .*oo] [= foo])", "*oo,fo*,foo", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
161 		test("(fo*&*oo&foo)", "(& [* fo.*] [* .*oo] [= foo])", "*oo,fo*,foo", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
162 		test("(fo*)&(*oo)&(foo)", "(& [* fo.*] [* .*oo] [= foo])", "*oo,fo*,foo", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
163 		test("  (  fo*  &  *oo  &  foo  )  ", "(& [* fo.*] [* .*oo] [= foo])", "*oo,fo*,foo", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
164 		test("((fo*)&(*oo)&(foo))", "(& [* fo.*] [* .*oo] [= foo])", "*oo,fo*,foo", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
165 		test("((((fo*))&((*oo))&((foo))))", "(& [* fo.*] [* .*oo] [= foo])", "*oo,fo*,foo", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
166 		test("  (  (  (  (  fo*  )  )  &  (  (  *oo  )  )  &  (  (  foo  )  )  )  )  ", "(& [* fo.*] [* .*oo] [= foo])", "*oo,fo*,foo", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
167 	}
168 
169 	//------------------------------------------------------------------------------------------------------------------
170 	// && operator
171 	//------------------------------------------------------------------------------------------------------------------
172 
173 	@Test void a08_and_doubleAmp() {
174 		test("fo*&&*oo&&foo", "(& [* fo.*] [* .*oo] [= foo])", "*oo,fo*,foo", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
175 		test("foo&&bar", "(& [= foo] [= bar])", "bar,foo", a("foo,bar", "foo,bar,baz"), a("foo", "foo,baz", "bar", "bar,baz"));
176 		test("foo&&bar", "(& [= foo] [= bar])", "bar,foo", a(), a(""));
177 		test("  fo*  &&  *oo  &&  foo  ", "(& [* fo.*] [* .*oo] [= foo])", "*oo,fo*,foo", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
178 		test("(fo*&&*oo&&foo)", "(& [* fo.*] [* .*oo] [= foo])", "*oo,fo*,foo", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
179 		test("(fo*)&&(*oo)&&(foo)", "(& [* fo.*] [* .*oo] [= foo])", "*oo,fo*,foo", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
180 		test("  (  fo*  &&  *oo  &&  foo  )  ", "(& [* fo.*] [* .*oo] [= foo])", "*oo,fo*,foo", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
181 		test("((fo*)&&(*oo)&&(foo))", "(& [* fo.*] [* .*oo] [= foo])", "*oo,fo*,foo", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
182 		test("((((fo*))&&((*oo))&&((foo))))", "(& [* fo.*] [* .*oo] [= foo])", "*oo,fo*,foo", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
183 		test("  (  (  (  (  fo*  )  )  &&  (  (  *oo  )  )  &&  (  (  foo  )  )  )  )  ", "(& [* fo.*] [* .*oo] [= foo])", "*oo,fo*,foo", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
184 	}
185 
186 	//------------------------------------------------------------------------------------------------------------------
187 	// | and & operators
188 	//------------------------------------------------------------------------------------------------------------------
189 
190 	@Test void a09_and_singleMixed() {
191 		test("fo*&*oo|bar", "(| (& [* fo.*] [* .*oo]) [= bar])", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
192 		test("foo|bar&baz", "(| [= foo] (& [= bar] [= baz]))", "bar,baz,foo", a("foo", "bar,baz", "foo,bar,baz", "foo,qux", "bar,baz,qux"), a("bar", "baz", "bar,qux", "baz,qux"));
193 		test("foo|bar&baz", "(| [= foo] (& [= bar] [= baz]))", "bar,baz,foo", a(), a(""));
194 		test("bar|fo*&*oo", "(| [= bar] (& [* fo.*] [* .*oo]))", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
195 		test("  fo*  &  *oo  |  bar  ", "(| (& [* fo.*] [* .*oo]) [= bar])", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
196 		test("  bar  |  fo*  &  *oo  ", "(| [= bar] (& [* fo.*] [* .*oo]))", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
197 		test("(fo*&*oo|bar)", "(| (& [* fo.*] [* .*oo]) [= bar])", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
198 		test("(bar|fo*&*oo)", "(| [= bar] (& [* fo.*] [* .*oo]))", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
199 		test("(fo*)&(*oo)|(bar)", "(| (& [* fo.*] [* .*oo]) [= bar])", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
200 		test("(bar)|(fo*)&(*oo)", "(| [= bar] (& [* fo.*] [* .*oo]))", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
201 		test("  (  fo*  &  *oo  |  bar  )  ", "(| (& [* fo.*] [* .*oo]) [= bar])", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
202 		test("  (  bar  |  fo*  &  *oo  )  ", "(| [= bar] (& [* fo.*] [* .*oo]))", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
203 		test("((fo*)&(*oo)|(bar))", "(| (& [* fo.*] [* .*oo]) [= bar])", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
204 		test("((bar)|(fo*)&(*oo))", "(| [= bar] (& [* fo.*] [* .*oo]))", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
205 		test("((((fo*))&((*oo))|((bar))))", "(| (& [* fo.*] [* .*oo]) [= bar])", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
206 		test("((((bar))|((fo*))&((*oo))))", "(| [= bar] (& [* fo.*] [* .*oo]))", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
207 		test("  (  (  (  (  fo*  )  )  &  (  (  *oo  )  )  |  (  (  bar  )  )  )  )  ", "(| (& [* fo.*] [* .*oo]) [= bar])", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
208 		test("  (  (  (  (  bar  )  )  |  (  (  fo*  )  )  &  (  (  *oo  )  )  )  )  ", "(| [= bar] (& [* fo.*] [* .*oo]))", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
209 	}
210 
211 	//------------------------------------------------------------------------------------------------------------------
212 	// "||" and "&&" operators
213 	//------------------------------------------------------------------------------------------------------------------
214 
215 	@Test void a10_and_doubleMixed() {
216 		test("fo*&&*oo||bar", "(| (& [* fo.*] [* .*oo]) [= bar])", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
217 		test("foo||bar&&baz", "(| [= foo] (& [= bar] [= baz]))", "bar,baz,foo", a("foo", "bar,baz", "foo,bar,baz", "foo,qux", "bar,baz,qux"), a("bar", "baz", "bar,qux", "baz,qux"));
218 		test("foo||bar&&baz", "(| [= foo] (& [= bar] [= baz]))", "bar,baz,foo", a(), a(""));
219 		test("bar||fo*&&*oo", "(| [= bar] (& [* fo.*] [* .*oo]))", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
220 		test("  fo*  &&  *oo  ||  bar  ", "(| (& [* fo.*] [* .*oo]) [= bar])", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
221 		test("  bar  ||  fo*  &&  *oo  ", "(| [= bar] (& [* fo.*] [* .*oo]))", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
222 		test("(fo*&&*oo||bar)", "(| (& [* fo.*] [* .*oo]) [= bar])", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
223 		test("(bar||fo*&&*oo)", "(| [= bar] (& [* fo.*] [* .*oo]))", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
224 		test("(fo*)&&(*oo)||(bar)", "(| (& [* fo.*] [* .*oo]) [= bar])", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
225 		test("(bar)||(fo*)&&(*oo)", "(| [= bar] (& [* fo.*] [* .*oo]))", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
226 		test("  (  fo*  &&  *oo  ||  bar  )  ", "(| (& [* fo.*] [* .*oo]) [= bar])", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
227 		test("  (  bar  ||  fo*  &&  *oo  )  ", "(| [= bar] (& [* fo.*] [* .*oo]))", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
228 		test("((fo*)&&(*oo)||(bar))", "(| (& [* fo.*] [* .*oo]) [= bar])", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
229 		test("((bar)||(fo*)&&(*oo))", "(| [= bar] (& [* fo.*] [* .*oo]))", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
230 		test("((((fo*))&&((*oo))||((bar))))", "(| (& [* fo.*] [* .*oo]) [= bar])", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
231 		test("((((bar))||((fo*))&&((*oo))))", "(| [= bar] (& [* fo.*] [* .*oo]))", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
232 		test("  (  (  (  (  fo*  )  )  &&  (  (  *oo  )  )  ||  (  (  bar  )  )  )  )  ", "(| (& [* fo.*] [* .*oo]) [= bar])", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
233 		test("  (  (  (  (  bar  )  )  ||  (  (  fo*  )  )  &&  (  (  *oo  )  )  )  )  ", "(| [= bar] (& [* fo.*] [* .*oo]))", "*oo,bar,fo*", a("foo", "bar"), a("foox", "xfoo", "fo", "baz", null));
234 	}
235 
236 	//------------------------------------------------------------------------------------------------------------------
237 	// | and & and () operators
238 	//------------------------------------------------------------------------------------------------------------------
239 
240 	@Test void a11_and_singleMixedParentheses() {
241 		test("fo*&(*oo|bar)", "(& [* fo.*] (| [* .*oo] [= bar]))", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
242 		test("foo&(bar|baz)", "(& [= foo] (| [= bar] [= baz]))", "bar,baz,foo", a("foo,bar", "foo,baz", "foo,bar,baz,qux"), a("foo", "bar", "baz", "bar,baz", "qux", null));
243 		test("foo&(bar|baz)", "(& [= foo] (| [= bar] [= baz]))", "bar,baz,foo", a(), a(""));
244 		test("(bar|fo*)&*oo", "(& (| [= bar] [* fo.*]) [* .*oo])", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
245 		test("  fo*  &  (  *oo  |  bar  )  ", "(& [* fo.*] (| [* .*oo] [= bar]))", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
246 		test("  (  bar  |  fo*  )  &  *oo  ", "(& (| [= bar] [* fo.*]) [* .*oo])", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
247 		test("(fo*&(*oo|bar))", "(& [* fo.*] (| [* .*oo] [= bar]))", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
248 		test("((bar|fo*)&*oo)", "(& (| [= bar] [* fo.*]) [* .*oo])", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
249 		test("(fo*)&((*oo)|(bar))", "(& [* fo.*] (| [* .*oo] [= bar]))", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
250 		test("((bar)|(fo*))&(*oo)", "(& (| [= bar] [* fo.*]) [* .*oo])", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
251 		test("  (  fo*  &  (  *oo  |  bar  )  )  ", "(& [* fo.*] (| [* .*oo] [= bar]))", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
252 		test("  (  (  bar  |  fo*  )  &  *oo  )  ", "(& (| [= bar] [* fo.*]) [* .*oo])", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
253 		test("((fo*)&((*oo)|(bar)))", "(& [* fo.*] (| [* .*oo] [= bar]))", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
254 		test("(((bar)|(fo*))&(*oo))", "(& (| [= bar] [* fo.*]) [* .*oo])", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
255 		test("((((fo*))&(((*oo))|((bar)))))", "(& [* fo.*] (| [* .*oo] [= bar]))", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
256 		test("(((((bar))|((fo*)))&((*oo))))", "(& (| [= bar] [* fo.*]) [* .*oo])", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
257 		test("  (  (  (  (  fo*  )  )  &  (  (  (  *oo  )  )  |  (  (  bar  )  )  )  )  )  ", "(& [* fo.*] (| [* .*oo] [= bar]))", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
258 		test("  (  (  (  (  (  bar  )  )  |  (  (  fo*  )  )  )  &  (  (  *oo  )  )  )  )  ", "(& (| [= bar] [* fo.*]) [* .*oo])", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
259 	}
260 
261 	//------------------------------------------------------------------------------------------------------------------
262 	// "||" and "&&" and "()" operators
263 	//------------------------------------------------------------------------------------------------------------------
264 
265 	@Test void a12_and_doubleMixedParentheses() {
266 		test("fo*&&(*oo||bar)", "(& [* fo.*] (| [* .*oo] [= bar]))", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
267 		test("foo&&(bar||baz)", "(& [= foo] (| [= bar] [= baz]))", "bar,baz,foo", a("foo,bar", "foo,baz", "foo,bar,baz,qux"), a("foo", "bar", "baz", "bar,baz", "qux", null));
268 		test("foo&&(bar||baz)", "(& [= foo] (| [= bar] [= baz]))", "bar,baz,foo", a(), a(""));
269 		test("(bar||fo*)&&*oo", "(& (| [= bar] [* fo.*]) [* .*oo])", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
270 		test("  fo*  &&  (  *oo  ||  bar  )  ", "(& [* fo.*] (| [* .*oo] [= bar]))", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
271 		test("  (  bar  ||  fo*  )  &&  *oo  ", "(& (| [= bar] [* fo.*]) [* .*oo])", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
272 		test("(fo*&&(*oo||bar))", "(& [* fo.*] (| [* .*oo] [= bar]))", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
273 		test("((bar||fo*)&&*oo)", "(& (| [= bar] [* fo.*]) [* .*oo])", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
274 		test("(fo*)&((*oo)||(bar))", "(& [* fo.*] (| [* .*oo] [= bar]))", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
275 		test("((bar)||(fo*))&&(*oo)", "(& (| [= bar] [* fo.*]) [* .*oo])", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
276 		test("  (  fo*  &&  (  *oo  ||  bar  )  )  ", "(& [* fo.*] (| [* .*oo] [= bar]))", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
277 		test("  (  (  bar  ||  fo*  )  &&  *oo  )  ", "(& (| [= bar] [* fo.*]) [* .*oo])", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
278 		test("((fo*)&&((*oo)||(bar)))", "(& [* fo.*] (| [* .*oo] [= bar]))", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
279 		test("(((bar)||(fo*))&&(*oo))", "(& (| [= bar] [* fo.*]) [* .*oo])", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
280 		test("((((fo*))&&(((*oo))||((bar)))))", "(& [* fo.*] (| [* .*oo] [= bar]))", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
281 		test("(((((bar))||((fo*)))&&((*oo))))", "(& (| [= bar] [* fo.*]) [* .*oo])", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
282 		test("  (  (  (  (  fo*  )  )  &&  (  (  (  *oo  )  )  ||  (  (  bar  )  )  )  )  )  ", "(& [* fo.*] (| [* .*oo] [= bar]))", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
283 		test("  (  (  (  (  (  bar  )  )  ||  (  (  fo*  )  )  )  &&  (  (  *oo  )  )  )  )  ", "(& (| [= bar] [* fo.*]) [* .*oo])", "*oo,bar,fo*", a("foo"), a("foox", "xfoo", "fo", "bar", "baz", null));
284 	}
285 
286 	//------------------------------------------------------------------------------------------------------------------
287 	// Error conditions
288 	//------------------------------------------------------------------------------------------------------------------
289 
290 	@Test void b01_errors() {
291 		assertThrows(ParseException.class, ()->new RoleMatcher("&foo"));
292 		assertThrows(ParseException.class, ()->new RoleMatcher("foo bar"));
293 		assertThrows(ParseException.class, ()->new RoleMatcher("(foo"));
294 		assertThrows(ParseException.class, ()->new RoleMatcher("foo &"));
295 		assertThrows(ParseException.class, ()->new RoleMatcher("foo ||"));
296 		assertThrows(ParseException.class, ()->new RoleMatcher("foo ,"));
297 		assertThrows(ParseException.class, ()->new RoleMatcher("foo & "));
298 		assertThrows(ParseException.class, ()->new RoleMatcher("foo || "));
299 		assertThrows(ParseException.class, ()->new RoleMatcher("foo , "));
300 	}
301 }