use of org.projectnessie.versioned.testworker.BaseContent in project nessie by projectnessie.
the class AbstractCommitScenarios method commitRenameTable.
/**
* Test whether a "table rename operation" works as expected.
*
* <p>A "table rename" is effectively a remove-operation plus a put-operation with a different key
* but the same content-id.
*
* <p>Parameterized to force operations to cross/not-cross the number of commits between "full key
* lists" and whether global-state shall be used.
*/
@ParameterizedTest
@MethodSource("commitRenameTableParams")
void commitRenameTable(RenameTable param) throws Exception {
BranchName branch = BranchName.of("main");
Key dummyKey = Key.of("dummy");
Key oldKey = Key.of("hello", "table");
Key newKey = Key.of("new", "name");
ContentId contentId = ContentId.of("id-42");
IntFunction<Hash> performDummyCommit = i -> {
try {
return databaseAdapter.commit(ImmutableCommitAttempt.builder().commitToBranch(branch).commitMetaSerialized(ByteString.copyFromUtf8("dummy commit meta " + i)).addUnchanged(dummyKey).build());
} catch (ReferenceNotFoundException | ReferenceConflictException e) {
throw new RuntimeException(e);
}
};
List<Hash> beforeInitial = IntStream.range(0, param.setupCommits).mapToObj(performDummyCommit).collect(Collectors.toList());
ImmutableCommitAttempt.Builder commit;
BaseContent initialContent;
BaseContent renamContent;
if (param.globalState) {
initialContent = WithGlobalStateContent.newWithGlobal("0", "initial commit content");
renamContent = WithGlobalStateContent.withGlobal("0", "rename commit content", initialContent.getId());
} else {
initialContent = OnRefOnly.newOnRef("initial commit content");
renamContent = OnRefOnly.onRef("rename commit content", initialContent.getId());
}
byte payload = SimpleStoreWorker.INSTANCE.getPayload(initialContent);
commit = ImmutableCommitAttempt.builder().commitToBranch(branch).commitMetaSerialized(ByteString.copyFromUtf8("initial commit meta")).addPuts(KeyWithBytes.of(oldKey, contentId, payload, SimpleStoreWorker.INSTANCE.toStoreOnReferenceState(initialContent)));
if (param.globalState) {
commit.putGlobal(contentId, SimpleStoreWorker.INSTANCE.toStoreGlobalState(initialContent)).putExpectedStates(contentId, Optional.empty());
}
Hash hashInitial = databaseAdapter.commit(commit.build());
List<Hash> beforeRename = IntStream.range(0, param.afterInitialCommits).mapToObj(performDummyCommit).collect(Collectors.toList());
commit = ImmutableCommitAttempt.builder().commitToBranch(branch).commitMetaSerialized(ByteString.copyFromUtf8("rename table")).addDeletes(oldKey).addPuts(KeyWithBytes.of(newKey, contentId, payload, SimpleStoreWorker.INSTANCE.toStoreOnReferenceState(renamContent)));
if (param.globalState) {
commit.putGlobal(contentId, SimpleStoreWorker.INSTANCE.toStoreGlobalState(renamContent)).putExpectedStates(contentId, Optional.of(SimpleStoreWorker.INSTANCE.toStoreGlobalState(initialContent)));
}
Hash hashRename = databaseAdapter.commit(commit.build());
List<Hash> beforeDelete = IntStream.range(0, param.afterRenameCommits).mapToObj(performDummyCommit).collect(Collectors.toList());
commit = ImmutableCommitAttempt.builder().commitToBranch(branch).commitMetaSerialized(ByteString.copyFromUtf8("delete table")).addDeletes(newKey);
if (param.globalState) {
commit.putGlobal(contentId, ByteString.copyFromUtf8("0")).putExpectedStates(contentId, Optional.of(ByteString.copyFromUtf8("0")));
}
Hash hashDelete = databaseAdapter.commit(commit.build());
List<Hash> afterDelete = IntStream.range(0, param.afterDeleteCommits).mapToObj(performDummyCommit).collect(Collectors.toList());
int expectedCommitCount = 1;
// Verify that the commits before the initial put return _no_ keys
expectedCommitCount = renameCommitVerify(beforeInitial.stream(), expectedCommitCount, keys -> assertThat(keys).isEmpty());
// Verify that the commits since the initial put and before the rename-operation return the
// _old_ key
expectedCommitCount = renameCommitVerify(Stream.concat(Stream.of(hashInitial), beforeRename.stream()), expectedCommitCount, keys -> assertThat(keys).containsExactly(KeyListEntry.of(oldKey, contentId, payload, hashInitial)));
// Verify that the commits since the rename-operation and before the delete-operation return the
// _new_ key
expectedCommitCount = renameCommitVerify(Stream.concat(Stream.of(hashRename), beforeDelete.stream()), expectedCommitCount, keys -> assertThat(keys).containsExactly(KeyListEntry.of(newKey, contentId, payload, hashRename)));
// Verify that the commits since the delete-operation return _no_ keys
expectedCommitCount = renameCommitVerify(Stream.concat(Stream.of(hashDelete), afterDelete.stream()), expectedCommitCount, keys -> assertThat(keys).isEmpty());
assertThat(expectedCommitCount - 1).isEqualTo(param.setupCommits + 1 + param.afterInitialCommits + 1 + param.afterRenameCommits + 1 + param.afterDeleteCommits);
}
use of org.projectnessie.versioned.testworker.BaseContent in project nessie by projectnessie.
the class AbstractDuplicateTable method duplicateTableOnBranches.
/**
* Test behavior when a table (content-key) is created on two different branches using either
* table-types with and without global-states and same/different content-ids.
*/
@ParameterizedTest
@EnumSource(value = DuplicateTableMode.class)
void duplicateTableOnBranches(DuplicateTableMode mode) throws Throwable {
Key key = Key.of("some", "table");
BranchName branch0 = BranchName.of("globalStateDuplicateTable-main");
store().create(branch0, Optional.empty());
// commit just something to have a "real" common ancestor and not "beginning of time", which
// means no-common-ancestor
Hash ancestor = store().commit(branch0, Optional.empty(), commitMessage("initial commit"), ImmutableList.of(Put.of(Key.of("unrelated", "table"), newOnRef("value"))));
// Create a table with the same name on two branches.
// WITH global-states, that must fail
// WITHOUT global-state, it is okay to work
BranchName branch1 = BranchName.of("globalStateDuplicateTable-branch1");
BranchName branch2 = BranchName.of("globalStateDuplicateTable-branch2");
assertThat(store().create(branch1, Optional.of(ancestor))).isEqualTo(ancestor);
assertThat(store().create(branch2, Optional.of(ancestor))).isEqualTo(ancestor);
List<Operation<BaseContent>> putForBranch1;
List<Operation<BaseContent>> putForBranch2;
BaseContent valuebranch1;
BaseContent valuebranch2;
switch(mode) {
case NO_GLOBAL:
valuebranch1 = newOnRef("create table");
valuebranch2 = newOnRef("create table");
putForBranch1 = ImmutableList.of(Put.of(key, valuebranch1));
putForBranch2 = ImmutableList.of(Put.of(key, valuebranch2));
break;
case STATEFUL_SAME_CONTENT_ID:
valuebranch1 = withGlobal("state", "create table", "content-id-equal");
valuebranch2 = withGlobal("state", "create table", "content-id-equal");
putForBranch1 = singletonList(Put.of(key, withGlobal("state", "create table", "content-id-equal")));
putForBranch2 = singletonList(Put.of(key, withGlobal("state", "create table", "content-id-equal")));
break;
case STATEFUL_DIFFERENT_CONTENT_ID:
valuebranch1 = withGlobal("state", "create table", "content-id-1");
valuebranch2 = withGlobal("state", "create table", "content-id-2");
putForBranch1 = singletonList(Put.of(key, withGlobal("state", "create table", "content-id-1")));
putForBranch2 = singletonList(Put.of(key, withGlobal("state", "create table", "content-id-2")));
break;
default:
throw new IllegalStateException();
}
store().commit(branch1, Optional.empty(), commitMessage("create table"), putForBranch1);
assertThat(store().getValue(branch1, key)).isEqualTo(valuebranch1);
ThrowingCallable createTableOnOtherBranch = () -> store().commit(branch2, Optional.empty(), commitMessage("create table on other branch"), putForBranch2);
if (mode == DuplicateTableMode.STATEFUL_SAME_CONTENT_ID) {
assertThatThrownBy(createTableOnOtherBranch).isInstanceOf(ReferenceConflictException.class).hasMessage("Global-state for content-id 'content-id-equal' already exists.");
assertThat(store().getValue(branch2, key)).isNull();
} else {
createTableOnOtherBranch.call();
assertThat(store().getValue(branch2, key)).isEqualTo(valuebranch2);
}
}
use of org.projectnessie.versioned.testworker.BaseContent in project nessie by projectnessie.
the class AbstractAssign method assignReferenceToFreshMain.
/**
* Assigning a branch/tag to a fresh main without any commits didn't work in 0.9.2
*/
@Test
public void assignReferenceToFreshMain() throws ReferenceNotFoundException, ReferenceAlreadyExistsException, ReferenceConflictException {
ReferenceInfo<CommitMessage> main = store.getNamedRef("main", GetNamedRefsParams.DEFAULT);
try (Stream<Commit<CommitMessage, BaseContent>> commits = store().getCommits(main.getHash(), false)) {
assertThat(commits).isEmpty();
}
try (Stream<ReferenceInfo<CommitMessage>> refs = store().getNamedRefs(GetNamedRefsParams.DEFAULT)) {
assertThat(refs).extracting(r -> r.getNamedRef().getName()).containsExactly(main.getNamedRef().getName());
}
BranchName testBranch = BranchName.of("testBranch");
Hash testBranchHash = store.create(testBranch, Optional.empty());
store.assign(testBranch, Optional.of(testBranchHash), main.getHash());
assertThat(store.getNamedRef(testBranch.getName(), GetNamedRefsParams.DEFAULT).getHash()).isEqualTo(main.getHash());
TagName testTag = TagName.of("testTag");
Hash testTagHash = store.create(testTag, Optional.empty());
store.assign(testTag, Optional.of(testTagHash), main.getHash());
assertThat(store.getNamedRef(testTag.getName(), GetNamedRefsParams.DEFAULT).getHash()).isEqualTo(main.getHash());
}
use of org.projectnessie.versioned.testworker.BaseContent in project nessie by projectnessie.
the class AbstractCommitLog method commitLogExtendedNoGlobalState.
@Test
public void commitLogExtendedNoGlobalState() throws Exception {
BranchName branch = BranchName.of("commitLogExtended");
Hash firstParent = store().create(branch, Optional.empty());
int numCommits = 10;
List<Hash> hashes = IntStream.rangeClosed(1, numCommits).mapToObj(i -> {
try {
return commit("Commit #" + i).put("k" + i, onRef("v" + i, "c" + i)).put("key" + i, onRef("value" + i, "cid" + i)).delete("delete" + i).toBranch(branch);
} catch (Exception e) {
throw new RuntimeException(e);
}
}).collect(Collectors.toList());
List<Hash> parentHashes = Stream.concat(Stream.of(firstParent), hashes.subList(0, 9).stream()).collect(Collectors.toList());
assertThat(Lists.reverse(commitsList(branch, false))).allSatisfy(c -> {
assertThat(c.getOperations()).isNull();
assertThat(c.getParentHash()).isNull();
}).extracting(Commit::getHash).containsExactlyElementsOf(hashes);
List<Commit<CommitMessage, BaseContent>> commits = Lists.reverse(commitsList(branch, true));
assertThat(IntStream.rangeClosed(1, numCommits)).allSatisfy(i -> {
Commit<CommitMessage, BaseContent> c = commits.get(i - 1);
assertThat(c).extracting(Commit::getCommitMeta, Commit::getHash, Commit::getParentHash, Commit::getOperations).containsExactly(commitMessage("Commit #" + i), hashes.get(i - 1), parentHashes.get(i - 1), Arrays.asList(Delete.of(Key.of("delete" + i)), Put.of(Key.of("k" + i), onRef("v" + i, "c" + i)), Put.of(Key.of("key" + i), onRef("value" + i, "cid" + i))));
});
}
use of org.projectnessie.versioned.testworker.BaseContent in project nessie by projectnessie.
the class AbstractCommitLog method commitLogPaging.
@Test
public void commitLogPaging() throws Exception {
BranchName branch = BranchName.of("commitLogPaging");
Hash createHash = store().create(branch, Optional.empty());
// this should be enough
int commits = 95;
Hash[] commitHashes = new Hash[commits];
List<CommitMessage> messages = new ArrayList<>(commits);
for (int i = 0; i < commits; i++) {
CommitMessage msg = commitMessage(String.format("commit#%05d", i));
messages.add(msg);
commitHashes[i] = store().commit(branch, Optional.of(i == 0 ? createHash : commitHashes[i - 1]), msg, ImmutableList.of(Put.of(Key.of("table"), newOnRef(String.format("value#%05d", i)))));
}
Collections.reverse(messages);
List<CommitMessage> justTwo = commitsList(branch, s -> s.limit(2).map(Commit::getCommitMeta), false);
assertEquals(messages.subList(0, 2), justTwo);
List<CommitMessage> justTen = commitsList(branch, s -> s.limit(10).map(Commit::getCommitMeta), false);
assertEquals(messages.subList(0, 10), justTen);
int pageSize = 10;
// Test parameter sanity check. Want the last page to be smaller than the page-size.
assertNotEquals(0, commits % (pageSize - 1));
Hash lastHash = null;
for (int offset = 0; ; ) {
List<Commit<CommitMessage, BaseContent>> logPage = commitsList(lastHash == null ? branch : lastHash, s -> s.limit(pageSize), false);
assertEquals(messages.subList(offset, Math.min(offset + pageSize, commits)), logPage.stream().map(Commit::getCommitMeta).collect(Collectors.toList()));
lastHash = logPage.get(logPage.size() - 1).getHash();
offset += pageSize - 1;
if (offset >= commits) {
// The "next after last page" should always return just a single commit, that's basically
// the "end of commit-log"-condition.
logPage = commitsList(lastHash, s -> s.limit(pageSize), false);
assertEquals(Collections.singletonList(messages.get(commits - 1)), logPage.stream().map(Commit::getCommitMeta).collect(Collectors.toList()));
break;
}
}
}
Aggregations