All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.projectnessie.versioned.tests.AbstractDiff Maven / Gradle / Ivy

There is a newer version: 0.100.2
Show newest version
/*
 * Copyright (C) 2022 Dremio
 *
 * 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 org.projectnessie.versioned.tests;

import static com.google.common.collect.Lists.newArrayList;
import static java.util.Collections.emptyList;
import static java.util.Objects.requireNonNull;
import static org.assertj.core.groups.Tuple.tuple;
import static org.projectnessie.versioned.VersionStore.KeyRestrictions.NO_KEY_RESTRICTIONS;
import static org.projectnessie.versioned.testworker.OnRefOnly.newOnRef;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.assertj.core.api.SoftAssertions;
import org.assertj.core.api.junit.jupiter.InjectSoftAssertions;
import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.projectnessie.model.Content;
import org.projectnessie.model.ContentKey;
import org.projectnessie.model.IcebergTable;
import org.projectnessie.model.IdentifiedContentKey;
import org.projectnessie.versioned.BranchName;
import org.projectnessie.versioned.ContentResult;
import org.projectnessie.versioned.Diff;
import org.projectnessie.versioned.Hash;
import org.projectnessie.versioned.ReferenceNotFoundException;
import org.projectnessie.versioned.VersionStore;
import org.projectnessie.versioned.VersionStore.KeyRestrictions;
import org.projectnessie.versioned.VersionStoreException;
import org.projectnessie.versioned.paging.PaginationIterator;
import org.projectnessie.versioned.testworker.OnRefOnly;

@ExtendWith(SoftAssertionsExtension.class)
public abstract class AbstractDiff extends AbstractNestedVersionStore {
  @InjectSoftAssertions protected SoftAssertions soft;

  public static final OnRefOnly V_1 = newOnRef("v1");
  public static final OnRefOnly V_2 = newOnRef("v2");
  public static final OnRefOnly V_2_A = newOnRef("v2a");
  public static final OnRefOnly V_3 = newOnRef("v3");
  public static final OnRefOnly V_1_A = newOnRef("v1a");
  public static final IcebergTable V_12 = IcebergTable.of("foo", 42, 43, 44, 45);
  public static final IcebergTable V_22 = IcebergTable.of("bar", 42, 43, 44, 45);

  protected AbstractDiff(VersionStore store) {
    super(store);
  }

  @Test
  protected void checkDiffDifferentContents() throws VersionStoreException {
    BranchName branch1 = BranchName.of("checkDiffOtherContent1");
    BranchName branch2 = BranchName.of("checkDiffOtherContent2");
    store().create(branch1, Optional.empty());
    store().create(branch2, Optional.empty());
    Hash commit1 = commit("Commit1").put("k1", V_1).put("k2", V_2).toBranch(branch1);
    Hash commit2 = commit("Commit2").put("k1", V_12).put("k2", V_22).toBranch(branch2);
    ContentKey k1 = ContentKey.of("k1");
    ContentKey k2 = ContentKey.of("k2");

    Map contents1 =
        store().getValues(branch1, newArrayList(k1, k2), false);
    IdentifiedContentKey ik11 = contents1.get(k1).identifiedKey();
    IdentifiedContentKey ik12 = contents1.get(k2).identifiedKey();

    Map contents2 =
        store().getValues(branch2, newArrayList(k1, k2), false);
    IdentifiedContentKey ik21 = contents2.get(k1).identifiedKey();
    IdentifiedContentKey ik22 = contents2.get(k2).identifiedKey();

    List diff = diffAsList(commit1, commit2);
    soft.assertThat(diffsWithoutContentId(diff))
        .extracting(Diff::getFromKey, Diff::getToKey, Diff::getFromValue, Diff::getToValue)
        .containsExactlyInAnyOrder(
            tuple(ik11, ik21, Optional.of(V_1), Optional.of(V_12)),
            tuple(ik12, ik22, Optional.of(V_2), Optional.of(V_22)));
  }

  @Test
  protected void checkDiffRename() throws VersionStoreException {
    BranchName branch1 = BranchName.of("checkDiffRename");
    ContentKey k1 = ContentKey.of("k1");
    ContentKey k2 = ContentKey.of("k2");

    store().create(branch1, Optional.empty());
    Hash commit1 = commit("Commit1").put("k1", V_1).toBranch(branch1);

    ContentResult contents1 = store().getValue(commit1, k1, false);
    IdentifiedContentKey ik1 = contents1.identifiedKey();
    Content content = requireNonNull(contents1.content());

    // Rename operation
    Hash commit2 = commit("Commit2").delete("k1").put("k2", content).toBranch(branch1);

    ContentResult contents2 = store().getValue(commit2, k2, false);
    IdentifiedContentKey ik2 = contents2.identifiedKey();

    List diff = diffAsList(commit1, commit2);
    soft.assertThat(ik1.lastElement().contentId()).isEqualTo(content.getId());
    soft.assertThat(ik2.lastElement().contentId()).isEqualTo(content.getId());
    soft.assertThat(diffsWithoutContentId(diff))
        .extracting(Diff::getFromKey, Diff::getToKey, Diff::getFromValue, Diff::getToValue)
        .containsExactlyInAnyOrder(
            tuple(ik1, null, Optional.of(V_1), Optional.empty()),
            tuple(null, ik2, Optional.empty(), Optional.of(V_1)));
  }

  @Test
  protected void checkDiffDropAndCreate() throws VersionStoreException {
    BranchName branch1 = BranchName.of("checkDiffReadd");
    ContentKey k1 = ContentKey.of("k1");
    ContentKey k2 = ContentKey.of("k2");

    store().create(branch1, Optional.empty());
    Hash commit1 = commit("Commit1").put("k1", V_1).toBranch(branch1);

    // Rename operation
    Hash commit2 = commit("Commit2").delete("k1").put("k2", V_2).toBranch(branch1);

    ContentResult contents1 = store().getValue(commit1, k1, false);
    IdentifiedContentKey ik1 = contents1.identifiedKey();
    Content content1 = requireNonNull(contents1.content());
    ContentResult contents2 = store().getValue(commit2, k2, false);
    IdentifiedContentKey ik2 = contents2.identifiedKey();
    Content content2 = requireNonNull(contents2.content());

    soft.assertThat(ik1.lastElement().contentId())
        .isEqualTo(content1.getId())
        .isNotEqualTo(content2.getId());
    soft.assertThat(ik2.lastElement().contentId())
        .isEqualTo(content2.getId())
        .isNotEqualTo(content1.getId());

    List diff = diffAsList(commit1, commit2);
    soft.assertThat(diffsWithoutContentId(diff))
        .extracting(Diff::getFromKey, Diff::getToKey, Diff::getFromValue, Diff::getToValue)
        .containsExactlyInAnyOrder(
            tuple(ik1, null, Optional.of(V_1), Optional.empty()),
            tuple(null, ik2, Optional.empty(), Optional.of(V_2)));
  }

  @Test
  protected void checkDiffReadd() throws VersionStoreException {
    BranchName branch1 = BranchName.of("checkDiffReadd");
    ContentKey k = ContentKey.of("k");

    store().create(branch1, Optional.empty());
    Hash commit1 = commit("Commit1").put("k", V_1).toBranch(branch1);
    Content content1 = requireNonNull(store().getValue(commit1, k, false).content());

    // Re-add operations (have to happen in 2 commits)
    commit("Commit2").delete("k").toBranch(branch1);
    Hash commit3 = commit("Commit3").put("k", V_2).toBranch(branch1);
    Content content3 = requireNonNull(store().getValue(commit3, k, false).content());

    ContentResult contents1 = store().getValue(commit1, k, false);
    IdentifiedContentKey ik1 = contents1.identifiedKey();
    ContentResult contents2 = store().getValue(commit3, k, false);
    IdentifiedContentKey ik2 = contents2.identifiedKey();

    soft.assertThat(ik1.lastElement().contentId())
        .isEqualTo(content1.getId())
        .isNotEqualTo(content3.getId());
    soft.assertThat(ik2.lastElement().contentId())
        .isEqualTo(content3.getId())
        .isNotEqualTo(content1.getId());

    List diff = diffAsList(commit1, commit3);
    soft.assertThat(diffsWithoutContentId(diff))
        .extracting(Diff::getFromKey, Diff::getToKey, Diff::getFromValue, Diff::getToValue)
        .containsExactlyInAnyOrder(tuple(ik1, ik2, Optional.of(V_1), Optional.of(V_2)));
  }

  @Test
  protected void checkDiff() throws VersionStoreException {
    BranchName branch = BranchName.of("checkDiff");
    store().create(branch, Optional.empty());
    Hash initial = store().hashOnReference(branch, Optional.empty(), emptyList());

    ContentKey k1 = ContentKey.of("k1");
    ContentKey k2 = ContentKey.of("k2");
    ContentKey k3 = ContentKey.of("k3");
    ContentKey k1a = ContentKey.of("k1a");

    Hash firstCommit = commit("First Commit").put("k1", V_1).put("k2", V_2).toBranch(branch);
    Content k2content =
        requireNonNull(store().getValue(branch, ContentKey.of("k2"), false).content());
    Hash secondCommit =
        commit("Second Commit")
            .put("k2", V_2_A.withId(k2content.getId()))
            .put("k3", V_3)
            .put("k1a", V_1_A)
            .toBranch(branch);

    Map contents =
        store().getValues(branch, newArrayList(k1, k2, k3, k1a), false);
    IdentifiedContentKey ik1 = contents.get(k1).identifiedKey();
    IdentifiedContentKey ik2 = contents.get(k2).identifiedKey();
    IdentifiedContentKey ik3 = contents.get(k3).identifiedKey();
    IdentifiedContentKey ik1a = contents.get(k1a).identifiedKey();

    List startToSecond = diffAsList(initial, secondCommit);
    soft.assertThat(diffsWithoutContentId(startToSecond))
        .extracting(Diff::getFromKey, Diff::getToKey, Diff::getFromValue, Diff::getToValue)
        .containsExactlyInAnyOrder(
            tuple(null, ik1, Optional.empty(), Optional.of(V_1)),
            tuple(null, ik2, Optional.empty(), Optional.of(V_2_A)),
            tuple(null, ik3, Optional.empty(), Optional.of(V_3)),
            tuple(null, ik1a, Optional.empty(), Optional.of(V_1_A)));

    List secondToStart = diffAsList(secondCommit, initial);
    soft.assertThat(diffsWithoutContentId(secondToStart))
        .extracting(Diff::getFromKey, Diff::getToKey, Diff::getFromValue, Diff::getToValue)
        .containsExactlyInAnyOrder(
            tuple(ik1, null, Optional.of(V_1), Optional.empty()),
            tuple(ik2, null, Optional.of(V_2_A), Optional.empty()),
            tuple(ik3, null, Optional.of(V_3), Optional.empty()),
            tuple(ik1a, null, Optional.of(V_1_A), Optional.empty()));

    List firstToSecond = diffAsList(firstCommit, secondCommit);
    soft.assertThat(diffsWithoutContentId(firstToSecond))
        .extracting(Diff::getFromKey, Diff::getToKey, Diff::getFromValue, Diff::getToValue)
        .containsExactlyInAnyOrder(
            tuple(null, ik1a, Optional.empty(), Optional.of(V_1_A)),
            tuple(ik2, ik2, Optional.of(V_2), Optional.of(V_2_A)),
            tuple(null, ik3, Optional.empty(), Optional.of(V_3)));

    List secondToFirst = diffAsList(secondCommit, firstCommit);
    soft.assertThat(diffsWithoutContentId(secondToFirst))
        .extracting(Diff::getFromKey, Diff::getToKey, Diff::getFromValue, Diff::getToValue)
        .containsExactlyInAnyOrder(
            tuple(ik1a, null, Optional.of(V_1_A), Optional.empty()),
            tuple(ik2, ik2, Optional.of(V_2_A), Optional.of(V_2)),
            tuple(ik3, null, Optional.of(V_3), Optional.empty()));

    soft.assertThat(diffAsList(firstCommit, firstCommit)).isEmpty();

    // Key restrictions
    soft.assertThat(
            diffAsList(
                initial,
                secondCommit,
                KeyRestrictions.builder()
                    .minKey(ContentKey.of("k"))
                    .maxKey(ContentKey.of("l"))
                    .build()))
        .extracting(Diff::getFromKey, Diff::getToKey)
        .containsExactlyInAnyOrder(
            tuple(null, ik1), tuple(null, ik2), tuple(null, ik3), tuple(null, ik1a));

    soft.assertThat(
            diffAsList(
                initial,
                secondCommit,
                KeyRestrictions.builder().minKey(ContentKey.of("k")).build()))
        .extracting(Diff::getFromKey, Diff::getToKey)
        .containsExactlyInAnyOrder(
            tuple(null, ik1), tuple(null, ik2), tuple(null, ik3), tuple(null, ik1a));

    soft.assertThat(diffAsList(initial, secondCommit, KeyRestrictions.builder().maxKey(k2).build()))
        .extracting(Diff::getFromKey, Diff::getToKey)
        .containsExactlyInAnyOrder(tuple(null, ik1), tuple(null, ik2), tuple(null, ik1a));

    soft.assertThat(
            diffAsList(
                initial, secondCommit, KeyRestrictions.builder().minKey(k1a).maxKey(k2).build()))
        .extracting(Diff::getFromKey, Diff::getToKey)
        .containsExactlyInAnyOrder(tuple(null, ik1a), tuple(null, ik2));

    soft.assertThat(
            diffAsList(
                initial, secondCommit, KeyRestrictions.builder().minKey(k2).maxKey(k2).build()))
        .extracting(Diff::getFromKey, Diff::getToKey)
        .containsExactlyInAnyOrder(tuple(null, ik2));

    soft.assertThat(
            diffAsList(
                initial,
                secondCommit,
                KeyRestrictions.builder()
                    .minKey(ContentKey.of("k4"))
                    .maxKey(ContentKey.of("l"))
                    .build()))
        .isEmpty();

    // prefix

    soft.assertThat(
            diffAsList(
                initial,
                secondCommit,
                KeyRestrictions.builder().prefixKey(ContentKey.of("k1")).build()))
        .extracting(Diff::getFromKey, Diff::getToKey)
        .containsExactlyInAnyOrder(tuple(null, ik1));

    soft.assertThat(
            diffAsList(
                initial,
                secondCommit,
                KeyRestrictions.builder().prefixKey(ContentKey.of("k")).build()))
        .extracting(Diff::getFromKey, Diff::getToKey)
        .isEmpty();

    soft.assertThat(
            diffAsList(
                initial,
                secondCommit,
                KeyRestrictions.builder().prefixKey(ContentKey.of("x")).build()))
        .isEmpty();
    soft.assertThat(
            diffAsList(
                initial,
                secondCommit,
                KeyRestrictions.builder()
                    .contentKeyPredicate((k, t) -> k1.equals(k) || k3.equals(k))
                    .build()))
        .extracting(Diff::getFromKey, Diff::getToKey)
        .containsExactlyInAnyOrder(tuple(null, ik1), tuple(null, ik3));

    soft.assertThat(
            diffAsList(
                initial,
                secondCommit,
                KeyRestrictions.builder().contentKeyPredicate((k, t) -> false).build()))
        .isEmpty();
  }

  private List diffAsList(Hash initial, Hash secondCommit) throws ReferenceNotFoundException {
    return diffAsList(initial, secondCommit, NO_KEY_RESTRICTIONS);
  }

  private List diffAsList(Hash initial, Hash secondCommit, KeyRestrictions keyRestrictions)
      throws ReferenceNotFoundException {
    try (PaginationIterator diffStream =
        store().getDiffs(initial, secondCommit, null, keyRestrictions)) {
      List r = new ArrayList<>();
      diffStream.forEachRemaining(r::add);
      return r;
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy