// Copyright (C) 2016 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.verifystatus;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;

import com.google.common.collect.Iterables;
import com.google.gerrit.acceptance.GerritConfig;
import com.google.gerrit.acceptance.LightweightPluginDaemonTest;
import com.google.gerrit.acceptance.PushOneCommit.Result;
import com.google.gerrit.acceptance.RestResponse;
import com.google.gerrit.acceptance.TestPlugin;
import com.google.gerrit.acceptance.UseLocalDisk;
import com.google.gson.reflect.TypeToken;
import com.google.gwtorm.jdbc.SimpleDataSource;
import com.googlesource.gerrit.plugins.verifystatus.common.VerificationInfo;
import com.googlesource.gerrit.plugins.verifystatus.common.VerifyInput;
import java.sql.Connection;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.junit.Before;
import org.junit.Test;

@TestPlugin(
    name = "verify-status",
    sysModule = "com.googlesource.gerrit.plugins.verifystatus.GlobalModule",
    httpModule = "com.googlesource.gerrit.plugins.verifystatus.HttpModule",
    sshModule = "com.googlesource.gerrit.plugins.verifystatus.SshModule")
public class VerifyStatusIT extends LightweightPluginDaemonTest {
  private static final String NAME = "verify-status";
  private static final String DB_TYPE_CONFIG = "plugin." + NAME + ".dbType";
  private static final String DB_URL_CONFIG = "plugin." + NAME + ".dbUrl";
  private static final String H2 = "h2";
  private static final String URL = "jdbc:h2:mem:TestCiDB;DB_CLOSE_DELAY=-1";
  private static final String TABLE = "PATCH_SET_VERIFICATIONS";
  private static final String CREATE_TABLE =
      "CREATE       TABLE IF NOT EXISTS "
          + TABLE
          + " ("
          + "VALUE        SMALLINT DEFAULT 0 NOT NULL,"
          + "GRANTED      TIMESTAMP NOT NULL,"
          + "URL          VARCHAR(255),"
          + "REPORTER     VARCHAR(255),"
          + "COMMENT      VARCHAR(255),"
          + "CATEGORY     VARCHAR(255),"
          + "DURATION     VARCHAR(255),"
          + "ABSTAIN      CHAR(1) DEFAULT 'N' NOT NULL,"
          + "RERUN        CHAR(1) DEFAULT 'N' NOT NULL,"
          + "NAME         VARCHAR(255),"
          + "CHANGE_ID    INTEGER DEFAULT 0 NOT NULL,"
          + "PATCH_SET_ID INTEGER DEFAULT 0 NOT NULL,"
          + "JOB_ID       VARCHAR(255) DEFAULT '' NOT NULL)";
  private static final String DELETE_TABLE = "DELETE FROM " + TABLE;

  @Before
  @Override
  public void setUp() throws Exception {
    super.setUp();
    allowGlobalCapabilities(REGISTERED_USERS, SaveReportCapability.getName(NAME));

    Properties p = new Properties();
    p.setProperty("driver", "org.h2.Driver");
    p.setProperty("url", URL);

    SimpleDataSource sds = new SimpleDataSource(p);
    try (Connection c = sds.getConnection();
        Statement s = c.createStatement()) {
      s.executeUpdate(CREATE_TABLE);
      // run the tests with the clean database
      s.execute(DELETE_TABLE);
    }
  }

  @Test
  @GerritConfig(name = DB_TYPE_CONFIG, value = H2)
  @GerritConfig(name = DB_URL_CONFIG, value = URL)
  @UseLocalDisk
  public void noVerificationTest() throws Exception {
    Result c = createChange();
    Map<String, VerificationInfo> infos = getVerifications(c, null);
    assertThat(infos).hasSize(0);
  }

