blob: 2bb3dcaa779b391bbea3a6d6514d6b44eae4dde4 [file] [log] [blame]
// 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;
}
}