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.Assert.assertEquals;
021import static org.junit.Assert.assertTrue;
022
023import org.apache.hadoop.hbase.HBaseClassTestRule;
024import org.apache.hadoop.hbase.security.visibility.expression.ExpressionNode;
025import org.apache.hadoop.hbase.security.visibility.expression.LeafExpressionNode;
026import org.apache.hadoop.hbase.security.visibility.expression.NonLeafExpressionNode;
027import org.apache.hadoop.hbase.security.visibility.expression.Operator;
028import org.apache.hadoop.hbase.testclassification.SecurityTests;
029import org.apache.hadoop.hbase.testclassification.SmallTests;
030import org.junit.ClassRule;
031import org.junit.Test;
032import org.junit.experimental.categories.Category;
033
034@Category({ SecurityTests.class, SmallTests.class })
035public class TestExpressionExpander {
036
037  @ClassRule
038  public static final HBaseClassTestRule CLASS_RULE =
039    HBaseClassTestRule.forClass(TestExpressionExpander.class);
040
041  @Test
042  public void testPositiveCases() throws Exception {
043    ExpressionExpander expander = new ExpressionExpander();
044
045    // (!a) -> (!a)
046    NonLeafExpressionNode exp1 =
047      new NonLeafExpressionNode(Operator.NOT, new LeafExpressionNode("a"));
048    ExpressionNode result = expander.expand(exp1);
049    assertTrue(result instanceof NonLeafExpressionNode);
050    NonLeafExpressionNode nlResult = (NonLeafExpressionNode) result;
051    assertEquals(Operator.NOT, nlResult.getOperator());
052    assertEquals("a", ((LeafExpressionNode) nlResult.getChildExps().get(0)).getIdentifier());
053
054    // (a | b) -> (a | b)
055    NonLeafExpressionNode exp2 = new NonLeafExpressionNode(Operator.OR, new LeafExpressionNode("a"),
056      new LeafExpressionNode("b"));
057    result = expander.expand(exp2);
058    assertTrue(result instanceof NonLeafExpressionNode);
059    nlResult = (NonLeafExpressionNode) result;
060    assertEquals(Operator.OR, nlResult.getOperator());
061    assertEquals(2, nlResult.getChildExps().size());
062    assertEquals("a", ((LeafExpressionNode) nlResult.getChildExps().get(0)).getIdentifier());
063    assertEquals("b", ((LeafExpressionNode) nlResult.getChildExps().get(1)).getIdentifier());
064
065    // (a & b) -> (a & b)
066    NonLeafExpressionNode exp3 = new NonLeafExpressionNode(Operator.AND,
067      new LeafExpressionNode("a"), new LeafExpressionNode("b"));
068    result = expander.expand(exp3);
069    assertTrue(result instanceof NonLeafExpressionNode);
070    nlResult = (NonLeafExpressionNode) result;
071    assertEquals(Operator.AND, nlResult.getOperator());
072    assertEquals(2, nlResult.getChildExps().size());
073    assertEquals("a", ((LeafExpressionNode) nlResult.getChildExps().get(0)).getIdentifier());
074    assertEquals("b", ((LeafExpressionNode) nlResult.getChildExps().get(1)).getIdentifier());
075
076    // ((a | b) | c) -> (a | b | c)
077    NonLeafExpressionNode exp4 =
078      new NonLeafExpressionNode(Operator.OR, new NonLeafExpressionNode(Operator.OR,
079        new LeafExpressionNode("a"), new LeafExpressionNode("b")), new LeafExpressionNode("c"));
080    result = expander.expand(exp4);
081    assertTrue(result instanceof NonLeafExpressionNode);
082    nlResult = (NonLeafExpressionNode) result;
083    assertEquals(Operator.OR, nlResult.getOperator());
084    assertEquals(3, nlResult.getChildExps().size());
085    assertEquals("a", ((LeafExpressionNode) nlResult.getChildExps().get(0)).getIdentifier());
086    assertEquals("b", ((LeafExpressionNode) nlResult.getChildExps().get(1)).getIdentifier());
087    assertEquals("c", ((LeafExpressionNode) nlResult.getChildExps().get(2)).getIdentifier());
088
089    // ((a & b) & c) -> (a & b & c)
090    NonLeafExpressionNode exp5 =
091      new NonLeafExpressionNode(Operator.AND, new NonLeafExpressionNode(Operator.AND,
092        new LeafExpressionNode("a"), new LeafExpressionNode("b")), new LeafExpressionNode("c"));
093    result = expander.expand(exp5);
094    assertTrue(result instanceof NonLeafExpressionNode);
095    nlResult = (NonLeafExpressionNode) result;
096    assertEquals(Operator.AND, nlResult.getOperator());
097    assertEquals(3, nlResult.getChildExps().size());
098    assertEquals("a", ((LeafExpressionNode) nlResult.getChildExps().get(0)).getIdentifier());
099    assertEquals("b", ((LeafExpressionNode) nlResult.getChildExps().get(1)).getIdentifier());
100    assertEquals("c", ((LeafExpressionNode) nlResult.getChildExps().get(2)).getIdentifier());
101
102    // (a | b) & c -> ((a & c) | (b & c))
103    NonLeafExpressionNode exp6 =
104      new NonLeafExpressionNode(Operator.AND, new NonLeafExpressionNode(Operator.OR,
105        new LeafExpressionNode("a"), new LeafExpressionNode("b")), new LeafExpressionNode("c"));
106    result = expander.expand(exp6);
107    assertTrue(result instanceof NonLeafExpressionNode);
108    nlResult = (NonLeafExpressionNode) result;
109    assertEquals(Operator.OR, nlResult.getOperator());
110    assertEquals(2, nlResult.getChildExps().size());
111    NonLeafExpressionNode temp = (NonLeafExpressionNode) nlResult.getChildExps().get(0);
112    assertEquals(Operator.AND, temp.getOperator());
113    assertEquals(2, temp.getChildExps().size());
114    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
115    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
116    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(1);
117    assertEquals(Operator.AND, temp.getOperator());
118    assertEquals(2, temp.getChildExps().size());
119    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
120    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
121
122    // (a & b) | c -> ((a & b) | c)
123    NonLeafExpressionNode exp7 =
124      new NonLeafExpressionNode(Operator.OR, new NonLeafExpressionNode(Operator.AND,
125        new LeafExpressionNode("a"), new LeafExpressionNode("b")), new LeafExpressionNode("c"));
126    result = expander.expand(exp7);
127    assertTrue(result instanceof NonLeafExpressionNode);
128    nlResult = (NonLeafExpressionNode) result;
129    assertEquals(Operator.OR, nlResult.getOperator());
130    assertEquals(2, nlResult.getChildExps().size());
131    assertEquals("c", ((LeafExpressionNode) nlResult.getChildExps().get(1)).getIdentifier());
132    nlResult = (NonLeafExpressionNode) nlResult.getChildExps().get(0);
133    assertEquals(Operator.AND, nlResult.getOperator());
134    assertEquals(2, nlResult.getChildExps().size());
135    assertEquals("a", ((LeafExpressionNode) nlResult.getChildExps().get(0)).getIdentifier());
136    assertEquals("b", ((LeafExpressionNode) nlResult.getChildExps().get(1)).getIdentifier());
137
138    // ((a & b) | c) & d -> (((a & b) & d) | (c & d))
139    NonLeafExpressionNode exp8 = new NonLeafExpressionNode(Operator.AND);
140    exp8.addChildExp(new NonLeafExpressionNode(Operator.OR, new NonLeafExpressionNode(Operator.AND,
141      new LeafExpressionNode("a"), new LeafExpressionNode("b")), new LeafExpressionNode("c")));
142    exp8.addChildExp(new LeafExpressionNode("d"));
143    result = expander.expand(exp8);
144    assertTrue(result instanceof NonLeafExpressionNode);
145    nlResult = (NonLeafExpressionNode) result;
146    assertEquals(Operator.OR, nlResult.getOperator());
147    assertEquals(2, nlResult.getChildExps().size());
148    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(1);
149    assertEquals(Operator.AND, temp.getOperator());
150    assertEquals(2, temp.getChildExps().size());
151    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
152    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
153    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(0);
154    assertEquals(Operator.AND, temp.getOperator());
155    assertEquals(2, temp.getChildExps().size());
156    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
157    temp = (NonLeafExpressionNode) temp.getChildExps().get(0);
158    assertEquals(Operator.AND, temp.getOperator());
159    assertEquals(2, temp.getChildExps().size());
160    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
161    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
162
163    // (a | b) | (c | d) -> (a | b | c | d)
164    NonLeafExpressionNode exp9 = new NonLeafExpressionNode(Operator.OR);
165    exp9.addChildExp(new NonLeafExpressionNode(Operator.OR, new LeafExpressionNode("a"),
166      new LeafExpressionNode("b")));
167    exp9.addChildExp(new NonLeafExpressionNode(Operator.OR, new LeafExpressionNode("c"),
168      new LeafExpressionNode("d")));
169    result = expander.expand(exp9);
170    assertTrue(result instanceof NonLeafExpressionNode);
171    nlResult = (NonLeafExpressionNode) result;
172    assertEquals(Operator.OR, nlResult.getOperator());
173    assertEquals(4, nlResult.getChildExps().size());
174    assertEquals("a", ((LeafExpressionNode) nlResult.getChildExps().get(0)).getIdentifier());
175    assertEquals("b", ((LeafExpressionNode) nlResult.getChildExps().get(1)).getIdentifier());
176    assertEquals("c", ((LeafExpressionNode) nlResult.getChildExps().get(2)).getIdentifier());
177    assertEquals("d", ((LeafExpressionNode) nlResult.getChildExps().get(3)).getIdentifier());
178
179    // (a & b) & (c & d) -> (a & b & c & d)
180    NonLeafExpressionNode exp10 = new NonLeafExpressionNode(Operator.AND);
181    exp10.addChildExp(new NonLeafExpressionNode(Operator.AND, new LeafExpressionNode("a"),
182      new LeafExpressionNode("b")));
183    exp10.addChildExp(new NonLeafExpressionNode(Operator.AND, new LeafExpressionNode("c"),
184      new LeafExpressionNode("d")));
185    result = expander.expand(exp10);
186    assertTrue(result instanceof NonLeafExpressionNode);
187    nlResult = (NonLeafExpressionNode) result;
188    assertEquals(Operator.AND, nlResult.getOperator());
189    assertEquals(4, nlResult.getChildExps().size());
190    assertEquals("a", ((LeafExpressionNode) nlResult.getChildExps().get(0)).getIdentifier());
191    assertEquals("b", ((LeafExpressionNode) nlResult.getChildExps().get(1)).getIdentifier());
192    assertEquals("c", ((LeafExpressionNode) nlResult.getChildExps().get(2)).getIdentifier());
193    assertEquals("d", ((LeafExpressionNode) nlResult.getChildExps().get(3)).getIdentifier());
194
195    // (a | b) & (c | d) -> ((a & c) | (a & d) | (b & c) | (b & d))
196    NonLeafExpressionNode exp11 = new NonLeafExpressionNode(Operator.AND);
197    exp11.addChildExp(new NonLeafExpressionNode(Operator.OR, new LeafExpressionNode("a"),
198      new LeafExpressionNode("b")));
199    exp11.addChildExp(new NonLeafExpressionNode(Operator.OR, new LeafExpressionNode("c"),
200      new LeafExpressionNode("d")));
201    result = expander.expand(exp11);
202    assertTrue(result instanceof NonLeafExpressionNode);
203    nlResult = (NonLeafExpressionNode) result;
204    assertEquals(Operator.OR, nlResult.getOperator());
205    assertEquals(4, nlResult.getChildExps().size());
206    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(0);
207    assertEquals(Operator.AND, temp.getOperator());
208    assertEquals(2, temp.getChildExps().size());
209    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
210    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
211    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(1);
212    assertEquals(Operator.AND, temp.getOperator());
213    assertEquals(2, temp.getChildExps().size());
214    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
215    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
216    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(2);
217    assertEquals(Operator.AND, temp.getOperator());
218    assertEquals(2, temp.getChildExps().size());
219    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
220    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
221    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(3);
222    assertEquals(Operator.AND, temp.getOperator());
223    assertEquals(2, temp.getChildExps().size());
224    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
225    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
226
227    // (((a | b) | c) | d) & e -> ((a & e) | (b & e) | (c & e) | (d & e))
228    NonLeafExpressionNode exp12 = new NonLeafExpressionNode(Operator.AND);
229    NonLeafExpressionNode tempExp1 = new NonLeafExpressionNode(Operator.OR,
230      new LeafExpressionNode("a"), new LeafExpressionNode("b"));
231    NonLeafExpressionNode tempExp2 =
232      new NonLeafExpressionNode(Operator.OR, tempExp1, new LeafExpressionNode("c"));
233    NonLeafExpressionNode tempExp3 =
234      new NonLeafExpressionNode(Operator.OR, tempExp2, new LeafExpressionNode("d"));
235    exp12.addChildExp(tempExp3);
236    exp12.addChildExp(new LeafExpressionNode("e"));
237    result = expander.expand(exp12);
238    assertTrue(result instanceof NonLeafExpressionNode);
239    nlResult = (NonLeafExpressionNode) result;
240    assertEquals(Operator.OR, nlResult.getOperator());
241    assertEquals(4, nlResult.getChildExps().size());
242    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(0);
243    assertEquals(Operator.AND, temp.getOperator());
244    assertEquals(2, temp.getChildExps().size());
245    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
246    assertEquals("e", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
247    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(1);
248    assertEquals(Operator.AND, temp.getOperator());
249    assertEquals(2, temp.getChildExps().size());
250    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
251    assertEquals("e", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
252    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(2);
253    assertEquals(Operator.AND, temp.getOperator());
254    assertEquals(2, temp.getChildExps().size());
255    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
256    assertEquals("e", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
257    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(3);
258    assertEquals(Operator.AND, temp.getOperator());
259    assertEquals(2, temp.getChildExps().size());
260    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
261    assertEquals("e", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
262
263    // (a | b | c) & d -> ((a & d) | (b & d) | (c & d))
264    NonLeafExpressionNode exp13 = new NonLeafExpressionNode(Operator.AND,
265      new NonLeafExpressionNode(Operator.OR, new LeafExpressionNode("a"),
266        new LeafExpressionNode("b"), new LeafExpressionNode("c")),
267      new LeafExpressionNode("d"));
268    result = expander.expand(exp13);
269    assertTrue(result instanceof NonLeafExpressionNode);
270    nlResult = (NonLeafExpressionNode) result;
271    assertEquals(Operator.OR, nlResult.getOperator());
272    assertEquals(3, nlResult.getChildExps().size());
273    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(0);
274    assertEquals(Operator.AND, temp.getOperator());
275    assertEquals(2, temp.getChildExps().size());
276    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
277    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
278    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(1);
279    assertEquals(Operator.AND, temp.getOperator());
280    assertEquals(2, temp.getChildExps().size());
281    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
282    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
283    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(2);
284    assertEquals(Operator.AND, temp.getOperator());
285    assertEquals(2, temp.getChildExps().size());
286    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
287    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
288
289    // ((a | b) & (c | d)) & (e | f) -> (((a & c) & e) | ((a & c) & f) | ((a & d) & e) | ((a & d) &
290    // f) | ((b & c) & e) | ((b & c) & f) | ((b & d) & e) | ((b & d) & f))
291    NonLeafExpressionNode exp15 = new NonLeafExpressionNode(Operator.AND);
292    NonLeafExpressionNode temp1 = new NonLeafExpressionNode(Operator.AND);
293    temp1.addChildExp(new NonLeafExpressionNode(Operator.OR, new LeafExpressionNode("a"),
294      new LeafExpressionNode("b")));
295    temp1.addChildExp(new NonLeafExpressionNode(Operator.OR, new LeafExpressionNode("c"),
296      new LeafExpressionNode("d")));
297    exp15.addChildExp(temp1);
298    exp15.addChildExp(new NonLeafExpressionNode(Operator.OR, new LeafExpressionNode("e"),
299      new LeafExpressionNode("f")));
300    result = expander.expand(exp15);
301    assertTrue(result instanceof NonLeafExpressionNode);
302    nlResult = (NonLeafExpressionNode) result;
303    assertEquals(Operator.OR, nlResult.getOperator());
304    assertEquals(8, nlResult.getChildExps().size());
305    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(0);
306    assertEquals(Operator.AND, temp.getOperator());
307    assertEquals(2, temp.getChildExps().size());
308    assertEquals("e", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
309    temp = (NonLeafExpressionNode) temp.getChildExps().get(0);
310    assertEquals(Operator.AND, temp.getOperator());
311    assertEquals(2, temp.getChildExps().size());
312    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
313    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
314
315    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(1);
316    assertEquals(Operator.AND, temp.getOperator());
317    assertEquals(2, temp.getChildExps().size());
318    assertEquals("f", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
319    temp = (NonLeafExpressionNode) temp.getChildExps().get(0);
320    assertEquals(Operator.AND, temp.getOperator());
321    assertEquals(2, temp.getChildExps().size());
322    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
323    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
324
325    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(2);
326    assertEquals(Operator.AND, temp.getOperator());
327    assertEquals(2, temp.getChildExps().size());
328    assertEquals("e", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
329    temp = (NonLeafExpressionNode) temp.getChildExps().get(0);
330    assertEquals(Operator.AND, temp.getOperator());
331    assertEquals(2, temp.getChildExps().size());
332    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
333    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
334
335    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(3);
336    assertEquals(Operator.AND, temp.getOperator());
337    assertEquals(2, temp.getChildExps().size());
338    assertEquals("f", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
339    temp = (NonLeafExpressionNode) temp.getChildExps().get(0);
340    assertEquals(Operator.AND, temp.getOperator());
341    assertEquals(2, temp.getChildExps().size());
342    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
343    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
344
345    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(4);
346    assertEquals(Operator.AND, temp.getOperator());
347    assertEquals(2, temp.getChildExps().size());
348    assertEquals("e", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
349    temp = (NonLeafExpressionNode) temp.getChildExps().get(0);
350    assertEquals(Operator.AND, temp.getOperator());
351    assertEquals(2, temp.getChildExps().size());
352    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
353    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
354
355    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(5);
356    assertEquals(Operator.AND, temp.getOperator());
357    assertEquals(2, temp.getChildExps().size());
358    assertEquals("f", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
359    temp = (NonLeafExpressionNode) temp.getChildExps().get(0);
360    assertEquals(Operator.AND, temp.getOperator());
361    assertEquals(2, temp.getChildExps().size());
362    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
363    assertEquals("c", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
364
365    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(6);
366    assertEquals(Operator.AND, temp.getOperator());
367    assertEquals(2, temp.getChildExps().size());
368    assertEquals("e", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
369    temp = (NonLeafExpressionNode) temp.getChildExps().get(0);
370    assertEquals(Operator.AND, temp.getOperator());
371    assertEquals(2, temp.getChildExps().size());
372    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
373    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
374
375    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(7);
376    assertEquals(Operator.AND, temp.getOperator());
377    assertEquals(2, temp.getChildExps().size());
378    assertEquals("f", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
379    temp = (NonLeafExpressionNode) temp.getChildExps().get(0);
380    assertEquals(Operator.AND, temp.getOperator());
381    assertEquals(2, temp.getChildExps().size());
382    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
383    assertEquals("d", ((LeafExpressionNode) temp.getChildExps().get(1)).getIdentifier());
384
385    // !(a | b) -> ((!a) & (!b))
386    NonLeafExpressionNode exp16 =
387      new NonLeafExpressionNode(Operator.NOT, new NonLeafExpressionNode(Operator.OR,
388        new LeafExpressionNode("a"), new LeafExpressionNode("b")));
389    result = expander.expand(exp16);
390    assertTrue(result instanceof NonLeafExpressionNode);
391    nlResult = (NonLeafExpressionNode) result;
392    assertEquals(Operator.AND, nlResult.getOperator());
393    assertEquals(2, nlResult.getChildExps().size());
394    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(0);
395    assertEquals(Operator.NOT, temp.getOperator());
396    assertEquals("a", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
397    temp = (NonLeafExpressionNode) nlResult.getChildExps().get(1);
398    assertEquals(Operator.NOT, temp.getOperator());
399    assertEquals("b", ((LeafExpressionNode) temp.getChildExps().get(0)).getIdentifier());
400  }
401}