// Copyright (C) 2018 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.entities.converter;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;

import com.google.common.collect.ImmutableMap;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.proto.Entities;
import com.google.gerrit.proto.testing.SerializedClassSubject;
import java.lang.reflect.Type;
import java.time.Instant;
import org.junit.Test;

public class ChangeProtoConverterTest {
  private final ChangeProtoConverter changeProtoConverter = ChangeProtoConverter.INSTANCE;
  private static final String TEST_SERVER_ID = "test-server-id";

  @Test
  public void allValuesConvertedToProto() {
    Change change =
        new Change(
            Change.key("change 1"),
            Change.id(14),
            Account.id(35),
            BranchNameKey.create(Project.nameKey("project 67"), "branch 74"),
            Instant.ofEpochMilli(987654L));
    change.setServerId(TEST_SERVER_ID);
    change.setLastUpdatedOn(Instant.ofEpochMilli(1234567L));
    change.setStatus(Change.Status.MERGED);
    change.setCurrentPatchSet(
        PatchSet.id(Change.id(14), 23), "subject XYZ", "original subject ABC");
    change.setTopic("my topic");
    change.setSubmissionId("submission ID 234");
    change.setPrivate(true);
    change.setWorkInProgress(true);
    change.setReviewStarted(true);
    change.setRevertOf(Change.id(180));

    Entities.Change proto = changeProtoConverter.toProto(change);

    Entities.Change expectedProto =
        Entities.Change.newBuilder()
            .setChangeId(Entities.Change_Id.newBuilder().setId(14))
            .setChangeKey(Entities.Change_Key.newBuilder().setId("change 1"))
            .setCreatedOn(987654L)
            .setLastUpdatedOn(1234567L)
            .setOwnerAccountId(Entities.Account_Id.newBuilder().setId(35))
            .setDest(
                Entities.Branch_NameKey.newBuilder()
                    .setProject(Entities.Project_NameKey.newBuilder().setName("project 67"))
                    .setBranch("refs/heads/branch 74"))
            .setStatus(Change.STATUS_MERGED)
            .setCurrentPatchSetId(23)
            .setSubject("subject XYZ")
            .setTopic("my topic")
            .setOriginalSubject("original subject ABC")
            .setSubmissionId("submission ID 234")
            .setIsPrivate(true)
            .setWorkInProgress(true)
            .setReviewStarted(true)
            .setRevertOf(Entities.Change_Id.newBuilder().setId(180))
            .setServerId(TEST_SERVER_ID)
            .build();
    assertThat(proto).isEqualTo(expectedProto);
  }

  @Test
  public void mandatoryValuesConvertedToProto() {
    Change change =
        new Change(
            Change.key("change 1"),
            Change.id(14),
            Account.id(35),
            BranchNameKey.create(Project.nameKey("project 67"), "branch-74"),
            Instant.ofEpochMilli(987654L));

    Entities.Change proto = changeProtoConverter.toProto(change);

    Entities.Change expectedProto =
        Entities.Change.newBuilder()
            .setChangeId(Entities.Change_Id.newBuilder().setId(14))
            .setChangeKey(Entities.Change_Key.newBuilder().setId("change 1"))
            .setCreatedOn(987654L)
            // Defaults to createdOn if not set.
            .setLastUpdatedOn(987654L)
            .setOwnerAccountId(Entities.Account_Id.newBuilder().setId(35))
            .setDest(
                Entities.Branch_NameKey.newBuilder()
                    .setProject(Entities.Project_NameKey.newBuilder().setName("project 67"))
                    .setBranch("refs/heads/branch-74"))
            // Default values which can't be unset.
            .setCurrentPatchSetId(0)
            .setStatus(Change.STATUS_NEW)
            .setIsPrivate(false)
            .setWorkInProgress(false)
            .setReviewStarted(false)
            .build();
    assertThat(proto).isEqualTo(expectedProto);
  }

