blob: 268c388f9ed50771f8d40bad5c41d576a3ce4787 [file] [log] [blame]
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.index.query;
import static com.google.gerrit.index.query.QueryParser.AND;
import static com.google.gerrit.index.query.QueryParser.COLON;
import static com.google.gerrit.index.query.QueryParser.DEFAULT_FIELD;
import static com.google.gerrit.index.query.QueryParser.EXACT_PHRASE;
import static com.google.gerrit.index.query.QueryParser.FIELD_NAME;
import static com.google.gerrit.index.query.QueryParser.NOT;
import static com.google.gerrit.index.query.QueryParser.OR;
import static com.google.gerrit.index.query.QueryParser.SINGLE_WORD;
import static com.google.gerrit.index.query.QueryParser.parse;
import static com.google.gerrit.index.query.testing.TreeSubject.assertThat;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import org.antlr.runtime.tree.Tree;
import org.junit.Test;
public class QueryParserTest {
@Test
public void fieldNameAndValue() throws Exception {
Tree r = parse("project:tools/gerrit");
assertThat(r).hasType(FIELD_NAME);
assertThat(r).hasText("project");
assertThat(r).hasChildCount(1);
assertThat(r).child(0).hasType(SINGLE_WORD);
assertThat(r).child(0).hasText("tools/gerrit");
assertThat(r).child(0).hasNoChildren();
}
@Test
public void fieldNameAndValueThatLooksLikeFieldNameColon() throws Exception {
// This should work, but doesn't due to a known issue.
assertParseFails("project:foo:");
}
@Test
public void fieldNameAndValueThatLooksLikeFieldNameColonValue() throws Exception {
Tree r = parse("project:foo:bar");
assertThat(r).hasType(FIELD_NAME);
assertThat(r).hasText("project");
assertThat(r).hasChildCount(3);
assertThat(r).child(0).hasType(SINGLE_WORD);
assertThat(r).child(0).hasText("foo");
assertThat(r).child(0).hasNoChildren();
assertThat(r).child(1).hasType(COLON);
assertThat(r).child(1).hasText(":");
assertThat(r).child(1).hasNoChildren();
assertThat(r).child(2).hasType(SINGLE_WORD);
assertThat(r).child(2).hasText("bar");
assertThat(r).child(2).hasNoChildren();
}
@Test
public void fieldNameAndValueThatLooksLikeWordColonValue() throws Exception {
Tree r = parse("project:x*y:a*b");
assertThat(r).hasType(FIELD_NAME);
assertThat(r).hasText("project");
assertThat(r).hasChildCount(3);
assertThat(r).child(0).hasType(SINGLE_WORD);
assertThat(r).child(0).hasText("x*y");
assertThat(r).child(0).hasNoChildren();
assertThat(r).child(1).hasType(COLON);
assertThat(r).child(1).hasText(":");
assertThat(r).child(1).hasNoChildren();
assertThat(r).child(2).hasType(SINGLE_WORD);
assertThat(r).child(2).hasText("a*b");
assertThat(r).child(2).hasNoChildren();
}
@Test
public void fieldNameAndValueThatLooksLikeWordColon() throws Exception {
// This should work, but doesn't due to a known issue.
assertParseFails("project:x*y:");
}
@Test
public void fieldNameAndValueWithMultipleColons() throws Exception {
Tree r = parse("project:*:*:*");
assertThat(r).hasType(FIELD_NAME);
assertThat(r).hasText("project");
assertThat(r).hasChildCount(5);
assertThat(r).child(0).hasType(SINGLE_WORD);
assertThat(r).child(0).hasText("*");
assertThat(r).child(0).hasNoChildren();
assertThat(r).child(1).hasType(COLON);
assertThat(r).child(1).hasText(":");
assertThat(r).child(1).hasNoChildren();
assertThat(r).child(2).hasType(SINGLE_WORD);
assertThat(r).child(2).hasText("*");
assertThat(r).child(2).hasNoChildren();
assertThat(r).child(3).hasType(COLON);
assertThat(r).child(3).hasText(":");
assertThat(r).child(3).hasNoChildren();
assertThat(r).child(4).hasType(SINGLE_WORD);
assertThat(r).child(4).hasText("*");
assertThat(r).child(4).hasNoChildren();
}
@Test
public void fieldNameAndValueWithColonFollowedByAnotherField() throws Exception {
Tree r = parse("project:foo:bar file:baz");
assertThat(r).hasType(AND);
assertThat(r).hasChildCount(2);
assertThat(r).child(0).hasType(FIELD_NAME);
assertThat(r).child(0).hasText("project");
assertThat(r).child(0).hasChildCount(3);
assertThat(r).child(0).child(0).hasType(SINGLE_WORD);
assertThat(r).child(0).child(0).hasText("foo");
assertThat(r).child(0).child(0).hasNoChildren();
assertThat(r).child(0).child(1).hasType(COLON);
assertThat(r).child(0).child(1).hasText(":");
assertThat(r).child(0).child(1).hasNoChildren();
assertThat(r).child(0).child(2).hasType(SINGLE_WORD);
assertThat(r).child(0).child(2).hasText("bar");
assertThat(r).child(0).child(2).hasNoChildren();
assertThat(r).child(1).hasType(FIELD_NAME);
assertThat(r).child(1).hasText("file");
assertThat(r).child(1).hasChildCount(1);
assertThat(r).child(1).child(0).hasType(SINGLE_WORD);
assertThat(r).child(1).child(0).hasText("baz");
assertThat(r).child(1).child(0).hasNoChildren();
}
@Test
public void fieldNameAndValueWithColonFollowedByOpenParen() throws Exception {
Tree r = parse("project:foo:bar (file:baz)");
assertThat(r).hasType(AND);
assertThat(r).hasChildCount(2);
assertThat(r).child(0).hasType(FIELD_NAME);
assertThat(r).child(0).hasText("project");
assertThat(r).child(0).hasChildCount(3);
assertThat(r).child(0).child(0).hasType(SINGLE_WORD);
assertThat(r).child(0).child(0).hasText("foo");
assertThat(r).child(0).child(0).hasNoChildren();
assertThat(r).child(0).child(1).hasType(COLON);
assertThat(r).child(0).child(1).hasText(":");
assertThat(r).child(0).child(1).hasNoChildren();
assertThat(r).child(0).child(2).hasType(SINGLE_WORD);
assertThat(r).child(0).child(2).hasText("bar");
assertThat(r).child(0).child(2).hasNoChildren();
assertThat(r).child(1).hasType(FIELD_NAME);
assertThat(r).child(1).hasText("file");
assertThat(r).child(1).hasChildCount(1);
assertThat(r).child(1).child(0).hasType(SINGLE_WORD);
assertThat(r).child(1).child(0).hasText("baz");
assertThat(r).child(1).child(0).hasNoChildren();
}
@Test
public void fieldNameAndValueWithColonFollowedByCloseParen() throws Exception {
Tree r = parse("(project:foo:bar) file:baz");
assertThat(r).hasType(AND);
assertThat(r).hasChildCount(2);
assertThat(r).child(0).hasType(FIELD_NAME);
assertThat(r).child(0).hasText("project");
assertThat(r).child(0).hasChildCount(3);
assertThat(r).child(0).child(0).hasType(SINGLE_WORD);
assertThat(r).child(0).child(0).hasText("foo");
assertThat(r).child(0).child(0).hasNoChildren();
assertThat(r).child(0).child(1).hasType(COLON);
assertThat(r).child(0).child(1).hasText(":");
assertThat(r).child(0).child(1).hasNoChildren();
assertThat(r).child(0).child(2).hasType(SINGLE_WORD);
assertThat(r).child(0).child(2).hasText("bar");
assertThat(r).child(0).child(2).hasNoChildren();
assertThat(r).child(1).hasType(FIELD_NAME);
assertThat(r).child(1).hasText("file");
assertThat(r).child(1).hasChildCount(1);
assertThat(r).child(1).child(0).hasType(SINGLE_WORD);
assertThat(r).child(1).child(0).hasText("baz");
assertThat(r).child(1).child(0).hasNoChildren();
}
@Test
public void defaultFieldWithColon() throws Exception {
Tree r = parse("CodeReview:+2");
assertThat(r).hasType(DEFAULT_FIELD);
assertThat(r).hasChildCount(3);
assertThat(r).child(0).hasType(SINGLE_WORD);
assertThat(r).child(0).hasText("CodeReview");
assertThat(r).child(0).hasNoChildren();
assertThat(r).child(1).hasType(COLON);
assertThat(r).child(1).hasText(":");
assertThat(r).child(1).hasNoChildren();
assertThat(r).child(2).hasType(SINGLE_WORD);
assertThat(r).child(2).hasText("+2");
assertThat(r).child(2).hasNoChildren();
}
@Test
public void fieldNameWithEscapedDoubleQuotesInValue() throws Exception {
// Actual String: A \"special\" word
String search = "message:\"A \\\"special\\\" word\"";
Tree r = parse(search);
assertThat(r).hasType(FIELD_NAME);
assertThat(r).hasChildCount(1);
assertThat(r).hasText("message");
assertThat(r).child(0).hasType(EXACT_PHRASE);
// Antlr escaped the double quotes in the phrase.
assertThat(r).child(0).hasText("A \"special\" word");
}
@Test
public void fieldNameWithEscapedTabCharacterIsPreserved() throws Exception {
String[] searches = {"message:\"A \\t word\"", "message:{A \\t word}"};
for (String search : searches) {
Tree r = parse(search);
assertThat(r).hasType(FIELD_NAME);
assertThat(r).hasChildCount(1);
assertThat(r).hasText("message");
assertThat(r).child(0).hasType(EXACT_PHRASE);
assertThat(r).child(0).hasText("A \t word");
}
}
@Test
public void fieldNameWithEscapedBackslashIsIncludedInOutput() throws Exception {
String search = "message:\"A backslash \\\\ in phrase\"";
Tree r = parse(search);
assertThat(r).hasType(FIELD_NAME);
assertThat(r).hasChildCount(1);
assertThat(r).hasText("message");
assertThat(r).child(0).hasType(EXACT_PHRASE);
assertThat(r).child(0).hasText("A backslash \\ in phrase");
}
@Test
public void upperCaseParsedAsOperators() throws Exception {
Tree r = parse("project:foo:bar AND file:baz");
assertThat(r).hasType(AND);
assertThat(r).hasChildCount(2);
r = parse("project:foo:bar OR file:baz");
assertThat(r).hasType(OR);
assertThat(r).hasChildCount(2);
r = parse("NOT project:foo:bar");
assertThat(r).hasType(NOT);
assertThat(r).hasChildCount(1);
}
@Test
public void lowerCaseParsedAsOperators() throws Exception {
Tree r = parse("project:foo:bar and file:baz");
assertThat(r).hasType(AND);
assertThat(r).hasChildCount(2);
r = parse("project:foo:bar or file:baz");
assertThat(r).hasType(OR);
assertThat(r).hasChildCount(2);
r = parse("not project:foo:bar");
assertThat(r).hasType(NOT);
assertThat(r).hasChildCount(1);
}
@Test
public void fieldNameWithNot() throws Exception {
Tree r = parse("-foo:bar");
assertThat(r).hasType(NOT);
assertThat(r).hasText("NOT");
assertThat(r).hasChildCount(1);
assertThat(r).child(0).hasType(FIELD_NAME);
assertThat(r).child(0).hasText("foo");
assertThat(r).child(0).hasChildCount(1);
assertThat(r).child(0).child(0).hasType(SINGLE_WORD);
assertThat(r).child(0).child(0).hasText("bar");
assertThat(r).child(0).child(0).hasNoChildren();
}
@Test
public void fieldNameWithDigit() throws Exception {
Tree r = parse("foo9:bar");
assertThat(r).hasType(DEFAULT_FIELD);
assertThat(r).hasChildCount(3);
assertThat(r).child(0).hasType(SINGLE_WORD);
assertThat(r).child(0).hasText("foo9");
assertThat(r).child(0).hasNoChildren();
assertThat(r).child(1).hasType(COLON);
assertThat(r).child(1).hasText(":");
assertThat(r).child(1).hasNoChildren();
assertThat(r).child(2).hasType(SINGLE_WORD);
assertThat(r).child(2).hasText("bar");
assertThat(r).child(2).hasNoChildren();
}
@Test
public void fieldNameWithUnderscore() throws Exception {
Tree r = parse("foo_bar:baz");
assertThat(r).hasType(FIELD_NAME);
assertThat(r).hasText("foo_bar");
assertThat(r).hasChildCount(1);
assertThat(r).child(0).hasType(SINGLE_WORD);
assertThat(r).child(0).hasText("baz");
assertThat(r).child(0).hasNoChildren();
}
@Test
public void fieldNameWithHyphen() throws Exception {
Tree r = parse("foo-bar:baz");
assertThat(r).hasType(FIELD_NAME);
assertThat(r).hasText("foo-bar");
assertThat(r).hasChildCount(1);
assertThat(r).child(0).hasType(SINGLE_WORD);
assertThat(r).child(0).hasText("baz");
assertThat(r).child(0).hasNoChildren();
}
@Test
public void fieldNameEndingWithHyphen() throws Exception {
Tree r = parse("foo-:bar");
assertThat(r).hasType(DEFAULT_FIELD);
assertThat(r).hasChildCount(3);
assertThat(r).child(0).hasType(SINGLE_WORD);
assertThat(r).child(0).hasText("foo-");
assertThat(r).child(0).hasNoChildren();
assertThat(r).child(1).hasType(COLON);
assertThat(r).child(1).hasText(":");
assertThat(r).child(1).hasNoChildren();
assertThat(r).child(2).hasType(SINGLE_WORD);
assertThat(r).child(2).hasText("bar");
assertThat(r).child(2).hasNoChildren();
}
@Test
public void fieldNameWithNotAndHyphen() throws Exception {
Tree r = parse("-foo-bar:baz");
assertThat(r).hasType(NOT);
assertThat(r).hasText("NOT");
assertThat(r).hasChildCount(1);
assertThat(r).child(0).hasType(FIELD_NAME);
assertThat(r).child(0).hasText("foo-bar");
assertThat(r).child(0).hasChildCount(1);
assertThat(r).child(0).child(0).hasType(SINGLE_WORD);
assertThat(r).child(0).child(0).hasText("baz");
assertThat(r).child(0).child(0).hasNoChildren();
}
@Test
public void fieldNameWithNotAndEndingWithHyphen() throws Exception {
Tree r = parse("-foo-bar-:baz");
assertThat(r).hasType(NOT);
assertThat(r).hasChildCount(1);
assertThat(r).child(0).hasType(DEFAULT_FIELD);
assertThat(r).child(0).hasChildCount(3);
assertThat(r).child(0).child(0).hasType(SINGLE_WORD);
assertThat(r).child(0).child(0).hasText("foo-bar-");
assertThat(r).child(0).child(0).hasNoChildren();
assertThat(r).child(0).child(1).hasType(COLON);
assertThat(r).child(0).child(1).hasText(":");
assertThat(r).child(0).child(1).hasNoChildren();
assertThat(r).child(0).child(2).hasType(SINGLE_WORD);
assertThat(r).child(0).child(2).hasText("baz");
assertThat(r).child(0).child(2).hasNoChildren();
}
@Test
public void fieldNameWithMiscellaneousCharacters() throws Exception {
Tree r = parse("-foo-bar_-baz_:qux");
assertThat(r).hasType(NOT);
assertThat(r).hasChildCount(1);
assertThat(r).child(0).hasType(FIELD_NAME);
assertThat(r).child(0).hasText("foo-bar_-baz_");
assertThat(r).child(0).hasChildCount(1);
assertThat(r).child(0).child(0).hasType(SINGLE_WORD);
assertThat(r).child(0).child(0).hasText("qux");
assertThat(r).child(0).child(0).hasNoChildren();
}
private static void assertParseFails(String query) {
assertThrows(QueryParseException.class, () -> parse(query));
}
}