// 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.googlesource.gerrit.plugins.webhooks;

import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;

import com.google.gerrit.entities.Project;
import com.google.gerrit.server.events.ProjectCreatedEvent;
import com.googlesource.gerrit.plugins.webhooks.HttpResponseHandler.HttpResult;
import java.io.IOException;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class PostTaskTest {

  private static final String WEBHOOK_URL = "webhook-url";
  private static final HttpResult OK_RESULT = new HttpResult(true, "");
  private static final HttpResult ERR_RESULT = new HttpResult(false, "");
  private static final int RETRY_INTERVAL = 100;
  private static final int MAX_TRIES = 3;

  @Mock private ProjectCreatedEvent projectCreated;

  @Mock private RemoteConfig remote;

  @Mock private Configuration cfg;

  @Mock private HttpSession session;

  @Mock private HttpSession.Factory sessionFactory;

  @Mock private ScheduledThreadPoolExecutor executor;

  @Mock private EventProcessor processor;

  @Mock private EventProcessor.Request content;

  private PostTask task;

  @Before
  public void setup() {
    when(remote.getRetryInterval()).thenReturn(RETRY_INTERVAL);
    when(remote.getMaxTries()).thenReturn(MAX_TRIES);
    when(remote.getUrl()).thenReturn(WEBHOOK_URL);
    when(processor.process(eq(projectCreated), eq(remote))).thenReturn(Optional.of(content));
    when(sessionFactory.create(eq(remote))).thenReturn(session);
    when(projectCreated.getProjectNameKey()).thenReturn(Project.nameKey("test"));
    task = new PostTask(executor, sessionFactory, processor, projectCreated, remote);
  }

  @Test
  public void noScheduleOnEmptyBody() throws Exception {
    when(processor.process(eq(projectCreated), eq(remote))).thenReturn(Optional.empty());
    task.run();
    verifyNoInteractions(session);
    verifyNoInteractions(executor);
  }

  @Test
  public void noRescheduleOnSuccess() throws IOException {
    when(session.post(eq(remote), eq(content))).thenReturn(OK_RESULT);
    task.run();
    verifyNoInteractions(executor);
  }

  @Test
  public void noRescheduleOnNonRecoverableException() throws IOException {
    when(session.post(eq(remote), eq(content))).thenThrow(SSLException.class);
    task.run();
    verifyNoInteractions(executor);
  }

  @Test
  public void rescheduleOnError() throws IOException {
    when(session.post(eq(remote), eq(content))).thenReturn(ERR_RESULT);
    task.run();
    verify(executor, times(1)).schedule(task, RETRY_INTERVAL, TimeUnit.MILLISECONDS);
  }

  @Test
  public void rescheduleOnRecoverableException() throws IOException {
    when(session.post(eq(remote), eq(content))).thenThrow(IOException.class);
    task.run();
    verify(executor, times(1)).schedule(task, RETRY_INTERVAL, TimeUnit.MILLISECONDS);
  }

  @Test
  public void keepReschedulingMaxTriesTimes() throws IOException {
    when(session.post(eq(remote), eq(content))).thenThrow(IOException.class);
    when(executor.schedule(task, RETRY_INTERVAL, TimeUnit.MILLISECONDS))
        .then(
            invocation -> {
              task.run();
              return null;
            });
    task.run();
    verify(executor, times(MAX_TRIES - 1)).schedule(task, RETRY_INTERVAL, TimeUnit.MILLISECONDS);
  }

  @Test
  public void executorSurvivesNonRecoverableExceptions()
      throws IOException, InterruptedException, ExecutionException {
    executor = new ScheduledThreadPoolExecutor(1);

    // schedule erroneous task for the first time
    when(session.post(eq(remote), eq(content))).thenThrow(RuntimeException.class);
    executor.schedule(task, 0L, TimeUnit.SECONDS).get();

    // schedule erroneous task again (with another non-recoverable exception)
    when(session.post(eq(remote), eq(content))).thenThrow(SSLException.class);
    executor.schedule(task, 0L, TimeUnit.SECONDS).get();

    // schedule task that finishes with success
    when(session.post(eq(remote), eq(content))).thenReturn(OK_RESULT);
    executor.schedule(task, 0L, TimeUnit.SECONDS).get();

    verify(session, times(3)).post(eq(remote), eq(content));
  }
}
