// 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.executor;

import static com.ericsson.gerrit.plugins.gcconductor.executor.GcExecutor.CONFIG_FILE_PROPERTY;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

import com.ericsson.gerrit.plugins.gcconductor.GcQueue;
import com.ericsson.gerrit.plugins.gcconductor.GcQueueException;
import com.ericsson.gerrit.plugins.gcconductor.RepositoryInfo;
import com.google.common.collect.ImmutableList;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class GcExecutorTest {

  private static final String HOSTNAME = "hostname";
  private static final String EXECUTOR = "hostname-0";
  private static final String REPOSITORY = "repository";

  @Mock private ExecutorConfig config;
  @Mock GcWorker.Factory gcWorkerFactory;
  @Mock private GcWorker gcWorker;
  @Mock private GcQueue gcQueue;
  @Mock private ScheduledEvaluator scheduledEvaluator;

  @Rule public TemporaryFolder testTempFolder = new TemporaryFolder();

  @Test
  public void testGcExecutor() {
    when(config.getExecutors()).thenReturn(1);
    when(gcWorkerFactory.create(EXECUTOR)).thenReturn(gcWorker);
    GcExecutor gcExecutor =
        new GcExecutor(gcQueue, config, gcWorkerFactory, scheduledEvaluator, HOSTNAME);
    verify(gcWorker).start();
    gcExecutor.onShutdown();
    verify(gcWorker).shutdown();
  }

  @Test
  public void testLeftOverReposAreUnpickedWhenStarting() throws Exception {
    when(config.getExecutors()).thenReturn(1);
    when(gcWorkerFactory.create(EXECUTOR)).thenReturn(gcWorker);
    when(gcQueue.list())
        .thenReturn(ImmutableList.of(new RepositoryInfo(REPOSITORY, null, EXECUTOR, HOSTNAME)));
    GcExecutor gcExecutor =
        new GcExecutor(gcQueue, config, gcWorkerFactory, scheduledEvaluator, HOSTNAME);
    verify(gcQueue).unpick(REPOSITORY);
    verify(gcWorker).start();
    gcExecutor.onShutdown();
    verify(gcWorker).shutdown();
  }

  @Test
  public void testUnassignedReposAreNotUnpickedWhenStarting() throws Exception {
    when(config.getExecutors()).thenReturn(1);
    when(gcWorkerFactory.create(EXECUTOR)).thenReturn(gcWorker);
    when(gcQueue.list())
        .thenReturn(ImmutableList.of(new RepositoryInfo(REPOSITORY, null, null, HOSTNAME)));
    GcExecutor gcExecutor =
        new GcExecutor(gcQueue, config, gcWorkerFactory, scheduledEvaluator, HOSTNAME);
    verify(gcQueue, never()).unpick(REPOSITORY);
    verify(gcWorker).start();
    gcExecutor.onShutdown();
    verify(gcWorker).shutdown();
  }

  @Test
  public void testExecutorDoesNotUnpickNotOwnedRepo() throws Exception {
    when(config.getExecutors()).thenReturn(1);
    when(gcWorkerFactory.create(EXECUTOR)).thenReturn(gcWorker);
    when(gcQueue.list())
        .thenReturn(
            ImmutableList.of(
                new RepositoryInfo(REPOSITORY, null, "another executor", "another hostname")));
    GcExecutor gcExecutor =
        new GcExecutor(gcQueue, config, gcWorkerFactory, scheduledEvaluator, HOSTNAME);
    verify(gcQueue, never()).unpick(REPOSITORY);
    verify(gcWorker).start();
    gcExecutor.onShutdown();
    verify(gcWorker).shutdown();
  }

  @Test
  public void testQueueThrowsExceptionUnpickingAtStart() throws Exception {
    when(config.getExecutors()).thenReturn(1);
    when(gcWorkerFactory.create(EXECUTOR)).thenReturn(gcWorker);
    doThrow(new GcQueueException("", new Throwable())).when(gcQueue).list();
    GcExecutor gcExecutor =
        new GcExecutor(gcQueue, config, gcWorkerFactory, scheduledEvaluator, HOSTNAME);
    verify(gcQueue, never()).unpick(REPOSITORY);
    verify(gcWorker).start();
    gcExecutor.onShutdown();
    verify(gcWorker).shutdown();
  }

  @Test
  public void testScheduledEvaluationIsConfigured() throws Exception {
    when(config.getExecutors()).thenReturn(1);
    when(config.getInitialDelay()).thenReturn(1L);
    when(config.getInterval()).thenReturn(1L);
    when(gcWorkerFactory.create(EXECUTOR)).thenReturn(gcWorker);
    when(gcQueue.list())
        .thenReturn(ImmutableList.of(new RepositoryInfo(REPOSITORY, null, null, HOSTNAME)));
    GcExecutor gcExecutor =
        new GcExecutor(gcQueue, config, gcWorkerFactory, scheduledEvaluator, HOSTNAME);
    verify(gcWorker).start();
    verify(scheduledEvaluator).scheduleWith(1L, 1L);
    gcExecutor.onShutdown();
    verify(gcWorker).shutdown();
  }

  @Test
  public void testScheduledEvaluationBothParametersRequired() throws Exception {
    when(config.getExecutors()).thenReturn(1);
    when(config.getInitialDelay()).thenReturn(1L);
    when(gcWorkerFactory.create(EXECUTOR)).thenReturn(gcWorker);
    when(gcQueue.list())
        .thenReturn(ImmutableList.of(new RepositoryInfo(REPOSITORY, null, null, HOSTNAME)));
    GcExecutor gcExecutor =
        new GcExecutor(gcQueue, config, gcWorkerFactory, scheduledEvaluator, HOSTNAME);
    verify(gcWorker).start();
    verifyZeroInteractions(scheduledEvaluator);
    gcExecutor.onShutdown();
    verify(gcWorker).shutdown();
  }

  @Test
  public void testloadConfigWhenNotSpecified() {
    Config config = GcExecutor.loadConfig();
    assertThat(config.toText()).isEmpty();
  }

  @Test
  public void testloadConfigFromWhenSpecifiedByProperty() throws Exception {
    File configFile = testTempFolder.newFile();
    FileBasedConfig specifiedConfig = new FileBasedConfig(configFile, FS.DETECTED);
    specifiedConfig.setString("otherSection", null, "otherKey", "otherValue");
    specifiedConfig.save();
    System.setProperty(CONFIG_FILE_PROPERTY, configFile.getAbsolutePath());
    Config config = GcExecutor.loadConfig();
    assertThat(config.toText()).isEqualTo(specifiedConfig.toText());
    System.clearProperty(CONFIG_FILE_PROPERTY);
  }

  @Test
  public void shouldReturnEmptyConfigIfAnErrorOccur() throws Exception {
    File file = testTempFolder.newFile();
    Files.write(file.toPath(), "[section]\n invalid!@$@#%#$".getBytes(), StandardOpenOption.CREATE);
    System.setProperty(CONFIG_FILE_PROPERTY, file.getAbsolutePath());
    Config config = GcExecutor.loadConfig();
    assertThat(config.toText()).isEmpty();
    System.clearProperty(CONFIG_FILE_PROPERTY);
  }
}
