Merge "Merge branch 'stable-2.16'"
diff --git a/javatests/com/google/gerrit/acceptance/git/AbstractSubmoduleSubscription.java b/javatests/com/google/gerrit/acceptance/git/AbstractSubmoduleSubscription.java
index 2633569..9e2efd8 100644
--- a/javatests/com/google/gerrit/acceptance/git/AbstractSubmoduleSubscription.java
+++ b/javatests/com/google/gerrit/acceptance/git/AbstractSubmoduleSubscription.java
@@ -108,19 +108,6 @@
return project;
}
- protected TestRepository<?> createProjectWithPush(String name) throws Exception {
- return createProjectWithPush(name, null, true, getSubmitType());
- }
-
- protected TestRepository<?> createProjectWithPush(
- String name,
- @Nullable Project.NameKey parent,
- boolean createEmptyCommit,
- SubmitType submitType)
- throws Exception {
- return cloneProject(createProjectForPush(name, parent, createEmptyCommit, submitType));
- }
-
private static AtomicInteger contentCounter = new AtomicInteger(0);
protected TestRepository<?> superRepo;
protected Project.NameKey superKey;
diff --git a/javatests/com/google/gerrit/acceptance/git/BUILD b/javatests/com/google/gerrit/acceptance/git/BUILD
index 3541fec..6fa510a 100644
--- a/javatests/com/google/gerrit/acceptance/git/BUILD
+++ b/javatests/com/google/gerrit/acceptance/git/BUILD
@@ -7,6 +7,7 @@
deps = [
":push_for_review",
":submodule_util",
+ "//lib/commons:lang",
],
)
diff --git a/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java b/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java
index 96b545c..d3d1ab3 100644
--- a/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java
@@ -21,15 +21,20 @@
import com.google.common.collect.ImmutableList;
import com.google.gerrit.acceptance.NoHttpd;
+import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
+import com.google.gerrit.common.data.Permission;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.client.ChangeStatus;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Project.NameKey;
import com.google.gerrit.server.change.TestSubmitInput;
import com.google.gerrit.testing.ConfigSuite;
+import com.google.inject.Inject;
import java.util.ArrayDeque;
import java.util.Map;
+import org.apache.commons.lang.RandomStringUtils;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
@@ -66,6 +71,8 @@
return submitByRebaseIfNecessaryConfig();
}
+ @Inject ProjectOperations projectOperations;
+
@Test
public void subscriptionUpdateOfManyChanges() throws Exception {
allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
@@ -270,66 +277,60 @@
@Test
public void updateManySubmodules() throws Exception {
- Project.NameKey subKey1 = createProjectForPush("sub1", null, true, getSubmitType());
- Project.NameKey subKey2 = createProjectForPush("sub2", null, true, getSubmitType());
- Project.NameKey subKey3 = createProjectForPush("sub3", null, true, getSubmitType());
+ Project.NameKey subKey[] = new NameKey[3];
+ TestRepository<?> sub[] = new TestRepository[3];
+ String prefix = RandomStringUtils.randomAlphabetic(8);
+ for (int i = 0; i < subKey.length; i++) {
+ subKey[i] =
+ projectOperations
+ .newProject()
+ .name(prefix + "sub" + i)
+ .withEmptyCommit()
+ .submitType(getSubmitType())
+ .create();
+ grant(subKey[i], "refs/heads/*", Permission.PUSH);
+ grant(subKey[i], "refs/for/refs/heads/*", Permission.SUBMIT);
+ sub[i] = cloneProject(subKey[i]);
+ }
- TestRepository<?> sub1 = cloneProject(subKey1);
- TestRepository<?> sub2 = cloneProject(subKey2);
- TestRepository<?> sub3 = cloneProject(subKey3);
-
- allowMatchingSubmoduleSubscription(subKey1, "refs/heads/master", superKey, "refs/heads/master");
- allowMatchingSubmoduleSubscription(subKey2, "refs/heads/master", superKey, "refs/heads/master");
- allowMatchingSubmoduleSubscription(subKey3, "refs/heads/master", superKey, "refs/heads/master");
+ for (int i = 0; i < subKey.length; i++) {
+ allowMatchingSubmoduleSubscription(
+ subKey[i], "refs/heads/master", superKey, "refs/heads/master");
+ }
Config config = new Config();
- prepareSubmoduleConfigEntry(config, subKey1, "master");
- prepareSubmoduleConfigEntry(config, subKey2, "master");
- prepareSubmoduleConfigEntry(config, subKey3, "master");
+ for (int i = 0; i < subKey.length; i++) {
+ prepareSubmoduleConfigEntry(config, subKey[i], "master");
+ }
pushSubmoduleConfig(superRepo, "master", config);
ObjectId superPreviousId = pushChangeTo(superRepo, "master");
- ObjectId sub1Id = pushChangeTo(sub1, "refs/for/master", "some message", "same-topic");
- ObjectId sub2Id = pushChangeTo(sub2, "refs/for/master", "some message", "same-topic");
- ObjectId sub3Id = pushChangeTo(sub3, "refs/for/master", "some message", "same-topic");
+ ObjectId subId[] = new ObjectId[3];
- approve(getChangeId(sub1, sub1Id).get());
- approve(getChangeId(sub2, sub2Id).get());
- approve(getChangeId(sub3, sub3Id).get());
+ for (int i = 0; i < sub.length; i++) {
+ subId[i] = pushChangeTo(sub[i], "refs/for/master", "some message", "same-topic");
+ approve(getChangeId(sub[i], subId[i]).get());
+ }
- gApi.changes().id(getChangeId(sub1, sub1Id).get()).current().submit();
+ gApi.changes().id(getChangeId(sub[0], subId[0]).get()).current().submit();
- expectToHaveSubmoduleState(superRepo, "master", subKey1, sub1, "master");
- expectToHaveSubmoduleState(superRepo, "master", subKey2, sub2, "master");
- expectToHaveSubmoduleState(superRepo, "master", subKey3, sub3, "master");
+ for (int i = 0; i < sub.length; i++) {
+ expectToHaveSubmoduleState(superRepo, "master", subKey[i], sub[i], "master");
+ }
- String sub1HEAD =
- sub1.git()
- .fetch()
- .setRemote("origin")
- .call()
- .getAdvertisedRef("refs/heads/master")
- .getObjectId()
- .name();
-
- String sub2HEAD =
- sub2.git()
- .fetch()
- .setRemote("origin")
- .call()
- .getAdvertisedRef("refs/heads/master")
- .getObjectId()
- .name();
-
- String sub3HEAD =
- sub3.git()
- .fetch()
- .setRemote("origin")
- .call()
- .getAdvertisedRef("refs/heads/master")
- .getObjectId()
- .name();
+ String heads[] = new String[3];
+ for (int i = 0; i < heads.length; i++) {
+ heads[i] =
+ sub[i]
+ .git()
+ .fetch()
+ .setRemote("origin")
+ .call()
+ .getAdvertisedRef("refs/heads/master")
+ .getObjectId()
+ .name();
+ }
if (getSubmitType() == SubmitType.MERGE_IF_NECESSARY) {
expectToHaveCommitMessage(
@@ -337,17 +338,17 @@
"master",
"Update git submodules\n\n"
+ "* Update "
- + subKey1.get()
+ + subKey[0].get()
+ " from branch 'master'\n to "
- + sub1HEAD
+ + heads[0]
+ "\n\n* Update "
- + subKey2.get()
+ + subKey[1].get()
+ " from branch 'master'\n to "
- + sub2HEAD
+ + heads[1]
+ "\n\n* Update "
- + subKey3.get()
+ + subKey[2].get()
+ " from branch 'master'\n to "
- + sub3HEAD);
+ + heads[2]);
}
superRepo
diff --git a/javatests/com/google/gerrit/acceptance/rest/AbstractRestApiBindingsTest.java b/javatests/com/google/gerrit/acceptance/rest/AbstractRestApiBindingsTest.java
deleted file mode 100644
index 2bb3dca..0000000
--- a/javatests/com/google/gerrit/acceptance/rest/AbstractRestApiBindingsTest.java
+++ /dev/null
@@ -1,165 +0,0 @@
-// 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.acceptance.rest;
-
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.truth.Truth.assertWithMessage;
-import static org.apache.http.HttpStatus.SC_FORBIDDEN;
-import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
-import static org.apache.http.HttpStatus.SC_METHOD_NOT_ALLOWED;
-import static org.apache.http.HttpStatus.SC_NOT_FOUND;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.ImmutableList;
-import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.RestResponse;
-import java.util.List;
-import java.util.Optional;
-import org.apache.commons.lang.StringUtils;
-import org.junit.Ignore;
-
-/**
- * Base class for testing the REST API bindings.
- *
- * <p>This test sends a request to each REST endpoint and verifies that an implementation is found
- * (no '404 Not Found' response) and that the request doesn't fail (no '500 Internal Server Error'
- * response). It doesn't verify that the REST endpoint works correctly. This is okay since the
- * purpose of the test is only to verify that the REST endpoint implementations are correctly bound.
- */
-@Ignore
-public abstract class AbstractRestApiBindingsTest extends AbstractDaemonTest {
- protected void execute(List<RestCall> restCalls, String... args) throws Exception {
- execute(restCalls, () -> {}, args);
- }
-
- protected void execute(List<RestCall> restCalls, BeforeRestCall beforeRestCall, String... args)
- throws Exception {
- for (RestCall restCall : restCalls) {
- beforeRestCall.run();
- execute(restCall, args);
- }
- }
-
- protected void execute(RestCall restCall, String... args) throws Exception {
- String method = restCall.httpMethod().name();
- String uri = restCall.uri(args);
-
- RestResponse response;
- switch (restCall.httpMethod()) {
- case GET:
- response = adminRestSession.get(uri);
- break;
- case PUT:
- response = adminRestSession.put(uri);
- break;
- case POST:
- response = adminRestSession.post(uri);
- break;
- case DELETE:
- response = adminRestSession.delete(uri);
- break;
- default:
- fail("unsupported method: %s", restCall.httpMethod().name());
- throw new IllegalStateException();
- }
-
- int status = response.getStatusCode();
- String body = response.hasContent() ? response.getEntityContent() : "";
-
- String msg = String.format("%s %s returned %d: %s", method, uri, status, body);
- if (restCall.expectedResponseCode().isPresent()) {
- assertWithMessage(msg).that(status).isEqualTo(restCall.expectedResponseCode().get());
- if (restCall.expectedMessage().isPresent()) {
- assertWithMessage(msg).that(body).contains(restCall.expectedMessage().get());
- }
- } else {
- assertWithMessage(msg)
- .that(status)
- .isNotIn(ImmutableList.of(SC_FORBIDDEN, SC_NOT_FOUND, SC_METHOD_NOT_ALLOWED));
- assertWithMessage(msg).that(status).isLessThan(SC_INTERNAL_SERVER_ERROR);
- }
- }
-
- enum Method {
- GET,
- PUT,
- POST,
- DELETE
- }
-
- @AutoValue
- abstract static class RestCall {
- static RestCall get(String uriFormat) {
- return builder(Method.GET, uriFormat).build();
- }
-
- static RestCall put(String uriFormat) {
- return builder(Method.PUT, uriFormat).build();
- }
-
- static RestCall post(String uriFormat) {
- return builder(Method.POST, uriFormat).build();
- }
-
- static RestCall delete(String uriFormat) {
- return builder(Method.DELETE, uriFormat).build();
- }
-
- static Builder builder(Method httpMethod, String uriFormat) {
- return new AutoValue_AbstractRestApiBindingsTest_RestCall.Builder()
- .httpMethod(httpMethod)
- .uriFormat(uriFormat);
- }
-
- abstract Method httpMethod();
-
- abstract String uriFormat();
-
- abstract Optional<Integer> expectedResponseCode();
-
- abstract Optional<String> expectedMessage();
-
- String uri(String... args) {
- String uriFormat = uriFormat();
- int expectedArgNum = StringUtils.countMatches(uriFormat, "%s");
- checkState(
- args.length == expectedArgNum,
- "uriFormat %s needs %s arguments, got only %s: %s",
- uriFormat,
- expectedArgNum,
- args.length,
- args);
- return String.format(uriFormat, (Object[]) args);
- }
-
- @AutoValue.Builder
- abstract static class Builder {
- abstract Builder httpMethod(Method httpMethod);
-
- abstract Builder uriFormat(String uriFormat);
-
- abstract Builder expectedResponseCode(int expectedResponseCode);
-
- abstract Builder expectedMessage(String expectedMessage);
-
- abstract RestCall build();
- }
- }
-
- @FunctionalInterface
- public interface BeforeRestCall {
- void run() throws Exception;
- }
-}
diff --git a/javatests/com/google/gerrit/acceptance/rest/BUILD b/javatests/com/google/gerrit/acceptance/rest/BUILD
index b94a98d..84887da 100644
--- a/javatests/com/google/gerrit/acceptance/rest/BUILD
+++ b/javatests/com/google/gerrit/acceptance/rest/BUILD
@@ -2,23 +2,9 @@
acceptance_tests(
srcs = glob(["*IT.java"]),
- group = "rest_bindings",
+ group = "rest_bindings_collection",
labels = ["rest"],
deps = [
- ":util",
"//java/com/google/gerrit/server/logging",
],
)
-
-java_library(
- name = "util",
- testonly = 1,
- srcs = [
- "AbstractRestApiBindingsTest.java",
- ],
- visibility = ["//visibility:public"],
- deps = [
- "//java/com/google/gerrit/acceptance:lib",
- "//lib/commons:lang",
- ],
-)
diff --git a/javatests/com/google/gerrit/acceptance/rest/DeleteOnCollectionIT.java b/javatests/com/google/gerrit/acceptance/rest/DeleteOnCollectionIT.java
index 4de436a..d891d6e 100644
--- a/javatests/com/google/gerrit/acceptance/rest/DeleteOnCollectionIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/DeleteOnCollectionIT.java
@@ -36,13 +36,8 @@
public void configure() {
deleteOnCollection(BRANCH_KIND)
.toInstance(
- new RestCollectionModifyView<ProjectResource, BranchResource, Object>() {
- @Override
- public Object apply(ProjectResource parentResource, Object input)
- throws Exception {
- return Response.none();
- }
- });
+ (RestCollectionModifyView<ProjectResource, BranchResource, Object>)
+ (parentResource, input) -> Response.none());
}
};
}
diff --git a/javatests/com/google/gerrit/acceptance/rest/AccountsRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/AccountsRestApiBindingsIT.java
similarity index 90%
rename from javatests/com/google/gerrit/acceptance/rest/AccountsRestApiBindingsIT.java
rename to javatests/com/google/gerrit/acceptance/rest/binding/AccountsRestApiBindingsIT.java
index b0adba7..7f55744 100644
--- a/javatests/com/google/gerrit/acceptance/rest/AccountsRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/AccountsRestApiBindingsIT.java
@@ -12,15 +12,18 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.acceptance.rest;
+package com.google.gerrit.acceptance.rest.binding;
-import static com.google.gerrit.acceptance.rest.AbstractRestApiBindingsTest.Method.PUT;
+import static com.google.gerrit.acceptance.rest.util.RestApiCallHelper.execute;
+import static com.google.gerrit.acceptance.rest.util.RestCall.Method.PUT;
import static com.google.gerrit.gpg.testing.TestKeys.validKeyWithoutExpiration;
import static org.apache.http.HttpStatus.SC_METHOD_NOT_ALLOWED;
import com.google.common.collect.ImmutableList;
+import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.GerritConfig;
import com.google.gerrit.acceptance.UseSsh;
+import com.google.gerrit.acceptance.rest.util.RestCall;
import com.google.gerrit.extensions.common.ChangeInput;
import com.google.gerrit.gpg.testing.TestKey;
import com.google.gerrit.server.ServerInitiated;
@@ -34,10 +37,9 @@
* Tests for checking the bindings of the accounts REST API.
*
* <p>These tests only verify that the account REST endpoints are correctly bound, they do no test
- * the functionality of the account REST endpoints (for details see JavaDoc on {@link
- * AbstractRestApiBindingsTest}).
+ * the functionality of the account REST endpoints.
*/
-public class AccountsRestApiBindingsIT extends AbstractRestApiBindingsTest {
+public class AccountsRestApiBindingsIT extends AbstractDaemonTest {
@Inject private @ServerInitiated Provider<AccountsUpdate> accountsUpdateProvider;
/**
@@ -143,12 +145,12 @@
@Test
public void accountEndpoints() throws Exception {
- execute(ACCOUNT_ENDPOINTS, "self");
+ execute(adminRestSession, ACCOUNT_ENDPOINTS, "self");
}
@Test
public void emailEndpoints() throws Exception {
- execute(EMAIL_ENDPOINTS, "self", admin.email);
+ execute(adminRestSession, EMAIL_ENDPOINTS, "self", admin.email);
}
@Test
@@ -172,20 +174,20 @@
.self()
.putGpgKeys(ImmutableList.of(key.getPublicKeyArmored()), ImmutableList.of());
- execute(GPG_KEY_ENDPOINTS, "self", id);
+ execute(adminRestSession, GPG_KEY_ENDPOINTS, "self", id);
}
@Test
@UseSsh
public void sshKeyEndpoints() throws Exception {
String sshKeySeq = Integer.toString(gApi.accounts().self().listSshKeys().size());
- execute(SSH_KEY_ENDPOINTS, "self", sshKeySeq);
+ execute(adminRestSession, SSH_KEY_ENDPOINTS, "self", sshKeySeq);
}
@Test
public void starEndpoints() throws Exception {
ChangeInput ci = new ChangeInput(project.get(), "master", "Test change");
String changeId = gApi.changes().create(ci).get().id;
- execute(STAR_ENDPOINTS, "self", changeId);
+ execute(adminRestSession, STAR_ENDPOINTS, "self", changeId);
}
}
diff --git a/javatests/com/google/gerrit/acceptance/rest/binding/BUILD b/javatests/com/google/gerrit/acceptance/rest/binding/BUILD
new file mode 100644
index 0000000..e4242a9
--- /dev/null
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/BUILD
@@ -0,0 +1,11 @@
+load("//javatests/com/google/gerrit/acceptance:tests.bzl", "acceptance_tests")
+
+acceptance_tests(
+ srcs = glob(["*IT.java"]),
+ group = "rest_bindings",
+ labels = ["rest"],
+ deps = [
+ "//java/com/google/gerrit/server/logging",
+ "//javatests/com/google/gerrit/acceptance/rest/util",
+ ],
+)
diff --git a/javatests/com/google/gerrit/acceptance/rest/ChangesRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/ChangesRestApiBindingsIT.java
similarity index 91%
rename from javatests/com/google/gerrit/acceptance/rest/ChangesRestApiBindingsIT.java
rename to javatests/com/google/gerrit/acceptance/rest/binding/ChangesRestApiBindingsIT.java
index 59c0903..628b63f 100644
--- a/javatests/com/google/gerrit/acceptance/rest/ChangesRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/ChangesRestApiBindingsIT.java
@@ -12,16 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.acceptance.rest;
+package com.google.gerrit.acceptance.rest.binding;
import static com.google.common.truth.TruthJUnit.assume;
-import static com.google.gerrit.acceptance.rest.AbstractRestApiBindingsTest.Method.GET;
+import static com.google.gerrit.acceptance.rest.util.RestCall.Method.GET;
import static com.google.gerrit.extensions.common.testing.RobotCommentInfoSubject.assertThatList;
import static java.util.stream.Collectors.toList;
import static org.apache.http.HttpStatus.SC_NOT_FOUND;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
+import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.rest.util.RestApiCallHelper;
+import com.google.gerrit.acceptance.rest.util.RestCall;
import com.google.gerrit.extensions.api.changes.AddReviewerInput;
import com.google.gerrit.extensions.api.changes.DraftInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
@@ -43,10 +46,9 @@
* Tests for checking the bindings of the changes REST API.
*
* <p>These tests only verify that the change REST endpoints are correctly bound, they do no test
- * the functionality of the change REST endpoints (for details see JavaDoc on {@link
- * AbstractRestApiBindingsTest}).
+ * the functionality of the change REST endpoints.
*/
-public class ChangesRestApiBindingsIT extends AbstractRestApiBindingsTest {
+public class ChangesRestApiBindingsIT extends AbstractDaemonTest {
/**
* Change REST endpoints to be tested, each URL contains a placeholder for the change identifier.
*/
@@ -279,7 +281,7 @@
public void changeEndpoints() throws Exception {
String changeId = createChange().getChangeId();
gApi.changes().id(changeId).edit().create();
- execute(CHANGE_ENDPOINTS, changeId);
+ RestApiCallHelper.execute(adminRestSession, CHANGE_ENDPOINTS, changeId);
}
@Test
@@ -287,7 +289,7 @@
assume().that(notesMigration.readChanges()).isTrue();
String changeId = createChange().getChangeId();
- execute(CHANGE_ENDPOINTS_NOTEDB, changeId);
+ RestApiCallHelper.execute(adminRestSession, CHANGE_ENDPOINTS_NOTEDB, changeId);
}
@Test
@@ -297,7 +299,8 @@
AddReviewerInput addReviewerInput = new AddReviewerInput();
addReviewerInput.reviewer = user.email;
- execute(
+ RestApiCallHelper.execute(
+ adminRestSession,
REVIEWER_ENDPOINTS,
() -> gApi.changes().id(changeId).addReviewer(addReviewerInput),
changeId,
@@ -308,7 +311,8 @@
public void voteEndpoints() throws Exception {
String changeId = createChange().getChangeId();
- execute(
+ RestApiCallHelper.execute(
+ adminRestSession,
VOTE_ENDPOINTS,
() -> gApi.changes().id(changeId).current().review(ReviewInput.approve()),
changeId,
@@ -319,7 +323,7 @@
@Test
public void revisionEndpoints() throws Exception {
String changeId = createChange().getChangeId();
- execute(REVISION_ENDPOINTS, changeId, "current");
+ RestApiCallHelper.execute(adminRestSession, REVISION_ENDPOINTS, changeId, "current");
}
@Test
@@ -329,7 +333,8 @@
AddReviewerInput addReviewerInput = new AddReviewerInput();
addReviewerInput.reviewer = user.email;
- execute(
+ RestApiCallHelper.execute(
+ adminRestSession,
REVISION_REVIEWER_ENDPOINTS,
() -> gApi.changes().id(changeId).addReviewer(addReviewerInput),
changeId,
@@ -341,7 +346,8 @@
public void revisionVoteEndpoints() throws Exception {
String changeId = createChange().getChangeId();
- execute(
+ RestApiCallHelper.execute(
+ adminRestSession,
REVISION_VOTE_ENDPOINTS,
() -> gApi.changes().id(changeId).current().review(ReviewInput.approve()),
changeId,
@@ -362,7 +368,7 @@
draftInput.message = "draft comment";
CommentInfo draftInfo = gApi.changes().id(changeId).current().createDraft(draftInput).get();
- execute(restCall, changeId, "current", draftInfo.id);
+ RestApiCallHelper.execute(adminRestSession, restCall, changeId, "current", draftInfo.id);
}
}
@@ -382,7 +388,7 @@
reviewInput.drafts = DraftHandling.PUBLISH;
gApi.changes().id(changeId).current().review(reviewInput);
- execute(restCall, changeId, "current", commentInfo.id);
+ RestApiCallHelper.execute(adminRestSession, restCall, changeId, "current", commentInfo.id);
}
}
@@ -409,7 +415,8 @@
gApi.changes().id(changeId).current().robotCommentsAsList();
RobotCommentInfo robotCommentInfo = Iterables.getOnlyElement(robotCommentInfos);
- execute(ROBOT_COMMENT_ENDPOINTS, changeId, "current", robotCommentInfo.id);
+ RestApiCallHelper.execute(
+ adminRestSession, ROBOT_COMMENT_ENDPOINTS, changeId, "current", robotCommentInfo.id);
}
@Test
@@ -449,13 +456,14 @@
List<String> fixIds = getFixIds(robotCommentInfos);
String fixId = Iterables.getOnlyElement(fixIds);
- execute(FIX_ENDPOINTS, changeId, "current", fixId);
+ RestApiCallHelper.execute(adminRestSession, FIX_ENDPOINTS, changeId, "current", fixId);
}
@Test
public void revisionFileEndpoints() throws Exception {
String changeId = createChange("Subject", FILENAME, "content").getChangeId();
- execute(REVISION_FILE_ENDPOINTS, changeId, "current", FILENAME);
+ RestApiCallHelper.execute(
+ adminRestSession, REVISION_FILE_ENDPOINTS, changeId, "current", FILENAME);
}
@Test
@@ -465,7 +473,8 @@
// A change message is created on change creation.
String changeMessageId = Iterables.getOnlyElement(gApi.changes().id(changeId).messages()).id;
- execute(CHANGE_MESSAGE_ENDPOINTS, changeId, changeMessageId);
+ RestApiCallHelper.execute(
+ adminRestSession, CHANGE_MESSAGE_ENDPOINTS, changeId, changeMessageId);
}
@Test
@@ -473,7 +482,8 @@
String changeId = createChange("Subject", FILENAME, "content").getChangeId();
// Each of the REST calls creates the change edit newly.
- execute(
+ RestApiCallHelper.execute(
+ adminRestSession,
CHANGE_EDIT_CREATE_ENDPOINTS,
() -> adminRestSession.delete("/changes/" + changeId + "/edit"),
changeId,
@@ -484,7 +494,7 @@
public void changeEditEndpoints() throws Exception {
String changeId = createChange("Subject", FILENAME, "content").getChangeId();
gApi.changes().id(changeId).edit().create();
- execute(CHANGE_EDIT_ENDPOINTS, changeId, FILENAME);
+ RestApiCallHelper.execute(adminRestSession, CHANGE_EDIT_ENDPOINTS, changeId, FILENAME);
}
private static Comment.Range createRange(
diff --git a/javatests/com/google/gerrit/acceptance/rest/ConfigRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/ConfigRestApiBindingsIT.java
similarity index 87%
rename from javatests/com/google/gerrit/acceptance/rest/ConfigRestApiBindingsIT.java
rename to javatests/com/google/gerrit/acceptance/rest/binding/ConfigRestApiBindingsIT.java
index 508d407..f187094 100644
--- a/javatests/com/google/gerrit/acceptance/rest/ConfigRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/ConfigRestApiBindingsIT.java
@@ -12,13 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.acceptance.rest;
+package com.google.gerrit.acceptance.rest.binding;
import static com.google.common.truth.Truth8.assertThat;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import com.google.common.collect.ImmutableList;
+import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.RestResponse;
+import com.google.gerrit.acceptance.rest.util.RestApiCallHelper;
+import com.google.gerrit.acceptance.rest.util.RestCall;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.server.project.ProjectCacheImpl;
import com.google.gerrit.server.restapi.config.ListTasks.TaskInfo;
@@ -31,10 +34,9 @@
* Tests for checking the bindings of the config REST API.
*
* <p>These tests only verify that the config REST endpoints are correctly bound, they do no test
- * the functionality of the config REST endpoints (for details see JavaDoc on {@link
- * AbstractRestApiBindingsTest}).
+ * the functionality of the config REST endpoints.
*/
-public class ConfigRestApiBindingsIT extends AbstractRestApiBindingsTest {
+public class ConfigRestApiBindingsIT extends AbstractDaemonTest {
/**
* Config REST endpoints to be tested, the URLs contain no placeholders since the only supported
* config identifier ('server') can be hard-coded.
@@ -83,12 +85,12 @@
// 'Access Database' is needed for the '/config/server/check.consistency' REST endpoint
allowGlobalCapabilities(REGISTERED_USERS, GlobalCapability.ACCESS_DATABASE);
- execute(CONFIG_ENDPOINTS);
+ RestApiCallHelper.execute(adminRestSession, CONFIG_ENDPOINTS);
}
@Test
public void cacheEndpoints() throws Exception {
- execute(CACHE_ENDPOINTS, ProjectCacheImpl.CACHE_NAME);
+ RestApiCallHelper.execute(adminRestSession, CACHE_ENDPOINTS, ProjectCacheImpl.CACHE_NAME);
}
@Test
@@ -106,6 +108,6 @@
.findFirst();
assertThat(id).isPresent();
- execute(TASK_ENDPOINTS, id.get());
+ RestApiCallHelper.execute(adminRestSession, TASK_ENDPOINTS, id.get());
}
}
diff --git a/javatests/com/google/gerrit/acceptance/rest/GroupsRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/GroupsRestApiBindingsIT.java
similarity index 85%
rename from javatests/com/google/gerrit/acceptance/rest/GroupsRestApiBindingsIT.java
rename to javatests/com/google/gerrit/acceptance/rest/binding/GroupsRestApiBindingsIT.java
index 4538f75..b37bb01 100644
--- a/javatests/com/google/gerrit/acceptance/rest/GroupsRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/GroupsRestApiBindingsIT.java
@@ -12,19 +12,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.acceptance.rest;
+package com.google.gerrit.acceptance.rest.binding;
import com.google.common.collect.ImmutableList;
+import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.rest.util.RestApiCallHelper;
+import com.google.gerrit.acceptance.rest.util.RestCall;
import org.junit.Test;
/**
* Tests for checking the bindings of the groups REST API.
*
* <p>These tests only verify that the group REST endpoints are correctly bound, they do no test the
- * functionality of the group REST endpoints (for details see JavaDoc on {@link
- * AbstractRestApiBindingsTest}).
+ * functionality of the group REST endpoints.
*/
-public class GroupsRestApiBindingsIT extends AbstractRestApiBindingsTest {
+public class GroupsRestApiBindingsIT extends AbstractDaemonTest {
/**
* Group REST endpoints to be tested, each URL contains a placeholder for the group identifier.
*/
@@ -80,14 +82,14 @@
@Test
public void groupEndpoints() throws Exception {
String group = gApi.groups().create("test-group").get().name;
- execute(GROUP_ENDPOINTS, group);
+ RestApiCallHelper.execute(adminRestSession, GROUP_ENDPOINTS, group);
}
@Test
public void memberEndpoints() throws Exception {
String group = gApi.groups().create("test-group").get().name;
gApi.groups().id(group).addMembers(admin.email);
- execute(MEMBER_ENDPOINTS, group, admin.email);
+ RestApiCallHelper.execute(adminRestSession, MEMBER_ENDPOINTS, group, admin.email);
}
@Test
@@ -95,6 +97,6 @@
String group = gApi.groups().create("test-group").get().name;
String subgroup = gApi.groups().create("test-subgroup").get().name;
gApi.groups().id(group).addGroups(subgroup);
- execute(SUBGROUP_ENDPOINTS, group, subgroup);
+ RestApiCallHelper.execute(adminRestSession, SUBGROUP_ENDPOINTS, group, subgroup);
}
}
diff --git a/javatests/com/google/gerrit/acceptance/rest/PluginsRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/PluginsRestApiBindingsIT.java
similarity index 85%
rename from javatests/com/google/gerrit/acceptance/rest/PluginsRestApiBindingsIT.java
rename to javatests/com/google/gerrit/acceptance/rest/binding/PluginsRestApiBindingsIT.java
index 07ea3d0..5616ebc 100644
--- a/javatests/com/google/gerrit/acceptance/rest/PluginsRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/PluginsRestApiBindingsIT.java
@@ -12,12 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.acceptance.rest;
+package com.google.gerrit.acceptance.rest.binding;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.collect.ImmutableList;
+import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.GerritConfig;
+import com.google.gerrit.acceptance.rest.util.RestApiCallHelper;
+import com.google.gerrit.acceptance.rest.util.RestCall;
import com.google.gerrit.common.RawInputUtil;
import com.google.gerrit.extensions.api.plugins.InstallPluginInput;
import com.google.gerrit.extensions.restapi.RawInput;
@@ -27,10 +30,9 @@
* Tests for checking the bindings of the plugins REST API.
*
* <p>These tests only verify that the plugin REST endpoints are correctly bound, they do no test
- * the functionality of the plugin REST endpoints (for details see JavaDoc on {@link
- * AbstractRestApiBindingsTest}).
+ * the functionality of the plugin REST endpoints.
*/
-public class PluginsRestApiBindingsIT extends AbstractRestApiBindingsTest {
+public class PluginsRestApiBindingsIT extends AbstractDaemonTest {
/**
* Plugin REST endpoints to be tested, each URL contains a placeholder for the plugin identifier.
*/
@@ -57,7 +59,7 @@
public void pluginEndpoints() throws Exception {
String pluginName = "my-plugin";
installPlugin(pluginName);
- execute(PLUGIN_ENDPOINTS, pluginName);
+ RestApiCallHelper.execute(adminRestSession, PLUGIN_ENDPOINTS, pluginName);
}
private void installPlugin(String pluginName) throws Exception {
diff --git a/javatests/com/google/gerrit/acceptance/rest/ProjectsRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/ProjectsRestApiBindingsIT.java
similarity index 87%
rename from javatests/com/google/gerrit/acceptance/rest/ProjectsRestApiBindingsIT.java
rename to javatests/com/google/gerrit/acceptance/rest/binding/ProjectsRestApiBindingsIT.java
index ca8d3ce..0c18dbb 100644
--- a/javatests/com/google/gerrit/acceptance/rest/ProjectsRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/ProjectsRestApiBindingsIT.java
@@ -12,18 +12,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.acceptance.rest;
+package com.google.gerrit.acceptance.rest.binding;
import static com.google.gerrit.acceptance.GitUtil.assertPushOk;
import static com.google.gerrit.acceptance.GitUtil.pushHead;
-import static com.google.gerrit.acceptance.rest.AbstractRestApiBindingsTest.Method.GET;
+import static com.google.gerrit.acceptance.rest.util.RestCall.Method.GET;
import static com.google.gerrit.reviewdb.client.RefNames.REFS_DASHBOARDS;
import static com.google.gerrit.server.restapi.project.DashboardsCollection.DEFAULT_DASHBOARD_NAME;
import static org.apache.http.HttpStatus.SC_METHOD_NOT_ALLOWED;
import static org.apache.http.HttpStatus.SC_NOT_FOUND;
import com.google.common.collect.ImmutableList;
+import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.GitUtil;
+import com.google.gerrit.acceptance.rest.util.RestApiCallHelper;
+import com.google.gerrit.acceptance.rest.util.RestCall;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.projects.BranchInput;
@@ -39,10 +42,9 @@
* Tests for checking the bindings of the projects REST API.
*
* <p>These tests only verify that the project REST endpoints are correctly bound, they do no test
- * the functionality of the project REST endpoints (for details see JavaDoc on {@link
- * AbstractRestApiBindingsTest}).
+ * the functionality of the project REST endpoints.
*/
-public class ProjectsRestApiBindingsIT extends AbstractRestApiBindingsTest {
+public class ProjectsRestApiBindingsIT extends AbstractDaemonTest {
private static final ImmutableList<RestCall> PROJECT_ENDPOINTS =
ImmutableList.of(
RestCall.get("/projects/%s"),
@@ -157,49 +159,53 @@
@Test
public void projectEndpoints() throws Exception {
- execute(PROJECT_ENDPOINTS, project.get());
+ RestApiCallHelper.execute(adminRestSession, PROJECT_ENDPOINTS, project.get());
}
@Test
public void childProjectEndpoints() throws Exception {
Project.NameKey childProject = createProject("test-child-repo", project);
- execute(CHILD_PROJECT_ENDPOINTS, project.get(), childProject.get());
+ RestApiCallHelper.execute(
+ adminRestSession, CHILD_PROJECT_ENDPOINTS, project.get(), childProject.get());
}
@Test
public void branchEndpoints() throws Exception {
- execute(BRANCH_ENDPOINTS, project.get(), "master");
+ RestApiCallHelper.execute(adminRestSession, BRANCH_ENDPOINTS, project.get(), "master");
}
@Test
public void branchFileEndpoints() throws Exception {
createAndSubmitChange(FILENAME);
- execute(BRANCH_FILE_ENDPOINTS, project.get(), "master", FILENAME);
+ RestApiCallHelper.execute(
+ adminRestSession, BRANCH_FILE_ENDPOINTS, project.get(), "master", FILENAME);
}
@Test
public void dashboardEndpoints() throws Exception {
createDefaultDashboard();
- execute(DASHBOARD_ENDPOINTS, project.get(), DEFAULT_DASHBOARD_NAME);
+ RestApiCallHelper.execute(
+ adminRestSession, DASHBOARD_ENDPOINTS, project.get(), DEFAULT_DASHBOARD_NAME);
}
@Test
public void tagEndpoints() throws Exception {
String tag = "test-tag";
gApi.projects().name(project.get()).tag(tag).create(new TagInput());
- execute(TAG_ENDPOINTS, project.get(), tag);
+ RestApiCallHelper.execute(adminRestSession, TAG_ENDPOINTS, project.get(), tag);
}
@Test
public void commitEndpoints() throws Exception {
String commit = createAndSubmitChange(FILENAME);
- execute(COMMIT_ENDPOINTS, project.get(), commit);
+ RestApiCallHelper.execute(adminRestSession, COMMIT_ENDPOINTS, project.get(), commit);
}
@Test
public void commitFileEndpoints() throws Exception {
String commit = createAndSubmitChange(FILENAME);
- execute(COMMIT_FILE_ENDPOINTS, project.get(), commit, FILENAME);
+ RestApiCallHelper.execute(
+ adminRestSession, COMMIT_FILE_ENDPOINTS, project.get(), commit, FILENAME);
}
private String createAndSubmitChange(String filename) throws Exception {
diff --git a/javatests/com/google/gerrit/acceptance/rest/RootCollectionsRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/RootCollectionsRestApiBindingsIT.java
similarity index 79%
rename from javatests/com/google/gerrit/acceptance/rest/RootCollectionsRestApiBindingsIT.java
rename to javatests/com/google/gerrit/acceptance/rest/binding/RootCollectionsRestApiBindingsIT.java
index a2c4ea6..6d140c6 100644
--- a/javatests/com/google/gerrit/acceptance/rest/RootCollectionsRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/RootCollectionsRestApiBindingsIT.java
@@ -12,23 +12,25 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.acceptance.rest;
+package com.google.gerrit.acceptance.rest.binding;
-import static com.google.gerrit.acceptance.rest.AbstractRestApiBindingsTest.Method.GET;
+import static com.google.gerrit.acceptance.rest.util.RestApiCallHelper.execute;
+import static com.google.gerrit.acceptance.rest.util.RestCall.Method.GET;
import static org.apache.http.HttpStatus.SC_NOT_FOUND;
import com.google.common.collect.ImmutableList;
+import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.GerritConfig;
+import com.google.gerrit.acceptance.rest.util.RestCall;
import org.junit.Test;
/**
* Tests for checking the bindings of the root REST API.
*
* <p>These tests only verify that the root REST endpoints are correctly bound, they do no test the
- * functionality of the root REST endpoints (for details see JavaDoc on {@link
- * AbstractRestApiBindingsTest}).
+ * functionality of the root REST endpoints.
*/
-public class RootCollectionsRestApiBindingsIT extends AbstractRestApiBindingsTest {
+public class RootCollectionsRestApiBindingsIT extends AbstractDaemonTest {
/** Root REST endpoints to be tested, the URLs contain no placeholders. */
private static final ImmutableList<RestCall> ROOT_ENDPOINTS =
ImmutableList.of(
@@ -51,6 +53,6 @@
@Test
@GerritConfig(name = "plugins.allowRemoteAdmin", value = "true")
public void rootEndpoints() throws Exception {
- execute(ROOT_ENDPOINTS);
+ execute(adminRestSession, ROOT_ENDPOINTS);
}
}
diff --git a/javatests/com/google/gerrit/acceptance/rest/util/BUILD b/javatests/com/google/gerrit/acceptance/rest/util/BUILD
new file mode 100644
index 0000000..115ea09
--- /dev/null
+++ b/javatests/com/google/gerrit/acceptance/rest/util/BUILD
@@ -0,0 +1,10 @@
+java_library(
+ name = "util",
+ testonly = 1,
+ srcs = glob(["*.java"]),
+ visibility = ["//visibility:public"],
+ deps = [
+ "//java/com/google/gerrit/acceptance:lib",
+ "//lib/commons:lang",
+ ],
+)
diff --git a/javatests/com/google/gerrit/acceptance/rest/util/RestApiCallHelper.java b/javatests/com/google/gerrit/acceptance/rest/util/RestApiCallHelper.java
new file mode 100644
index 0000000..52e72fe
--- /dev/null
+++ b/javatests/com/google/gerrit/acceptance/rest/util/RestApiCallHelper.java
@@ -0,0 +1,104 @@
+// 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.acceptance.rest.util;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+import static com.google.common.truth.Truth.assert_;
+import static org.apache.http.HttpStatus.SC_FORBIDDEN;
+import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
+import static org.apache.http.HttpStatus.SC_METHOD_NOT_ALLOWED;
+import static org.apache.http.HttpStatus.SC_NOT_FOUND;
+
+import com.google.common.collect.ImmutableList;
+import com.google.gerrit.acceptance.RestResponse;
+import com.google.gerrit.acceptance.RestSession;
+import java.util.List;
+import org.junit.Ignore;
+
+/** Helper to execute REST API calls using the HTTP client. */
+@Ignore
+public class RestApiCallHelper {
+ /** @see #execute(RestSession, List, BeforeRestCall, String...) */
+ public static void execute(RestSession restSession, List<RestCall> restCalls, String... args)
+ throws Exception {
+ execute(restSession, restCalls, () -> {}, args);
+ }
+
+ /** @see #execute(RestSession, List, BeforeRestCall, String...) */
+ public static void execute(
+ RestSession restSession,
+ List<RestCall> restCalls,
+ BeforeRestCall beforeRestCall,
+ String... args)
+ throws Exception {
+ for (RestCall restCall : restCalls) {
+ beforeRestCall.run();
+ execute(restSession, restCall, args);
+ }
+ }
+
+ /**
+ * This method sends a request to a given REST endpoint and verifies that an implementation is
+ * found (no '404 Not Found' response) and that the request doesn't fail (no '500 Internal Server
+ * Error' response). It doesn't verify that the REST endpoint works correctly. This is okay since
+ * the purpose of the test is only to verify that the REST endpoint implementations are correctly
+ * bound.
+ */
+ public static void execute(RestSession restSession, RestCall restCall, String... args)
+ throws Exception {
+ String method = restCall.httpMethod().name();
+ String uri = restCall.uri(args);
+
+ RestResponse response;
+ switch (restCall.httpMethod()) {
+ case GET:
+ response = restSession.get(uri);
+ break;
+ case PUT:
+ response = restSession.put(uri);
+ break;
+ case POST:
+ response = restSession.post(uri);
+ break;
+ case DELETE:
+ response = restSession.delete(uri);
+ break;
+ default:
+ assert_().fail(String.format("unsupported method: %s", restCall.httpMethod().name()));
+ throw new IllegalStateException();
+ }
+
+ int status = response.getStatusCode();
+ String body = response.hasContent() ? response.getEntityContent() : "";
+
+ String msg = String.format("%s %s returned %d: %s", method, uri, status, body);
+ if (restCall.expectedResponseCode().isPresent()) {
+ assertWithMessage(msg).that(status).isEqualTo(restCall.expectedResponseCode().get());
+ if (restCall.expectedMessage().isPresent()) {
+ assertWithMessage(msg).that(body).contains(restCall.expectedMessage().get());
+ }
+ } else {
+ assertWithMessage(msg)
+ .that(status)
+ .isNotIn(ImmutableList.of(SC_FORBIDDEN, SC_NOT_FOUND, SC_METHOD_NOT_ALLOWED));
+ assertWithMessage(msg).that(status).isLessThan(SC_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ @FunctionalInterface
+ public interface BeforeRestCall {
+ void run() throws Exception;
+ }
+}
diff --git a/javatests/com/google/gerrit/acceptance/rest/util/RestCall.java b/javatests/com/google/gerrit/acceptance/rest/util/RestCall.java
new file mode 100644
index 0000000..a322089
--- /dev/null
+++ b/javatests/com/google/gerrit/acceptance/rest/util/RestCall.java
@@ -0,0 +1,88 @@
+// 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.acceptance.rest.util;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.auto.value.AutoValue;
+import java.util.Optional;
+import jdk.nashorn.internal.ir.annotations.Ignore;
+import org.apache.commons.lang.StringUtils;
+
+/** Data container for test REST requests. */
+@Ignore
+@AutoValue
+public abstract class RestCall {
+ public enum Method {
+ GET,
+ PUT,
+ POST,
+ DELETE
+ }
+
+ public static RestCall get(String uriFormat) {
+ return builder(Method.GET, uriFormat).build();
+ }
+
+ public static RestCall put(String uriFormat) {
+ return builder(Method.PUT, uriFormat).build();
+ }
+
+ public static RestCall post(String uriFormat) {
+ return builder(Method.POST, uriFormat).build();
+ }
+
+ public static RestCall delete(String uriFormat) {
+ return builder(Method.DELETE, uriFormat).build();
+ }
+
+ public static Builder builder(Method httpMethod, String uriFormat) {
+ return new AutoValue_RestCall.Builder().httpMethod(httpMethod).uriFormat(uriFormat);
+ }
+
+ public abstract Method httpMethod();
+
+ public abstract String uriFormat();
+
+ public abstract Optional<Integer> expectedResponseCode();
+
+ public abstract Optional<String> expectedMessage();
+
+ public String uri(String... args) {
+ String uriFormat = uriFormat();
+ int expectedArgNum = StringUtils.countMatches(uriFormat, "%s");
+ checkState(
+ args.length == expectedArgNum,
+ "uriFormat %s needs %s arguments, got only %s: %s",
+ uriFormat,
+ expectedArgNum,
+ args.length,
+ args);
+ return String.format(uriFormat, (Object[]) args);
+ }
+
+ @AutoValue.Builder
+ public abstract static class Builder {
+ public abstract Builder httpMethod(Method httpMethod);
+
+ public abstract Builder uriFormat(String uriFormat);
+
+ public abstract Builder expectedResponseCode(int expectedResponseCode);
+
+ public abstract Builder expectedMessage(String expectedMessage);
+
+ public abstract RestCall build();
+ }
+}