// Copyright (C) 2017 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.ericsson.gerrit.plugins.gcconductor.postgresqueue;

import static com.ericsson.gerrit.plugins.gcconductor.postgresqueue.TestUtil.configMockFor;
import static com.ericsson.gerrit.plugins.gcconductor.postgresqueue.TestUtil.deleteDatabase;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.ericsson.gerrit.plugins.gcconductor.GcQueueException;
import com.ericsson.gerrit.plugins.gcconductor.RepositoryInfo;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import org.apache.commons.dbcp.BasicDataSource;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class PostgresQueueTest {

  private static final String TEST_DATABASE_NAME = "gc_test_queue";
  private BasicDataSource dataSource;
  private PostgresQueue queue;

  @Before
  public void setUp() throws SQLException {
    dataSource =
        new PostgresModule(null).provideGcDatabaseAccess(configMockFor(TEST_DATABASE_NAME));
    queue = new PostgresQueue(dataSource);
  }

  @After
  public void tearDown() throws SQLException {
    if (dataSource != null) {
      dataSource.close();
    }
    deleteDatabase(TEST_DATABASE_NAME);
  }

  @Test
  public void shouldCreateSchemaOnInit() throws GcQueueException {
    assertThat(queue.list()).isEmpty();
  }

  @Test(expected = SQLException.class)
  public void shouldThrowExceptionIfFailsToCreateSchemaOnInit() throws Exception {
    BasicDataSource dataSouceMock = mock(BasicDataSource.class);
    when(dataSouceMock.getConnection()).thenThrow(new SQLException("some message"));
    queue = new PostgresQueue(dataSouceMock);
  }

  @Test
  public void testAddContainsAndRemove() throws GcQueueException {
    String repoPath = "/some/path/to/some/repository";
    String hostname = "someHostname";

    assertThat(queue.list()).isEmpty();
    assertThat(queue.contains(repoPath)).isFalse();

    queue.add(repoPath, hostname);
    assertThat(queue.list().size()).isEqualTo(1);
    assertThat(queue.contains(repoPath)).isTrue();

    queue.add(repoPath, hostname);
    assertThat(queue.list().size()).isEqualTo(1);
    assertThat(queue.contains(repoPath)).isTrue();

    String repoPath2 = "/some/path/to/some/repository2";
    String hostname2 = "someHostname2";

    queue.add(repoPath2, hostname2);
    assertThat(queue.list().size()).isEqualTo(2);
    assertThat(queue.contains(repoPath)).isTrue();
    assertThat(queue.contains(repoPath2)).isTrue();

    queue.remove(repoPath2);
    assertThat(queue.list().size()).isEqualTo(1);
    assertThat(queue.contains(repoPath)).isTrue();
    assertThat(queue.contains(repoPath2)).isFalse();

    queue.remove(repoPath);
    assertThat(queue.list().size()).isEqualTo(0);
    assertThat(queue.contains(repoPath)).isFalse();

    queue.remove(repoPath);
    assertThat(queue.list().size()).isEqualTo(0);
    assertThat(queue.contains(repoPath)).isFalse();
  }

  @Test(expected = GcQueueException.class)
  public void testAddThatFailsWhenGettingConnection() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenGettingConnection());
    queue.add("repo", "hostname");
  }

  @Test(expected = GcQueueException.class)
  public void testAddThatFailsWhenCreatingStatement() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenCreatingStatement());
    queue.add("repo", "hostname");
  }

  @Test(expected = GcQueueException.class)
  public void testAddThatFailsWhenExecutingQuery() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenExecutingQuery());
    queue.add("repo", "hostname");
  }

  @Test(expected = GcQueueException.class)
  public void testContainsThatFailsWhenGettingConnection() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenGettingConnection());
    queue.contains("repo");
  }

  @Test(expected = GcQueueException.class)
  public void testContainsThatFailsWhenCreatingStatement() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenCreatingStatement());
    queue.contains("repo");
  }

  @Test(expected = GcQueueException.class)
  public void testContainsThatFailsWhenExecutingQuery() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenExecutingQuery());
    queue.contains("repo");
  }

  @Test(expected = GcQueueException.class)
  public void testContainsThatFailsWhenIteratingResults() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenIteratingResults());
    queue.contains("repo");
  }

  @Test(expected = GcQueueException.class)
  public void testRemoveThatFailsWhenGettingConnection() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenGettingConnection());
    queue.remove("repo");
  }

  @Test(expected = GcQueueException.class)
  public void testRemoveThatFailsWhenCreatingStatement() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenCreatingStatement());
    queue.remove("repo");
  }

  @Test(expected = GcQueueException.class)
  public void testRemoveThatFailsWhenExecutingQuery() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenExecutingQuery());
    queue.remove("repo");
  }

  @Test
  public void testList() throws GcQueueException {
    String repoPath = "/some/path/to/some/repository.git";
    String repoPath2 = "/some/path/to/some/repository2.git";
    String hostname = "hostname";
    String executor = "hostname-1";

    assertThat(queue.list()).isEmpty();
    Timestamp before = new Timestamp(System.currentTimeMillis());
    queue.add(repoPath, hostname);
    queue.add(repoPath2, hostname);
    queue.pick(executor, 0, Optional.empty());

    assertThat(queue.list().size()).isEqualTo(2);

    assertThat(queue.list().get(0).getPath()).isEqualTo(repoPath);
    assertThat(queue.list().get(0).getExecutor()).isEqualTo(executor);
    assertThat(queue.list().get(0).getQueuedAt()).isAtLeast(before);
    assertThat(queue.list().get(0).getQueuedAt())
        .isAtMost(new Timestamp(System.currentTimeMillis()));
    assertThat(queue.list().get(0).getQueuedFrom()).isEqualTo(hostname);

    assertThat(queue.list().get(1).getPath()).isEqualTo(repoPath2);
    assertThat(queue.list().get(1).getExecutor()).isNull();
    assertThat(queue.list().get(1).getQueuedAt()).isAtLeast(queue.list().get(0).getQueuedAt());
    assertThat(queue.list().get(1).getQueuedAt())
        .isAtMost(new Timestamp(System.currentTimeMillis()));
    assertThat(queue.list().get(1).getQueuedFrom()).isEqualTo(hostname);
  }

  @Test(expected = GcQueueException.class)
  public void testListThatFailsWhenGettingConnection() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenGettingConnection());
    queue.list();
  }

  @Test(expected = GcQueueException.class)
  public void testListThatFailsWhenCreatingStatement() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenCreatingStatement());
    queue.list();
  }

  @Test(expected = GcQueueException.class)
  public void testListThatFailsWhenExecutingQuery() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenExecutingQuery());
    queue.list();
  }

  @Test(expected = GcQueueException.class)
  public void testListThatFailsWhenIteratingResults() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenIteratingResults());
    queue.list();
  }

  @Test
  public void testPick() throws GcQueueException {
    String repoPath = "/some/path/to/some/repository";
    String hostname = "someHostname";
    String executor = "someExecutor";
    String executor2 = "someExecutor2";

    // queue is empty nothing to pick
    assertThat(queue.list()).isEmpty();
    assertThat(queue.pick(executor, 0, Optional.empty())).isNull();

    // queue contains 1 repository, should pick that one
    queue.add(repoPath, hostname);
    RepositoryInfo picked = queue.pick(executor, 0, Optional.empty());
    assertThat(picked).isNotNull();
    assertThat(picked.getPath()).isEqualTo(repoPath);
    assertThat(picked.getExecutor()).isEqualTo(executor);

    // queue contains 1 already picked repository, should pick same one
    picked = queue.pick(executor, 0, Optional.empty());
    assertThat(picked).isNotNull();
    assertThat(picked.getPath()).isEqualTo(repoPath);
    assertThat(picked.getExecutor()).isEqualTo(executor);

    // queue contains 1 already picked repository, nothing to pick for other
    // executors
    assertThat(queue.pick(executor2, 0, Optional.empty())).isNull();
  }

  @Test
  public void testPickRepositoriesInOrder() throws GcQueueException {
    String repositoryFormat = "my/path%s.git";
    for (int i = 0; i < 100; i++) {
      queue.add(String.format(repositoryFormat, i), "someHostname");
    }
    for (int i = 0; i < 100; i++) {
      String pickedRepo = queue.pick("someExecutor", 0, Optional.empty()).getPath();
      assertThat(pickedRepo).isEqualTo(String.format(repositoryFormat, i));
      queue.remove(pickedRepo);
    }
  }

  @Test
  public void testPickInQueueForLongerThan() throws GcQueueException, InterruptedException {
    String repoPath = "/some/path/to/some/repository";
    String hostname = "someHostname";
    String executor = "someExecutor";

    // pick repository older than 10 seconds, nothing to pick
    queue.add(repoPath, hostname);
    assertThat(queue.pick(executor, 10, Optional.empty())).isNull();
    assertThat(queue.list().get(0).getExecutor()).isNull();

    // make 2 seconds elapse and pick repository older than 1 second, should pick one
    TimeUnit.SECONDS.sleep((2));
    RepositoryInfo picked = queue.pick(executor, 1, Optional.empty());
    assertThat(picked.getPath()).isEqualTo(repoPath);
    assertThat(picked.getExecutor()).isEqualTo(executor);
  }

  @Test
  public void testPickQueuedFrom() throws GcQueueException {
    String repoPath = "/some/path/to/some/repository";
    String hostname = "hostname";
    String otherHostname = "otherHostname";
    String executor = "hostname-1";

    // pick repository queued from otherHostname, nothing to pick
    queue.add(repoPath, hostname);
    assertThat(queue.pick(executor, 0, Optional.of(otherHostname))).isNull();
    assertThat(queue.list().get(0).getExecutor()).isNull();

    // pick repository queued from hostname, should pick one
    RepositoryInfo picked = queue.pick(executor, 0, Optional.of(hostname));
    assertThat(picked.getPath()).isEqualTo(repoPath);
    assertThat(picked.getExecutor()).isEqualTo(executor);
  }

  @Test(expected = GcQueueException.class)
  public void testPickThatFailsWhenGettingConnection() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenGettingConnection());
    queue.pick("executor", 0, Optional.empty());
  }

  @Test(expected = GcQueueException.class)
  public void testPickThatFailsWhenCreatingStatement() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenCreatingStatement());
    queue.pick("executor", 0, Optional.empty());
  }

  @Test(expected = GcQueueException.class)
  public void testPickThatFailsWhenExecutingQuery() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenExecutingQuery());
    queue.pick("executor", 0, Optional.empty());
  }

  @Test(expected = GcQueueException.class)
  public void testPickThatFailsWhenIteratingResults() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenIteratingResults());
    queue.pick("executor", 0, Optional.empty());
  }

  @Test
  public void testUnpick() throws GcQueueException {
    String repoPath = "/some/path/to/some/repository";
    String hostname = "someHostname";
    String executor = "someExecutor";

    // queue contains 1 repository, should pick that one
    queue.add(repoPath, hostname);
    RepositoryInfo picked = queue.pick(executor, 0, Optional.empty());
    assertThat(picked.getPath()).isEqualTo(repoPath);
    assertThat(picked.getExecutor()).isEqualTo(executor);

    queue.unpick(repoPath);
    // unpick repo so should pick that one again
    queue.unpick(repoPath);
    picked = queue.pick(executor, 0, Optional.empty());
    assertThat(picked.getPath()).isEqualTo(repoPath);
    assertThat(picked.getExecutor()).isEqualTo(executor);
  }

  @Test(expected = GcQueueException.class)
  public void testUnpickThatFailsWhenGettingConnection() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenGettingConnection());
    queue.unpick("/some/path/to/some/repository.git");
  }

  @Test(expected = GcQueueException.class)
  public void testUnpickFailsWhenCreatingStatement() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenCreatingStatement());
    queue.unpick("/some/path/to/some/repository.git");
  }

  @Test(expected = GcQueueException.class)
  public void testUnpickThatFailsWhenExecutingQuery() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenExecutingQuery());
    queue.unpick("/some/path/to/some/repository.git");
  }

  @Test
  public void testResetQueuedFrom() throws GcQueueException {
    String repoPath = "/some/path/to/some/repository";
    String repoPath2 = "/some/path/to/some/repository2";
    String hostname = "hostname";
    String otherHostname = "otherHostname";

    queue.add(repoPath, hostname);
    queue.add(repoPath2, hostname);
    assertThat(queue.list().get(0).getQueuedFrom()).isEqualTo(hostname);
    assertThat(queue.list().get(1).getQueuedFrom()).isEqualTo(hostname);

    queue.resetQueuedFrom(otherHostname);
    assertThat(queue.list().get(0).getQueuedFrom()).isEqualTo(otherHostname);
    assertThat(queue.list().get(1).getQueuedFrom()).isEqualTo(otherHostname);
  }

  @Test(expected = GcQueueException.class)
  public void testResetQueuedFromThatFailsWhenGettingConnection() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenGettingConnection());
    queue.resetQueuedFrom("someHostname");
  }

  @Test(expected = GcQueueException.class)
  public void testResetQueuedFromFailsWhenCreatingStatement() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenCreatingStatement());
    queue.resetQueuedFrom("someHostname");
  }

  @Test(expected = GcQueueException.class)
  public void testResetQueuedFromThatFailsWhenExecutingQuery() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenExecutingQuery());
    queue.resetQueuedFrom("someHostname");
  }

  @Test
  public void testBumpToFirst() throws GcQueueException {
    String repoPath = "/some/path/to/some/repository";
    String repoPath2 = "/some/path/to/some/repository2";
    String repoPath3 = "/some/path/to/some/repository3";
    String hostname = "hostname";

    // Queue contains 1 repository, bumping should have no effect
    queue.add(repoPath, hostname);
    assertThat(queue.list().get(0).getPath()).isEqualTo(repoPath);
    queue.bumpToFirst(repoPath);
    assertThat(queue.list().get(0).getPath()).isEqualTo(repoPath);

    // Queue has 3 repositories, should be able to change their order
    queue.add(repoPath2, hostname);
    queue.add(repoPath3, hostname);
    assertThat(queue.list().get(1).getPath()).isEqualTo(repoPath2);
    assertThat(queue.list().get(2).getPath()).isEqualTo(repoPath3);

    // repoPath3 should be first, all other repositories should be shifted down
    queue.bumpToFirst(repoPath3);
    assertThat(queue.list().get(0).getPath()).isEqualTo(repoPath3);
    assertThat(queue.list().get(1).getPath()).isEqualTo(repoPath);
    assertThat(queue.list().get(2).getPath()).isEqualTo(repoPath2);

    // Bumping a repository that is already first priority should have no effect
    queue.bumpToFirst(repoPath3);
    assertThat(queue.list().get(0).getPath()).isEqualTo(repoPath3);
    assertThat(queue.list().get(1).getPath()).isEqualTo(repoPath);
    assertThat(queue.list().get(2).getPath()).isEqualTo(repoPath2);
  }

  @Test(expected = GcQueueException.class)
  public void testBumpToFirstThatFailsWhenGettingConnection() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenGettingConnection());
    queue.bumpToFirst("someHostname");
  }

  @Test(expected = GcQueueException.class)
  public void testBumpToFirstFailsWhenCreatingStatement() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenCreatingStatement());
    queue.bumpToFirst("someHostname");
  }

  @Test(expected = GcQueueException.class)
  public void testBumpToFirstThatFailsWhenExecutingQuery() throws Exception {
    queue = new PostgresQueue(createDataSourceThatFailsWhenExecutingQuery());
    queue.bumpToFirst("someHostname");
  }

  private BasicDataSource createDataSourceThatFailsWhenGettingConnection() throws SQLException {
    BasicDataSource dataSouceMock = mock(BasicDataSource.class);
    Connection connectionMock = mock(Connection.class);
    Statement statementMock = mock(Statement.class);

    when(dataSouceMock.getConnection()).thenReturn(connectionMock).thenThrow(new SQLException());
    when(connectionMock.createStatement()).thenReturn(statementMock);

    return dataSouceMock;
  }

  private BasicDataSource createDataSourceThatFailsWhenCreatingStatement() throws SQLException {
    BasicDataSource dataSouceMock = mock(BasicDataSource.class);
    Connection connectionMock = mock(Connection.class);
    Statement statementMock = mock(Statement.class);

    when(dataSouceMock.getConnection()).thenReturn(connectionMock);
    when(connectionMock.createStatement()).thenReturn(statementMock).thenThrow(new SQLException());

    return dataSouceMock;
  }

  private BasicDataSource createDataSourceThatFailsWhenExecutingQuery() throws SQLException {
    BasicDataSource dataSouceMock = mock(BasicDataSource.class);
    Connection connectionMock = mock(Connection.class);
    Statement statementMock = mock(Statement.class);

    when(dataSouceMock.getConnection()).thenReturn(connectionMock);
    when(connectionMock.createStatement()).thenReturn(statementMock);
    when(statementMock.execute(anyString())).thenReturn(true).thenThrow(new SQLException());
    when(statementMock.executeQuery(anyString())).thenThrow(new SQLException());

    return dataSouceMock;
  }

  private BasicDataSource createDataSourceThatFailsWhenIteratingResults() throws SQLException {
    BasicDataSource dataSouceMock = mock(BasicDataSource.class);
    Connection connectionMock = mock(Connection.class);
    Statement statementMock = mock(Statement.class);
    ResultSet resultSetMock = mock(ResultSet.class);

    when(dataSouceMock.getConnection()).thenReturn(connectionMock);
    when(connectionMock.createStatement()).thenReturn(statementMock);
    when(statementMock.executeQuery(anyString())).thenReturn(resultSetMock);
    when(resultSetMock.next()).thenThrow(new SQLException());

    return dataSouceMock;
  }
}
