// 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.google.gerrit.server.notedb;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.common.TimeUtil.nowTs;
import static com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage.NOTE_DB;
import static com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage.REVIEW_DB;
import static com.google.gerrit.server.notedb.NoteDbChangeState.applyDelta;
import static com.google.gerrit.server.notedb.NoteDbChangeState.parse;
import static org.eclipse.jgit.lib.ObjectId.zeroId;

import com.google.common.collect.ImmutableMap;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.notedb.NoteDbChangeState.Delta;
import com.google.gerrit.server.notedb.NoteDbChangeState.RefState;
import com.google.gerrit.testutil.GerritBaseTests;
import com.google.gerrit.testutil.TestChanges;
import com.google.gerrit.testutil.TestTimeUtil;
import java.sql.Timestamp;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.lib.ObjectId;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/** Unit tests for {@link NoteDbChangeState}. */
public class NoteDbChangeStateTest extends GerritBaseTests {
  ObjectId SHA1 = ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
  ObjectId SHA2 = ObjectId.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
  ObjectId SHA3 = ObjectId.fromString("badc0feebadc0feebadc0feebadc0feebadc0fee");

  @Before
  public void setUp() {
    TestTimeUtil.resetWithClockStep(1, TimeUnit.SECONDS);
  }

  @After
  public void tearDown() {
    TestTimeUtil.useSystemTime();
  }

  @Test
  public void parseReviewDbWithoutDrafts() {
    NoteDbChangeState state = parse(new Change.Id(1), SHA1.name());
    assertThat(state.getPrimaryStorage()).isEqualTo(REVIEW_DB);
    assertThat(state.getChangeId()).isEqualTo(new Change.Id(1));
    assertThat(state.getChangeMetaId()).isEqualTo(SHA1);
    assertThat(state.getDraftIds()).isEmpty();
    assertThat(state.getReadOnlyUntil().isPresent()).isFalse();
    assertThat(state.toString()).isEqualTo(SHA1.name());

    state = parse(new Change.Id(1), "R," + SHA1.name());
    assertThat(state.getPrimaryStorage()).isEqualTo(REVIEW_DB);
    assertThat(state.getChangeId()).isEqualTo(new Change.Id(1));
    assertThat(state.getChangeMetaId()).isEqualTo(SHA1);
    assertThat(state.getDraftIds()).isEmpty();
    assertThat(state.getReadOnlyUntil().isPresent()).isFalse();
    assertThat(state.toString()).isEqualTo(SHA1.name());
  }

  @Test
  public void parseReviewDbWithDrafts() {
    String str = SHA1.name() + ",2003=" + SHA2.name() + ",1001=" + SHA3.name();
    String expected = SHA1.name() + ",1001=" + SHA3.name() + ",2003=" + SHA2.name();
    NoteDbChangeState state = parse(new Change.Id(1), str);
    assertThat(state.getPrimaryStorage()).isEqualTo(REVIEW_DB);
    assertThat(state.getChangeId()).isEqualTo(new Change.Id(1));
    assertThat(state.getChangeMetaId()).isEqualTo(SHA1);
    assertThat(state.getDraftIds())
        .containsExactly(
            new Account.Id(1001), SHA3,
            new Account.Id(2003), SHA2);
    assertThat(state.getReadOnlyUntil().isPresent()).isFalse();
    assertThat(state.toString()).isEqualTo(expected);

    state = parse(new Change.Id(1), "R," + str);
    assertThat(state.getPrimaryStorage()).isEqualTo(REVIEW_DB);
    assertThat(state.getChangeId()).isEqualTo(new Change.Id(1));
    assertThat(state.getChangeMetaId()).isEqualTo(SHA1);
    assertThat(state.getDraftIds())
        .containsExactly(
            new Account.Id(1001), SHA3,
            new Account.Id(2003), SHA2);
    assertThat(state.getReadOnlyUntil().isPresent()).isFalse();
    assertThat(state.toString()).isEqualTo(expected);
  }

  @Test
  public void parseReadOnlyUntil() {
    Timestamp ts = new Timestamp(12345);
    String str = "R=12345," + SHA1.name();
    NoteDbChangeState state = parse(new Change.Id(1), str);
    assertThat(state.getPrimaryStorage()).isEqualTo(REVIEW_DB);
    assertThat(state.getChangeId()).isEqualTo(new Change.Id(1));
    assertThat(state.getChangeMetaId()).isEqualTo(SHA1);
    assertThat(state.getReadOnlyUntil().get()).isEqualTo(ts);
    assertThat(state.toString()).isEqualTo(str);

    str = "N=12345";
    state = parse(new Change.Id(1), str);
    assertThat(state.getPrimaryStorage()).isEqualTo(NOTE_DB);
    assertThat(state.getChangeId()).isEqualTo(new Change.Id(1));
    assertThat(state.getRefState().isPresent()).isFalse();
    assertThat(state.getReadOnlyUntil().get()).isEqualTo(ts);
    assertThat(state.toString()).isEqualTo(str);
  }