  @Test
  @GerritConfig(name = DB_TYPE_CONFIG, value = H2)
  @GerritConfig(name = DB_URL_CONFIG, value = URL)
  @UseLocalDisk
  public void verificationOneTest() throws Exception {
    VerifyInput in = new VerifyInput();
    in.verifications = new HashMap<>();
    VerificationInfo i = new VerificationInfo();
    i.name = "job42";
    i.value = 1;
    i.reporter = "zuul@openstack.org";
    i.rerun = true;
    i.comment = "Test CI";
    i.url = "url";
    i.category = "bar";
    i.duration = "1h 30min";
    in.verifications.put("foo", i);

    Result c = createChange();
    String endPoint = url(c);
    RestResponse r = adminRestSession.post(endPoint, in);
    r.assertNoContent();

    Map<String, VerificationInfo> infos = getVerifications(c, null);
    assertThat(infos).hasSize(1);
    assertVerification(Iterables.getOnlyElement(infos.values()), i);
  }

  @Test
  @GerritConfig(name = DB_TYPE_CONFIG, value = H2)
  @GerritConfig(name = DB_URL_CONFIG, value = URL)
  @UseLocalDisk
  public void verificationTwoTest() throws Exception {
    VerifyInput in = new VerifyInput();
    in.verifications = new HashMap<>();
    VerificationInfo i = new VerificationInfo();
    i.name = "job43";
    i.value = 1;
    i.reporter = "zuul@openstack.org";
    i.comment = "Test CI";
    i.url = "url";
    i.category = "bar";
    i.duration = "1h 30min";
    in.verifications.put(i.name, i);

    VerificationInfo j = new VerificationInfo();
    j = new VerificationInfo();
    j.name = "job44";
    j.value = -1;
    j.reporter = "zuul@openstack.org";
    j.comment = "Test CI";
    j.url = "url";
    j.category = "bar";
    j.duration = "1h 30min";
    in.verifications.put(j.name, j);

    Result c = createChange();
    String endPoint = url(c);
    RestResponse r = adminRestSession.post(endPoint, in);
    r.assertNoContent();

    Map<String, VerificationInfo> infos = getVerifications(c, null);
    assertThat(infos).hasSize(2);
  }

  @Test
  @GerritConfig(name = DB_TYPE_CONFIG, value = H2)
  @GerritConfig(name = DB_URL_CONFIG, value = URL)
  @UseLocalDisk
  public void verificationTestNullReporter() throws Exception {
    VerifyInput in = new VerifyInput();
    in.verifications = new HashMap<>();
    VerificationInfo i = new VerificationInfo();
    i.name = "job42";
    i.value = 1;
    i.rerun = true;
    i.comment = "Test CI";
    i.url = "url";
    i.category = "bar";
    i.duration = "1h 30min";
    in.verifications.put("foo", i);

    Result c = createChange();
    String endPoint = url(c);
    RestResponse r = adminRestSession.post(endPoint, in);
    r.assertNoContent();

    Map<String, VerificationInfo> infos = getVerifications(c, "CURRENT");
    assertThat(infos).hasSize(1);
    assertThat(Iterables.getOnlyElement(infos.values()).reporter).isNull();
    assertVerification(Iterables.getOnlyElement(infos.values()), i);
  }

  private Map<String, VerificationInfo> getVerifications(Result c, String filter) throws Exception {
    String endPoint = url(c);
    if (filter != null) {
      endPoint += "/?filter=" + filter;
    }
    RestResponse r = adminRestSession.get(endPoint);
    r.assertOK();

    return newGson()
        .fromJson(r.getReader(), new TypeToken<Map<String, VerificationInfo>>() {}.getType());
  }

  private String url(Result c) throws Exception {
    return "/changes/"
        + c.getChangeId()
        + "/revisions/"
        + c.getPatchSetId().get()
        + "/verify-status~verifications";
  }

  private static void assertVerification(VerificationInfo r, VerificationInfo e) {
    assertThat(r.value).isEqualTo(e.value);
    assertThat(r.reporter).isEqualTo(e.reporter);
    assertThat(r.comment).isEqualTo(e.comment);
    assertThat(r.url).isEqualTo(e.url);
    assertThat(r.category).isEqualTo(e.category);
    assertThat(r.duration).isEqualTo(e.duration);
    assertThat(r.rerun).isEqualTo(e.rerun);
  }
}
