@@ -0,0 +1,2731 @@
+// Copyright (C) 2019 The Android Open Source Project%0A//%0A// Licensed under the Apache License, Version 2.0 (the %22License%22);%0A// you may not use this file except in compliance with the License.%0A// You may obtain a copy of the License at%0A//%0A// http://www.apache.org/licenses/LICENSE-2.0%0A//%0A// Unless required by applicable law or agreed to in writing, software%0A// distributed under the License is distributed on an %22AS IS%22 BASIS,%0A// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.%0A// See the License for the specific language governing permissions and%0A// limitations under the License.%0A%0Apackage com.google.gerrit.index.query;%0A%0Aimport static com.google.common.truth.Truth.assertThat;%0A%0Aimport com.google.common.truth.ThrowableSubject;%0Aimport com.google.gerrit.testing.GerritBaseTests;%0Aimport java.util.Collection;%0Aimport java.util.Objects;%0Aimport org.junit.Test;%0A%0Apublic class QueryBuilderTest extends GerritBaseTests %7B%0A  private static class TestPredicate extends Predicate%3CObject%3E %7B%0A    private final String field;%0A    private final String value;%0A%0A    TestPredicate(String field, String value) %7B%0A      this.field = field;%0A      this.value = value;%0A    %7D%0A%0A    @Override%0A    public Predicate%3CObject%3E copy(Collection%3C? extends Predicate%3CObject%3E%3E children) %7B%0A      throw new UnsupportedOperationException();%0A    %7D%0A%0A    @Override%0A    public int hashCode() %7B%0A      return Objects.hash(field, value);%0A    %7D%0A%0A    @Override%0A    public boolean equals(Object o) %7B%0A      if (!(o instanceof TestPredicate)) %7B%0A        return false;%0A      %7D%0A      TestPredicate p = (TestPredicate) o;%0A      return Objects.equals(field, p.field) && Objects.equals(value, p.value);%0A    %7D%0A  %7D%0A%0A  private static class TestQueryBuilder extends QueryBuilder%3CObject%3E %7B%0A    TestQueryBuilder() %7B%0A      super(new QueryBuilder.Definition%3C%3E(TestQueryBuilder.class));%0A    %7D%0A%0A    @Operator%0A    public Predicate%3CObject%3E a(String value) %7B%0A      return new TestPredicate(%22a%22, value);%0A    %7D%0A  %7D%0A%0A  @Test%0A  public void fieldNameAndValue() throws Exception %7B%0A    assertThat(parse(%22a:foo%22)).isEqualTo(new TestPredicate(%22a%22, %22foo%22));%0A  %7D%0A%0A  @Test%0A  public void fieldWithParenthesizedValues() throws Exception %7B%0A    assertThatParseException(%22a:(foo bar)%22)%0A        .hasMessageThat()%0A        .isEqualTo(%22line 1:2 no viable alternative at input '('%22);%0A  %7D%0A%0A  private static Predicate%3CObject%3E parse(String query) throws Exception %7B%0A    return new TestQueryBuilder().parse(query);%0A  %7D%0A%0A  private static ThrowableSubject assertThatParseException(String query) %7B%0A    try %7B%0A      new TestQueryBuilder().parse(query);%0A      throw new AssertionError(%22expected QueryParseException for %22 + query);%0A    %7D catch (QueryParseException e) %7B%0A      return assertThat(e);%0A    %7D%0A  %7D%0A%7D%0A

Add simple test of index-agnostic QueryBuilder