  // This test documents a special behavior which is necessary to ensure binary compatibility.
  @Test
  public void currentPatchSetIsAlwaysSetWhenConvertedToProto() {
    Change change =
        new Change(
            Change.key("change 1"),
            Change.id(14),
            Account.id(35),
            BranchNameKey.create(Project.nameKey("project 67"), "branch-74"),
            Instant.ofEpochMilli(987654L));
    change.setServerId(TEST_SERVER_ID);
    // O as ID actually means that no current patch set is present.
    change.setCurrentPatchSet(PatchSet.id(Change.id(14), 0), null, null);

    Entities.Change proto = changeProtoConverter.toProto(change);

    Entities.Change expectedProto =
        Entities.Change.newBuilder()
            .setChangeId(Entities.Change_Id.newBuilder().setId(14))
            .setChangeKey(Entities.Change_Key.newBuilder().setId("change 1"))
            .setCreatedOn(987654L)
            // Defaults to createdOn if not set.
            .setLastUpdatedOn(987654L)
            .setOwnerAccountId(Entities.Account_Id.newBuilder().setId(35))
            .setDest(
                Entities.Branch_NameKey.newBuilder()
                    .setProject(Entities.Project_NameKey.newBuilder().setName("project 67"))
                    .setBranch("refs/heads/branch-74"))
            .setCurrentPatchSetId(0)
            // Default values which can't be unset.
            .setStatus(Change.STATUS_NEW)
            .setIsPrivate(false)
            .setWorkInProgress(false)
            .setReviewStarted(false)
            .setServerId(TEST_SERVER_ID)
            .build();
    assertThat(proto).isEqualTo(expectedProto);
  }

  // This test documents a special behavior which is necessary to ensure binary compatibility.
  @Test
  public void originalSubjectIsNotAutomaticallySetToSubjectWhenConvertedToProto() {
    Change change =
        new Change(
            Change.key("change 1"),
            Change.id(14),
            Account.id(35),
            BranchNameKey.create(Project.nameKey("project 67"), "branch-74"),
            Instant.ofEpochMilli(987654L));
    change.setServerId(TEST_SERVER_ID);
    change.setCurrentPatchSet(PatchSet.id(Change.id(14), 23), "subject ABC", null);

    Entities.Change proto = changeProtoConverter.toProto(change);

    Entities.Change expectedProto =
        Entities.Change.newBuilder()
            .setChangeId(Entities.Change_Id.newBuilder().setId(14))
            .setChangeKey(Entities.Change_Key.newBuilder().setId("change 1"))
            .setCreatedOn(987654L)
            // Defaults to createdOn if not set.
            .setLastUpdatedOn(987654L)
            .setOwnerAccountId(Entities.Account_Id.newBuilder().setId(35))
            .setDest(
                Entities.Branch_NameKey.newBuilder()
                    .setProject(Entities.Project_NameKey.newBuilder().setName("project 67"))
                    .setBranch("refs/heads/branch-74"))
            .setCurrentPatchSetId(23)
            .setSubject("subject ABC")
            // Default values which can't be unset.
            .setStatus(Change.STATUS_NEW)
            .setIsPrivate(false)
            .setWorkInProgress(false)
            .setReviewStarted(false)
            .setServerId(TEST_SERVER_ID)
            .build();
    assertThat(proto).isEqualTo(expectedProto);
  }

  @Test
  public void allValuesConvertedToProtoAndBackAgainExceptNullServerId() {
    Change change =
        new Change(
            Change.key("change 1"),
            Change.id(14),
            Account.id(35),
            BranchNameKey.create(Project.nameKey("project 67"), "branch-74"),
            Instant.ofEpochMilli(987654L));
    change.setServerId(null);
    change.setLastUpdatedOn(Instant.ofEpochMilli(1234567L));
    change.setStatus(Change.Status.MERGED);
    change.setCurrentPatchSet(
        PatchSet.id(Change.id(14), 23), "subject XYZ", "original subject ABC");
    change.setTopic("my topic");
    change.setSubmissionId("submission ID 234");
    change.setPrivate(true);
    change.setWorkInProgress(true);
    change.setReviewStarted(true);
    change.setRevertOf(Change.id(180));

    Change convertedChange = changeProtoConverter.fromProto(changeProtoConverter.toProto(change));
    assertEqualChange(convertedChange, change);
  }

  @Test
  public void mandatoryValuesConvertedToProtoAndBackAgain() {
    Change change =
        new Change(
            Change.key("change 1"),
            Change.id(14),
            Account.id(35),
            BranchNameKey.create(Project.nameKey("project 67"), "branch-74"),
            Instant.ofEpochMilli(987654L));

    Change convertedChange = changeProtoConverter.fromProto(changeProtoConverter.toProto(change));
    assertEqualChange(convertedChange, change);
  }

