001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.security.visibility;
019
020import static org.junit.jupiter.api.Assertions.assertEquals;
021import static org.junit.jupiter.api.Assertions.assertTrue;
022
023import org.apache.hadoop.hbase.security.visibility.expression.ExpressionNode;
024import org.apache.hadoop.hbase.security.visibility.expression.LeafExpressionNode;
025import org.apache.hadoop.hbase.security.visibility.expression.NonLeafExpressionNode;
026import org.apache.hadoop.hbase.security.visibility.expression.Operator;
027import org.apache.hadoop.hbase.testclassification.SecurityTests;
028import org.apache.hadoop.hbase.testclassification.SmallTests;
029import org.junit.jupiter.api.Tag;
030import org.junit.jupiter.api.Test;
031
032@Tag(SecurityTests.TAG)
033@Tag(SmallTests.TAG)
034public class TestExpressionExpander {
035
036  @Test
037  public void testPositiveCases() throws Exception {
038    ExpressionExpander expander = new ExpressionExpander();
039
040    // (!a) -> (!a)
041    NonLeafExpressionNode exp1 =
042      new NonLeafExpressionNode(Operator.NOT, new LeafExpressionNode("a"));
043    ExpressionNode result = expander.expand(exp1);
044    assertTrue(result instanceof NonLeafExpressionNode);
045    NonLeafExpressionNode nlResult = (NonLeafExpressionNode) result;
046    assertEquals(Operator.NOT, nlResult.getOperator());
047    assertEquals("a", ((LeafExpressionNode) nlResult.getChildExps().get(0)).getIdentifier());
048
049    // (a | b) -> (a | b)
050    NonLeafExpressionNode exp2 = new NonLeafExpressionNode(Operator.OR, new LeafExpressionNode("a"),
051      new LeafExpressionNode("b"));
052    result = expander.expand(exp2);
053    assertTrue(result instanceof NonLeafExpressionNode);
054    nlResult = (NonLeafExpressionNode) result;
055    assertEquals(Operator.OR, nlResult.getOperator());
056    assertEquals(2, nlResult.getChildExps().size());
057    assertEquals("a", ((LeafExpressionNode) nlResult.getChildExps().get(0)).getIdentifier());
058    assertEquals("b", ((LeafExpressionNode) nlResult.getChildExps().get(1)).getIdentifier());
059
060    // (a & b) -> (a & b)
061    NonLeafExpressionNode exp3 = new NonLeafExpressionNode(Operator.AND,
062      new LeafExpressionNode("a"), new LeafExpressionNode("b"));
063    result = expander.expand(exp3);
064    assertTrue(result instanceof NonLeafExpressionNode);
065    nlResult = (NonLeafExpressionNode) result;
066    assertEquals(Operator.AND, nlResult.getOperator());
067    assertEquals(2, nlResult.getChildExps().size());
068    assertEquals("a", ((LeafExpressionNode) nlResult.getChildExps().get(0)).getIdentifier());
069    assertEquals("b", ((LeafExpressionNode) nlResult.getChildExps().get(1)).getIdentifier());
070
071    // ((a | b) | c) -> (a | b | c)
072    NonLeafExpressionNode exp4 =
073      new NonLeafExpressionNode(Operator.OR, new NonLeafExpressionNode(Operator.OR,
074        new LeafExpressionNode("a"), new LeafExpressionNode("b")), new LeafExpressionNode("c"));
075    result = expander.expand(exp4);
076    assertTrue(result instanceof NonLeafExpressionNode);
077    nlResult = (NonLeafExpressionNode) result;
078    assertEquals(Operator.OR, nlResult.getOperator());
079    assertEquals(3, nlResult.getChildExps().size());
080    assertEquals("a", ((LeafExpressionNode) nlResult.getChildExps().get(0)).getIdentifier());
081    assertEquals("b", ((LeafExpressionNode) nlResult.getChildExps().get(1)).getIdentifier());
082    assertEquals("c", ((LeafExpressionNode) nlResult.getChildExps().get(2)).getIdentifier());
083
084    // ((a & b) & c) -> (a & b & c)
085    NonLeafExpressionNode exp5 =
086      new NonLeafExpressionNode(Operator.AND, new NonLeafExpressionNode(Operator.AND,
087        new LeafExpressionNode("a"), new LeafExpressionNode("b")), new LeafExpressionNode("c"));
088    result = expander.expand(exp5);
089    assertTrue(result instanceof NonLeafExpressionNode);
090    nlResult = (NonLeafExpressionNode) result;
091    assertEquals(Operator.AND, nlResult.getOperator());
092    assertEquals(3, nlResult.getChildExps().size());
093    assertEquals("a", ((LeafExpressionNode) nlResult.getChildExps().get(0)).getIdentifier());
094    assertEquals("b", ((LeafExpressionNode) nlResult.getChildExps().get(1)).getIdentifier());
095    assertEquals("c", ((LeafExpressionNode) nlResult.getChildExps().get(2)).getIdentifier());
096
097    // (a | b) & c -> ((a & c) | (b & c))
098    NonLeafExpressionNode exp6 =
099      new NonLeafExpressionNode(Operator.AND, new NonLeafExpressionNode(Operator.OR,
100        new LeafExpressionNode("a"), new LeafExpressionNode("b")), new LeafExpressionNode("c"));
101    result = expander.expand(exp6);
102    assertTrue(result instanceof NonLeafExpressionNode);
103    nlResult = (NonLeafExpressionNode) result;
104    assertEquals(Operator.OR, nlResult.getOperator());
105    assertEquals(2, nlResult.getChildExps().size());
106    NonLeafExpressionNode temp = (NonLeafExpressionNode) nlResult.getChildExps().get(0);
107    assertEquals(Operator.AND, temp.getOperator());
108    assertEquals(2, temp.getChildExps().size());
109    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
110    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
111    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(1);
112    assertEquals(Operator.AND, temp.getOperator());
113    assertEquals(2, temp.getChildExps().size());
114    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
115    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
116
117    // (a & b) | c -> ((a & b) | c)
118    NonLeafExpressionNode exp7 =
119      new NonLeafExpressionNode(Operator.OR, new NonLeafExpressionNode(Operator.AND,
120        new LeafExpressionNode("a"), new LeafExpressionNode("b")), new LeafExpressionNode("c"));
121    result = expander.expand(exp7);
122    assertTrue(result instanceof NonLeafExpressionNode);
123    nlResult = (NonLeafExpressionNode) result;
124    assertEquals(Operator.OR, nlResult.getOperator());
125    assertEquals(2, nlResult.getChildExps().size());
126    assertEquals("c", ((LeafExpressionNode) nlResult.getChildExps().get(1)).getIdentifier());
127    nlResult = (NonLeafExpressionNode) nlResult.getChildExps().get(0);
128    assertEquals(Operator.AND, nlResult.getOperator());
129    assertEquals(2, nlResult.getChildExps().size());
130    assertEquals("a", ((LeafExpressionNode) nlResult.getChildExps().get(0)).getIdentifier());
131    assertEquals("b", ((LeafExpressionNode) nlResult.getChildExps().get(1)).getIdentifier());
132
133    // ((a & b) | c) & d -> (((a & b) & d) | (c & d))
134    NonLeafExpressionNode exp8 = new NonLeafExpressionNode(Operator.AND);
135    exp8.addChildExp(new NonLeafExpressionNode(Operator.OR, new NonLeafExpressionNode(Operator.AND,
136      new LeafExpressionNode("a"), new LeafExpressionNode("b")), new LeafExpressionNode("c")));
137    exp8.addChildExp(new LeafExpressionNode("d"));
138    result = expander.expand(exp8);
139    assertTrue(result instanceof NonLeafExpressionNode);
140    nlResult = (NonLeafExpressionNode) result;
141    assertEquals(Operator.OR, nlResult.getOperator());
142    assertEquals(2, nlResult.getChildExps().size());
143    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(1);
144    assertEquals(Operator.AND, temp.getOperator());
145    assertEquals(2, temp.getChildExps().size());
146    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
147    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
148    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(0);
149    assertEquals(Operator.AND, temp.getOperator());
150    assertEquals(2, temp.getChildExps().size());
151    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
152    temp = (NonLeafExpressionNode) temp.getChildExps().get(0);
153    assertEquals(Operator.AND, temp.getOperator());
154    assertEquals(2, temp.getChildExps().size());
155    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
156    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
157
158    // (a | b) | (c | d) -> (a | b | c | d)
159    NonLeafExpressionNode exp9 = new NonLeafExpressionNode(Operator.OR);
160    exp9.addChildExp(new NonLeafExpressionNode(Operator.OR, new LeafExpressionNode("a"),
161      new LeafExpressionNode("b")));
162    exp9.addChildExp(new NonLeafExpressionNode(Operator.OR, new LeafExpressionNode("c"),
163      new LeafExpressionNode("d")));
164    result = expander.expand(exp9);
165    assertTrue(result instanceof NonLeafExpressionNode);
166    nlResult = (NonLeafExpressionNode) result;
167    assertEquals(Operator.OR, nlResult.getOperator());
168    assertEquals(4, nlResult.getChildExps().size());
169    assertEquals("a", ((LeafExpressionNode) nlResult.getChildExps().get(0)).getIdentifier());
170    assertEquals("b", ((LeafExpressionNode) nlResult.getChildExps().get(1)).getIdentifier());
171    assertEquals("c", ((LeafExpressionNode) nlResult.getChildExps().get(2)).getIdentifier());
172    assertEquals("d", ((LeafExpressionNode) nlResult.getChildExps().get(3)).getIdentifier());
173
174    // (a & b) & (c & d) -> (a & b & c & d)
175    NonLeafExpressionNode exp10 = new NonLeafExpressionNode(Operator.AND);
176    exp10.addChildExp(new NonLeafExpressionNode(Operator.AND, new LeafExpressionNode("a"),
177      new LeafExpressionNode("b")));
178    exp10.addChildExp(new NonLeafExpressionNode(Operator.AND, new LeafExpressionNode("c"),
179      new LeafExpressionNode("d")));
180    result = expander.expand(exp10);
181    assertTrue(result instanceof NonLeafExpressionNode);
182    nlResult = (NonLeafExpressionNode) result;
183    assertEquals(Operator.AND, nlResult.getOperator());
184    assertEquals(4, nlResult.getChildExps().size());
185    assertEquals("a", ((LeafExpressionNode) nlResult.getChildExps().get(0)).getIdentifier());
186    assertEquals("b", ((LeafExpressionNode) nlResult.getChildExps().get(1)).getIdentifier());
187    assertEquals("c", ((LeafExpressionNode) nlResult.getChildExps().get(2)).getIdentifier());
188    assertEquals("d", ((LeafExpressionNode) nlResult.getChildExps().get(3)).getIdentifier());
189
190    // (a | b) & (c | d) -> ((a & c) | (a & d) | (b & c) | (b & d))
191    NonLeafExpressionNode exp11 = new NonLeafExpressionNode(Operator.AND);
192    exp11.addChildExp(new NonLeafExpressionNode(Operator.OR, new LeafExpressionNode("a"),
193      new LeafExpressionNode("b")));
194    exp11.addChildExp(new NonLeafExpressionNode(Operator.OR, new LeafExpressionNode("c"),
195      new LeafExpressionNode("d")));
196    result = expander.expand(exp11);
197    assertTrue(result instanceof NonLeafExpressionNode);
198    nlResult = (NonLeafExpressionNode) result;
199    assertEquals(Operator.OR, nlResult.getOperator());
200    assertEquals(4, nlResult.getChildExps().size());
201    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(0);
202    assertEquals(Operator.AND, temp.getOperator());
203    assertEquals(2, temp.getChildExps().size());
204    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
205    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
206    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(1);
207    assertEquals(Operator.AND, temp.getOperator());
208    assertEquals(2, temp.getChildExps().size());
209    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
210    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
211    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(2);
212    assertEquals(Operator.AND, temp.getOperator());
213    assertEquals(2, temp.getChildExps().size());
214    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
215    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
216    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(3);
217    assertEquals(Operator.AND, temp.getOperator());
218    assertEquals(2, temp.getChildExps().size());
219    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
220    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
221
222    // (((a | b) | c) | d) & e -> ((a & e) | (b & e) | (c & e) | (d & e))
223    NonLeafExpressionNode exp12 = new NonLeafExpressionNode(Operator.AND);
224    NonLeafExpressionNode tempExp1 = new NonLeafExpressionNode(Operator.OR,
225      new LeafExpressionNode("a"), new LeafExpressionNode("b"));
226    NonLeafExpressionNode tempExp2 =
227      new NonLeafExpressionNode(Operator.OR, tempExp1, new LeafExpressionNode("c"));
228    NonLeafExpressionNode tempExp3 =
229      new NonLeafExpressionNode(Operator.OR, tempExp2, new LeafExpressionNode("d"));
230    exp12.addChildExp(tempExp3);
231    exp12.addChildExp(new LeafExpressionNode("e"));
232    result = expander.expand(exp12);
233    assertTrue(result instanceof NonLeafExpressionNode);
234    nlResult = (NonLeafExpressionNode) result;
235    assertEquals(Operator.OR, nlResult.getOperator());
236    assertEquals(4, nlResult.getChildExps().size());
237    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(0);
238    assertEquals(Operator.AND, temp.getOperator());
239    assertEquals(2, temp.getChildExps().size());
240    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
241    assertEquals("e", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
242    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(1);
243    assertEquals(Operator.AND, temp.getOperator());
244    assertEquals(2, temp.getChildExps().size());
245    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
246    assertEquals("e", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
247    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(2);
248    assertEquals(Operator.AND, temp.getOperator());
249    assertEquals(2, temp.getChildExps().size());
250    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
251    assertEquals("e", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
252    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(3);
253    assertEquals(Operator.AND, temp.getOperator());
254    assertEquals(2, temp.getChildExps().size());
255    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
256    assertEquals("e", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
257
258    // (a | b | c) & d -> ((a & d) | (b & d) | (c & d))
259    NonLeafExpressionNode exp13 = new NonLeafExpressionNode(Operator.AND,
260      new NonLeafExpressionNode(Operator.OR, new LeafExpressionNode("a"),
261        new LeafExpressionNode("b"), new LeafExpressionNode("c")),
262      new LeafExpressionNode("d"));
263    result = expander.expand(exp13);
264    assertTrue(result instanceof NonLeafExpressionNode);
265    nlResult = (NonLeafExpressionNode) result;
266    assertEquals(Operator.OR, nlResult.getOperator());
267    assertEquals(3, nlResult.getChildExps().size());
268    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(0);
269    assertEquals(Operator.AND, temp.getOperator());
270    assertEquals(2, temp.getChildExps().size());
271    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
272    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
273    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(1);
274    assertEquals(Operator.AND, temp.getOperator());
275    assertEquals(2, temp.getChildExps().size());
276    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
277    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
278    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(2);
279    assertEquals(Operator.AND, temp.getOperator());
280    assertEquals(2, temp.getChildExps().size());
281    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
282    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
283
284    // ((a | b) & (c | d)) & (e | f) -> (((a & c) & e) | ((a & c) & f) | ((a & d) & e) | ((a & d) &
285    // f) | ((b & c) & e) | ((b & c) & f) | ((b & d) & e) | ((b & d) & f))
286    NonLeafExpressionNode exp15 = new NonLeafExpressionNode(Operator.AND);
287    NonLeafExpressionNode temp1 = new NonLeafExpressionNode(Operator.AND);
288    temp1.addChildExp(new NonLeafExpressionNode(Operator.OR, new LeafExpressionNode("a"),
289      new LeafExpressionNode("b")));
290    temp1.addChildExp(new NonLeafExpressionNode(Operator.OR, new LeafExpressionNode("c"),
291      new LeafExpressionNode("d")));
292    exp15.addChildExp(temp1);
293    exp15.addChildExp(new NonLeafExpressionNode(Operator.OR, new LeafExpressionNode("e"),
294      new LeafExpressionNode("f")));
295    result = expander.expand(exp15);
296    assertTrue(result instanceof NonLeafExpressionNode);
297    nlResult = (NonLeafExpressionNode) result;
298    assertEquals(Operator.OR, nlResult.getOperator());
299    assertEquals(8, nlResult.getChildExps().size());
300    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(0);
301    assertEquals(Operator.AND, temp.getOperator());
302    assertEquals(2, temp.getChildExps().size());
303    assertEquals("e", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
304    temp = (NonLeafExpressionNode) temp.getChildExps().get(0);
305    assertEquals(Operator.AND, temp.getOperator());
306    assertEquals(2, temp.getChildExps().size());
307    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
308    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
309
310    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(1);
311    assertEquals(Operator.AND, temp.getOperator());
312    assertEquals(2, temp.getChildExps().size());
313    assertEquals("f", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
314    temp = (NonLeafExpressionNode) temp.getChildExps().get(0);
315    assertEquals(Operator.AND, temp.getOperator());
316    assertEquals(2, temp.getChildExps().size());
317    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
318    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
319
320    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(2);
321    assertEquals(Operator.AND, temp.getOperator());
322    assertEquals(2, temp.getChildExps().size());
323    assertEquals("e", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
324    temp = (NonLeafExpressionNode) temp.getChildExps().get(0);
325    assertEquals(Operator.AND, temp.getOperator());
326    assertEquals(2, temp.getChildExps().size());
327    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
328    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
329
330    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(3);
331    assertEquals(Operator.AND, temp.getOperator());
332    assertEquals(2, temp.getChildExps().size());
333    assertEquals("f", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
334    temp = (NonLeafExpressionNode) temp.getChildExps().get(0);
335    assertEquals(Operator.AND, temp.getOperator());
336    assertEquals(2, temp.getChildExps().size());
337    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
338    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
339
340    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(4);
341    assertEquals(Operator.AND, temp.getOperator());
342    assertEquals(2, temp.getChildExps().size());
343    assertEquals("e", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
344    temp = (NonLeafExpressionNode) temp.getChildExps().get(0);
345    assertEquals(Operator.AND, temp.getOperator());
346    assertEquals(2, temp.getChildExps().size());
347    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
348    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
349
350    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(5);
351    assertEquals(Operator.AND, temp.getOperator());
352    assertEquals(2, temp.getChildExps().size());
353    assertEquals("f", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
354    temp = (NonLeafExpressionNode) temp.getChildExps().get(0);
355    assertEquals(Operator.AND, temp.getOperator());
356    assertEquals(2, temp.getChildExps().size());
357    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
358    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
359
360    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(6);
361    assertEquals(Operator.AND, temp.getOperator());
362    assertEquals(2, temp.getChildExps().size());
363    assertEquals("e", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
364    temp = (NonLeafExpressionNode) temp.getChildExps().get(0);
365    assertEquals(Operator.AND, temp.getOperator());
366    assertEquals(2, temp.getChildExps().size());
367    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
368    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
369
370    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(7);
371    assertEquals(Operator.AND, temp.getOperator());
372    assertEquals(2, temp.getChildExps().size());
373    assertEquals("f", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
374    temp = (NonLeafExpressionNode) temp.getChildExps().get(0);
375    assertEquals(Operator.AND, temp.getOperator());
376    assertEquals(2, temp.getChildExps().size());
377    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
378    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
379
380    // !(a | b) -> ((!a) & (!b))
381    NonLeafExpressionNode exp16 =
382      new NonLeafExpressionNode(Operator.NOT, new NonLeafExpressionNode(Operator.OR,
383        new LeafExpressionNode("a"), new LeafExpressionNode("b")));
384    result = expander.expand(exp16);
385    assertTrue(result instanceof NonLeafExpressionNode);
386    nlResult = (NonLeafExpressionNode) result;
387    assertEquals(Operator.AND, nlResult.getOperator());
388    assertEquals(2, nlResult.getChildExps().size());
389    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(0);
390    assertEquals(Operator.NOT, temp.getOperator());
391    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
392    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(1);
393    assertEquals(Operator.NOT, temp.getOperator());
394    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
395  }
396}