  @Test
  public void applyDeltaToNullWithNoNewMetaId() throws Exception {
    Change c = newChange();
    assertThat(c.getNoteDbState()).isNull();
    applyDelta(c, Delta.create(c.getId(), noMetaId(), noDrafts()));
    assertThat(c.getNoteDbState()).isNull();

    applyDelta(c, Delta.create(c.getId(), noMetaId(), drafts(new Account.Id(1001), zeroId())));
    assertThat(c.getNoteDbState()).isNull();
  }

  @Test
  public void applyDeltaToMetaId() throws Exception {
    Change c = newChange();
    applyDelta(c, Delta.create(c.getId(), metaId(SHA1), noDrafts()));
    assertThat(c.getNoteDbState()).isEqualTo(SHA1.name());

    applyDelta(c, Delta.create(c.getId(), metaId(SHA2), noDrafts()));
    assertThat(c.getNoteDbState()).isEqualTo(SHA2.name());

    // No-op delta.
    applyDelta(c, Delta.create(c.getId(), noMetaId(), noDrafts()));
    assertThat(c.getNoteDbState()).isEqualTo(SHA2.name());

    // Set to zero clears the field.
    applyDelta(c, Delta.create(c.getId(), metaId(zeroId()), noDrafts()));
    assertThat(c.getNoteDbState()).isNull();
  }

  @Test
  public void applyDeltaToDrafts() throws Exception {
    Change c = newChange();
    applyDelta(c, Delta.create(c.getId(), metaId(SHA1), drafts(new Account.Id(1001), SHA2)));
    assertThat(c.getNoteDbState()).isEqualTo(SHA1.name() + ",1001=" + SHA2.name());

    applyDelta(c, Delta.create(c.getId(), noMetaId(), drafts(new Account.Id(2003), SHA3)));
    assertThat(c.getNoteDbState())
        .isEqualTo(SHA1.name() + ",1001=" + SHA2.name() + ",2003=" + SHA3.name());

    applyDelta(c, Delta.create(c.getId(), noMetaId(), drafts(new Account.Id(2003), zeroId())));
    assertThat(c.getNoteDbState()).isEqualTo(SHA1.name() + ",1001=" + SHA2.name());

    applyDelta(c, Delta.create(c.getId(), metaId(SHA3), noDrafts()));
    assertThat(c.getNoteDbState()).isEqualTo(SHA3.name() + ",1001=" + SHA2.name());
  }

  @Test
  public void applyDeltaToReadOnly() throws Exception {
    Timestamp ts = nowTs();
    Change c = newChange();
    NoteDbChangeState state =
        new NoteDbChangeState(
            c.getId(),
            REVIEW_DB,
            Optional.of(RefState.create(SHA1, ImmutableMap.of())),
            Optional.of(new Timestamp(ts.getTime() + 10000)));
    c.setNoteDbState(state.toString());
    Delta delta = Delta.create(c.getId(), metaId(SHA2), noDrafts());
    applyDelta(c, delta);
    assertThat(NoteDbChangeState.parse(c))
        .isEqualTo(
            new NoteDbChangeState(
                state.getChangeId(),
                state.getPrimaryStorage(),
                Optional.of(RefState.create(SHA2, ImmutableMap.of())),
                state.getReadOnlyUntil()));
  }

  @Test
  public void parseNoteDbPrimary() {
    NoteDbChangeState state = parse(new Change.Id(1), "N");
    assertThat(state.getPrimaryStorage()).isEqualTo(NOTE_DB);
    assertThat(state.getRefState().isPresent()).isFalse();
    assertThat(state.getReadOnlyUntil().isPresent()).isFalse();
  }

  @Test(expected = IllegalArgumentException.class)
  public void parseInvalidPrimaryStorage() {
    parse(new Change.Id(1), "X");
  }

  @Test
  public void applyDeltaToNoteDbPrimaryIsNoOp() throws Exception {
    Change c = newChange();
    c.setNoteDbState("N");
    applyDelta(c, Delta.create(c.getId(), metaId(SHA1), drafts(new Account.Id(1001), SHA2)));
    assertThat(c.getNoteDbState()).isEqualTo("N");
  }

  private static Change newChange() {
    return TestChanges.newChange(new Project.NameKey("project"), new Account.Id(12345));
  }

  // Static factory methods to avoid type arguments when using as method args.

  private static Optional<ObjectId> noMetaId() {
    return Optional.empty();
  }

  private static Optional<ObjectId> metaId(ObjectId id) {
    return Optional.of(id);
  }

  private static ImmutableMap<Account.Id, ObjectId> noDrafts() {
    return ImmutableMap.of();
  }

  private static ImmutableMap<Account.Id, ObjectId> drafts(Object... args) {
    checkArgument(args.length % 2 == 0);
    ImmutableMap.Builder<Account.Id, ObjectId> b = ImmutableMap.builder();
    for (int i = 0; i < args.length / 2; i++) {
      b.put((Account.Id) args[2 * i], (ObjectId) args[2 * i + 1]);
    }
    return b.build();
  }
}
