// Copyright (C) 2019 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.testing.GerritJUnit.assertThrows;

import com.google.common.collect.ImmutableList;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeDataSource;
import com.google.gerrit.server.query.change.OrSource;
import java.util.Collection;
import java.util.Iterator;
import org.junit.Test;

/**
 * Tests that boolean data sources are lazy in that they don't call {@link ResultSet#toList()} or
 * {@link ResultSet#toList()}. This is necessary because it allows Gerrit to send multiple queries
 * to the index in parallel, have the results come in asynchronously and wait for them only when we
 * call aforementioned methods on the {@link ResultSet}.
 */
public class LazyDataSourceTest {

  /** Helper to avoid a mock which would be hard to create because of the type inference. */
  static class LazyPredicate extends Predicate<ChangeData> implements ChangeDataSource {
    @Override
    public int getCardinality() {
      return 1;
    }

    @Override
    public ResultSet<ChangeData> read() {
      return new FailingResultSet<>();
    }

    @Override
    public ResultSet<FieldBundle> readRaw() {
      return new FailingResultSet<>();
    }

    @Override
    public Predicate<ChangeData> copy(Collection<? extends Predicate<ChangeData>> children) {
      throw new UnsupportedOperationException("not implemented");
    }

    @Override
    public int hashCode() {
      throw new UnsupportedOperationException("not implemented");
    }

    @Override
    public boolean equals(Object other) {
      throw new UnsupportedOperationException("not implemented");
    }

    @Override
    public boolean hasChange() {
      throw new UnsupportedOperationException("not implemented");
    }
  }

  /** Implementation that throws {@link AssertionError} when accessing results. */
  static class FailingResultSet<T> implements ResultSet<T> {
    @Override
    public Iterator<T> iterator() {
      throw new AssertionError(
          "called iterator() on the result set, but shouldn't have because the data source must be"
              + " lazy");
    }

    @Override
    public ImmutableList<T> toList() {
      throw new AssertionError(
          "called toList() on the result set, but shouldn't have because the data source must be"
              + " lazy");
    }

    @Override
    public void close() {
      // No-op
    }

    @Override
    public Object searchAfter() {
      return null;
    }
  }

  @Test
  public void andSourceIsLazy() {
    AndSource<ChangeData> and =
        new AndSource<>(ImmutableList.of(new LazyPredicate()), IndexConfig.createDefault());
    ResultSet<ChangeData> resultSet = and.read();
    assertThrows(AssertionError.class, () -> resultSet.toList());
  }

  @Test
  public void orSourceIsLazy() {
    OrSource or = new OrSource(ImmutableList.of(new LazyPredicate()));
    ResultSet<ChangeData> resultSet = or.read();
    assertThrows(AssertionError.class, () -> resultSet.toList());
  }
}