  // We need this special test as some values are only optional in the protobuf definition but can
  // never be unset in our entity object.
  @Test
  public void protoWithOnlyRequiredValuesCanBeConvertedBack() {
    Entities.Change proto =
        Entities.Change.newBuilder().setChangeId(Entities.Change_Id.newBuilder().setId(14)).build();
    Change change = changeProtoConverter.fromProto(proto);

    assertThat(change.getChangeId()).isEqualTo(14);
    // Values which can't be null according to ReviewDb's column definition but which are optional.
    assertThat(change.getKey()).isNull();
    assertThat(change.getOwner()).isNull();
    assertThat(change.getDest()).isNull();
    assertThat(change.getCreatedOn()).isEqualTo(Instant.EPOCH);
    assertThat(change.getLastUpdatedOn()).isEqualTo(Instant.EPOCH);
    assertThat(change.getSubject()).isNull();
    assertThat(change.currentPatchSetId()).isNull();
    // Default values for unset protobuf fields which can't be unset in the entity object.
    assertThat(change.isNew()).isTrue();
    assertThat(change.isPrivate()).isFalse();
    assertThat(change.isWorkInProgress()).isFalse();
    assertThat(change.hasReviewStarted()).isFalse();
  }

  @Test
  public void unsetLastUpdatedOnIsAutomaticallySetToCreatedOnWhenConvertedBack() {
    Entities.Change proto =
        Entities.Change.newBuilder()
            .setChangeId(Entities.Change_Id.newBuilder().setId(14))
            .setChangeKey(Entities.Change_Key.newBuilder().setId("change 1"))
            .setCreatedOn(987654L)
            .setOwnerAccountId(Entities.Account_Id.newBuilder().setId(35))
            .setDest(
                Entities.Branch_NameKey.newBuilder()
                    .setProject(Entities.Project_NameKey.newBuilder().setName("project 67"))
                    .setBranch("branch 74"))
            .build();
    Change change = changeProtoConverter.fromProto(proto);

    assertThat(change.getLastUpdatedOn()).isEqualTo(Instant.ofEpochMilli(987654L));
  }

  /** See {@link SerializedClassSubject} for background and what to do if this test fails. */
  @Test
  public void fieldsExistAsExpected() {
    assertThatSerializedClass(Change.class)
        .hasFields(
            ImmutableMap.<String, Type>builder()
                .put("changeId", Change.Id.class)
                .put("serverId", String.class)
                .put("changeKey", Change.Key.class)
                .put("createdOn", Instant.class)
                .put("lastUpdatedOn", Instant.class)
                .put("owner", Account.Id.class)
                .put("dest", BranchNameKey.class)
                .put("status", char.class)
                .put("currentPatchSetId", int.class)
                .put("subject", String.class)
                .put("topic", String.class)
                .put("originalSubject", String.class)
                .put("submissionId", String.class)
                .put("isPrivate", boolean.class)
                .put("workInProgress", boolean.class)
                .put("reviewStarted", boolean.class)
                .put("revertOf", Change.Id.class)
                .put("cherryPickOf", PatchSet.Id.class)
                .build());
  }

  // Unfortunately, Change doesn't implement equals(). Remove this method when we switch Change to
  // an AutoValue.
  private static void assertEqualChange(Change change, Change expectedChange) {
    assertThat(change.getChangeId()).isEqualTo(expectedChange.getChangeId());
    assertThat(change.getServerId()).isEqualTo(expectedChange.getServerId());
    assertThat(change.getKey()).isEqualTo(expectedChange.getKey());
    assertThat(change.getCreatedOn()).isEqualTo(expectedChange.getCreatedOn());
    assertThat(change.getLastUpdatedOn()).isEqualTo(expectedChange.getLastUpdatedOn());
    assertThat(change.getOwner()).isEqualTo(expectedChange.getOwner());
    assertThat(change.getDest()).isEqualTo(expectedChange.getDest());
    assertThat(change.getStatus()).isEqualTo(expectedChange.getStatus());
    assertThat(change.currentPatchSetId()).isEqualTo(expectedChange.currentPatchSetId());
    assertThat(change.getSubject()).isEqualTo(expectedChange.getSubject());
    assertThat(change.getTopic()).isEqualTo(expectedChange.getTopic());
    assertThat(change.getOriginalSubject()).isEqualTo(expectedChange.getOriginalSubject());
    assertThat(change.getSubmissionId()).isEqualTo(expectedChange.getSubmissionId());
    assertThat(change.isPrivate()).isEqualTo(expectedChange.isPrivate());
    assertThat(change.isWorkInProgress()).isEqualTo(expectedChange.isWorkInProgress());
    assertThat(change.hasReviewStarted()).isEqualTo(expectedChange.hasReviewStarted());
    assertThat(change.getRevertOf()).isEqualTo(expectedChange.getRevertOf());
  }
}
