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;
022import static org.junit.jupiter.api.Assertions.fail;
023
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.jupiter.api.Tag;
031import org.junit.jupiter.api.Test;
032
033@Tag(SecurityTests.TAG)
034@Tag(SmallTests.TAG)
035public class TestExpressionParser {
036
037  private ExpressionParser parser = new ExpressionParser();
038
039  @Test
040  public void testPositiveCases() throws Exception {
041    // abc -> (abc)
042    ExpressionNode node = parser.parse("abc");
043    assertTrue(node instanceof LeafExpressionNode);
044    assertEquals("abc", ((LeafExpressionNode) node).getIdentifier());
045
046    // a&b|c&d -> (((a & b) | c) & )
047    node = parser.parse("a&b|c&d");
048    assertTrue(node instanceof NonLeafExpressionNode);
049    NonLeafExpressionNode nlNode = (NonLeafExpressionNode) node;
050    assertEquals(Operator.AND, nlNode.getOperator());
051    assertEquals(2, nlNode.getChildExps().size());
052    assertEquals("d", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
053    assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
054    nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
055    assertEquals(Operator.OR, nlNode.getOperator());
056    assertEquals(2, nlNode.getChildExps().size());
057    assertEquals("c", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
058    assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
059    nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
060    assertEquals(Operator.AND, nlNode.getOperator());
061    assertEquals(2, nlNode.getChildExps().size());
062    assertEquals("b", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
063    assertEquals("a", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
064
065    // (a) -> (a)
066    node = parser.parse("(a)");
067    assertTrue(node instanceof LeafExpressionNode);
068    assertEquals("a", ((LeafExpressionNode) node).getIdentifier());
069
070    // (a&b) -> (a & b)
071    node = parser.parse(" ( a & b )");
072    assertTrue(node instanceof NonLeafExpressionNode);
073    nlNode = (NonLeafExpressionNode) node;
074    assertEquals(Operator.AND, nlNode.getOperator());
075    assertEquals(2, nlNode.getChildExps().size());
076    assertEquals("a", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
077    assertEquals("b", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
078
079    // ((((a&b)))) -> (a & b)
080    node = parser.parse("((((a&b))))");
081    assertTrue(node instanceof NonLeafExpressionNode);
082    nlNode = (NonLeafExpressionNode) node;
083    assertEquals(Operator.AND, nlNode.getOperator());
084    assertEquals(2, nlNode.getChildExps().size());
085    assertEquals("a", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
086    assertEquals("b", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
087
088    // (a|b)&(cc|def) -> ((a | b) & (cc | def))
089    node = parser.parse("( a | b ) & (cc|def)");
090    assertTrue(node instanceof NonLeafExpressionNode);
091    nlNode = (NonLeafExpressionNode) node;
092    assertEquals(Operator.AND, nlNode.getOperator());
093    assertEquals(2, nlNode.getChildExps().size());
094    assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
095    assertTrue(nlNode.getChildExps().get(1) instanceof NonLeafExpressionNode);
096    NonLeafExpressionNode nlNodeLeft = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
097    NonLeafExpressionNode nlNodeRight = (NonLeafExpressionNode) nlNode.getChildExps().get(1);
098    assertEquals(Operator.OR, nlNodeLeft.getOperator());
099    assertEquals(2, nlNodeLeft.getChildExps().size());
100    assertEquals("a", ((LeafExpressionNode) nlNodeLeft.getChildExps().get(0)).getIdentifier());
101    assertEquals("b", ((LeafExpressionNode) nlNodeLeft.getChildExps().get(1)).getIdentifier());
102    assertEquals(Operator.OR, nlNodeRight.getOperator());
103    assertEquals(2, nlNodeRight.getChildExps().size());
104    assertEquals("cc", ((LeafExpressionNode) nlNodeRight.getChildExps().get(0)).getIdentifier());
105    assertEquals("def", ((LeafExpressionNode) nlNodeRight.getChildExps().get(1)).getIdentifier());
106
107    // a&(cc|de) -> (a & (cc | de))
108    node = parser.parse("a&(cc|de)");
109    assertTrue(node instanceof NonLeafExpressionNode);
110    nlNode = (NonLeafExpressionNode) node;
111    assertEquals(Operator.AND, nlNode.getOperator());
112    assertEquals(2, nlNode.getChildExps().size());
113    assertEquals("a", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
114    assertTrue(nlNode.getChildExps().get(1) instanceof NonLeafExpressionNode);
115    nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(1);
116    assertEquals(Operator.OR, nlNode.getOperator());
117    assertEquals(2, nlNode.getChildExps().size());
118    assertEquals("cc", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
119    assertEquals("de", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
120
121    // (a&b)|c -> ((a & b) | c)
122    node = parser.parse("(a&b)|c");
123    assertTrue(node instanceof NonLeafExpressionNode);
124    nlNode = (NonLeafExpressionNode) node;
125    assertEquals(Operator.OR, nlNode.getOperator());
126    assertEquals(2, nlNode.getChildExps().size());
127    assertEquals("c", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
128    assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
129    nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
130    assertEquals(Operator.AND, nlNode.getOperator());
131    assertEquals(2, nlNode.getChildExps().size());
132    assertEquals("a", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
133    assertEquals("b", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
134
135    // (a&b&c)|d -> (((a & b) & c) | d)
136    node = parser.parse("(a&b&c)|d");
137    assertTrue(node instanceof NonLeafExpressionNode);
138    nlNode = (NonLeafExpressionNode) node;
139    assertEquals(Operator.OR, nlNode.getOperator());
140    assertEquals(2, nlNode.getChildExps().size());
141    assertEquals("d", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
142    assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
143    nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
144    assertEquals(Operator.AND, nlNode.getOperator());
145    assertEquals(2, nlNode.getChildExps().size());
146    assertEquals("c", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
147    assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
148    nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
149    assertEquals(Operator.AND, nlNode.getOperator());
150    assertEquals(2, nlNode.getChildExps().size());
151    assertEquals("b", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
152    assertEquals("a", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
153
154    // a&(b|(c|d)) -> (a & (b | (c | d)))
155    node = parser.parse("a&(b|(c|d))");
156    assertTrue(node instanceof NonLeafExpressionNode);
157    nlNode = (NonLeafExpressionNode) node;
158    assertEquals(Operator.AND, nlNode.getOperator());
159    assertEquals(2, nlNode.getChildExps().size());
160    assertEquals("a", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
161    assertTrue(nlNode.getChildExps().get(1) instanceof NonLeafExpressionNode);
162    nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(1);
163    assertEquals(Operator.OR, nlNode.getOperator());
164    assertEquals(2, nlNode.getChildExps().size());
165    assertEquals("b", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
166    assertTrue(nlNode.getChildExps().get(1) instanceof NonLeafExpressionNode);
167    nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(1);
168    assertEquals(Operator.OR, nlNode.getOperator());
169    assertEquals(2, nlNode.getChildExps().size());
170    assertEquals("c", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
171    assertEquals("d", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
172
173    // (!a) -> (!a)
174    node = parser.parse("(!a)");
175    assertTrue(node instanceof NonLeafExpressionNode);
176    nlNode = (NonLeafExpressionNode) node;
177    assertEquals(Operator.NOT, nlNode.getOperator());
178    assertEquals("a", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
179
180    // a&(!b) -> (a & (!b))
181    node = parser.parse("a&(!b)");
182    assertTrue(node instanceof NonLeafExpressionNode);
183    nlNode = (NonLeafExpressionNode) node;
184    assertEquals(Operator.AND, nlNode.getOperator());
185    assertEquals(2, nlNode.getChildExps().size());
186    assertEquals("a", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
187    assertTrue(nlNode.getChildExps().get(1) instanceof NonLeafExpressionNode);
188    nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(1);
189    assertEquals(Operator.NOT, nlNode.getOperator());
190    assertEquals(1, nlNode.getChildExps().size());
191    assertEquals("b", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
192
193    // !a&b -> ((!a) & b)
194    node = parser.parse("!a&b");
195    assertTrue(node instanceof NonLeafExpressionNode);
196    nlNode = (NonLeafExpressionNode) node;
197    assertEquals(Operator.AND, nlNode.getOperator());
198    assertEquals(2, nlNode.getChildExps().size());
199    assertEquals("b", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
200    assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
201    nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
202    assertEquals(Operator.NOT, nlNode.getOperator());
203    assertEquals(1, nlNode.getChildExps().size());
204    assertEquals("a", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
205
206    // !a&(!b) -> ((!a) & (!b))
207    node = parser.parse("!a&(!b)");
208    assertTrue(node instanceof NonLeafExpressionNode);
209    nlNode = (NonLeafExpressionNode) node;
210    assertEquals(Operator.AND, nlNode.getOperator());
211    assertEquals(2, nlNode.getChildExps().size());
212    assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
213    assertTrue(nlNode.getChildExps().get(1) instanceof NonLeafExpressionNode);
214    nlNodeLeft = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
215    nlNodeRight = (NonLeafExpressionNode) nlNode.getChildExps().get(1);
216    assertEquals(Operator.NOT, nlNodeLeft.getOperator());
217    assertEquals(1, nlNodeLeft.getChildExps().size());
218    assertEquals("a", ((LeafExpressionNode) nlNodeLeft.getChildExps().get(0)).getIdentifier());
219    assertEquals(Operator.NOT, nlNodeRight.getOperator());
220    assertEquals(1, nlNodeRight.getChildExps().size());
221    assertEquals("b", ((LeafExpressionNode) nlNodeRight.getChildExps().get(0)).getIdentifier());
222
223    // !a&!b -> ((!a) & (!b))
224    node = parser.parse("!a&!b");
225    assertTrue(node instanceof NonLeafExpressionNode);
226    nlNode = (NonLeafExpressionNode) node;
227    assertEquals(Operator.AND, nlNode.getOperator());
228    assertEquals(2, nlNode.getChildExps().size());
229    assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
230    assertTrue(nlNode.getChildExps().get(1) instanceof NonLeafExpressionNode);
231    nlNodeLeft = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
232    nlNodeRight = (NonLeafExpressionNode) nlNode.getChildExps().get(1);
233    assertEquals(Operator.NOT, nlNodeLeft.getOperator());
234    assertEquals(1, nlNodeLeft.getChildExps().size());
235    assertEquals("a", ((LeafExpressionNode) nlNodeLeft.getChildExps().get(0)).getIdentifier());
236    assertEquals(Operator.NOT, nlNodeRight.getOperator());
237    assertEquals(1, nlNodeRight.getChildExps().size());
238    assertEquals("b", ((LeafExpressionNode) nlNodeRight.getChildExps().get(0)).getIdentifier());
239
240    // !(a&b) -> (!(a & b))
241    node = parser.parse("!(a&b)");
242    assertTrue(node instanceof NonLeafExpressionNode);
243    nlNode = (NonLeafExpressionNode) node;
244    assertEquals(Operator.NOT, nlNode.getOperator());
245    assertEquals(1, nlNode.getChildExps().size());
246    nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
247    assertEquals(Operator.AND, nlNode.getOperator());
248    assertEquals(2, nlNode.getChildExps().size());
249    assertEquals("a", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
250    assertEquals("b", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
251
252    // a&!b -> (a & (!b))
253    node = parser.parse("a&!b");
254    assertTrue(node instanceof NonLeafExpressionNode);
255    nlNode = (NonLeafExpressionNode) node;
256    assertEquals(Operator.AND, nlNode.getOperator());
257    assertEquals(2, nlNode.getChildExps().size());
258    assertEquals("a", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
259    assertTrue(nlNode.getChildExps().get(1) instanceof NonLeafExpressionNode);
260    nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(1);
261    assertEquals(Operator.NOT, nlNode.getOperator());
262    assertEquals(1, nlNode.getChildExps().size());
263    assertEquals("b", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
264
265    // !((a|b)&!(c&!b)) -> (!((a | b) & (!(c & (!b)))))
266    node = parser.parse("!((a | b) & !(c & !b))");
267    assertTrue(node instanceof NonLeafExpressionNode);
268    nlNode = (NonLeafExpressionNode) node;
269    assertEquals(Operator.NOT, nlNode.getOperator());
270    assertEquals(1, nlNode.getChildExps().size());
271    nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
272    assertEquals(Operator.AND, nlNode.getOperator());
273    assertEquals(2, nlNode.getChildExps().size());
274    assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
275    assertTrue(nlNode.getChildExps().get(1) instanceof NonLeafExpressionNode);
276    nlNodeLeft = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
277    nlNodeRight = (NonLeafExpressionNode) nlNode.getChildExps().get(1);
278    assertEquals(Operator.OR, nlNodeLeft.getOperator());
279    assertEquals("a", ((LeafExpressionNode) nlNodeLeft.getChildExps().get(0)).getIdentifier());
280    assertEquals("b", ((LeafExpressionNode) nlNodeLeft.getChildExps().get(1)).getIdentifier());
281    assertEquals(Operator.NOT, nlNodeRight.getOperator());
282    assertEquals(1, nlNodeRight.getChildExps().size());
283    nlNodeRight = (NonLeafExpressionNode) nlNodeRight.getChildExps().get(0);
284    assertEquals(Operator.AND, nlNodeRight.getOperator());
285    assertEquals(2, nlNodeRight.getChildExps().size());
286    assertEquals("c", ((LeafExpressionNode) nlNodeRight.getChildExps().get(0)).getIdentifier());
287    assertTrue(nlNodeRight.getChildExps().get(1) instanceof NonLeafExpressionNode);
288    nlNodeRight = (NonLeafExpressionNode) nlNodeRight.getChildExps().get(1);
289    assertEquals(Operator.NOT, nlNodeRight.getOperator());
290    assertEquals(1, nlNodeRight.getChildExps().size());
291    assertEquals("b", ((LeafExpressionNode) nlNodeRight.getChildExps().get(0)).getIdentifier());
292  }
293
294  @Test
295  public void testNegativeCases() throws Exception {
296    executeNegativeCase("(");
297    executeNegativeCase(")");
298    executeNegativeCase("()");
299    executeNegativeCase("(a");
300    executeNegativeCase("a&");
301    executeNegativeCase("a&|b");
302    executeNegativeCase("!");
303    executeNegativeCase("a!");
304    executeNegativeCase("a!&");
305    executeNegativeCase("&");
306    executeNegativeCase("|");
307    executeNegativeCase("!(a|(b&c)&!b");
308    executeNegativeCase("!!a");
309    executeNegativeCase("( a & b ) | ( c & d e)");
310    executeNegativeCase("! a");
311  }
312
313  @Test
314  public void testNonAsciiCases() throws Exception {
315    ExpressionNode node =
316      parser.parse(CellVisibility.quote("\u0027") + "&" + CellVisibility.quote("\u002b") + "|"
317        + CellVisibility.quote("\u002d") + "&" + CellVisibility.quote("\u003f"));
318    assertTrue(node instanceof NonLeafExpressionNode);
319    NonLeafExpressionNode nlNode = (NonLeafExpressionNode) node;
320    assertEquals(Operator.AND, nlNode.getOperator());
321    assertEquals(2, nlNode.getChildExps().size());
322    assertEquals("\u003f", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
323    assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
324    nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
325    assertEquals(Operator.OR, nlNode.getOperator());
326    assertEquals(2, nlNode.getChildExps().size());
327    assertEquals("\u002d", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
328    assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
329    nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
330    assertEquals(Operator.AND, nlNode.getOperator());
331    assertEquals(2, nlNode.getChildExps().size());
332    assertEquals("\u002b", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
333    assertEquals("\u0027", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
334
335    node = parser.parse(CellVisibility.quote("\u0027") + "&" + CellVisibility.quote("\u002b") + "|"
336      + CellVisibility.quote("\u002d") + "&" + CellVisibility.quote("\u003f"));
337    assertTrue(node instanceof NonLeafExpressionNode);
338    nlNode = (NonLeafExpressionNode) node;
339    assertEquals(Operator.AND, nlNode.getOperator());
340    assertEquals(2, nlNode.getChildExps().size());
341    assertEquals("\u003f", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
342    assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
343    nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
344    assertEquals(Operator.OR, nlNode.getOperator());
345    assertEquals(2, nlNode.getChildExps().size());
346    assertEquals("\u002d", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
347    assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
348    nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
349    assertEquals(Operator.AND, nlNode.getOperator());
350    assertEquals(2, nlNode.getChildExps().size());
351    assertEquals("\u002b", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
352    assertEquals("\u0027", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
353  }
354
355  @Test
356  public void testCasesSeperatedByDoubleQuotes() throws Exception {
357    ExpressionNode node = null;
358    try {
359      node = parser.parse("\u0027&\"|\u002b&\u003f");
360      fail("Excpetion must be thrown as there are special characters without quotes");
361    } catch (ParseException e) {
362    }
363    node = parser.parse(CellVisibility.quote("\u0027") + "&" + CellVisibility.quote("\"") + "|"
364      + CellVisibility.quote("\u002b" + "&" + "\u003f"));
365    assertTrue(node instanceof NonLeafExpressionNode);
366    NonLeafExpressionNode nlNode = (NonLeafExpressionNode) node;
367    assertEquals(Operator.OR, nlNode.getOperator());
368    assertEquals(2, nlNode.getChildExps().size());
369    assertEquals("\u002b" + "&" + "\u003f",
370      ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
371    assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
372    nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
373    assertEquals(Operator.AND, nlNode.getOperator());
374    assertEquals(2, nlNode.getChildExps().size());
375    assertEquals("\"", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
376    assertEquals("\u0027", ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
377    try {
378      node = parser.parse(CellVisibility.quote("\u0027&\\") + "|"
379        + CellVisibility.quote("\u002b" + "&" + "\\") + CellVisibility.quote("$$\""));
380      fail("Excpetion must be thrown as there is not operator");
381    } catch (ParseException e) {
382    }
383    node = parser.parse(CellVisibility.quote("\u0027" + "&" + "\\") + "|"
384      + CellVisibility.quote("\u003f" + "&" + "\\") + "&" + CellVisibility.quote("$$\""));
385    assertTrue(node instanceof NonLeafExpressionNode);
386    nlNode = (NonLeafExpressionNode) node;
387    assertEquals(Operator.AND, nlNode.getOperator());
388    assertEquals(2, nlNode.getChildExps().size());
389    assertEquals("$$\"", ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
390    assertTrue(nlNode.getChildExps().get(0) instanceof NonLeafExpressionNode);
391    nlNode = (NonLeafExpressionNode) nlNode.getChildExps().get(0);
392    assertEquals(Operator.OR, nlNode.getOperator());
393    assertEquals(2, nlNode.getChildExps().size());
394    assertEquals("\u0027" + "&" + "\\",
395      ((LeafExpressionNode) nlNode.getChildExps().get(0)).getIdentifier());
396    assertEquals("\u003f" + "&" + "\\",
397      ((LeafExpressionNode) nlNode.getChildExps().get(1)).getIdentifier());
398    try {
399      node = parser.parse(
400        CellVisibility.quote("\u002b&\\") + "|" + CellVisibility.quote("\u0027&\\") + "&" + "\"$$");
401      fail("Excpetion must be thrown as there is no end quote");
402    } catch (ParseException e) {
403    }
404  }
405
406  private void executeNegativeCase(String exp) {
407    try {
408      parser.parse(exp);
409      fail("Expected ParseException for expression " + exp);
410    } catch (ParseException e) {
411    }
412  }
413}