@Test
public void testInfoFiltersParsing() throws Exception {

  String expr = "(((key11 ne 234 AND key12 eq val12) AND " +
      "(key13 ene val13 OR key14 eq 567)) OR (key21 eq val_21 OR key22 eq " +
      "5.0))";
  TimelineFilterList expectedList = new TimelineFilterList(
      Operator.OR,
      new TimelineFilterList(
          Operator.AND,
          new TimelineFilterList(
              Operator.AND,
              new TimelineKeyValueFilter(TimelineCompareOp.NOT_EQUAL,
                  "key11", 234, false),
              new TimelineKeyValueFilter(TimelineCompareOp.EQUAL,
                  "key12", "val12", true)
          ),
          new TimelineFilterList(
              Operator.OR,
              new TimelineKeyValueFilter(TimelineCompareOp.NOT_EQUAL,
                  "key13", "val13", true),
              new TimelineKeyValueFilter(TimelineCompareOp.EQUAL,
                  "key14", 567, true)
          )
      ),
      new TimelineFilterList(
          Operator.OR,
          new TimelineKeyValueFilter(TimelineCompareOp.EQUAL,
              "key21", "val_21", true),
          new TimelineKeyValueFilter(TimelineCompareOp.EQUAL,
              "key22", 5.0, true)
      )
  );
  verifyFilterList(expr, TimelineReaderWebServicesUtils.
      parseKVFilters(expr, false), expectedList);
  expr = "abc ne 234 AND def eq 23 OR rst ene 24 OR xyz eq 456 AND pqr eq " +
      "val.1234";
  expectedList = new TimelineFilterList(
      new TimelineFilterList(
          Operator.OR,
          new TimelineFilterList(
              new TimelineKeyValueFilter(TimelineCompareOp.NOT_EQUAL,
                  "abc", 234, false),
              new TimelineKeyValueFilter(TimelineCompareOp.EQUAL,
                  "def", 23, true)
          ),
          new TimelineKeyValueFilter(TimelineCompareOp.NOT_EQUAL,
              "rst", 24, true),
          new TimelineKeyValueFilter(TimelineCompareOp.EQUAL,
              "xyz", 456, true)
      ),
      new TimelineKeyValueFilter(TimelineCompareOp.EQUAL,
          "pqr", "val.1234", true)
  );
  verifyFilterList(expr, TimelineReaderWebServicesUtils.
      parseKVFilters(expr, false), expectedList);
  // Test with unnecessary spaces.
  expr = "  abc ne   234       AND       def           eq 23 OR     rst ene "+
      "           24     OR xyz     eq     456    AND pqr eq 2        ";
  expectedList = new TimelineFilterList(
      new TimelineFilterList(
          Operator.OR,
          new TimelineFilterList(
              new TimelineKeyValueFilter(TimelineCompareOp.NOT_EQUAL,
                  "abc", 234, false),
              new TimelineKeyValueFilter(TimelineCompareOp.EQUAL,
                  "def", 23, true)
          ),
          new TimelineKeyValueFilter(TimelineCompareOp.NOT_EQUAL,
              "rst", 24, true),
          new TimelineKeyValueFilter(TimelineCompareOp.EQUAL,
              "xyz", 456, true)
      ),
      new TimelineKeyValueFilter(TimelineCompareOp.EQUAL,
          "pqr", 2, true)
  );
  verifyFilterList(expr, TimelineReaderWebServicesUtils.
      parseKVFilters(expr, false), expectedList);
  expr = "abdeq";
  try {
    TimelineReaderWebServicesUtils.parseKVFilters(expr, false);
    Assert.fail("Expression valuation should throw exception.");
  } catch (TimelineParseException e) {
    // expected: do nothing
  }
  expr = "abc gt 234 AND defeq";
  try {
    TimelineReaderWebServicesUtils.parseKVFilters(expr, false);
    Assert.fail("Expression valuation should throw exception.");
  } catch (TimelineParseException e) {
    // expected: do nothing
  }
  expr = "((key11 ne 234 AND key12 eq val12) AND (key13eq OR key14 eq va14))";
  try {
    TimelineReaderWebServicesUtils.parseKVFilters(expr, false);
    Assert.fail("Expression valuation should throw exception.");
  } catch (TimelineParseException e) {
    // expected: do nothing
  }
}