Skip to content

Commit

Permalink
Combined Nessie server+client for testing (#7527)
Browse files Browse the repository at this point in the history
Introduce a new `:nessie-combined-cs` module (under `testing/`) providing a Nessie-API (v2) client that directly calls the service implementations, using the v2 REST endpoint implementations. This eliminates the need for a Jersey/Weld based Nessie endpoint for testing purposes. The implementation in this PR (currently) provides only a new-storage model in-memory backend.
  • Loading branch information
snazy committed Sep 25, 2023
1 parent 45b9bff commit 9463b47
Show file tree
Hide file tree
Showing 30 changed files with 1,603 additions and 0 deletions.
1 change: 1 addition & 0 deletions bom/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ dependencies {
constraints {
api(rootProject)
api(project(":nessie-client"))
api(project(":nessie-combined-cs"))
api(project(":nessie-compatibility-common"))
api(project(":nessie-compatibility-tests"))
api(project(":nessie-compatibility-jersey"))
Expand Down
1 change: 1 addition & 0 deletions gradle/projects.main.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
nessie-bom=bom
nessie-client=api/client
nessie-client-testextension=api/client-testextension
nessie-combined-cs=testing/combined-cs
nessie-compatibility-common=compatibility/common
nessie-compatibility-tests=compatibility/compatibility-tests
nessie-compatibility-jersey=compatibility/jersey
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
import org.projectnessie.client.ext.NessieClientFactory;
import org.projectnessie.error.BaseNessieClientServerException;
import org.projectnessie.error.ContentKeyErrorDetails;
import org.projectnessie.error.ErrorCode;
import org.projectnessie.error.NessieBadRequestException;
import org.projectnessie.error.NessieConflictException;
import org.projectnessie.error.NessieContentNotFoundException;
Expand Down Expand Up @@ -2019,4 +2020,43 @@ void renameTwice() throws Exception {
.hasSize(1)
.containsEntry(key, tableNew);
}

@Test
@NessieApiVersions(versions = {NessieApiVersion.V2})
public void testErrorsV2() throws Exception {
ContentKey key = ContentKey.of("namespace", "foo");
IcebergTable table = IcebergTable.of("content-table1", 42, 42, 42, 42);

Branch main = api().getDefaultBranch();

Branch branch =
(Branch)
api()
.createReference()
.reference(Branch.of("ref-conflicts", main.getHash()))
.sourceRefName(main.getName())
.create();

soft.assertThatThrownBy(
() ->
api()
.commitMultipleOperations()
.commitMeta(fromMessage("commit"))
.operation(Put.of(key, table))
.branch(branch)
.commit())
.isInstanceOf(NessieReferenceConflictException.class)
.asInstanceOf(type(NessieReferenceConflictException.class))
.matches(e -> e.getErrorCode().equals(ErrorCode.REFERENCE_CONFLICT))
.extracting(NessieReferenceConflictException::getErrorDetails)
.asInstanceOf(type(ReferenceConflicts.class))
.extracting(ReferenceConflicts::conflicts, list(Conflict.class))
.hasSize(1)
.extracting(Conflict::conflictType)
.containsExactly(ConflictType.NAMESPACE_ABSENT);

soft.assertThatThrownBy(() -> api().getReference().refName("main@12345678").get())
.isInstanceOf(NessieBadRequestException.class)
.hasMessageEndingWith("Hashes are not allowed when fetching a reference by name");
}
}
10 changes: 10 additions & 0 deletions testing/combined-cs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Nessie Client directly accessing a Nessie backend

... without REST or any other intermediate protocol.

**NOT FOR PRODUCTION USE**

* No access checks
* (possibly) not fully tested and (possibly) does not provide the same behavior
* Meant for testing use cases that do not want to or cannot use (another) Jersey/Weld instance
* (Currently?) only implemented for (and useful with?) an in-memory backend
73 changes: 73 additions & 0 deletions testing/combined-cs/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (C) 2023 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.
*/

plugins {
id("nessie-conventions-server")
id("nessie-jacoco")
}

extra["maven.name"] = "Nessie - Combined Client and Server"

dependencies {
api(project(":nessie-client"))
api(project(":nessie-model"))
implementation(project(":nessie-rest-services"))
implementation(project(":nessie-services"))
implementation(project(":nessie-server-store"))
implementation(project(":nessie-versioned-spi"))
implementation(project(":nessie-versioned-persist-store"))
implementation(project(":nessie-versioned-storage-common"))
implementation(project(":nessie-versioned-storage-inmemory"))
implementation(project(":nessie-versioned-storage-store"))
implementation(libs.slf4j.api)

// javax/jakarta
compileOnly(libs.jakarta.ws.rs.api)
compileOnly(libs.javax.ws.rs21)
compileOnly(libs.jakarta.enterprise.cdi.api)
compileOnly(libs.javax.enterprise.cdi.api)
compileOnly(libs.jakarta.annotation.api)
compileOnly(libs.findbugs.jsr305)
compileOnly(libs.jakarta.validation.api)
compileOnly(libs.javax.validation.api)

compileOnly(libs.microprofile.openapi)

compileOnly(libs.hibernate.validator.cdi)

implementation(platform(libs.jackson.bom))
implementation("com.fasterxml.jackson.core:jackson-databind")
compileOnly("com.fasterxml.jackson.core:jackson-annotations")

compileOnly(libs.bundles.junit.testing)
compileOnly(project(":nessie-client-testextension"))
compileOnly("org.junit.jupiter:junit-jupiter-engine")

testImplementation(project(":nessie-jaxrs-tests"))

testRuntimeOnly(libs.h2)
testRuntimeOnly(libs.logback.classic)

// javax/jakarta
testCompileOnly(libs.jakarta.annotation.api)
testCompileOnly(libs.findbugs.jsr305)

testCompileOnly(libs.microprofile.openapi)

testImplementation(libs.bundles.junit.testing)
testImplementation(project(":nessie-client-testextension"))
testCompileOnly("org.junit.jupiter:junit-jupiter-engine")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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.nessie.combined;

import org.projectnessie.api.v2.TreeApi;
import org.projectnessie.client.builder.BaseAssignReferenceBuilder;
import org.projectnessie.error.NessieConflictException;
import org.projectnessie.error.NessieNotFoundException;
import org.projectnessie.model.Reference;

abstract class BaseCombinedAssignReference<T extends Reference, B>
extends BaseAssignReferenceBuilder<B> {

private final TreeApi treeApi;

BaseCombinedAssignReference(TreeApi treeApi) {
this.treeApi = treeApi;
}

public void assign() throws NessieNotFoundException, NessieConflictException {
assignAndGet();
}

@SuppressWarnings("unchecked")
public T assignAndGet() throws NessieNotFoundException, NessieConflictException {
try {
String type = super.type != null ? super.type.name() : null;
return (T)
treeApi
.assignReference(type, Reference.toPathString(refName, expectedHash), assignTo)
.getReference();
} catch (RuntimeException e) {
throw CombinedClientImpl.maybeWrapException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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.nessie.combined;

import org.projectnessie.api.v2.TreeApi;
import org.projectnessie.client.builder.BaseChangeReferenceBuilder;
import org.projectnessie.error.NessieConflictException;
import org.projectnessie.error.NessieNotFoundException;
import org.projectnessie.model.Reference;

abstract class BaseCombinedDeleteReference<T extends Reference, B>
extends BaseChangeReferenceBuilder<B> {

private final TreeApi treeApi;

BaseCombinedDeleteReference(TreeApi treeApi) {
this.treeApi = treeApi;
}

public void delete() throws NessieConflictException, NessieNotFoundException {
getAndDelete();
}

@SuppressWarnings("unchecked")
public T getAndDelete() throws NessieNotFoundException, NessieConflictException {
String type = super.type != null ? super.type.name() : null;
try {
return (T)
treeApi
.deleteReference(type, Reference.toPathString(refName, expectedHash))
.getReference();
} catch (RuntimeException e) {
throw CombinedClientImpl.maybeWrapException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* 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.nessie.combined;

import org.projectnessie.api.v2.TreeApi;
import org.projectnessie.client.api.AssignBranchBuilder;
import org.projectnessie.model.Branch;
import org.projectnessie.model.Reference.ReferenceType;

final class CombinedAssignBranch extends BaseCombinedAssignReference<Branch, AssignBranchBuilder>
implements AssignBranchBuilder {

CombinedAssignBranch(TreeApi treeApi) {
super(treeApi);
refType(ReferenceType.BRANCH);
}

@Override
public AssignBranchBuilder branchName(String branchName) {
return refName(branchName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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.nessie.combined;

import org.projectnessie.api.v2.TreeApi;
import org.projectnessie.client.api.AssignReferenceBuilder;
import org.projectnessie.model.Reference;

final class CombinedAssignReference
extends BaseCombinedAssignReference<Reference, AssignReferenceBuilder<Reference>>
implements AssignReferenceBuilder<Reference> {

CombinedAssignReference(TreeApi treeApi) {
super(treeApi);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* 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.nessie.combined;

import org.projectnessie.api.v2.TreeApi;
import org.projectnessie.client.api.AssignTagBuilder;
import org.projectnessie.model.Reference.ReferenceType;
import org.projectnessie.model.Tag;

final class CombinedAssignTag extends BaseCombinedAssignReference<Tag, AssignTagBuilder>
implements AssignTagBuilder {

CombinedAssignTag(TreeApi treeApi) {
super(treeApi);
refType(ReferenceType.TAG);
}

@Override
public AssignTagBuilder tagName(String tagName) {
return refName(tagName);
}
}

0 comments on commit 9463b47

Please sign in to comment.